]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2015 01:12:07 +0000 (18:12 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2015 01:12:07 +0000 (18:12 -0700)
Pull RCU updates from Ingo Molnar:
 "The main RCU changes in this cycle are:

   - the combination of tree geometry-initialization simplifications and
     OS-jitter-reduction changes to expedited grace periods.  These two
     are stacked due to the large number of conflicts that would
     otherwise result.

   - privatize smp_mb__after_unlock_lock().

     This commit moves the definition of smp_mb__after_unlock_lock() to
     kernel/rcu/tree.h, in recognition of the fact that RCU is the only
     thing using this, that nothing else is likely to use it, and that
     it is likely to go away completely.

   - documentation updates.

   - torture-test updates.

   - misc fixes"

* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (60 commits)
  rcu,locking: Privatize smp_mb__after_unlock_lock()
  rcu: Silence lockdep false positive for expedited grace periods
  rcu: Don't disable CPU hotplug during OOM notifiers
  scripts: Make checkpatch.pl warn on expedited RCU grace periods
  rcu: Update MAINTAINERS entry
  rcu: Clarify CONFIG_RCU_EQS_DEBUG help text
  rcu: Fix backwards RCU_LOCKDEP_WARN() in synchronize_rcu_tasks()
  rcu: Rename rcu_lockdep_assert() to RCU_LOCKDEP_WARN()
  rcu: Make rcu_is_watching() really notrace
  cpu: Wait for RCU grace periods concurrently
  rcu: Create a synchronize_rcu_mult()
  rcu: Fix obsolete priority-boosting comment
  rcu: Use WRITE_ONCE in RCU_INIT_POINTER
  rcu: Hide RCU_NOCB_CPU behind RCU_EXPERT
  rcu: Add RCU-sched flavors of get-state and cond-sync
  rcu: Add fastpath bypassing funnel locking
  rcu: Rename RCU_GP_DONE_FQS to RCU_GP_DOING_FQS
  rcu: Pull out wait_event*() condition into helper function
  documentation: Describe new expedited stall warnings
  rcu: Add stall warnings to synchronize_sched_expedited()
  ...

2165 files changed:
.get_maintainer.ignore [new file with mode: 0644]
.mailmap
Documentation/ABI/stable/sysfs-bus-vmbus [new file with mode: 0644]
Documentation/ABI/testing/configfs-usb-gadget-loopback
Documentation/ABI/testing/configfs-usb-gadget-sourcesink
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
Documentation/ABI/testing/sysfs-bus-iio
Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
Documentation/ABI/testing/sysfs-bus-usb
Documentation/ABI/testing/sysfs-class-power-twl4030 [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-sunxi-sid [deleted file]
Documentation/CodingStyle
Documentation/DocBook/Makefile
Documentation/DocBook/crypto-API.tmpl
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/iio.tmpl [new file with mode: 0644]
Documentation/DocBook/stylesheet.xsl
Documentation/HOWTO
Documentation/Intel-IOMMU.txt
Documentation/SubmittingPatches
Documentation/adding-syscalls.txt [new file with mode: 0644]
Documentation/arm/Samsung/Bootloader-interface.txt
Documentation/arm/keystone/Overview.txt [new file with mode: 0644]
Documentation/clk.txt
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/arm/coresight.txt
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
Documentation/devicetree/bindings/arm/sp810.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/gpio-mux-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/hi6220-clock.txt
Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ux500.txt [new file with mode: 0644]
Documentation/devicetree/bindings/crypto/fsl-sec4.txt
Documentation/devicetree/bindings/crypto/sun4i-ss.txt [new file with mode: 0644]
Documentation/devicetree/bindings/extcon/extcon-palmas.txt
Documentation/devicetree/bindings/hwmon/lm70.txt [new file with mode: 0644]
Documentation/devicetree/bindings/hwmon/ltc2978.txt
Documentation/devicetree/bindings/iio/adc/mcp320x.txt
Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/st-sensors.txt
Documentation/devicetree/bindings/leds/common.txt
Documentation/devicetree/bindings/leds/leds-ns2.txt
Documentation/devicetree/bindings/mfd/rk808.txt
Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt [moved from Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt with 78% similarity]
Documentation/devicetree/bindings/nvmem/nvmem.txt [new file with mode: 0644]
Documentation/devicetree/bindings/nvmem/qfprom.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/ti-pci.txt
Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
Documentation/devicetree/bindings/power/qcom,coincell-charger.txt [new file with mode: 0644]
Documentation/devicetree/bindings/powerpc/fsl/mpc5121-psc.txt
Documentation/devicetree/bindings/regulator/da9210.txt
Documentation/devicetree/bindings/regulator/da9211.txt
Documentation/devicetree/bindings/regulator/max8973-regulator.txt
Documentation/devicetree/bindings/regulator/mt6311-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/pwm-regulator.txt
Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/devicetree/bindings/serial/atmel-usart.txt
Documentation/devicetree/bindings/serial/axis,etraxfs-uart.txt
Documentation/devicetree/bindings/serial/omap_serial.txt
Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
Documentation/devicetree/bindings/spi/spi-davinci.txt
Documentation/devicetree/bindings/spi/spi-img-spfi.txt
Documentation/devicetree/bindings/spi/spi-mt65xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-xlp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
Documentation/devicetree/bindings/usb/generic.txt
Documentation/devicetree/bindings/usb/msm-hsusb.txt
Documentation/devicetree/bindings/usb/qcom,usb-8x16-phy.txt [new file with mode: 0644]
Documentation/email-clients.txt
Documentation/fb/sm712fb.txt [new file with mode: 0644]
Documentation/filesystems/btrfs.txt
Documentation/filesystems/debugfs.txt
Documentation/filesystems/sysfs.txt
Documentation/hwmon/adm1275
Documentation/hwmon/fam15h_power
Documentation/hwmon/it87
Documentation/hwmon/ltc2978
Documentation/hwmon/max20751 [new file with mode: 0644]
Documentation/hwmon/nct7802
Documentation/hwmon/pmbus
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/kernel-parameters.txt
Documentation/mailbox.txt
Documentation/men-chameleon-bus.txt [new file with mode: 0644]
Documentation/misc-devices/mei/mei.txt
Documentation/networking/can.txt
Documentation/nvmem/nvmem.txt [new file with mode: 0644]
Documentation/power/suspend-and-cpuhotplug.txt
Documentation/powerpc/cxl.txt
Documentation/powerpc/dscr.txt
Documentation/powerpc/qe_firmware.txt
Documentation/pps/pps.txt
Documentation/s390/00-INDEX
Documentation/s390/kvm.txt [deleted file]
Documentation/sysctl/vm.txt
Documentation/trace/coresight.txt
Documentation/usb/gadget-testing.txt
Documentation/usb/power-management.txt
Documentation/virtual/kvm/api.txt
Documentation/x86/kernel-stacks
MAINTAINERS
Makefile
README
arch/alpha/Kconfig
arch/alpha/include/asm/spinlock.h
arch/alpha/kernel/pci.c
arch/arm/Makefile
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/k2e.dtsi
arch/arm/boot/dts/k2hk.dtsi
arch/arm/boot/dts/k2l.dtsi
arch/arm/boot/dts/keystone.dtsi
arch/arm/boot/dts/kirkwood-d2net.dts
arch/arm/boot/dts/kirkwood-is2.dts
arch/arm/boot/dts/kirkwood-ns2.dts
arch/arm/boot/dts/kirkwood-ns2max.dts
arch/arm/boot/dts/kirkwood-ns2mini.dts
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts
arch/arm/boot/dts/qcom-pm8941.dtsi
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun9i-a80.dtsi
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/crypto/.gitignore
arch/arm/include/asm/mach/pci.h
arch/arm/kernel/bios32.c
arch/arm/kernel/entry-common.S
arch/arm/kernel/head.S
arch/arm/kernel/vdso.c
arch/arm/lib/uaccess_with_memcpy.c
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-hisi/hisilicon.c
arch/arm/mach-keystone/pm_domain.c
arch/arm/mach-mvebu/board-v7.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clkt34xx_dpll3m2.c
arch/arm/mach-omap2/clkt_clksel.c [deleted file]
arch/arm/mach-omap2/clkt_iclk.c [deleted file]
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2430.c [deleted file]
arch/arm/mach-omap2/clock2xxx.c [deleted file]
arch/arm/mach-omap2/clock34xx.c [deleted file]
arch/arm/mach-omap2/clock34xx.h [deleted file]
arch/arm/mach-omap2/clock3517.c [deleted file]
arch/arm/mach-omap2/clock3517.h [deleted file]
arch/arm/mach-omap2/clock36xx.c [deleted file]
arch/arm/mach-omap2/clock36xx.h [deleted file]
arch/arm/mach-omap2/clock3xxx.c [deleted file]
arch/arm/mach-omap2/clock44xx.h [deleted file]
arch/arm/mach-omap2/clock_common_data.c [deleted file]
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-orion5x/board-dt.c
arch/arm/mach-s3c64xx/common.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-ux500/cpu.c
arch/arm/vdso/Makefile
arch/arm64/boot/dts/apm/apm-storm.dtsi
arch/arm64/crypto/aes-ce-ccm-glue.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/vdso.c
arch/arm64/kvm/inject_fault.c
arch/frv/mb93090-mb00/pci-frv.c
arch/frv/mb93090-mb00/pci-frv.h
arch/frv/mb93090-mb00/pci-vdk.c
arch/ia64/pci/pci.c
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/kernel/bootinfo_proc.c
arch/microblaze/pci/pci-common.c
arch/mips/alchemy/common/clock.c
arch/mips/kernel/genex.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/pci/pci.c
arch/mn10300/unit-asb2305/pci-asb2305.c
arch/mn10300/unit-asb2305/pci-asb2305.h
arch/mn10300/unit-asb2305/pci.c
arch/powerpc/include/asm/mpc52xx_psc.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_of_scan.c
arch/powerpc/kernel/process.c
arch/powerpc/platforms/512x/clock-commonclk.c
arch/s390/Kbuild
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/configs/default_defconfig
arch/s390/configs/gcov_defconfig
arch/s390/configs/performance_defconfig
arch/s390/crypto/aes_s390.c
arch/s390/crypto/des_s390.c
arch/s390/crypto/ghash_s390.c
arch/s390/crypto/prng.c
arch/s390/crypto/sha1_s390.c
arch/s390/crypto/sha256_s390.c
arch/s390/crypto/sha512_s390.c
arch/s390/include/asm/cpufeature.h [new file with mode: 0644]
arch/s390/include/asm/ctl_reg.h
arch/s390/include/asm/etr.h
arch/s390/include/asm/fpu-internal.h [new file with mode: 0644]
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/linkage.h
arch/s390/include/asm/mmzone.h [new file with mode: 0644]
arch/s390/include/asm/numa.h [new file with mode: 0644]
arch/s390/include/asm/pci.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/sclp.h
arch/s390/include/asm/switch_to.h
arch/s390/include/asm/topology.h
arch/s390/include/asm/unistd.h
arch/s390/include/asm/vx-insn.h [new file with mode: 0644]
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/Makefile
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/entry.S
arch/s390/kernel/head.S
arch/s390/kernel/jump_label.c
arch/s390/kernel/nmi.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/process.c
arch/s390/kernel/processor.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/s390_ksyms.c
arch/s390/kernel/sclp.S [deleted file]
arch/s390/kernel/sclp.c [new file with mode: 0644]
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/traps.c
arch/s390/kernel/vdso32/Makefile
arch/s390/kernel/vdso64/Makefile
arch/s390/kernel/vtime.c
arch/s390/kvm/diag.c
arch/s390/kvm/guestdbg.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/kvm/trace-s390.h
arch/s390/lib/delay.c
arch/s390/lib/uaccess.c
arch/s390/mm/fault.c
arch/s390/mm/gup.c
arch/s390/mm/init.c
arch/s390/mm/pgtable.c
arch/s390/numa/Makefile [new file with mode: 0644]
arch/s390/numa/mode_emu.c [new file with mode: 0644]
arch/s390/numa/numa.c [new file with mode: 0644]
arch/s390/numa/numa_mode.h [new file with mode: 0644]
arch/s390/numa/toptree.c [new file with mode: 0644]
arch/s390/numa/toptree.h [new file with mode: 0644]
arch/s390/pci/pci.c
arch/s390/pci/pci_dma.c
arch/s390/pci/pci_event.c
arch/s390/pci/pci_insn.c
arch/s390/pci/pci_sysfs.c
arch/sh/drivers/pci/pci-sh4.h
arch/sh/kernel/cpu/sh4/sq.c
arch/sparc/kernel/pci.c
arch/tile/kernel/sysfs.c
arch/x86/crypto/Makefile
arch/x86/crypto/aesni-intel_glue.c
arch/x86/crypto/chacha20-avx2-x86_64.S [new file with mode: 0644]
arch/x86/crypto/chacha20-ssse3-x86_64.S [new file with mode: 0644]
arch/x86/crypto/chacha20_glue.c [new file with mode: 0644]
arch/x86/crypto/poly1305-avx2-x86_64.S [new file with mode: 0644]
arch/x86/crypto/poly1305-sse2-x86_64.S [new file with mode: 0644]
arch/x86/crypto/poly1305_glue.c [new file with mode: 0644]
arch/x86/entry/entry_64_compat.S
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/sigcontext.h
arch/x86/include/asm/switch_to.h
arch/x86/include/asm/vmx.h
arch/x86/include/uapi/asm/hyperv.h
arch/x86/include/uapi/asm/sigcontext.h
arch/x86/include/uapi/asm/vmx.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/vector.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_cqm.c
arch/x86/kernel/fpu/core.c
arch/x86/kernel/fpu/init.c
arch/x86/kernel/process.c
arch/x86/kernel/signal.c
arch/x86/kernel/step.c
arch/x86/kvm/Makefile
arch/x86/kvm/hyperv.c [new file with mode: 0644]
arch/x86/kvm/hyperv.h [new file with mode: 0644]
arch/x86/kvm/i8259.c
arch/x86/kvm/irq.h
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu.h
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/pmu_amd.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/math-emu/fpu_entry.c
arch/x86/math-emu/fpu_system.h
arch/x86/math-emu/get_address.c
arch/x86/pci/common.c
arch/x86/pci/fixup.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
arch/x86/xen/Kconfig
arch/x86/xen/Makefile
arch/x86/xen/xen-ops.h
arch/xtensa/Kconfig
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/atomic.h
arch/xtensa/include/asm/cmpxchg.h
arch/xtensa/include/asm/device.h [new file with mode: 0644]
arch/xtensa/include/asm/dma-mapping.h
arch/xtensa/include/asm/irqflags.h
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/stacktrace.h
arch/xtensa/include/asm/traps.h
arch/xtensa/kernel/Makefile
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/pci-dma.c
arch/xtensa/kernel/pci.c
arch/xtensa/kernel/perf_event.c [new file with mode: 0644]
arch/xtensa/kernel/stacktrace.c
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vectors.S
arch/xtensa/mm/fault.c
arch/xtensa/oprofile/backtrace.c
arch/xtensa/platforms/iss/network.c
block/blk-settings.c
crypto/Kconfig
crypto/Makefile
crypto/aead.c
crypto/algapi.c
crypto/algboss.c
crypto/algif_aead.c
crypto/authenc.c
crypto/authencesn.c
crypto/ccm.c
crypto/chacha20_generic.c
crypto/chacha20poly1305.c
crypto/cryptd.c
crypto/crypto_user.c
crypto/echainiv.c
crypto/gcm.c
crypto/jitterentropy-kcapi.c
crypto/pcrypt.c
crypto/poly1305_generic.c
crypto/rsa.c
crypto/rsa_helper.c
crypto/seqiv.c
crypto/skcipher.c [new file with mode: 0644]
crypto/tcrypt.c
crypto/tcrypt.h
crypto/testmgr.c
crypto/testmgr.h
drivers/Kconfig
drivers/Makefile
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_pnp.c
drivers/acpi/nfit.c
drivers/acpi/pci_irq.c
drivers/acpi/video_detect.c
drivers/ata/ahci.c
drivers/ata/ahci_brcmstb.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
drivers/ata/pata_jmicron.c
drivers/ata/sata_sx4.c
drivers/auxdisplay/ks0108.c
drivers/base/base.h
drivers/base/core.c
drivers/base/cpu.c
drivers/base/dd.c
drivers/base/devres.c
drivers/base/firmware_class.c
drivers/base/regmap/regcache-rbtree.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkfront.c
drivers/block/zram/zram_drv.c
drivers/char/misc.c
drivers/char/nvram.c
drivers/char/toshiba.c
drivers/char/xillybus/xillybus_pcie.c
drivers/clk/Makefile
drivers/clk/at91/clk-main.c
drivers/clk/at91/clk-master.c
drivers/clk/at91/clk-peripheral.c
drivers/clk/at91/clk-programmable.c
drivers/clk/at91/clk-slow.c
drivers/clk/at91/clk-smd.c
drivers/clk/at91/clk-usb.c
drivers/clk/at91/pmc.c
drivers/clk/at91/pmc.h
drivers/clk/bcm/clk-kona.c
drivers/clk/berlin/berlin2-pll.c
drivers/clk/clk-axi-clkgen.c
drivers/clk/clk-bcm2835.c
drivers/clk/clk-cdce706.c
drivers/clk/clk-cdce925.c
drivers/clk/clk-clps711x.c
drivers/clk/clk-composite.c
drivers/clk/clk-divider.c
drivers/clk/clk-efm32gg.c
drivers/clk/clk-fixed-factor.c
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-gate.c
drivers/clk/clk-gpio-gate.c [deleted file]
drivers/clk/clk-gpio.c [new file with mode: 0644]
drivers/clk/clk-highbank.c
drivers/clk/clk-moxart.c
drivers/clk/clk-mux.c
drivers/clk/clk-nomadik.c
drivers/clk/clk-palmas.c
drivers/clk/clk-rk808.c
drivers/clk/clk-s2mps11.c
drivers/clk/clk-si5351.c
drivers/clk/clk-si570.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-twl6040.c
drivers/clk/clk-u300.c
drivers/clk/clk-wm831x.c
drivers/clk/clk-xgene.c
drivers/clk/clk.c
drivers/clk/h8300/clk-div.c
drivers/clk/h8300/clk-h8s2678.c
drivers/clk/hisilicon/Kconfig
drivers/clk/hisilicon/Makefile
drivers/clk/hisilicon/clk-hi3620.c
drivers/clk/hisilicon/clk-hi6220-stub.c [new file with mode: 0644]
drivers/clk/hisilicon/clk-hip04.c
drivers/clk/hisilicon/clk.c
drivers/clk/hisilicon/clkgate-separated.c
drivers/clk/imx/Makefile
drivers/clk/imx/clk-imx1.c
drivers/clk/imx/clk-imx21.c
drivers/clk/imx/clk-imx31.c
drivers/clk/imx/clk-imx35.c
drivers/clk/imx/clk-imx6q.c
drivers/clk/imx/clk-imx6ul.c [new file with mode: 0644]
drivers/clk/imx/clk-pfd.c
drivers/clk/imx/clk-pllv1.c
drivers/clk/imx/clk-pllv3.c
drivers/clk/ingenic/cgu.c
drivers/clk/keystone/gate.c
drivers/clk/keystone/pll.c
drivers/clk/mediatek/clk-gate.h
drivers/clk/mediatek/clk-mt8135.c
drivers/clk/mediatek/clk-mt8173.c
drivers/clk/mediatek/clk-mtk.h
drivers/clk/mediatek/clk-pll.c
drivers/clk/meson/clk-cpu.c
drivers/clk/meson/clkc.c
drivers/clk/mmp/clk-apbc.c
drivers/clk/mmp/clk-apmu.c
drivers/clk/mmp/clk-gate.c
drivers/clk/mmp/clk-mix.c
drivers/clk/mmp/clk.c
drivers/clk/mvebu/clk-cpu.c
drivers/clk/mvebu/common.c
drivers/clk/mxs/clk-div.c
drivers/clk/mxs/clk-frac.c
drivers/clk/mxs/clk-imx23.c
drivers/clk/mxs/clk-imx28.c
drivers/clk/mxs/clk-pll.c
drivers/clk/mxs/clk-ref.c
drivers/clk/mxs/clk.h
drivers/clk/nxp/clk-lpc18xx-cgu.c
drivers/clk/pistachio/clk-pistachio.c
drivers/clk/pistachio/clk-pll.c
drivers/clk/pistachio/clk.c
drivers/clk/pistachio/clk.h
drivers/clk/pxa/clk-pxa25x.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/pxa/clk-pxa3xx.c
drivers/clk/qcom/clk-branch.c
drivers/clk/qcom/clk-pll.c
drivers/clk/qcom/clk-pll.h
drivers/clk/qcom/clk-rcg.c
drivers/clk/qcom/clk-rcg2.c
drivers/clk/qcom/common.c
drivers/clk/qcom/gcc-apq8084.c
drivers/clk/qcom/gcc-ipq806x.c
drivers/clk/qcom/gcc-msm8660.c
drivers/clk/qcom/gcc-msm8916.c
drivers/clk/qcom/gcc-msm8960.c
drivers/clk/qcom/gcc-msm8974.c
drivers/clk/qcom/lcc-ipq806x.c
drivers/clk/qcom/lcc-msm8960.c
drivers/clk/qcom/mmcc-apq8084.c
drivers/clk/qcom/mmcc-msm8960.c
drivers/clk/qcom/mmcc-msm8974.c
drivers/clk/rockchip/Makefile
drivers/clk/rockchip/clk-cpu.c
drivers/clk/rockchip/clk-inverter.c [new file with mode: 0644]
drivers/clk/rockchip/clk-mmc-phase.c
drivers/clk/rockchip/clk-pll.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk-rk3368.c [new file with mode: 0644]
drivers/clk/rockchip/clk.c
drivers/clk/rockchip/clk.h
drivers/clk/samsung/clk-cpu.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos4415.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5260.c
drivers/clk/samsung/clk-exynos5410.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/samsung/clk-exynos5440.c
drivers/clk/samsung/clk-exynos7.c
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-s3c2410-dclk.c
drivers/clk/samsung/clk-s3c2410.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clk/samsung/clk-s5pv210-audss.c
drivers/clk/samsung/clk-s5pv210.c
drivers/clk/samsung/clk.c
drivers/clk/samsung/clk.h
drivers/clk/shmobile/clk-div6.c
drivers/clk/shmobile/clk-r8a73a4.c
drivers/clk/shmobile/clk-r8a7740.c
drivers/clk/shmobile/clk-r8a7778.c
drivers/clk/shmobile/clk-r8a7779.c
drivers/clk/shmobile/clk-rcar-gen2.c
drivers/clk/shmobile/clk-sh73a0.c
drivers/clk/sirf/clk-atlas6.c
drivers/clk/sirf/clk-atlas7.c
drivers/clk/sirf/clk-common.c
drivers/clk/sirf/clk-prima2.c
drivers/clk/socfpga/clk-gate-a10.c
drivers/clk/socfpga/clk-gate.c
drivers/clk/socfpga/clk-periph-a10.c
drivers/clk/socfpga/clk-periph.c
drivers/clk/socfpga/clk-pll-a10.c
drivers/clk/socfpga/clk-pll.c
drivers/clk/socfpga/clk.h
drivers/clk/spear/clk-vco-pll.c
drivers/clk/spear/spear1310_clock.c
drivers/clk/spear/spear1340_clock.c
drivers/clk/spear/spear6xx_clock.c
drivers/clk/st/clk-flexgen.c
drivers/clk/st/clkgen-fsyn.c
drivers/clk/st/clkgen-mux.c
drivers/clk/st/clkgen-pll.c
drivers/clk/sunxi/Makefile
drivers/clk/sunxi/clk-a20-gmac.c
drivers/clk/sunxi/clk-factors.c
drivers/clk/sunxi/clk-mod0.c
drivers/clk/sunxi/clk-simple-gates.c [new file with mode: 0644]
drivers/clk/sunxi/clk-sun6i-ar100.c
drivers/clk/sunxi/clk-sun8i-mbus.c
drivers/clk/sunxi/clk-sun9i-core.c
drivers/clk/sunxi/clk-sun9i-mmc.c
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/sunxi/clk-usb.c
drivers/clk/tegra/Makefile
drivers/clk/tegra/clk-dfll.c [new file with mode: 0644]
drivers/clk/tegra/clk-dfll.h [new file with mode: 0644]
drivers/clk/tegra/clk-divider.c
drivers/clk/tegra/clk-emc.c
drivers/clk/tegra/clk-periph-gate.c
drivers/clk/tegra/clk-periph.c
drivers/clk/tegra/clk-pll-out.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-super.c
drivers/clk/tegra/clk-tegra-audio.c
drivers/clk/tegra/clk-tegra-fixed.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-pmc.c
drivers/clk/tegra/clk-tegra-super-gen4.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124-dfll-fcpu.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h
drivers/clk/tegra/cvb.c [new file with mode: 0644]
drivers/clk/tegra/cvb.h [new file with mode: 0644]
drivers/clk/ti/Makefile
drivers/clk/ti/apll.c
drivers/clk/ti/autoidle.c
drivers/clk/ti/clk-2xxx.c
drivers/clk/ti/clk-33xx.c
drivers/clk/ti/clk-3xxx-legacy.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-43xx.c
drivers/clk/ti/clk-44xx.c
drivers/clk/ti/clk-54xx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clk-816x.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clk.c
drivers/clk/ti/clkt_dflt.c [new file with mode: 0644]
drivers/clk/ti/clkt_dpll.c [moved from arch/arm/mach-omap2/clkt_dpll.c with 92% similarity]
drivers/clk/ti/clkt_iclk.c [new file with mode: 0644]
drivers/clk/ti/clock.h
drivers/clk/ti/clockdomain.c
drivers/clk/ti/composite.c
drivers/clk/ti/divider.c
drivers/clk/ti/dpll.c
drivers/clk/ti/dpll3xxx.c [moved from arch/arm/mach-omap2/dpll3xxx.c with 79% similarity]
drivers/clk/ti/dpll44xx.c [moved from arch/arm/mach-omap2/dpll44xx.c with 79% similarity]
drivers/clk/ti/fapll.c
drivers/clk/ti/fixed-factor.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/clk/ti/mux.c
drivers/clk/ux500/Makefile
drivers/clk/ux500/abx500-clk.c
drivers/clk/ux500/clk-prcmu.c
drivers/clk/ux500/clk-sysctrl.c
drivers/clk/ux500/clk.h
drivers/clk/ux500/u8500_clk.c [deleted file]
drivers/clk/ux500/u8500_of_clk.c
drivers/clk/ux500/u8540_clk.c
drivers/clk/ux500/u9540_clk.c
drivers/clk/versatile/clk-icst.c
drivers/clk/versatile/clk-impd1.c
drivers/clk/versatile/clk-realview.c
drivers/clk/versatile/clk-sp810.c
drivers/clk/versatile/clk-versatile.c
drivers/clk/zte/Makefile
drivers/clk/zte/clk-zx296702.c
drivers/clk/zte/clk.c [moved from drivers/clk/zte/clk-pll.c with 55% similarity]
drivers/clk/zte/clk.h
drivers/clk/zynq/clkc.c
drivers/clocksource/cadence_ttc_timer.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/timer-imx-gpt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/exynos-cpufreq.c
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/crypto/amcc/crypto4xx_core.c
drivers/crypto/caam/Kconfig
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamhash.c
drivers/crypto/caam/caamrng.c
drivers/crypto/caam/compat.h
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/desc.h
drivers/crypto/caam/desc_constr.h
drivers/crypto/caam/intern.h
drivers/crypto/caam/jr.c
drivers/crypto/caam/regs.h
drivers/crypto/caam/sg_sw_sec4.h
drivers/crypto/ccp/ccp-platform.c
drivers/crypto/img-hash.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/marvell/cesa.c
drivers/crypto/nx/Kconfig
drivers/crypto/nx/Makefile
drivers/crypto/nx/nx-842-crypto.c [deleted file]
drivers/crypto/nx/nx-842-platform.c [deleted file]
drivers/crypto/nx/nx-842-powernv.c
drivers/crypto/nx/nx-842-pseries.c
drivers/crypto/nx/nx-842.c
drivers/crypto/nx/nx-842.h
drivers/crypto/nx/nx-aes-ccm.c
drivers/crypto/nx/nx-aes-ctr.c
drivers/crypto/nx/nx-aes-gcm.c
drivers/crypto/nx/nx-sha256.c
drivers/crypto/nx/nx-sha512.c
drivers/crypto/nx/nx.c
drivers/crypto/nx/nx.h
drivers/crypto/omap-aes.c
drivers/crypto/picoxcell_crypto.c
drivers/crypto/qat/Kconfig
drivers/crypto/qat/Makefile
drivers/crypto/qat/qat_common/.gitignore [new file with mode: 0644]
drivers/crypto/qat/qat_common/Makefile
drivers/crypto/qat/qat_common/adf_accel_devices.h
drivers/crypto/qat/qat_common/adf_accel_engine.c
drivers/crypto/qat/qat_common/adf_admin.c [new file with mode: 0644]
drivers/crypto/qat/qat_common/adf_aer.c
drivers/crypto/qat/qat_common/adf_cfg.c
drivers/crypto/qat/qat_common/adf_cfg_common.h
drivers/crypto/qat/qat_common/adf_common_drv.h
drivers/crypto/qat/qat_common/adf_ctl_drv.c
drivers/crypto/qat/qat_common/adf_dev_mgr.c
drivers/crypto/qat/qat_common/adf_hw_arbiter.c [moved from drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c with 85% similarity]
drivers/crypto/qat/qat_common/adf_init.c
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c [new file with mode: 0644]
drivers/crypto/qat/qat_common/adf_pf2vf_msg.h [new file with mode: 0644]
drivers/crypto/qat/qat_common/adf_sriov.c [new file with mode: 0644]
drivers/crypto/qat/qat_common/adf_transport.c
drivers/crypto/qat/qat_common/adf_transport_access_macros.h
drivers/crypto/qat/qat_common/icp_qat_fw.h
drivers/crypto/qat/qat_common/icp_qat_fw_pke.h [new file with mode: 0644]
drivers/crypto/qat/qat_common/qat_algs.c
drivers/crypto/qat/qat_common/qat_asym_algs.c [new file with mode: 0644]
drivers/crypto/qat/qat_common/qat_crypto.c
drivers/crypto/qat/qat_common/qat_crypto.h
drivers/crypto/qat/qat_common/qat_hal.c
drivers/crypto/qat/qat_common/qat_rsakey.asn1 [new file with mode: 0644]
drivers/crypto/qat/qat_common/qat_uclo.c
drivers/crypto/qat/qat_dh895xcc/Makefile
drivers/crypto/qat/qat_dh895xcc/adf_admin.c [deleted file]
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h
drivers/crypto/qat/qat_dh895xcc/adf_drv.c
drivers/crypto/qat/qat_dh895xcc/adf_drv.h
drivers/crypto/qat/qat_dh895xcc/adf_isr.c
drivers/crypto/qat/qat_dh895xccvf/Makefile [new file with mode: 0644]
drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c [new file with mode: 0644]
drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.h [new file with mode: 0644]
drivers/crypto/qat/qat_dh895xccvf/adf_drv.c [new file with mode: 0644]
drivers/crypto/qat/qat_dh895xccvf/adf_drv.h [moved from drivers/crypto/qat/qat_dh895xcc/qat_admin.c with 61% similarity]
drivers/crypto/qat/qat_dh895xccvf/adf_isr.c [new file with mode: 0644]
drivers/crypto/sahara.c
drivers/crypto/sunxi-ss/Makefile [new file with mode: 0644]
drivers/crypto/sunxi-ss/sun4i-ss-cipher.c [new file with mode: 0644]
drivers/crypto/sunxi-ss/sun4i-ss-core.c [new file with mode: 0644]
drivers/crypto/sunxi-ss/sun4i-ss-hash.c [new file with mode: 0644]
drivers/crypto/sunxi-ss/sun4i-ss.h [new file with mode: 0644]
drivers/crypto/talitos.c
drivers/crypto/talitos.h
drivers/crypto/vmx/aes.c
drivers/crypto/vmx/aes_cbc.c
drivers/crypto/vmx/aes_ctr.c
drivers/crypto/vmx/aesp8-ppc.pl
drivers/crypto/vmx/ghash.c
drivers/crypto/vmx/ghashp8-ppc.pl
drivers/crypto/vmx/ppc-xlate.pl
drivers/dma/dmaengine.c
drivers/edac/ppc4xx_edac.c
drivers/extcon/extcon-arizona.c
drivers/extcon/extcon-gpio.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max77843.c
drivers/extcon/extcon-palmas.c
drivers/extcon/extcon-rt8973a.c
drivers/extcon/extcon-sm5502.c
drivers/extcon/extcon-usb-gpio.c
drivers/extcon/extcon.c
drivers/firmware/broadcom/bcm47xx_nvram.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/hv/hv.c
drivers/hv/hv_balloon.c
drivers/hv/hv_fcopy.c
drivers/hv/hv_kvp.c
drivers/hv/hv_utils_transport.c
drivers/hv/hyperv_vmbus.h
drivers/hv/ring_buffer.c
drivers/hv/vmbus_drv.c
drivers/hwmon/Kconfig
drivers/hwmon/f71882fg.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/g762.c
drivers/hwmon/it87.c
drivers/hwmon/lm70.c
drivers/hwmon/nct7802.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/Makefile
drivers/hwmon/pmbus/adm1275.c
drivers/hwmon/pmbus/lm25066.c
drivers/hwmon/pmbus/ltc2978.c
drivers/hwmon/pmbus/max20751.c [new file with mode: 0644]
drivers/hwmon/pmbus/max34440.c
drivers/hwmon/pmbus/max8688.c
drivers/hwmon/pmbus/pmbus.c
drivers/hwmon/pmbus/pmbus.h
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/pmbus/zl6100.c
drivers/hwmon/sht15.c
drivers/hwtracing/coresight/coresight-etm.h
drivers/hwtracing/coresight/coresight-etm3x.c
drivers/hwtracing/coresight/coresight-etm4x.c
drivers/hwtracing/coresight/coresight-etm4x.h
drivers/hwtracing/coresight/coresight-replicator.c
drivers/iio/accel/Kconfig
drivers/iio/accel/bma180.c
drivers/iio/accel/bmc150-accel.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/accel/mma8452.c
drivers/iio/accel/mma9551_core.c
drivers/iio/accel/mma9551_core.h
drivers/iio/accel/mma9553.c
drivers/iio/accel/st_accel.h
drivers/iio/accel/st_accel_core.c
drivers/iio/accel/st_accel_i2c.c
drivers/iio/accel/st_accel_spi.c
drivers/iio/accel/stk8312.c
drivers/iio/accel/stk8ba50.c
drivers/iio/adc/Kconfig
drivers/iio/adc/berlin2-adc.c
drivers/iio/adc/cc10001_adc.c
drivers/iio/adc/mcp320x.c
drivers/iio/adc/mcp3422.c
drivers/iio/adc/ti-adc081c.c
drivers/iio/adc/vf610_adc.c
drivers/iio/common/ssp_sensors/ssp_dev.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/dac/ad5064.c
drivers/iio/dac/ad5380.c
drivers/iio/dac/ad5446.c
drivers/iio/dac/max5821.c
drivers/iio/frequency/adf4350.c
drivers/iio/gyro/Kconfig
drivers/iio/gyro/adis16136.c
drivers/iio/gyro/adis16260.c
drivers/iio/gyro/itg3200_core.c
drivers/iio/gyro/st_gyro_core.c
drivers/iio/gyro/st_gyro_i2c.c
drivers/iio/humidity/dht11.c
drivers/iio/humidity/si7005.c
drivers/iio/imu/adis16400_core.c
drivers/iio/imu/adis16480.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/kmx61.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/industrialio-trigger.c
drivers/iio/industrialio-triggered-buffer.c
drivers/iio/light/Kconfig
drivers/iio/light/Makefile
drivers/iio/light/acpi-als.c
drivers/iio/light/apds9300.c
drivers/iio/light/bh1750.c
drivers/iio/light/cm32181.c
drivers/iio/light/cm3232.c
drivers/iio/light/cm3323.c
drivers/iio/light/cm36651.c
drivers/iio/light/gp2ap020a00f.c
drivers/iio/light/hid-sensor-prox.c
drivers/iio/light/isl29125.c
drivers/iio/light/jsa1212.c
drivers/iio/light/ltr501.c
drivers/iio/light/opt3001.c [new file with mode: 0644]
drivers/iio/light/pa12203001.c [new file with mode: 0644]
drivers/iio/light/rpr0521.c [new file with mode: 0644]
drivers/iio/light/stk3310.c
drivers/iio/light/tcs3414.c
drivers/iio/light/tcs3472.c
drivers/iio/light/tsl4531.c
drivers/iio/light/vcnl4000.c
drivers/iio/magnetometer/bmc150_magn.c
drivers/iio/magnetometer/mmc35240.c
drivers/iio/magnetometer/st_magn.h
drivers/iio/magnetometer/st_magn_buffer.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/magnetometer/st_magn_i2c.c
drivers/iio/magnetometer/st_magn_spi.c
drivers/iio/pressure/Kconfig
drivers/iio/pressure/ms5611.h
drivers/iio/pressure/ms5611_core.c
drivers/iio/pressure/ms5611_i2c.c
drivers/iio/pressure/ms5611_spi.c
drivers/iio/pressure/st_pressure_core.c
drivers/iio/pressure/st_pressure_i2c.c
drivers/iio/temperature/mlx90614.c
drivers/iio/temperature/tmp006.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/input/keyboard/gpio_keys_polled.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/max77693-haptic.c
drivers/input/misc/max77843-haptic.c [deleted file]
drivers/iommu/intel-iommu.c
drivers/irqchip/irq-crossbar.c
drivers/leds/Kconfig
drivers/leds/led-class.c
drivers/leds/leds-fsg.c
drivers/leds/leds-lm3530.c
drivers/leds/leds-lm355x.c
drivers/leds/leds-lm3642.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lp5562.c
drivers/leds/leds-lp55xx-common.c
drivers/leds/leds-lp55xx-common.h
drivers/leds/leds-lp8501.c
drivers/leds/leds-lp8860.c
drivers/leds/leds-max77693.c
drivers/leds/leds-ns2.c
drivers/leds/leds-pca955x.c
drivers/leds/leds-pca963x.c
drivers/leds/leds-syscon.c
drivers/leds/leds-tca6507.c
drivers/leds/leds-tlc591xx.c
drivers/leds/trigger/Kconfig
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-policy-smq.c
drivers/md/dm-ioctl.c
drivers/md/dm-thin-metadata.c
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree-spine.c
drivers/md/persistent-data/dm-btree.c
drivers/media/dvb-frontends/Kconfig
drivers/media/pci/cobalt/Kconfig
drivers/media/pci/cobalt/cobalt-irq.c
drivers/media/pci/mantis/mantis_dma.c
drivers/media/rc/ir-rc5-decoder.c
drivers/media/rc/ir-rc6-decoder.c
drivers/media/rc/nuvoton-cir.c
drivers/media/rc/nuvoton-cir.h
drivers/media/rc/rc-core-priv.h
drivers/media/rc/rc-ir-raw.c
drivers/media/rc/rc-loopback.c
drivers/media/rc/rc-main.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/memory/omap-gpmc.c
drivers/mfd/max77693.c
drivers/mfd/max77843.c
drivers/mfd/twl-core.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/ad525x_dpot-i2c.c
drivers/misc/apds990x.c
drivers/misc/bh1770glc.c
drivers/misc/bmp085-i2c.c
drivers/misc/cxl/sysfs.c
drivers/misc/ds1682.c
drivers/misc/eeprom/Kconfig
drivers/misc/eeprom/Makefile
drivers/misc/eeprom/at24.c
drivers/misc/eeprom/eeprom.c
drivers/misc/eeprom/eeprom_93xx46.c
drivers/misc/eeprom/max6875.c
drivers/misc/eeprom/sunxi_sid.c [deleted file]
drivers/misc/isl29003.c
drivers/misc/lis3lv02d/lis3lv02d_i2c.c
drivers/misc/mei/Makefile
drivers/misc/mei/bus-fixup.c [new file with mode: 0644]
drivers/misc/mei/bus.c
drivers/misc/mei/client.c
drivers/misc/mei/client.h
drivers/misc/mei/debugfs.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hbm.h
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-me.h
drivers/misc/mei/hw.h
drivers/misc/mei/init.c
drivers/misc/mei/interrupt.c
drivers/misc/mei/main.c
drivers/misc/mei/mei_dev.h
drivers/misc/mei/nfc.c [deleted file]
drivers/misc/mei/pci-me.c
drivers/misc/qcom-coincell.c [new file with mode: 0644]
drivers/misc/ti-st/st_kim.c
drivers/misc/ti-st/st_ll.c
drivers/misc/tsl2550.c
drivers/misc/vmw_balloon.c
drivers/misc/vmw_vmci/vmci_host.c
drivers/net/bonding/bond_main.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_core.h
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/Makefile
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/cavium/Kconfig
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/fs_enet/mac-fec.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/ethernet/intel/fm10k/fm10k_main.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/micrel/ks8842.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/rocker/rocker.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
drivers/net/ethernet/ti/netcp.h
drivers/net/ethernet/ti/netcp_core.c
drivers/net/hamradio/mkiss.c
drivers/net/phy/fixed_phy.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/smsc.c
drivers/net/ppp/ppp_generic.c
drivers/net/rionet.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wan/cosa.c
drivers/net/wireless/b43/tables_nphy.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
drivers/net/wireless/rsi/rsi_91x_usb_ops.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/rtlwifi/rtl8723be/sw.c
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/nfc/mei_phy.c
drivers/nvmem/Kconfig [new file with mode: 0644]
drivers/nvmem/Makefile [new file with mode: 0644]
drivers/nvmem/core.c [new file with mode: 0644]
drivers/nvmem/qfprom.c [new file with mode: 0644]
drivers/nvmem/sunxi_sid.c [new file with mode: 0644]
drivers/parisc/dino.c
drivers/parisc/lba_pci.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/access.c
drivers/pci/ats.c
drivers/pci/host/Kconfig
drivers/pci/host/pci-dra7xx.c
drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-keystone-dw.c
drivers/pci/host/pci-mvebu.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pci-xgene-msi.c
drivers/pci/host/pci-xgene.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-iproc.c
drivers/pci/host/pcie-iproc.h
drivers/pci/host/pcie-rcar.c
drivers/pci/host/pcie-spear13xx.c
drivers/pci/host/pcie-xilinx.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/msi.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/slot.c
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/phy-armada375-usb2.c
drivers/phy/phy-bcm-kona-usb2.c
drivers/phy/phy-berlin-sata.c
drivers/phy/phy-berlin-usb.c
drivers/phy/phy-brcmstb-sata.c
drivers/phy/phy-dm816x-usb.c
drivers/phy/phy-exynos-dp-video.c
drivers/phy/phy-exynos-mipi-video.c
drivers/phy/phy-exynos5-usbdrd.c
drivers/phy/phy-exynos5250-sata.c
drivers/phy/phy-hix5hd2-sata.c
drivers/phy/phy-lpc18xx-usb-otg.c [new file with mode: 0644]
drivers/phy/phy-miphy28lp.c
drivers/phy/phy-miphy365x.c
drivers/phy/phy-mvebu-sata.c
drivers/phy/phy-omap-usb2.c
drivers/phy/phy-qcom-apq8064-sata.c
drivers/phy/phy-qcom-ipq806x-sata.c
drivers/phy/phy-qcom-ufs-i.h
drivers/phy/phy-qcom-ufs-qmp-14nm.c
drivers/phy/phy-qcom-ufs-qmp-20nm.c
drivers/phy/phy-qcom-ufs.c
drivers/phy/phy-rcar-gen2.c
drivers/phy/phy-rockchip-usb.c
drivers/phy/phy-samsung-usb2.c
drivers/phy/phy-spear1310-miphy.c
drivers/phy/phy-spear1340-miphy.c
drivers/phy/phy-stih41x-usb.c
drivers/phy/phy-sun4i-usb.c
drivers/phy/phy-sun9i-usb.c
drivers/phy/phy-ti-pipe3.c
drivers/phy/phy-tusb1210.c
drivers/phy/ulpi_phy.h
drivers/power/Kconfig
drivers/power/bq2415x_charger.c
drivers/power/bq24190_charger.c
drivers/power/bq24735-charger.c
drivers/power/bq27x00_battery.c
drivers/power/ds2780_battery.c
drivers/power/ds2781_battery.c
drivers/power/ltc2941-battery-gauge.c
drivers/power/max77693_charger.c
drivers/power/olpc_battery.c
drivers/power/pm2301_charger.c
drivers/power/reset/Kconfig
drivers/power/reset/Makefile
drivers/power/reset/at91-reset.c
drivers/power/reset/zx-reboot.c [new file with mode: 0644]
drivers/power/rt5033_battery.c
drivers/power/rt9455_charger.c
drivers/power/rx51_battery.c
drivers/power/twl4030_charger.c
drivers/regulator/88pm800.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/act8865-regulator.c
drivers/regulator/ad5398.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/core.c
drivers/regulator/da9062-regulator.c
drivers/regulator/da9210-regulator.c
drivers/regulator/da9211-regulator.c
drivers/regulator/da9211-regulator.h
drivers/regulator/fan53555.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/isl9305.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/lp872x.c
drivers/regulator/ltc3589.c
drivers/regulator/max1586.c
drivers/regulator/max77693.c
drivers/regulator/max77843.c [deleted file]
drivers/regulator/max8660.c
drivers/regulator/max8973-regulator.c
drivers/regulator/mt6311-regulator.c [new file with mode: 0644]
drivers/regulator/mt6311-regulator.h [new file with mode: 0644]
drivers/regulator/of_regulator.c
drivers/regulator/pbias-regulator.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/pwm-regulator.c
drivers/regulator/qcom_smd-regulator.c [new file with mode: 0644]
drivers/regulator/qcom_spmi-regulator.c
drivers/regulator/rk808-regulator.c
drivers/regulator/tps51632-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/rtc/rtc-ds1374.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_int.h
drivers/s390/block/dcssblk.c
drivers/s390/char/con3270.c
drivers/s390/char/ctrlchar.c
drivers/s390/char/ctrlchar.h
drivers/s390/char/diag_ftp.c
drivers/s390/char/monreader.c
drivers/s390/char/sclp.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tty3270.c
drivers/s390/cio/chsc.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/eadm_sch.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/scsi/zfcp_fsf.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libiscsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_pm.c
drivers/scsi/sd.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx-hsspi.c
drivers/spi/spi-bitbang-txrx.h
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-fsl-lib.c
drivers/spi/spi-fsl-lib.h
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-img-spfi.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mt65xx.c [new file with mode: 0644]
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.h
drivers/spi/spi-rockchip.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-xcomm.c
drivers/spi/spi-xilinx.c
drivers/spi/spi-xlp.c [new file with mode: 0644]
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/spmi/Kconfig
drivers/spmi/spmi-pmic-arb.c
drivers/spmi/spmi.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/Kconfig
drivers/staging/android/TODO
drivers/staging/android/ashmem.c
drivers/staging/android/ion/ion.c
drivers/staging/android/ion/ion_chunk_heap.c
drivers/staging/android/ion/ion_cma_heap.c
drivers/staging/android/ion/ion_page_pool.c
drivers/staging/android/ion/ion_system_heap.c
drivers/staging/android/ion/ion_test.c
drivers/staging/android/sync.h
drivers/staging/android/timed_gpio.c
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_compat32.c
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
drivers/staging/comedi/drivers/addi_apci_1564.c
drivers/staging/comedi/drivers/addi_apci_3501.c
drivers/staging/comedi/drivers/addi_tcw.h
drivers/staging/comedi/drivers/adl_pci7x3x.c
drivers/staging/comedi/drivers/cb_pcimdas.c
drivers/staging/comedi/drivers/dac02.c
drivers/staging/comedi/drivers/das08_cs.c
drivers/staging/comedi/drivers/das16.c
drivers/staging/comedi/drivers/das16m1.c
drivers/staging/comedi/drivers/dmm32at.c
drivers/staging/comedi/drivers/fl512.c
drivers/staging/comedi/drivers/me4000.c
drivers/staging/comedi/drivers/ni_daq_dio24.c
drivers/staging/comedi/drivers/ni_usb6501.c
drivers/staging/comedi/drivers/pcl816.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/comedi/drivers/serial2002.c
drivers/staging/comedi/drivers/usbduxsigma.c
drivers/staging/comedi/range.c
drivers/staging/dgap/dgap.c
drivers/staging/dgnc/dgnc_driver.h
drivers/staging/dgnc/dgnc_sysfs.h
drivers/staging/emxx_udc/emxx_udc.c
drivers/staging/fbtft/Kconfig
drivers/staging/fbtft/Makefile
drivers/staging/fbtft/fb_uc1611.c [new file with mode: 0644]
drivers/staging/fbtft/fbtft-core.c
drivers/staging/fbtft/fbtft.h
drivers/staging/fbtft/fbtft_device.c
drivers/staging/fbtft/flexfb.c
drivers/staging/fsl-mc/README.txt [new file with mode: 0644]
drivers/staging/fsl-mc/TODO
drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
drivers/staging/ft1000/ft1000-usb/ft1000_download.c
drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
drivers/staging/gdm72xx/usb_ids.h
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/addac/adt7316-i2c.c
drivers/staging/iio/iio_dummy_evgen.c
drivers/staging/iio/iio_simple_dummy.c
drivers/staging/iio/iio_simple_dummy.h
drivers/staging/iio/iio_simple_dummy_buffer.c
drivers/staging/iio/iio_simple_dummy_events.c
drivers/staging/iio/light/isl29018.c
drivers/staging/iio/light/isl29028.c
drivers/staging/iio/meter/ade7854.h
drivers/staging/iio/trigger/iio-trig-bfin-timer.c
drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
drivers/staging/lustre/include/linux/libcfs/libcfs.h
drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h
drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
drivers/staging/lustre/lnet/lnet/router_proc.c
drivers/staging/lustre/lnet/selftest/console.h
drivers/staging/lustre/lnet/selftest/framework.c
drivers/staging/lustre/lustre/fid/fid_request.c
drivers/staging/lustre/lustre/fld/fld_cache.c
drivers/staging/lustre/lustre/fld/fld_request.c
drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
drivers/staging/lustre/lustre/include/lprocfs_status.h
drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
drivers/staging/lustre/lustre/include/lustre/lustre_user.h
drivers/staging/lustre/lustre/include/lustre_dlm.h
drivers/staging/lustre/lustre/include/lustre_export.h
drivers/staging/lustre/lustre/include/lustre_import.h
drivers/staging/lustre/lustre/include/lustre_net.h
drivers/staging/lustre/lustre/include/obd.h
drivers/staging/lustre/lustre/include/obd_class.h
drivers/staging/lustre/lustre/include/obd_support.h
drivers/staging/lustre/lustre/lclient/lcommon_cl.c
drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
drivers/staging/lustre/lustre/libcfs/debug.c
drivers/staging/lustre/lustre/libcfs/fail.c
drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
drivers/staging/lustre/lustre/libcfs/libcfs_string.c
drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
drivers/staging/lustre/lustre/libcfs/module.c
drivers/staging/lustre/lustre/libcfs/tracefile.c
drivers/staging/lustre/lustre/libcfs/tracefile.h
drivers/staging/lustre/lustre/llite/dcache.c
drivers/staging/lustre/lustre/llite/dir.c
drivers/staging/lustre/lustre/llite/file.c
drivers/staging/lustre/lustre/llite/llite_capa.c
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/lloop.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/llite/remote_perm.c
drivers/staging/lustre/lustre/llite/vvp_io.c
drivers/staging/lustre/lustre/llite/vvp_page.c
drivers/staging/lustre/lustre/llite/xattr_cache.c
drivers/staging/lustre/lustre/lmv/lmv_intent.c
drivers/staging/lustre/lustre/lmv/lmv_obd.c
drivers/staging/lustre/lustre/lov/lov_dev.c
drivers/staging/lustre/lustre/lov/lov_io.c
drivers/staging/lustre/lustre/lov/lov_merge.c
drivers/staging/lustre/lustre/lov/lov_obd.c
drivers/staging/lustre/lustre/lov/lov_pool.c
drivers/staging/lustre/lustre/lov/lov_request.c
drivers/staging/lustre/lustre/mdc/mdc_lib.c
drivers/staging/lustre/lustre/mdc/mdc_request.c
drivers/staging/lustre/lustre/mgc/mgc_request.c
drivers/staging/lustre/lustre/obdclass/acl.c
drivers/staging/lustre/lustre/obdclass/cl_page.c
drivers/staging/lustre/lustre/obdclass/class_obd.c
drivers/staging/lustre/lustre/obdclass/genops.c
drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
drivers/staging/lustre/lustre/obdclass/llog.c
drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
drivers/staging/lustre/lustre/obdclass/lu_object.c
drivers/staging/lustre/lustre/obdclass/lustre_peer.c
drivers/staging/lustre/lustre/obdclass/obd_config.c
drivers/staging/lustre/lustre/obdclass/obd_mount.c
drivers/staging/lustre/lustre/obdclass/uuid.c
drivers/staging/lustre/lustre/obdecho/echo_client.c
drivers/staging/lustre/lustre/osc/osc_cache.c
drivers/staging/lustre/lustre/osc/osc_dev.c
drivers/staging/lustre/lustre/osc/osc_page.c
drivers/staging/lustre/lustre/osc/osc_request.c
drivers/staging/lustre/lustre/ptlrpc/client.c
drivers/staging/lustre/lustre/ptlrpc/events.c
drivers/staging/lustre/lustre/ptlrpc/import.c
drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
drivers/staging/lustre/lustre/ptlrpc/nrs.c
drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
drivers/staging/lustre/lustre/ptlrpc/pinger.c
drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
drivers/staging/lustre/lustre/ptlrpc/sec_config.c
drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
drivers/staging/lustre/lustre/ptlrpc/service.c
drivers/staging/lustre/sysfs-fs-lustre
drivers/staging/most/Documentation/ABI/sysfs-class-most.txt [new file with mode: 0644]
drivers/staging/most/Documentation/driver_usage.txt [new file with mode: 0644]
drivers/staging/most/Kconfig [new file with mode: 0644]
drivers/staging/most/Makefile [new file with mode: 0644]
drivers/staging/most/TODO [new file with mode: 0644]
drivers/staging/most/aim-cdev/Kconfig [new file with mode: 0644]
drivers/staging/most/aim-cdev/Makefile [new file with mode: 0644]
drivers/staging/most/aim-cdev/cdev.c [new file with mode: 0644]
drivers/staging/most/aim-network/Kconfig [new file with mode: 0644]
drivers/staging/most/aim-network/Makefile [new file with mode: 0644]
drivers/staging/most/aim-network/networking.c [new file with mode: 0644]
drivers/staging/most/aim-network/networking.h [new file with mode: 0644]
drivers/staging/most/aim-sound/Kconfig [new file with mode: 0644]
drivers/staging/most/aim-sound/Makefile [new file with mode: 0644]
drivers/staging/most/aim-sound/sound.c [new file with mode: 0644]
drivers/staging/most/aim-v4l2/Kconfig [new file with mode: 0644]
drivers/staging/most/aim-v4l2/Makefile [new file with mode: 0644]
drivers/staging/most/aim-v4l2/video.c [new file with mode: 0644]
drivers/staging/most/hdm-dim2/Kconfig [new file with mode: 0644]
drivers/staging/most/hdm-dim2/Makefile [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_errors.h [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_hal.c [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_hal.h [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_hdm.c [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_hdm.h [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_reg.h [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_sysfs.c [new file with mode: 0644]
drivers/staging/most/hdm-dim2/dim2_sysfs.h [new file with mode: 0644]
drivers/staging/most/hdm-i2c/Kconfig [new file with mode: 0644]
drivers/staging/most/hdm-i2c/Makefile [new file with mode: 0644]
drivers/staging/most/hdm-i2c/hdm_i2c.c [new file with mode: 0644]
drivers/staging/most/hdm-usb/Kconfig [new file with mode: 0644]
drivers/staging/most/hdm-usb/Makefile [new file with mode: 0644]
drivers/staging/most/hdm-usb/hdm_usb.c [new file with mode: 0644]
drivers/staging/most/mostcore/Kconfig [new file with mode: 0644]
drivers/staging/most/mostcore/Makefile [new file with mode: 0644]
drivers/staging/most/mostcore/core.c [new file with mode: 0644]
drivers/staging/most/mostcore/mostcore.h [new file with mode: 0644]
drivers/staging/mt29f_spinand/mt29f_spinand.c
drivers/staging/mt29f_spinand/mt29f_spinand.h
drivers/staging/netlogic/platform_net.c
drivers/staging/netlogic/xlr_net.h
drivers/staging/nvec/nvec.h
drivers/staging/octeon/ethernet-mdio.h
drivers/staging/octeon/ethernet-rgmii.c
drivers/staging/octeon/ethernet-tx.c
drivers/staging/octeon/ethernet.c
drivers/staging/octeon/octeon-ethernet.h
drivers/staging/olpc_dcon/olpc_dcon.h
drivers/staging/ozwpan/Kconfig [deleted file]
drivers/staging/ozwpan/Makefile [deleted file]
drivers/staging/ozwpan/README [deleted file]
drivers/staging/ozwpan/TODO [deleted file]
drivers/staging/ozwpan/ozappif.h [deleted file]
drivers/staging/ozwpan/ozcdev.c [deleted file]
drivers/staging/ozwpan/ozcdev.h [deleted file]
drivers/staging/ozwpan/ozdbg.h [deleted file]
drivers/staging/ozwpan/ozeltbuf.c [deleted file]
drivers/staging/ozwpan/ozeltbuf.h [deleted file]
drivers/staging/ozwpan/ozhcd.c [deleted file]
drivers/staging/ozwpan/ozhcd.h [deleted file]
drivers/staging/ozwpan/ozmain.c [deleted file]
drivers/staging/ozwpan/ozpd.c [deleted file]
drivers/staging/ozwpan/ozpd.h [deleted file]
drivers/staging/ozwpan/ozproto.c [deleted file]
drivers/staging/ozwpan/ozproto.h [deleted file]
drivers/staging/ozwpan/ozprotocol.h [deleted file]
drivers/staging/ozwpan/ozurbparanoia.c [deleted file]
drivers/staging/ozwpan/ozurbparanoia.h [deleted file]
drivers/staging/ozwpan/ozusbif.h [deleted file]
drivers/staging/ozwpan/ozusbsvc.c [deleted file]
drivers/staging/ozwpan/ozusbsvc.h [deleted file]
drivers/staging/ozwpan/ozusbsvc1.c [deleted file]
drivers/staging/panel/panel.c
drivers/staging/rtl8188eu/core/rtw_ap.c
drivers/staging/rtl8188eu/core/rtw_debug.c
drivers/staging/rtl8188eu/core/rtw_efuse.c
drivers/staging/rtl8188eu/core/rtw_ieee80211.c
drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
drivers/staging/rtl8188eu/core/rtw_mlme.c
drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
drivers/staging/rtl8188eu/core/rtw_recv.c
drivers/staging/rtl8188eu/core/rtw_security.c
drivers/staging/rtl8188eu/core/rtw_wlan_util.c
drivers/staging/rtl8188eu/core/rtw_xmit.c
drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
drivers/staging/rtl8188eu/hal/bb_cfg.c
drivers/staging/rtl8188eu/hal/hal_com.c
drivers/staging/rtl8188eu/hal/hal_intf.c
drivers/staging/rtl8188eu/hal/odm.c
drivers/staging/rtl8188eu/hal/rf.c
drivers/staging/rtl8188eu/hal/rf_cfg.c
drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
drivers/staging/rtl8188eu/hal/usb_halinit.c
drivers/staging/rtl8188eu/include/HalVerDef.h
drivers/staging/rtl8188eu/include/hal_intf.h
drivers/staging/rtl8188eu/include/ieee80211.h
drivers/staging/rtl8188eu/include/osdep_service.h
drivers/staging/rtl8188eu/include/recv_osdep.h
drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
drivers/staging/rtl8188eu/include/rtl8188e_hal.h
drivers/staging/rtl8188eu/include/rtw_mlme.h
drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
drivers/staging/rtl8188eu/include/sta_info.h
drivers/staging/rtl8188eu/include/wifi.h
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8188eu/os_dep/os_intfs.c
drivers/staging/rtl8188eu/os_dep/recv_linux.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8192e/dot11d.c
drivers/staging/rtl8192e/dot11d.h
drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
drivers/staging/rtl8192e/rtl8192e/rtl_core.c
drivers/staging/rtl8192e/rtl8192e/rtl_core.h
drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
drivers/staging/rtl8192e/rtl819x_BA.h
drivers/staging/rtl8192e/rtl819x_BAProc.c
drivers/staging/rtl8192e/rtl819x_HT.h
drivers/staging/rtl8192e/rtl819x_HTProc.c
drivers/staging/rtl8192e/rtl819x_Qos.h
drivers/staging/rtl8192e/rtl819x_TS.h
drivers/staging/rtl8192e/rtl819x_TSProc.c
drivers/staging/rtl8192e/rtllib.h
drivers/staging/rtl8192e/rtllib_debug.h
drivers/staging/rtl8192e/rtllib_rx.c
drivers/staging/rtl8192e/rtllib_softmac.c
drivers/staging/rtl8192e/rtllib_tx.c
drivers/staging/rtl8192u/ieee80211/ieee80211.h
drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c
drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
drivers/staging/rtl8192u/r8190_rtl8256.h
drivers/staging/rtl8192u/r8192U.h
drivers/staging/rtl8192u/r8192U_core.c
drivers/staging/rtl8192u/r8192U_dm.c
drivers/staging/rtl8192u/r8192U_dm.h
drivers/staging/rtl8192u/r8192U_wx.h
drivers/staging/rtl8192u/r819xU_cmdpkt.h
drivers/staging/rtl8192u/r819xU_firmware.c
drivers/staging/rtl8192u/r819xU_phy.h
drivers/staging/rtl8712/ieee80211.c
drivers/staging/rtl8712/rtl8712_recv.c
drivers/staging/rtl8712/rtl871x_cmd.c
drivers/staging/rtl8712/rtl871x_cmd.h
drivers/staging/rtl8712/rtl871x_event.h
drivers/staging/rtl8712/rtl871x_ioctl.h
drivers/staging/rtl8712/rtl871x_ioctl_linux.c
drivers/staging/rtl8712/rtl871x_mlme.c
drivers/staging/rtl8712/rtl871x_mlme.h
drivers/staging/rtl8712/rtl871x_mp_ioctl.c
drivers/staging/rtl8712/rtl871x_security.c
drivers/staging/rtl8712/wlan_bssdef.h
drivers/staging/rtl8723au/core/rtw_recv.c
drivers/staging/rtl8723au/core/rtw_security.c
drivers/staging/rtl8723au/hal/odm.c
drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
drivers/staging/rts5208/ms.c
drivers/staging/rts5208/sd.c
drivers/staging/slicoss/slicoss.c
drivers/staging/sm750fb/ddk750_chip.c
drivers/staging/sm750fb/ddk750_chip.h
drivers/staging/sm750fb/ddk750_display.c
drivers/staging/sm750fb/ddk750_display.h
drivers/staging/sm750fb/ddk750_dvi.c
drivers/staging/sm750fb/ddk750_dvi.h
drivers/staging/sm750fb/ddk750_help.c
drivers/staging/sm750fb/ddk750_help.h
drivers/staging/sm750fb/ddk750_hwi2c.c
drivers/staging/sm750fb/ddk750_mode.c
drivers/staging/sm750fb/ddk750_mode.h
drivers/staging/sm750fb/ddk750_power.c
drivers/staging/sm750fb/ddk750_power.h
drivers/staging/sm750fb/ddk750_reg.h
drivers/staging/sm750fb/ddk750_sii164.c
drivers/staging/sm750fb/ddk750_sii164.h
drivers/staging/sm750fb/sm750.c
drivers/staging/sm750fb/sm750.h
drivers/staging/sm750fb/sm750_accel.c
drivers/staging/sm750fb/sm750_accel.h
drivers/staging/sm750fb/sm750_cursor.c
drivers/staging/sm750fb/sm750_cursor.h
drivers/staging/sm750fb/sm750_help.h
drivers/staging/sm750fb/sm750_hw.c
drivers/staging/sm750fb/sm750_hw.h
drivers/staging/sm7xxfb/Kconfig [deleted file]
drivers/staging/sm7xxfb/Makefile [deleted file]
drivers/staging/sm7xxfb/TODO [deleted file]
drivers/staging/speakup/buffers.c
drivers/staging/speakup/i18n.c
drivers/staging/speakup/i18n.h
drivers/staging/speakup/keyhelp.c
drivers/staging/speakup/kobjects.c
drivers/staging/speakup/main.c
drivers/staging/speakup/selection.c
drivers/staging/speakup/serialio.c
drivers/staging/speakup/speakup.h
drivers/staging/speakup/speakup_acnt.h
drivers/staging/speakup/speakup_decpc.c
drivers/staging/speakup/speakup_dtlk.h
drivers/staging/speakup/speakup_soft.c
drivers/staging/speakup/thread.c
drivers/staging/speakup/varhandlers.c
drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
drivers/staging/unisys/Kconfig
drivers/staging/unisys/include/channel_guid.h
drivers/staging/unisys/include/visorbus.h
drivers/staging/unisys/visorbus/controlvmchannel.h
drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
drivers/staging/unisys/visorbus/iovmcall_gnuc.h
drivers/staging/unisys/visorbus/periodic_work.c
drivers/staging/unisys/visorbus/vbuschannel.h
drivers/staging/unisys/visorbus/vbusdeviceinfo.h
drivers/staging/unisys/visorbus/visorbus_main.c
drivers/staging/unisys/visorbus/visorbus_private.h
drivers/staging/unisys/visorbus/visorchannel.c
drivers/staging/unisys/visorbus/visorchipset.c
drivers/staging/unisys/visorbus/vmcallinterface.h
drivers/staging/unisys/visornic/visornic_main.c
drivers/staging/vme/devices/vme_pio2_core.c
drivers/staging/vme/devices/vme_user.c
drivers/staging/vt6655/baseband.c
drivers/staging/vt6655/card.c
drivers/staging/vt6655/desc.h
drivers/staging/vt6655/device.h
drivers/staging/vt6655/device_cfg.h
drivers/staging/vt6655/device_main.c
drivers/staging/vt6655/dpc.c
drivers/staging/vt6655/mac.c
drivers/staging/vt6655/power.c
drivers/staging/vt6655/rf.c
drivers/staging/vt6655/rf.h
drivers/staging/vt6655/rxtx.c
drivers/staging/vt6655/rxtx.h
drivers/staging/vt6655/upc.h
drivers/staging/vt6656/rxtx.c
drivers/staging/wilc1000/Kconfig
drivers/staging/wilc1000/Makefile
drivers/staging/wilc1000/coreconfigsimulator.h [deleted file]
drivers/staging/wilc1000/coreconfigurator.c
drivers/staging/wilc1000/coreconfigurator.h
drivers/staging/wilc1000/fifo_buffer.c [deleted file]
drivers/staging/wilc1000/fifo_buffer.h [deleted file]
drivers/staging/wilc1000/host_interface.c
drivers/staging/wilc1000/host_interface.h
drivers/staging/wilc1000/linux_mon.c
drivers/staging/wilc1000/linux_wlan.c
drivers/staging/wilc1000/linux_wlan_common.h
drivers/staging/wilc1000/linux_wlan_sdio.c
drivers/staging/wilc1000/wilc_debugfs.c
drivers/staging/wilc1000/wilc_exported_buf.c
drivers/staging/wilc1000/wilc_log.h [deleted file]
drivers/staging/wilc1000/wilc_memory.c
drivers/staging/wilc1000/wilc_memory.h
drivers/staging/wilc1000/wilc_msgqueue.c
drivers/staging/wilc1000/wilc_msgqueue.h
drivers/staging/wilc1000/wilc_osconfig.h [deleted file]
drivers/staging/wilc1000/wilc_oswrapper.h
drivers/staging/wilc1000/wilc_platform.h
drivers/staging/wilc1000/wilc_sdio.c
drivers/staging/wilc1000/wilc_sleep.c [deleted file]
drivers/staging/wilc1000/wilc_sleep.h [deleted file]
drivers/staging/wilc1000/wilc_spi.c
drivers/staging/wilc1000/wilc_strutils.c [deleted file]
drivers/staging/wilc1000/wilc_strutils.h [deleted file]
drivers/staging/wilc1000/wilc_timer.c [deleted file]
drivers/staging/wilc1000/wilc_timer.h [deleted file]
drivers/staging/wilc1000/wilc_type.h [deleted file]
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
drivers/staging/wilc1000/wilc_wfi_netdevice.c [deleted file]
drivers/staging/wilc1000/wilc_wfi_netdevice.h
drivers/staging/wilc1000/wilc_wlan.c
drivers/staging/wilc1000/wilc_wlan.h
drivers/staging/wilc1000/wilc_wlan_cfg.c
drivers/staging/wilc1000/wilc_wlan_if.h
drivers/staging/xgifb/Makefile
drivers/staging/xgifb/XGI_main_26.c
drivers/staging/xgifb/vb_init.h
drivers/staging/xgifb/vb_setmode.h
drivers/staging/xgifb/vb_util.c [deleted file]
drivers/staging/xgifb/vb_util.h
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_configfs.c
drivers/target/target_core_hba.c
drivers/target/target_core_spc.c
drivers/thermal/cpu_cooling.c
drivers/thermal/power_allocator.c
drivers/tty/n_gsm.c
drivers/tty/n_tty.c
drivers/tty/pty.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_early.c
drivers/tty/serial/8250/8250_fintek.c
drivers/tty/serial/8250/8250_ingenic.c
drivers/tty/serial/8250/8250_omap.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_pnp.c
drivers/tty/serial/8250/8250_port.c [new file with mode: 0644]
drivers/tty/serial/8250/8250_uniphier.c
drivers/tty/serial/8250/Makefile
drivers/tty/serial/Kconfig
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/etraxfs-uart.c
drivers/tty/serial/imx.c
drivers/tty/serial/lantiq.c
drivers/tty/serial/men_z135_uart.c
drivers/tty/serial/mpc52xx_uart.c
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/samsung.c
drivers/tty/serial/samsung.h
drivers/tty/serial/sc16is7xx.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sirfsoc_uart.c
drivers/tty/serial/sirfsoc_uart.h
drivers/tty/serial/sn_console.c
drivers/tty/serial/stm32-usart.c
drivers/tty/serial/suncore.c
drivers/tty/serial/sunhv.c
drivers/tty/serial/ucc_uart.c
drivers/tty/tty_buffer.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/tty_ldisc.c
drivers/uio/Kconfig
drivers/uio/uio.c
drivers/uio/uio_fsl_elbc_gpcm.c
drivers/usb/atm/cxacru.c
drivers/usb/chipidea/bits.h
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/otg_fsm.c
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/usbmisc_imx.c
drivers/usb/class/usblp.c
drivers/usb/common/common.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/endpoint.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/otg_whitelist.h
drivers/usb/core/sysfs.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/Makefile
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-keystone.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/dwc3-qcom.c
drivers/usb/dwc3/dwc3-st.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/config.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/epautoconf.c
drivers/usb/gadget/function/f_acm.c
drivers/usb/gadget/function/f_ecm.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_loopback.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_mass_storage.h
drivers/usb/gadget/function/f_midi.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/function/f_obex.c
drivers/usb/gadget/function/f_printer.c
drivers/usb/gadget/function/f_serial.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/f_uvc.c
drivers/usb/gadget/function/storage_common.h
drivers/usb/gadget/function/u_ether.h
drivers/usb/gadget/function/u_uac1.h
drivers/usb/gadget/legacy/Kconfig
drivers/usb/gadget/legacy/acm_ms.c
drivers/usb/gadget/legacy/audio.c
drivers/usb/gadget/legacy/cdc2.c
drivers/usb/gadget/legacy/dbgp.c
drivers/usb/gadget/legacy/ether.c
drivers/usb/gadget/legacy/g_ffs.c
drivers/usb/gadget/legacy/gmidi.c
drivers/usb/gadget/legacy/hid.c
drivers/usb/gadget/legacy/mass_storage.c
drivers/usb/gadget/legacy/multi.c
drivers/usb/gadget/legacy/ncm.c
drivers/usb/gadget/legacy/nokia.c
drivers/usb/gadget/legacy/printer.c
drivers/usb/gadget/legacy/serial.c
drivers/usb/gadget/legacy/zero.c
drivers/usb/gadget/udc/amd5536udc.c
drivers/usb/gadget/udc/at91_udc.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/bcm63xx_udc.c
drivers/usb/gadget/udc/bdc/bdc_ep.c
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/fotg210-udc.c
drivers/usb/gadget/udc/fsl_qe_udc.c
drivers/usb/gadget/udc/fsl_udc_core.c
drivers/usb/gadget/udc/fusb300_udc.c
drivers/usb/gadget/udc/gadget_chips.h [deleted file]
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/gadget/udc/gr_udc.c
drivers/usb/gadget/udc/lpc32xx_udc.c
drivers/usb/gadget/udc/m66592-udc.c
drivers/usb/gadget/udc/mv_u3d_core.c
drivers/usb/gadget/udc/mv_udc_core.c
drivers/usb/gadget/udc/net2272.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/omap_udc.c
drivers/usb/gadget/udc/pch_udc.c
drivers/usb/gadget/udc/pxa25x_udc.c
drivers/usb/gadget/udc/pxa27x_udc.c
drivers/usb/gadget/udc/pxa27x_udc.h
drivers/usb/gadget/udc/r8a66597-udc.c
drivers/usb/gadget/udc/s3c-hsudc.c
drivers/usb/gadget/udc/s3c2410_udc.c
drivers/usb/gadget/udc/udc-core.c
drivers/usb/gadget/udc/udc-xilinx.c
drivers/usb/host/Kconfig
drivers/usb/host/bcma-hcd.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-fsl.h
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-st.c
drivers/usb/host/ehci-sysfs.c
drivers/usb/host/ehci.h
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/isp1760/isp1760-udc.c
drivers/usb/misc/ftdi-elan.c
drivers/usb/misc/usbtest.c
drivers/usb/musb/Kconfig
drivers/usb/musb/Makefile
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/sunxi.c [new file with mode: 0644]
drivers/usb/phy/Kconfig
drivers/usb/phy/Makefile
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-keystone.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-omap-otg.c
drivers/usb/phy/phy-qcom-8x16-usb.c [new file with mode: 0644]
drivers/usb/phy/phy-tahvo.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/mxuport.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/symbolserial.c
drivers/usb/serial/usb_wwan.c
drivers/usb/storage/transport.c
drivers/vhost/scsi.c
drivers/video/fbdev/Kconfig
drivers/video/fbdev/Makefile
drivers/video/fbdev/hyperv_fb.c
drivers/video/fbdev/simplefb.c
drivers/video/fbdev/sm712.h [moved from drivers/staging/sm7xxfb/sm7xx.h with 81% similarity]
drivers/video/fbdev/sm712fb.c [moved from drivers/staging/sm7xxfb/sm7xxfb.c with 97% similarity]
drivers/w1/masters/ds2482.c
drivers/w1/masters/matrox_w1.c
drivers/watchdog/at91rm9200_wdt.c
drivers/watchdog/ks8695_wdt.c
drivers/watchdog/ts72xx_wdt.c
drivers/xen/events/events_base.c
drivers/xen/events/events_fifo.c
drivers/xen/events/events_internal.h
drivers/xen/xenbus/xenbus_client.c
fs/btrfs/super.c
fs/char_dev.c
fs/dlm/plock.c
fs/dlm/user.c
fs/fs-writeback.c
fs/fuse/dev.c
fs/ocfs2/stack_user.c
include/crypto/aead.h
include/crypto/algapi.h
include/crypto/chacha20.h [new file with mode: 0644]
include/crypto/hash.h
include/crypto/internal/aead.h
include/crypto/internal/geniv.h
include/crypto/internal/skcipher.h
include/crypto/poly1305.h [new file with mode: 0644]
include/crypto/skcipher.h
include/drm/drm_crtc.h
include/drm/drm_edid.h
include/drm/drm_pciids.h
include/dt-bindings/clock/exynos3250.h
include/dt-bindings/clock/exynos5250.h
include/dt-bindings/clock/imx6qdl-clock.h
include/dt-bindings/clock/imx6ul-clock.h [new file with mode: 0644]
include/dt-bindings/clock/rk3066a-cru.h
include/dt-bindings/clock/rk3188-cru-common.h
include/dt-bindings/clock/rk3188-cru.h
include/dt-bindings/clock/rk3288-cru.h
include/dt-bindings/clock/rk3368-cru.h [new file with mode: 0644]
include/dt-bindings/clock/zx296702-clock.h
include/dt-bindings/leds/leds-ns2.h [new file with mode: 0644]
include/dt-bindings/reset/tegra124-car.h [new file with mode: 0644]
include/linux/amba/serial.h
include/linux/ata.h
include/linux/atmel_serial.h
include/linux/clk-provider.h
include/linux/clk/clk-conf.h
include/linux/clk/tegra.h
include/linux/clk/ti.h
include/linux/coresight.h
include/linux/cpufeature.h
include/linux/crypto.h
include/linux/device.h
include/linux/extcon.h
include/linux/fsl_devices.h
include/linux/hyperv.h
include/linux/iio/common/st_sensors.h
include/linux/iio/consumer.h
include/linux/iio/iio.h
include/linux/iio/sysfs.h
include/linux/iio/trigger.h
include/linux/iio/triggered_buffer.h
include/linux/irq.h
include/linux/kexec.h
include/linux/kvm_host.h
include/linux/mei_cl_bus.h
include/linux/mfd/max77693-common.h [new file with mode: 0644]
include/linux/mfd/max77693-private.h
include/linux/mfd/max77843-private.h
include/linux/mfd/palmas.h
include/linux/miscdevice.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/nvmem-consumer.h [new file with mode: 0644]
include/linux/nvmem-provider.h [new file with mode: 0644]
include/linux/pci-ats.h
include/linux/pci.h
include/linux/platform_data/atmel.h
include/linux/platform_data/clk-ux500.h
include/linux/platform_data/leds-kirkwood-ns2.h
include/linux/platform_data/spi-davinci.h
include/linux/platform_data/spi-mt65xx.h [new file with mode: 0644]
include/linux/pxa2xx_ssp.h
include/linux/regulator/consumer.h
include/linux/regulator/da9211.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h
include/linux/regulator/mt6311.h [new file with mode: 0644]
include/linux/serial_8250.h
include/linux/skbuff.h
include/linux/spi/spi.h
include/linux/ti_wilink_st.h
include/linux/tty.h
include/linux/tty_driver.h
include/linux/usb/chipidea.h
include/linux/usb/composite.h
include/linux/usb/gadget.h
include/linux/usb/hcd.h
include/linux/usb/msm_hsusb.h
include/linux/usb/of.h
include/linux/usb/otg.h
include/media/rc-core.h
include/media/videobuf2-core.h
include/scsi/scsi_eh.h
include/sound/soc-topology.h
include/trace/events/spmi.h [new file with mode: 0644]
include/uapi/linux/gsmmux.h
include/uapi/linux/kvm.h
include/uapi/linux/mei.h
include/uapi/linux/usb/ch9.h
include/uapi/sound/asoc.h
ipc/sem.c
kernel/cpu.c
kernel/cpuset.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/irq/chip.c
kernel/locking/qspinlock_paravirt.h
kernel/time/timer.c
lib/mpi/mpicoder.c
lib/vsprintf.c
mm/cma.h
mm/kasan/kasan.c
mm/kasan/report.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/page_alloc.c
mm/slab.c
mm/slub.c
net/9p/client.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/gateway_client.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/mgmt.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/core/datagram.c
net/core/pktgen.c
net/core/request_sock.c
net/core/skbuff.c
net/dsa/slave.c
net/ipv4/fib_trie.c
net/ipv4/igmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/mcast_snoop.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/key/af_key.c
net/mac80211/rc80211_minstrel.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_synproxy_core.c
net/netfilter/xt_CT.c
net/netlink/af_netlink.c
net/openvswitch/actions.c
net/rds/info.c
net/sched/act_mirred.c
net/sched/cls_u32.c
net/sched/sch_fq_codel.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/xfrm/xfrm_algo.c
scripts/checkkconfigsymbols.py
scripts/kernel-doc
scripts/kernel-doc-xml-ref [new file with mode: 0755]
security/security.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_generic.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/Kconfig
sound/soc/Makefile
sound/usb/card.c
sound/usb/quirks.c
tools/hv/lsvmbus [new file with mode: 0644]
tools/iio/generic_buffer.c
tools/iio/iio_event_monitor.c
tools/iio/iio_utils.c
tools/iio/iio_utils.h
tools/iio/lsiio.c
tools/perf/arch/xtensa/Build [new file with mode: 0644]
tools/perf/arch/xtensa/Makefile [new file with mode: 0644]
tools/perf/arch/xtensa/util/Build [new file with mode: 0644]
tools/perf/arch/xtensa/util/dwarf-regs.c [new file with mode: 0644]
tools/perf/builtin-record.c
tools/perf/builtin-top.c
tools/perf/config/Makefile
tools/perf/util/machine.c
tools/perf/util/stat-shadow.c
tools/perf/util/thread.c
tools/testing/selftests/firmware/fw_filesystem.sh
tools/testing/selftests/firmware/fw_userhelper.sh
virt/kvm/kvm_main.c

diff --git a/.get_maintainer.ignore b/.get_maintainer.ignore
new file mode 100644 (file)
index 0000000..cca6d87
--- /dev/null
@@ -0,0 +1 @@
+Christoph Hellwig <hch@lst.de>
index b4091b7a78fe11ccd0e5f44f0703ace69dc09707..4b31af54ccd5864359c0810f9733f3026181a631 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -17,6 +17,7 @@ Aleksey Gorelov <aleksey_gorelov@phoenix.com>
 Al Viro <viro@ftp.linux.org.uk>
 Al Viro <viro@zenIV.linux.org.uk>
 Andreas Herrmann <aherrman@de.ibm.com>
+Andrey Ryabinin <ryabinin.a.a@gmail.com> <a.ryabinin@samsung.com>
 Andrew Morton <akpm@linux-foundation.org>
 Andrew Vasquez <andrew.vasquez@qlogic.com>
 Andy Adamson <andros@citi.umich.edu>
diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus
new file mode 100644 (file)
index 0000000..636e938
--- /dev/null
@@ -0,0 +1,29 @@
+What:          /sys/bus/vmbus/devices/vmbus_*/id
+Date:          Jul 2009
+KernelVersion: 2.6.31
+Contact:       K. Y. Srinivasan <kys@microsoft.com>
+Description:   The VMBus child_relid of the device's primary channel
+Users:         tools/hv/lsvmbus
+
+What:          /sys/bus/vmbus/devices/vmbus_*/class_id
+Date:          Jul 2009
+KernelVersion: 2.6.31
+Contact:       K. Y. Srinivasan <kys@microsoft.com>
+Description:   The VMBus interface type GUID of the device
+Users:         tools/hv/lsvmbus
+
+What:          /sys/bus/vmbus/devices/vmbus_*/device_id
+Date:          Jul 2009
+KernelVersion: 2.6.31
+Contact:       K. Y. Srinivasan <kys@microsoft.com>
+Description:   The VMBus interface instance GUID of the device
+Users:         tools/hv/lsvmbus
+
+What:          /sys/bus/vmbus/devices/vmbus_*/channel_vp_mapping
+Date:          Jul 2015
+KernelVersion: 4.2.0
+Contact:       K. Y. Srinivasan <kys@microsoft.com>
+Description:   The mapping of which primary/sub channels are bound to which
+               Virtual Processors.
+               Format: <channel's child_relid:the bound cpu's number>
+Users:         tools/hv/lsvmbus
index 9aae5bfb990887a6ad3faee29830d1603a7ecb19..06beefbcf061a76f2dc1deb5696649eda35c1aaa 100644 (file)
@@ -5,4 +5,4 @@ Description:
                The attributes:
 
                qlen            - depth of loopback queue
-               bulk_buflen     - buffer length
+               buflen          - buffer length
index 29477c319f61bf16f1259962237f4b3f0a7e6287..bc7ff731aa0cf839fdc88e60e4934526387adc6a 100644 (file)
@@ -9,4 +9,4 @@ Description:
                isoc_maxpacket  - 0 - 1023 (fs), 0 - 1024 (hs/ss)
                isoc_mult       - 0..2 (hs/ss only)
                isoc_maxburst   - 0..15 (ss only)
-               qlen            - buffer length
+               buflen          - buffer length
index b4d0b99afffbd38a9ed14847e6387b0fda10f614..d72ca1736ba49b33e4eb0b5e8a1e25441ce5a07c 100644 (file)
@@ -112,7 +112,7 @@ KernelVersion:      3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
 Description:   (RW) Mask to apply to all the context ID comparator.
 
-What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_val
+What:          /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_pid
 Date:          November 2014
 KernelVersion: 3.19
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
index 2fe2e3dae487a094c7e6aba3def141ee3544ffca..2355ed8ae31f732d1567f2b9085d86574f817523 100644 (file)
@@ -249,7 +249,7 @@ KernelVersion:      4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
 Description:   (RW) Select which context ID comparator to work with.
 
-What:          /sys/bus/coresight/devices/<memory_map>.etm/ctxid_val
+What:          /sys/bus/coresight/devices/<memory_map>.etm/ctxid_pid
 Date:          April 2015
 KernelVersion: 4.01
 Contact:       Mathieu Poirier <mathieu.poirier@linaro.org>
index 70c9b1ac66dbc5880c90312b47ba0b28669a77a6..42d360fe66a5785929c42f2e36c3fcd3d0f6b58b 100644 (file)
@@ -413,6 +413,11 @@ Description:
                to compute the calories burnt by the user.
 
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available
+What:          /sys/.../iio:deviceX/in_anglvel_scale_available
+What:          /sys/.../iio:deviceX/in_magn_scale_available
+What:          /sys/.../iio:deviceX/in_illuminance_scale_available
+What:          /sys/.../iio:deviceX/in_intensity_scale_available
+What:          /sys/.../iio:deviceX/in_proximity_scale_available
 What:          /sys/.../iio:deviceX/in_voltageX_scale_available
 What:          /sys/.../iio:deviceX/in_voltage-voltage_scale_available
 What:          /sys/.../iio:deviceX/out_voltageX_scale_available
@@ -488,7 +493,7 @@ Contact:    linux-iio@vger.kernel.org
 Description:
                Specifies the output powerdown mode.
                DAC output stage is disconnected from the amplifier and
-               1kohm_to_gnd: connected to ground via an 1kOhm resistor,
+               1kohm_to_gnd: connected to ground via an 1kOhm resistor,
                6kohm_to_gnd: connected to ground via a 6kOhm resistor,
                20kohm_to_gnd: connected to ground via a 20kOhm resistor,
                100kohm_to_gnd: connected to ground via an 100kOhm resistor,
@@ -498,9 +503,9 @@ Description:
                outX_powerdown_mode_available. If Y is not present the
                mode is shared across all outputs.
 
-What:          /sys/.../iio:deviceX/out_votlageY_powerdown_mode_available
+What:          /sys/.../iio:deviceX/out_voltageY_powerdown_mode_available
 What:          /sys/.../iio:deviceX/out_voltage_powerdown_mode_available
-What:          /sys/.../iio:deviceX/out_altvotlageY_powerdown_mode_available
+What:          /sys/.../iio:deviceX/out_altvoltageY_powerdown_mode_available
 What:          /sys/.../iio:deviceX/out_altvoltage_powerdown_mode_available
 KernelVersion: 2.6.38
 Contact:       linux-iio@vger.kernel.org
@@ -1035,13 +1040,6 @@ Contact: linux-iio@vger.kernel.org
 Description:
                Number of scans contained by the buffer.
 
-What:          /sys/bus/iio/devices/iio:deviceX/buffer/bytes_per_datum
-KernelVersion: 2.6.37
-Contact:       linux-iio@vger.kernel.org
-Description:
-               Bytes per scan.  Due to alignment fun, the scan may be larger
-               than implied directly by the scan_element parameters.
-
 What:          /sys/bus/iio/devices/iio:deviceX/buffer/enable
 KernelVersion: 2.6.35
 Contact:       linux-iio@vger.kernel.org
index 5235e6c749ab413657d93e7039d11670522b8bcf..bbb039237a2580307d614030ea5013b71f749f6f 100644 (file)
@@ -9,3 +9,12 @@ Description:
                automated testing or in situations, where other trigger methods
                are not applicable. For example no RTC or spare GPIOs.
                X is the IIO index of the trigger.
+
+What:          /sys/bus/iio/devices/triggerX/name
+KernelVersion: 2.6.39
+Contact:       linux-iio@vger.kernel.org
+Description:
+               The name attribute holds a description string for the current
+               trigger. In order to associate the trigger with an IIO device
+               one should write this name string to
+               /sys/bus/iio/devices/iio:deviceY/trigger/current_trigger.
index e5cc7633d0131db82951d489b311195967db2db8..864637f25bee49a616865901ed6b0d4daa1791c8 100644 (file)
@@ -114,6 +114,20 @@ Description:
                enabled for the device. Developer can write y/Y/1 or n/N/0 to
                the file to enable/disable the feature.
 
+What:          /sys/bus/usb/devices/.../power/usb3_hardware_lpm
+Date:          June 2015
+Contact:       Kevin Strasser <kevin.strasser@linux.intel.com>
+Description:
+               If CONFIG_PM is set and a USB 3.0 lpm-capable device is plugged
+               in to a xHCI host which supports link PM, it will check if U1
+               and U2 exit latencies have been set in the BOS descriptor; if
+               the check is is passed and the host supports USB3 hardware LPM,
+               USB3 hardware LPM will be enabled for the device and the USB
+               device directory will contain a file named
+               power/usb3_hardware_lpm. The file holds a string value (enable
+               or disable) indicating whether or not USB3 hardware LPM is
+               enabled for the device.
+
 What:          /sys/bus/usb/devices/.../removable
 Date:          February 2012
 Contact:       Matthew Garrett <mjg@redhat.com>
diff --git a/Documentation/ABI/testing/sysfs-class-power-twl4030 b/Documentation/ABI/testing/sysfs-class-power-twl4030
new file mode 100644 (file)
index 0000000..be26af0
--- /dev/null
@@ -0,0 +1,45 @@
+What: /sys/class/power_supply/twl4030_ac/max_current
+      /sys/class/power_supply/twl4030_usb/max_current
+Description:
+       Read/Write limit on current which may
+       be drawn from the ac (Accessory Charger) or
+       USB port.
+
+       Value is in micro-Amps.
+
+       Value is set automatically to an appropriate
+       value when a cable is plugged or unplugged.
+
+       Value can the set by writing to the attribute.
+       The change will only persist until the next
+       plug event.  These event are reported via udev.
+
+
+What: /sys/class/power_supply/twl4030_usb/mode
+Description:
+       Changing mode for USB port.
+       Writing to this can disable charging.
+
+       Possible values are:
+               "auto" - draw power as appropriate for detected
+                        power source and battery status.
+               "off"  - do not draw any power.
+               "continuous"
+                      - activate mode described as "linear" in
+                        TWL data sheets.  This uses whatever
+                        current is available and doesn't switch off
+                        when voltage drops.
+
+                        This is useful for unstable power sources
+                        such as bicycle dynamo, but care should
+                        be taken that battery is not over-charged.
+
+What: /sys/class/power_supply/twl4030_ac/mode
+Description:
+       Changing mode for 'ac' port.
+       Writing to this can disable charging.
+
+       Possible values are:
+               "auto" - draw power as appropriate for detected
+                        power source and battery status.
+               "off"  - do not draw any power.
diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
deleted file mode 100644 (file)
index ffb9536..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-What:          /sys/devices/*/<our-device>/eeprom
-Date:          August 2013
-Contact:       Oliver Schinagl <oliver@schinagl.nl>
-Description:   read-only access to the SID (Security-ID) on current
-               A-series SoC's from Allwinner. Currently supports A10, A10s, A13
-               and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
-               whereas the newer A20 SoC exposes 512 bytes split into sections.
-               Besides the 16 bytes of SID, there's also an SJTAG area,
-               HDMI-HDCP key and some custom keys. Below a quick overview, for
-               details see the user manual:
-               0x000  128 bit root-key (sun[457]i)
-               0x010  128 bit boot-key (sun7i)
-               0x020   64 bit security-jtag-key (sun7i)
-               0x028   16 bit key configuration (sun7i)
-               0x02b   16 bit custom-vendor-key (sun7i)
-               0x02c  320 bit low general key (sun7i)
-               0x040   32 bit read-control access (sun7i)
-               0x064  224 bit low general key (sun7i)
-               0x080 2304 bit HDCP-key (sun7i)
-               0x1a0  768 bit high general key (sun7i)
-Users:         any user space application which wants to read the SID on
-               Allwinner's A-series of CPU's.
index b713c35f85436316f79f2520436c02297c2e10e1..c06f817b3091cdb6e4be6e91dbbb98210177b370 100644 (file)
@@ -929,13 +929,11 @@ The C Programming Language, Second Edition
 by Brian W. Kernighan and Dennis M. Ritchie.
 Prentice Hall, Inc., 1988.
 ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
-URL: http://cm.bell-labs.com/cm/cs/cbook/
 
 The Practice of Programming
 by Brian W. Kernighan and Rob Pike.
 Addison-Wesley, Inc., 1999.
 ISBN 0-201-61586-X.
-URL: http://cm.bell-labs.com/cm/cs/tpop/
 
 GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
 gcc internals and indent, all available from http://www.gnu.org/manual/
index b6a6a2e0dd3bb69c4db3ba362e3540737ce20db0..93eff64387cd2324f3f0731ffaba1bca9f39cfb9 100644 (file)
@@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
            80211.xml debugobjects.xml sh.xml regulator.xml \
            alsa-driver-api.xml writing-an-alsa-driver.xml \
            tracepoint.xml drm.xml media_api.xml w1.xml \
-           writing_musb_glue_layer.xml crypto-API.xml
+           writing_musb_glue_layer.xml crypto-API.xml iio.xml
 
 include Documentation/DocBook/media/Makefile
 
@@ -56,16 +56,19 @@ htmldocs: $(HTML)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
-       find $(obj)/man -name '*.9' | xargs gzip -f
+       find $(obj)/man -name '*.9' | xargs gzip -nf
 
 installmandocs: mandocs
        mkdir -p /usr/local/man/man9/
-       install $(obj)/man/*.9.gz /usr/local/man/man9/
+       find $(obj)/man -name '*.9.gz' -printf '%h %f\n' | \
+               sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \
+               xargs install -m 644 -t /usr/local/man/man9/
 
 ###
 #External programs used
-KERNELDOC = $(srctree)/scripts/kernel-doc
-DOCPROC   = $(objtree)/scripts/docproc
+KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref
+KERNELDOC       = $(srctree)/scripts/kernel-doc
+DOCPROC         = $(objtree)/scripts/docproc
 
 XMLTOFLAGS = -m $(srctree)/$(src)/stylesheet.xsl
 XMLTOFLAGS += --skip-validation
@@ -89,7 +92,7 @@ define rule_docproc
         ) > $(dir $@).$(notdir $@).cmd
 endef
 
-%.xml: %.tmpl $(KERNELDOC) $(DOCPROC) FORCE
+%.xml: %.tmpl $(KERNELDOC) $(DOCPROC) $(KERNELDOCXMLREF) FORCE
        $(call if_changed_rule,docproc)
 
 # Tell kbuild to always build the programs
@@ -140,7 +143,20 @@ quiet_cmd_db2html = HTML    $@
                echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
                $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
 
-%.html:        %.xml
+###
+# Rules to create an aux XML and .db, and use them to re-process the DocBook XML
+# to fill internal hyperlinks
+       gen_aux_xml = :
+ quiet_gen_aux_xml = echo '  XMLREF  $@'
+silent_gen_aux_xml = :
+%.aux.xml: %.xml
+       @$($(quiet)gen_aux_xml)
+       @rm -rf $@
+       @(cat $< | egrep "^<refentry id" | egrep -o "\".*\"" | cut -f 2 -d \" > $<.db)
+       @$(KERNELDOCXMLREF) -db $<.db $< > $@
+.PRECIOUS: %.aux.xml
+
+%.html:        %.aux.xml
        @(which xmlto > /dev/null 2>&1) || \
         (echo "*** You need to install xmlto ***"; \
          exit 1)
@@ -150,12 +166,12 @@ quiet_cmd_db2html = HTML    $@
             cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
 
 quiet_cmd_db2man = MAN     $@
-      cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; fi
+      cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man/$(*F) $< ; fi
 %.9 : %.xml
        @(which xmlto > /dev/null 2>&1) || \
         (echo "*** You need to install xmlto ***"; \
          exit 1)
-       $(Q)mkdir -p $(obj)/man
+       $(Q)mkdir -p $(obj)/man/$(*F)
        $(call cmd,db2man)
        @touch $@
 
@@ -209,15 +225,18 @@ dochelp:
 ###
 # Temporary files left by various tools
 clean-files := $(DOCBOOKS) \
-       $(patsubst %.xml, %.dvi,  $(DOCBOOKS)) \
-       $(patsubst %.xml, %.aux,  $(DOCBOOKS)) \
-       $(patsubst %.xml, %.tex,  $(DOCBOOKS)) \
-       $(patsubst %.xml, %.log,  $(DOCBOOKS)) \
-       $(patsubst %.xml, %.out,  $(DOCBOOKS)) \
-       $(patsubst %.xml, %.ps,   $(DOCBOOKS)) \
-       $(patsubst %.xml, %.pdf,  $(DOCBOOKS)) \
-       $(patsubst %.xml, %.html, $(DOCBOOKS)) \
-       $(patsubst %.xml, %.9,    $(DOCBOOKS)) \
+       $(patsubst %.xml, %.dvi,     $(DOCBOOKS)) \
+       $(patsubst %.xml, %.aux,     $(DOCBOOKS)) \
+       $(patsubst %.xml, %.tex,     $(DOCBOOKS)) \
+       $(patsubst %.xml, %.log,     $(DOCBOOKS)) \
+       $(patsubst %.xml, %.out,     $(DOCBOOKS)) \
+       $(patsubst %.xml, %.ps,      $(DOCBOOKS)) \
+       $(patsubst %.xml, %.pdf,     $(DOCBOOKS)) \
+       $(patsubst %.xml, %.html,    $(DOCBOOKS)) \
+       $(patsubst %.xml, %.9,       $(DOCBOOKS)) \
+       $(patsubst %.xml, %.aux.xml, $(DOCBOOKS)) \
+       $(patsubst %.xml, %.xml.db,  $(DOCBOOKS)) \
+       $(patsubst %.xml, %.xml,     $(DOCBOOKS)) \
        $(index)
 
 clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
index 0992531ffefb761eb047d22003130cf45ede9584..07df23ea06e4936d6de435ba4c862ffdb4b299d1 100644 (file)
@@ -585,7 +585,7 @@ kernel crypto API                                |   IPSEC Layer
 +-----------+                                    |
 |           |            (1)
 |   aead    | <-----------------------------------  esp_output
-| (seqniv)  | ---+
+|  (seqiv)  | ---+
 +-----------+    |
                  | (2)
 +-----------+    |
@@ -1101,7 +1101,7 @@ kernel crypto API            |       Caller
     </para>
 
     <para>
-     [1] http://www.chronox.de/libkcapi.html
+     [1] <ulink url="http://www.chronox.de/libkcapi.html">http://www.chronox.de/libkcapi.html</ulink>
     </para>
 
    </sect1>
@@ -1661,7 +1661,7 @@ read(opfd, out, outlen);
     </para>
 
     <para>
-     [1] http://www.chronox.de/libkcapi.html
+     [1] <ulink url="http://www.chronox.de/libkcapi.html">http://www.chronox.de/libkcapi.html</ulink>
     </para>
 
    </sect1>
@@ -1687,7 +1687,7 @@ read(opfd, out, outlen);
 !Pinclude/linux/crypto.h Block Cipher Algorithm Definitions
 !Finclude/linux/crypto.h crypto_alg
 !Finclude/linux/crypto.h ablkcipher_alg
-!Finclude/linux/crypto.h aead_alg
+!Finclude/crypto/aead.h aead_alg
 !Finclude/linux/crypto.h blkcipher_alg
 !Finclude/linux/crypto.h cipher_alg
 !Finclude/crypto/rng.h rng_alg
index faf09d4a0ea8b3fe6eb5647ab2e851a922899f7e..bbc1d7ee9c764a61eb71615d0ea654e5ed8897a9 100644 (file)
@@ -66,6 +66,7 @@
 !Ekernel/time/hrtimer.c
      </sect1>
      <sect1><title>Workqueues and Kevents</title>
+!Iinclude/linux/workqueue.h
 !Ekernel/workqueue.c
      </sect1>
      <sect1><title>Internal Functions</title>
diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl
new file mode 100644 (file)
index 0000000..06bb53d
--- /dev/null
@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="iioid">
+  <bookinfo>
+    <title>Industrial I/O driver developer's guide </title>
+
+    <authorgroup>
+      <author>
+        <firstname>Daniel</firstname>
+        <surname>Baluta</surname>
+        <affiliation>
+          <address>
+            <email>daniel.baluta@intel.com</email>
+          </address>
+        </affiliation>
+      </author>
+    </authorgroup>
+
+    <copyright>
+      <year>2015</year>
+      <holder>Intel Corporation</holder>
+    </copyright>
+
+    <legalnotice>
+      <para>
+        This documentation is free software; you can redistribute
+        it and/or modify it under the terms of the GNU General Public
+        License version 2.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+  <toc></toc>
+
+  <chapter id="intro">
+    <title>Introduction</title>
+    <para>
+      The main purpose of the Industrial I/O subsystem (IIO) is to provide
+      support for devices that in some sense perform either analog-to-digital
+      conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
+      is to fill the gap between the somewhat similar hwmon and input
+      subsystems.
+      Hwmon is directed at low sample rate sensors used to monitor and
+      control the system itself, like fan speed control or temperature
+      measurement. Input is, as its name suggests, focused on human interaction
+      input devices (keyboard, mouse, touchscreen). In some cases there is
+      considerable overlap between these and IIO.
+  </para>
+  <para>
+    Devices that fall into this category include:
+    <itemizedlist>
+      <listitem>
+        analog to digital converters (ADCs)
+      </listitem>
+      <listitem>
+        accelerometers
+      </listitem>
+      <listitem>
+        capacitance to digital converters (CDCs)
+      </listitem>
+      <listitem>
+        digital to analog converters (DACs)
+      </listitem>
+      <listitem>
+        gyroscopes
+      </listitem>
+      <listitem>
+        inertial measurement units (IMUs)
+      </listitem>
+      <listitem>
+        color and light sensors
+      </listitem>
+      <listitem>
+        magnetometers
+      </listitem>
+      <listitem>
+        pressure sensors
+      </listitem>
+      <listitem>
+        proximity sensors
+      </listitem>
+      <listitem>
+        temperature sensors
+      </listitem>
+    </itemizedlist>
+    Usually these sensors are connected via SPI or I2C. A common use case of the
+    sensors devices is to have combined functionality (e.g. light plus proximity
+    sensor).
+  </para>
+  </chapter>
+  <chapter id='iiosubsys'>
+    <title>Industrial I/O core</title>
+    <para>
+      The Industrial I/O core offers:
+      <itemizedlist>
+        <listitem>
+         a unified framework for writing drivers for many different types of
+         embedded sensors.
+        </listitem>
+        <listitem>
+         a standard interface to user space applications manipulating sensors.
+        </listitem>
+      </itemizedlist>
+      The implementation can be found under <filename>
+      drivers/iio/industrialio-*</filename>
+  </para>
+  <sect1 id="iiodevice">
+    <title> Industrial I/O devices </title>
+
+!Finclude/linux/iio/iio.h iio_dev
+!Fdrivers/iio/industrialio-core.c iio_device_alloc
+!Fdrivers/iio/industrialio-core.c iio_device_free
+!Fdrivers/iio/industrialio-core.c iio_device_register
+!Fdrivers/iio/industrialio-core.c iio_device_unregister
+
+    <para>
+      An IIO device usually corresponds to a single hardware sensor and it
+      provides all the information needed by a driver handling a device.
+      Let's first have a look at the functionality embedded in an IIO
+      device then we will show how a device driver makes use of an IIO
+      device.
+    </para>
+    <para>
+        There are two ways for a user space application to interact
+        with an IIO driver.
+      <itemizedlist>
+        <listitem>
+          <filename>/sys/bus/iio/iio:deviceX/</filename>, this
+          represents a hardware sensor and groups together the data
+          channels of the same chip.
+        </listitem>
+        <listitem>
+          <filename>/dev/iio:deviceX</filename>, character device node
+          interface used for buffered data transfer and for events information
+          retrieval.
+        </listitem>
+      </itemizedlist>
+    </para>
+    A typical IIO driver will register itself as an I2C or SPI driver and will
+    create two routines, <function> probe </function> and <function> remove
+    </function>. At <function>probe</function>:
+    <itemizedlist>
+    <listitem>call <function>iio_device_alloc</function>, which allocates memory
+      for an IIO device.
+    </listitem>
+    <listitem> initialize IIO device fields with driver specific information
+              (e.g. device name, device channels).
+    </listitem>
+    <listitem>call <function> iio_device_register</function>, this registers the
+      device with the IIO core. After this call the device is ready to accept
+      requests from user space applications.
+    </listitem>
+    </itemizedlist>
+      At <function>remove</function>, we free the resources allocated in
+      <function>probe</function> in reverse order:
+    <itemizedlist>
+    <listitem><function>iio_device_unregister</function>, unregister the device
+      from the IIO core.
+    </listitem>
+    <listitem><function>iio_device_free</function>, free the memory allocated
+      for the IIO device.
+    </listitem>
+    </itemizedlist>
+
+    <sect2 id="iioattr"> <title> IIO device sysfs interface </title>
+      <para>
+        Attributes are sysfs files used to expose chip info and also allowing
+        applications to set various configuration parameters. For device
+        with index X, attributes can be found under
+        <filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
+        Common attributes are:
+        <itemizedlist>
+          <listitem><filename>name</filename>, description of the physical
+            chip.
+          </listitem>
+          <listitem><filename>dev</filename>, shows the major:minor pair
+            associated with <filename>/dev/iio:deviceX</filename> node.
+          </listitem>
+          <listitem><filename>sampling_frequency_available</filename>,
+            available discrete set of sampling frequency values for
+            device.
+          </listitem>
+      </itemizedlist>
+      Available standard attributes for IIO devices are described in the
+      <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
+      in the Linux kernel sources.
+      </para>
+    </sect2>
+    <sect2 id="iiochannel"> <title> IIO device channels </title>
+!Finclude/linux/iio/iio.h iio_chan_spec structure.
+      <para>
+        An IIO device channel is a representation of a data channel. An
+        IIO device can have one or multiple channels. For example:
+        <itemizedlist>
+          <listitem>
+          a thermometer sensor has one channel representing the
+          temperature measurement.
+          </listitem>
+          <listitem>
+          a light sensor with two channels indicating the measurements in
+          the visible and infrared spectrum.
+          </listitem>
+          <listitem>
+          an accelerometer can have up to 3 channels representing
+          acceleration on X, Y and Z axes.
+          </listitem>
+        </itemizedlist>
+      An IIO channel is described by the <type> struct iio_chan_spec
+      </type>. A thermometer driver for the temperature sensor in the
+      example above would have to describe its channel as follows:
+      <programlisting>
+      static const struct iio_chan_spec temp_channel[] = {
+          {
+              .type = IIO_TEMP,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+          },
+      };
+
+      </programlisting>
+      Channel sysfs attributes exposed to userspace are specified in
+      the form of <emphasis>bitmasks</emphasis>. Depending on their
+      shared info, attributes can be set in one of the following masks:
+      <itemizedlist>
+      <listitem><emphasis>info_mask_separate</emphasis>, attributes will
+        be specific to this channel</listitem>
+      <listitem><emphasis>info_mask_shared_by_type</emphasis>,
+        attributes are shared by all channels of the same type</listitem>
+      <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
+        are shared by all channels of the same direction </listitem>
+      <listitem><emphasis>info_mask_shared_by_all</emphasis>,
+        attributes are shared by all channels</listitem>
+      </itemizedlist>
+      When there are multiple data channels per channel type we have two
+      ways to distinguish between them:
+      <itemizedlist>
+      <listitem> set <emphasis> .modified</emphasis> field of <type>
+        iio_chan_spec</type> to 1. Modifiers are specified using
+        <emphasis>.channel2</emphasis> field of the same
+        <type>iio_chan_spec</type> structure and are used to indicate a
+        physically unique characteristic of the channel such as its direction
+        or spectral response. For example, a light sensor can have two channels,
+        one for infrared light and one for both infrared and visible light.
+      </listitem>
+      <listitem> set <emphasis>.indexed </emphasis> field of
+        <type>iio_chan_spec</type> to 1. In this case the channel is
+        simply another instance with an index specified by the
+        <emphasis>.channel</emphasis> field.
+      </listitem>
+      </itemizedlist>
+      Here is how we can make use of the channel's modifiers:
+      <programlisting>
+      static const struct iio_chan_spec light_channels[] = {
+          {
+              .type = IIO_INTENSITY,
+              .modified = 1,
+              .channel2 = IIO_MOD_LIGHT_IR,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+              .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+          },
+          {
+              .type = IIO_INTENSITY,
+              .modified = 1,
+              .channel2 = IIO_MOD_LIGHT_BOTH,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+              .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+          },
+          {
+              .type = IIO_LIGHT,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+              .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+          },
+
+      }
+      </programlisting>
+      This channel's definition will generate two separate sysfs files
+      for raw data retrieval:
+      <itemizedlist>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
+      </listitem>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
+      </listitem>
+      </itemizedlist>
+      one file for processed data:
+      <itemizedlist>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
+      </filename>
+      </listitem>
+      </itemizedlist>
+      and one shared sysfs file for sampling frequency:
+      <itemizedlist>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/sampling_frequency.
+      </filename>
+      </listitem>
+      </itemizedlist>
+      </para>
+      <para>
+      Here is how we can make use of the channel's indexing:
+      <programlisting>
+      static const struct iio_chan_spec light_channels[] = {
+          {
+              .type = IIO_VOLTAGE,
+              .indexed = 1,
+              .channel = 0,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+          },
+          {
+              .type = IIO_VOLTAGE,
+              .indexed = 1,
+              .channel = 1,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+          },
+      }
+      </programlisting>
+      This will generate two separate attributes files for raw data
+      retrieval:
+      <itemizedlist>
+      <listitem>
+        <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
+          representing voltage measurement for channel 0.
+      </listitem>
+      <listitem>
+        <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
+          representing voltage measurement for channel 1.
+      </listitem>
+      </itemizedlist>
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
+!Finclude/linux/iio/buffer.h iio_buffer
+!Edrivers/iio/industrialio-buffer.c
+
+    <para>
+    The Industrial I/O core offers a way for continuous data capture
+    based on a trigger source. Multiple data channels can be read at once
+    from <filename>/dev/iio:deviceX</filename> character device node,
+    thus reducing the CPU load.
+    </para>
+
+    <sect2 id="iiobuffersysfs">
+    <title>IIO buffer sysfs interface </title>
+    <para>
+      An IIO buffer has an associated attributes directory under <filename>
+      /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
+      attributes:
+      <itemizedlist>
+      <listitem>
+      <emphasis>length</emphasis>, the total number of data samples
+      (capacity) that can be stored by the buffer.
+      </listitem>
+      <listitem>
+        <emphasis>enable</emphasis>, activate buffer capture.
+      </listitem>
+      </itemizedlist>
+
+    </para>
+    </sect2>
+    <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
+      <para>The meta information associated with a channel reading
+        placed in a buffer is called a <emphasis> scan element </emphasis>.
+        The important bits configuring scan elements are exposed to
+        userspace applications via the <filename>
+        /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
+        file contains attributes of the following form:
+      <itemizedlist>
+      <listitem><emphasis>enable</emphasis>, used for enabling a channel.
+        If and only if its attribute is non zero, then a triggered capture
+        will contain data samples for this channel.
+      </listitem>
+      <listitem><emphasis>type</emphasis>, description of the scan element
+        data storage within the buffer and hence the form in which it is
+        read from user space. Format is <emphasis>
+        [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
+        <itemizedlist>
+        <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis>, specifies
+          big or little endian.
+        </listitem>
+        <listitem>
+        <emphasis>s </emphasis>or <emphasis>u</emphasis>, specifies if
+          signed (2's complement) or unsigned.
+        </listitem>
+        <listitem><emphasis>bits</emphasis>, is the number of valid data
+          bits.
+        </listitem>
+        <listitem><emphasis>storagebits</emphasis>, is the number of bits
+          (after padding) that it occupies in the buffer.
+        </listitem>
+        <listitem>
+        <emphasis>shift</emphasis>, if specified, is the shift that needs
+          to be applied prior to masking out unused bits.
+        </listitem>
+        <listitem>
+        <emphasis>repeat</emphasis>, specifies the number of bits/storagebits
+        repetitions. When the repeat element is 0 or 1, then the repeat
+        value is omitted.
+        </listitem>
+        </itemizedlist>
+      </listitem>
+      </itemizedlist>
+      For example, a driver for a 3-axis accelerometer with 12 bit
+      resolution where data is stored in two 8-bits registers as
+      follows:
+      <programlisting>
+        7   6   5   4   3   2   1   0
+      +---+---+---+---+---+---+---+---+
+      |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
+      +---+---+---+---+---+---+---+---+
+
+        7   6   5   4   3   2   1   0
+      +---+---+---+---+---+---+---+---+
+      |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
+      +---+---+---+---+---+---+---+---+
+      </programlisting>
+
+      will have the following scan element type for each axis:
+      <programlisting>
+      $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
+      le:s12/16>>4
+      </programlisting>
+      A user space application will interpret data samples read from the
+      buffer as two byte little endian signed data, that needs a 4 bits
+      right shift before masking out the 12 valid bits of data.
+    </para>
+    <para>
+      For implementing buffer support a driver should initialize the following
+      fields in <type>iio_chan_spec</type> definition:
+      <programlisting>
+          struct iio_chan_spec {
+              /* other members */
+              int scan_index
+              struct {
+                  char sign;
+                  u8 realbits;
+                  u8 storagebits;
+                  u8 shift;
+                  u8 repeat;
+                  enum iio_endian endianness;
+              } scan_type;
+          };
+      </programlisting>
+      The driver implementing the accelerometer described above will
+      have the following channel definition:
+      <programlisting>
+      struct struct iio_chan_spec accel_channels[] = {
+          {
+            .type = IIO_ACCEL,
+            .modified = 1,
+            .channel2 = IIO_MOD_X,
+            /* other stuff here */
+            .scan_index = 0,
+            .scan_type = {
+              .sign = 's',
+              .realbits = 12,
+              .storgebits = 16,
+              .shift = 4,
+              .endianness = IIO_LE,
+            },
+        }
+        /* similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1)
+         * and Z (with channel2 = IIO_MOD_Z, scan_index = 2) axis
+         */
+    }
+    </programlisting>
+    </para>
+    <para>
+    Here <emphasis> scan_index </emphasis> defines the order in which
+    the enabled channels are placed inside the buffer. Channels with a lower
+    scan_index will be placed before channels with a higher index. Each
+    channel needs to have a unique scan_index.
+    </para>
+    <para>
+    Setting scan_index to -1 can be used to indicate that the specific
+    channel does not support buffered capture. In this case no entries will
+    be created for the channel in the scan_elements directory.
+    </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="iiotrigger"> <title> Industrial I/O triggers  </title>
+!Finclude/linux/iio/trigger.h iio_trigger
+!Edrivers/iio/industrialio-trigger.c
+    <para>
+      In many situations it is useful for a driver to be able to
+      capture data based on some external event (trigger) as opposed
+      to periodically polling for data. An IIO trigger can be provided
+      by a device driver that also has an IIO device based on hardware
+      generated events (e.g. data ready or threshold exceeded) or
+      provided by a separate driver from an independent interrupt
+      source (e.g. GPIO line connected to some external system, timer
+      interrupt or user space writing a specific file in sysfs). A
+      trigger may initiate data capture for a number of sensors and
+      also it may be completely unrelated to the sensor itself.
+    </para>
+
+    <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
+      There are two locations in sysfs related to triggers:
+      <itemizedlist>
+        <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
+          this file is created once an IIO trigger is registered with
+          the IIO core and corresponds to trigger with index Y. Because
+          triggers can be very different depending on type there are few
+          standard attributes that we can describe here:
+          <itemizedlist>
+            <listitem>
+              <emphasis>name</emphasis>, trigger name that can be later
+                used for association with a device.
+            </listitem>
+            <listitem>
+            <emphasis>sampling_frequency</emphasis>, some timer based
+              triggers use this attribute to specify the frequency for
+              trigger calls.
+            </listitem>
+          </itemizedlist>
+        </listitem>
+        <listitem>
+          <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
+          directory is created once the device supports a triggered
+          buffer. We can associate a trigger with our device by writing
+          the trigger's name in the <filename>current_trigger</filename> file.
+        </listitem>
+      </itemizedlist>
+    </sect2>
+
+    <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
+
+    <para>
+      Let's see a simple example of how to setup a trigger to be used
+      by a driver.
+
+      <programlisting>
+      struct iio_trigger_ops trigger_ops = {
+          .set_trigger_state = sample_trigger_state,
+          .validate_device = sample_validate_device,
+      }
+
+      struct iio_trigger *trig;
+
+      /* first, allocate memory for our trigger */
+      trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
+
+      /* setup trigger operations field */
+      trig->ops = &amp;trigger_ops;
+
+      /* now register the trigger with the IIO core */
+      iio_trigger_register(trig);
+      </programlisting>
+    </para>
+    </sect2>
+
+    <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
+!Finclude/linux/iio/trigger.h iio_trigger_ops
+     <para>
+        Notice that a trigger has a set of operations attached:
+        <itemizedlist>
+        <listitem>
+          <function>set_trigger_state</function>, switch the trigger on/off
+          on demand.
+        </listitem>
+        <listitem>
+          <function>validate_device</function>, function to validate the
+          device when the current trigger gets changed.
+        </listitem>
+        </itemizedlist>
+      </para>
+    </sect2>
+  </sect1>
+  <sect1 id="iiotriggered_buffer">
+    <title> Industrial I/O triggered buffers </title>
+    <para>
+    Now that we know what buffers and triggers are let's see how they
+    work together.
+    </para>
+    <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
+!Edrivers/iio/industrialio-triggered-buffer.c
+!Finclude/linux/iio/iio.h iio_buffer_setup_ops
+
+
+    <para>
+    A typical triggered buffer setup looks like this:
+    <programlisting>
+    const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
+      .preenable    = sensor_buffer_preenable,
+      .postenable   = sensor_buffer_postenable,
+      .postdisable  = sensor_buffer_postdisable,
+      .predisable   = sensor_buffer_predisable,
+    };
+
+    irqreturn_t sensor_iio_pollfunc(int irq, void *p)
+    {
+        pf->timestamp = iio_get_time_ns();
+        return IRQ_WAKE_THREAD;
+    }
+
+    irqreturn_t sensor_trigger_handler(int irq, void *p)
+    {
+        u16 buf[8];
+        int i = 0;
+
+        /* read data for each active channel */
+        for_each_set_bit(bit, active_scan_mask, masklength)
+            buf[i++] = sensor_get_data(bit)
+
+        iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp);
+
+        iio_trigger_notify_done(trigger);
+        return IRQ_HANDLED;
+    }
+
+    /* setup triggered buffer, usually in probe function */
+    iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
+                               sensor_trigger_handler,
+                               sensor_buffer_setup_ops);
+    </programlisting>
+    </para>
+    The important things to notice here are:
+    <itemizedlist>
+    <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
+    functions to be called at predefined points in the buffer configuration
+    sequence (e.g. before enable, after disable). If not specified, the
+    IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
+    </listitem>
+    <listitem><function>sensor_iio_pollfunc</function>, the function that
+    will be used as top half of poll function. It should do as little
+    processing as possible, because it runs in interrupt context. The most
+    common operation is recording of the current timestamp and for this reason
+    one can use the IIO core defined <function>iio_pollfunc_store_time
+    </function> function.
+    </listitem>
+    <listitem><function>sensor_trigger_handler</function>, the function that
+    will be used as bottom half of the poll function. This runs in the
+    context of a kernel thread and all the processing takes place here.
+    It usually reads data from the device and stores it in the internal
+    buffer together with the timestamp recorded in the top half.
+    </listitem>
+    </itemizedlist>
+    </sect2>
+  </sect1>
+  </chapter>
+  <chapter id='iioresources'>
+    <title> Resources </title>
+      IIO core may change during time so the best documentation to read is the
+      source code. There are several locations where you should look:
+      <itemizedlist>
+        <listitem>
+          <filename>drivers/iio/</filename>, contains the IIO core plus
+          and directories for each sensor type (e.g. accel, magnetometer,
+          etc.)
+        </listitem>
+        <listitem>
+          <filename>include/linux/iio/</filename>, contains the header
+          files, nice to read for the internal kernel interfaces.
+        </listitem>
+        <listitem>
+        <filename>include/uapi/linux/iio/</filename>, contains files to be
+          used by user space applications.
+        </listitem>
+        <listitem>
+         <filename>tools/iio/</filename>, contains tools for rapidly
+          testing buffers, events and device creation.
+        </listitem>
+        <listitem>
+          <filename>drivers/staging/iio/</filename>, contains code for some
+          drivers or experimental features that are not yet mature enough
+          to be moved out.
+        </listitem>
+      </itemizedlist>
+    <para>
+    Besides the code, there are some good online documentation sources:
+    <itemizedlist>
+    <listitem>
+      <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
+      list </ulink>
+    </listitem>
+    <listitem>
+      <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
+      Analog Device IIO wiki page </ulink>
+    </listitem>
+    <listitem>
+      <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
+      Using the Linux IIO framework for SDR, Lars-Peter Clausen's
+      presentation at FOSDEM </ulink>
+    </listitem>
+    </itemizedlist>
+    </para>
+  </chapter>
+</book>
+
+<!--
+vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
+-->
index 85b25275196ffab5d34e31e207b78a483128a3f1..3bf4ecf3d760c8145479be580d6db8da17543447 100644 (file)
@@ -5,6 +5,7 @@
 <param name="funcsynopsis.tabular.threshold">80</param>
 <param name="callout.graphics">0</param>
 <!-- <param name="paper.type">A4</param> -->
+<param name="generate.consistent.ids">1</param>
 <param name="generate.section.toc.level">2</param>
 <param name="use.id.as.filename">1</param>
 </stylesheet>
index 93aa8604630e769dd531fe8856c59d6d7390e6cc..21152d397b88ecbe45bca161444fcee38158e96b 100644 (file)
@@ -218,16 +218,16 @@ The development process
 Linux kernel development process currently consists of a few different
 main kernel "branches" and lots of different subsystem-specific kernel
 branches.  These different branches are:
-  - main 3.x kernel tree
-  - 3.x.y -stable kernel tree
-  - 3.x -git kernel patches
+  - main 4.x kernel tree
+  - 4.x.y -stable kernel tree
+  - 4.x -git kernel patches
   - subsystem specific kernel trees and patches
-  - the 3.x -next kernel tree for integration tests
+  - the 4.x -next kernel tree for integration tests
 
-3.x kernel tree
+4.x kernel tree
 -----------------
-3.x kernels are maintained by Linus Torvalds, and can be found on
-kernel.org in the pub/linux/kernel/v3.x/ directory.  Its development
+4.x kernels are maintained by Linus Torvalds, and can be found on
+kernel.org in the pub/linux/kernel/v4.x/ directory.  Its development
 process is as follows:
   - As soon as a new kernel is released a two weeks window is open,
     during this period of time maintainers can submit big diffs to
@@ -262,20 +262,20 @@ mailing list about kernel releases:
        released according to perceived bug status, not according to a
        preconceived timeline."
 
-3.x.y -stable kernel tree
+4.x.y -stable kernel tree
 ---------------------------
 Kernels with 3-part versions are -stable kernels. They contain
 relatively small and critical fixes for security problems or significant
-regressions discovered in a given 3.x kernel.
+regressions discovered in a given 4.x kernel.
 
 This is the recommended branch for users who want the most recent stable
 kernel and are not interested in helping test development/experimental
 versions.
 
-If no 3.x.y kernel is available, then the highest numbered 3.x
+If no 4.x.y kernel is available, then the highest numbered 4.x
 kernel is the current stable kernel.
 
-3.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
+4.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
 are released as needs dictate.  The normal release period is approximately
 two weeks, but it can be longer if there are no pressing problems.  A
 security-related problem, instead, can cause a release to happen almost
@@ -285,7 +285,7 @@ The file Documentation/stable_kernel_rules.txt in the kernel tree
 documents what kinds of changes are acceptable for the -stable tree, and
 how the release process works.
 
-3.x -git patches
+4.x -git patches
 ------------------
 These are daily snapshots of Linus' kernel tree which are managed in a
 git repository (hence the name.) These patches are usually released
@@ -317,9 +317,9 @@ revisions to it, and maintainers can mark patches as under review,
 accepted, or rejected.  Most of these patchwork sites are listed at
 http://patchwork.kernel.org/.
 
-3.x -next kernel tree for integration tests
+4.x -next kernel tree for integration tests
 ---------------------------------------------
-Before updates from subsystem trees are merged into the mainline 3.x
+Before updates from subsystem trees are merged into the mainline 4.x
 tree, they need to be integration-tested.  For this purpose, a special
 testing repository exists into which virtually all subsystem trees are
 pulled on an almost daily basis:
index cf9431db873150d38a3d2477280d481ff42bfa83..7b57fc087088f49756eeb8eaabf403bfbbd92b93 100644 (file)
@@ -10,7 +10,7 @@ This guide gives a quick cheat sheet for some basic understanding.
 Some Keywords
 
 DMAR - DMA remapping
-DRHD - DMA Engine Reporting Structure
+DRHD - DMA Remapping Hardware Unit Definition
 RMRR - Reserved memory Region Reporting Structure
 ZLR  - Zero length reads from PCI devices
 IOVA - IO Virtual address.
index 27e7e5edeca8b3fc7d38d334393f0fa1a3288eee..fa596d8a3ab0ca689223f4d104024df2db9a4d37 100644 (file)
@@ -90,11 +90,11 @@ patch.
 
 Make sure your patch does not include any extra files which do not
 belong in a patch submission.  Make sure to review your patch -after-
-generated it with diff(1), to ensure accuracy.
+generating it with diff(1), to ensure accuracy.
 
 If your changes produce a lot of deltas, you need to split them into
 individual patches which modify things in logical stages; see section
-#3.  This will facilitate easier reviewing by other kernel developers,
+#3.  This will facilitate review by other kernel developers,
 very important if you want your patch accepted.
 
 If you're using git, "git rebase -i" can help you with this process.  If
@@ -267,7 +267,7 @@ You should always copy the appropriate subsystem maintainer(s) on any patch
 to code that they maintain; look through the MAINTAINERS file and the
 source code revision history to see who those maintainers are.  The
 script scripts/get_maintainer.pl can be very useful at this step.  If you
-cannot find a maintainer for the subsystem your are working on, Andrew
+cannot find a maintainer for the subsystem you are working on, Andrew
 Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
 
 You should also normally choose at least one mailing list to receive a copy
@@ -340,7 +340,7 @@ on the changes you are submitting.  It is important for a kernel
 developer to be able to "quote" your changes, using standard e-mail
 tools, so that they may comment on specific portions of your code.
 
-For this reason, all patches should be submitting e-mail "inline".
+For this reason, all patches should be submitted by e-mail "inline".
 WARNING:  Be wary of your editor's word-wrap corrupting your patch,
 if you choose to cut-n-paste your patch.
 
@@ -739,7 +739,7 @@ interest on a single line; it should look something like:
 
       git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
 
-  to get these changes:"
+  to get these changes:
 
 A pull request should also include an overall message saying what will be
 included in the request, a "git shortlog" listing of the patches
@@ -796,7 +796,7 @@ NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
   <https://lkml.org/lkml/2005/7/11/336>
 
 Kernel Documentation/CodingStyle:
-  <http://users.sosdg.org/~qiyong/lxr/source/Documentation/CodingStyle>
+  <Documentation/CodingStyle>
 
 Linus Torvalds's mail on the canonical patch format:
   <http://lkml.org/lkml/2005/4/7/183>
diff --git a/Documentation/adding-syscalls.txt b/Documentation/adding-syscalls.txt
new file mode 100644 (file)
index 0000000..cc2d4ac
--- /dev/null
@@ -0,0 +1,527 @@
+Adding a New System Call
+========================
+
+This document describes what's involved in adding a new system call to the
+Linux kernel, over and above the normal submission advice in
+Documentation/SubmittingPatches.
+
+
+System Call Alternatives
+------------------------
+
+The first thing to consider when adding a new system call is whether one of
+the alternatives might be suitable instead.  Although system calls are the
+most traditional and most obvious interaction points between userspace and the
+kernel, there are other possibilities -- choose what fits best for your
+interface.
+
+ - If the operations involved can be made to look like a filesystem-like
+   object, it may make more sense to create a new filesystem or device.  This
+   also makes it easier to encapsulate the new functionality in a kernel module
+   rather than requiring it to be built into the main kernel.
+     - If the new functionality involves operations where the kernel notifies
+       userspace that something has happened, then returning a new file
+       descriptor for the relevant object allows userspace to use
+       poll/select/epoll to receive that notification.
+     - However, operations that don't map to read(2)/write(2)-like operations
+       have to be implemented as ioctl(2) requests, which can lead to a
+       somewhat opaque API.
+ - If you're just exposing runtime system information, a new node in sysfs
+   (see Documentation/filesystems/sysfs.txt) or the /proc filesystem may be
+   more appropriate.  However, access to these mechanisms requires that the
+   relevant filesystem is mounted, which might not always be the case (e.g.
+   in a namespaced/sandboxed/chrooted environment).  Avoid adding any API to
+   debugfs, as this is not considered a 'production' interface to userspace.
+ - If the operation is specific to a particular file or file descriptor, then
+   an additional fcntl(2) command option may be more appropriate.  However,
+   fcntl(2) is a multiplexing system call that hides a lot of complexity, so
+   this option is best for when the new function is closely analogous to
+   existing fcntl(2) functionality, or the new functionality is very simple
+   (for example, getting/setting a simple flag related to a file descriptor).
+ - If the operation is specific to a particular task or process, then an
+   additional prctl(2) command option may be more appropriate.  As with
+   fcntl(2), this system call is a complicated multiplexor so is best reserved
+   for near-analogs of existing prctl() commands or getting/setting a simple
+   flag related to a process.
+
+
+Designing the API: Planning for Extension
+-----------------------------------------
+
+A new system call forms part of the API of the kernel, and has to be supported
+indefinitely.  As such, it's a very good idea to explicitly discuss the
+interface on the kernel mailing list, and it's important to plan for future
+extensions of the interface.
+
+(The syscall table is littered with historical examples where this wasn't done,
+together with the corresponding follow-up system calls -- eventfd/eventfd2,
+dup2/dup3, inotify_init/inotify_init1,  pipe/pipe2, renameat/renameat2 -- so
+learn from the history of the kernel and plan for extensions from the start.)
+
+For simpler system calls that only take a couple of arguments, the preferred
+way to allow for future extensibility is to include a flags argument to the
+system call.  To make sure that userspace programs can safely use flags
+between kernel versions, check whether the flags value holds any unknown
+flags, and reject the system call (with EINVAL) if it does:
+
+    if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
+        return -EINVAL;
+
+(If no flags values are used yet, check that the flags argument is zero.)
+
+For more sophisticated system calls that involve a larger number of arguments,
+it's preferred to encapsulate the majority of the arguments into a structure
+that is passed in by pointer.  Such a structure can cope with future extension
+by including a size argument in the structure:
+
+    struct xyzzy_params {
+        u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */
+        u32 param_1;
+        u64 param_2;
+        u64 param_3;
+    };
+
+As long as any subsequently added field, say param_4, is designed so that a
+zero value gives the previous behaviour, then this allows both directions of
+version mismatch:
+
+ - To cope with a later userspace program calling an older kernel, the kernel
+   code should check that any memory beyond the size of the structure that it
+   expects is zero (effectively checking that param_4 == 0).
+ - To cope with an older userspace program calling a newer kernel, the kernel
+   code can zero-extend a smaller instance of the structure (effectively
+   setting param_4 = 0).
+
+See perf_event_open(2) and the perf_copy_attr() function (in
+kernel/events/core.c) for an example of this approach.
+
+
+Designing the API: Other Considerations
+---------------------------------------
+
+If your new system call allows userspace to refer to a kernel object, it
+should use a file descriptor as the handle for that object -- don't invent a
+new type of userspace object handle when the kernel already has mechanisms and
+well-defined semantics for using file descriptors.
+
+If your new xyzzy(2) system call does return a new file descriptor, then the
+flags argument should include a value that is equivalent to setting O_CLOEXEC
+on the new FD.  This makes it possible for userspace to close the timing
+window between xyzzy() and calling fcntl(fd, F_SETFD, FD_CLOEXEC), where an
+unexpected fork() and execve() in another thread could leak a descriptor to
+the exec'ed program. (However, resist the temptation to re-use the actual value
+of the O_CLOEXEC constant, as it is architecture-specific and is part of a
+numbering space of O_* flags that is fairly full.)
+
+If your system call returns a new file descriptor, you should also consider
+what it means to use the poll(2) family of system calls on that file
+descriptor. Making a file descriptor ready for reading or writing is the
+normal way for the kernel to indicate to userspace that an event has
+occurred on the corresponding kernel object.
+
+If your new xyzzy(2) system call involves a filename argument:
+
+    int sys_xyzzy(const char __user *path, ..., unsigned int flags);
+
+you should also consider whether an xyzzyat(2) version is more appropriate:
+
+    int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
+
+This allows more flexibility for how userspace specifies the file in question;
+in particular it allows userspace to request the functionality for an
+already-opened file descriptor using the AT_EMPTY_PATH flag, effectively giving
+an fxyzzy(3) operation for free:
+
+ - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...)
+ - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...)
+
+(For more details on the rationale of the *at() calls, see the openat(2) man
+page; for an example of AT_EMPTY_PATH, see the statat(2) man page.)
+
+If your new xyzzy(2) system call involves a parameter describing an offset
+within a file, make its type loff_t so that 64-bit offsets can be supported
+even on 32-bit architectures.
+
+If your new xyzzy(2) system call involves privileged functionality, it needs
+to be governed by the appropriate Linux capability bit (checked with a call to
+capable()), as described in the capabilities(7) man page.  Choose an existing
+capability bit that governs related functionality, but try to avoid combining
+lots of only vaguely related functions together under the same bit, as this
+goes against capabilities' purpose of splitting the power of root.  In
+particular, avoid adding new uses of the already overly-general CAP_SYS_ADMIN
+capability.
+
+If your new xyzzy(2) system call manipulates a process other than the calling
+process, it should be restricted (using a call to ptrace_may_access()) so that
+only a calling process with the same permissions as the target process, or
+with the necessary capabilities, can manipulate the target process.
+
+Finally, be aware that some non-x86 architectures have an easier time if
+system call parameters that are explicitly 64-bit fall on odd-numbered
+arguments (i.e. parameter 1, 3, 5), to allow use of contiguous pairs of 32-bit
+registers.  (This concern does not apply if the arguments are part of a
+structure that's passed in by pointer.)
+
+
+Proposing the API
+-----------------
+
+To make new system calls easy to review, it's best to divide up the patchset
+into separate chunks.  These should include at least the following items as
+distinct commits (each of which is described further below):
+
+ - The core implementation of the system call, together with prototypes,
+   generic numbering, Kconfig changes and fallback stub implementation.
+ - Wiring up of the new system call for one particular architecture, usually
+   x86 (including all of x86_64, x86_32 and x32).
+ - A demonstration of the use of the new system call in userspace via a
+   selftest in tools/testing/selftests/.
+ - A draft man-page for the new system call, either as plain text in the
+   cover letter, or as a patch to the (separate) man-pages repository.
+
+New system call proposals, like any change to the kernel's API, should always
+be cc'ed to linux-api@vger.kernel.org.
+
+
+Generic System Call Implementation
+----------------------------------
+
+The main entry point for your new xyzzy(2) system call will be called
+sys_xyzzy(), but you add this entry point with the appropriate
+SYSCALL_DEFINEn() macro rather than explicitly.  The 'n' indicates the number
+of arguments to the system call, and the macro takes the system call name
+followed by the (type, name) pairs for the parameters as arguments.  Using
+this macro allows metadata about the new system call to be made available for
+other tools.
+
+The new entry point also needs a corresponding function prototype, in
+include/linux/syscalls.h, marked as asmlinkage to match the way that system
+calls are invoked:
+
+    asmlinkage long sys_xyzzy(...);
+
+Some architectures (e.g. x86) have their own architecture-specific syscall
+tables, but several other architectures share a generic syscall table. Add your
+new system call to the generic list by adding an entry to the list in
+include/uapi/asm-generic/unistd.h:
+
+    #define __NR_xyzzy 292
+    __SYSCALL(__NR_xyzzy, sys_xyzzy)
+
+Also update the __NR_syscalls count to reflect the additional system call, and
+note that if multiple new system calls are added in the same merge window,
+your new syscall number may get adjusted to resolve conflicts.
+
+The file kernel/sys_ni.c provides a fallback stub implementation of each system
+call, returning -ENOSYS.  Add your new system call here too:
+
+    cond_syscall(sys_xyzzy);
+
+Your new kernel functionality, and the system call that controls it, should
+normally be optional, so add a CONFIG option (typically to init/Kconfig) for
+it. As usual for new CONFIG options:
+
+ - Include a description of the new functionality and system call controlled
+   by the option.
+ - Make the option depend on EXPERT if it should be hidden from normal users.
+ - Make any new source files implementing the function dependent on the CONFIG
+   option in the Makefile (e.g. "obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.c").
+ - Double check that the kernel still builds with the new CONFIG option turned
+   off.
+
+To summarize, you need a commit that includes:
+
+ - CONFIG option for the new function, normally in init/Kconfig
+ - SYSCALL_DEFINEn(xyzzy, ...) for the entry point
+ - corresponding prototype in include/linux/syscalls.h
+ - generic table entry in include/uapi/asm-generic/unistd.h
+ - fallback stub in kernel/sys_ni.c
+
+
+x86 System Call Implementation
+------------------------------
+
+To wire up your new system call for x86 platforms, you need to update the
+master syscall tables.  Assuming your new system call isn't special in some
+way (see below), this involves a "common" entry (for x86_64 and x32) in
+arch/x86/entry/syscalls/syscall_64.tbl:
+
+    333   common   xyzzy     sys_xyzzy
+
+and an "i386" entry in arch/x86/entry/syscalls/syscall_32.tbl:
+
+    380   i386     xyzzy     sys_xyzzy
+
+Again, these numbers are liable to be changed if there are conflicts in the
+relevant merge window.
+
+
+Compatibility System Calls (Generic)
+------------------------------------
+
+For most system calls the same 64-bit implementation can be invoked even when
+the userspace program is itself 32-bit; even if the system call's parameters
+include an explicit pointer, this is handled transparently.
+
+However, there are a couple of situations where a compatibility layer is
+needed to cope with size differences between 32-bit and 64-bit.
+
+The first is if the 64-bit kernel also supports 32-bit userspace programs, and
+so needs to parse areas of (__user) memory that could hold either 32-bit or
+64-bit values.  In particular, this is needed whenever a system call argument
+is:
+
+ - a pointer to a pointer
+ - a pointer to a struct containing a pointer (e.g. struct iovec __user *)
+ - a pointer to a varying sized integral type (time_t, off_t, long, ...)
+ - a pointer to a struct containing a varying sized integral type.
+
+The second situation that requires a compatibility layer is if one of the
+system call's arguments has a type that is explicitly 64-bit even on a 32-bit
+architecture, for example loff_t or __u64.  In this case, a value that arrives
+at a 64-bit kernel from a 32-bit application will be split into two 32-bit
+values, which then need to be re-assembled in the compatibility layer.
+
+(Note that a system call argument that's a pointer to an explicit 64-bit type
+does *not* need a compatibility layer; for example, splice(2)'s arguments of
+type loff_t __user * do not trigger the need for a compat_ system call.)
+
+The compatibility version of the system call is called compat_sys_xyzzy(), and
+is added with the COMPAT_SYSCALL_DEFINEn() macro, analogously to
+SYSCALL_DEFINEn.  This version of the implementation runs as part of a 64-bit
+kernel, but expects to receive 32-bit parameter values and does whatever is
+needed to deal with them.  (Typically, the compat_sys_ version converts the
+values to 64-bit versions and either calls on to the sys_ version, or both of
+them call a common inner implementation function.)
+
+The compat entry point also needs a corresponding function prototype, in
+include/linux/compat.h, marked as asmlinkage to match the way that system
+calls are invoked:
+
+    asmlinkage long compat_sys_xyzzy(...);
+
+If the system call involves a structure that is laid out differently on 32-bit
+and 64-bit systems, say struct xyzzy_args, then the include/linux/compat.h
+header file should also include a compat version of the structure (struct
+compat_xyzzy_args) where each variable-size field has the appropriate compat_
+type that corresponds to the type in struct xyzzy_args.  The
+compat_sys_xyzzy() routine can then use this compat_ structure to parse the
+arguments from a 32-bit invocation.
+
+For example, if there are fields:
+
+    struct xyzzy_args {
+        const char __user *ptr;
+        __kernel_long_t varying_val;
+        u64 fixed_val;
+        /* ... */
+    };
+
+in struct xyzzy_args, then struct compat_xyzzy_args would have:
+
+    struct compat_xyzzy_args {
+        compat_uptr_t ptr;
+        compat_long_t varying_val;
+        u64 fixed_val;
+        /* ... */
+    };
+
+The generic system call list also needs adjusting to allow for the compat
+version; the entry in include/uapi/asm-generic/unistd.h should use
+__SC_COMP rather than __SYSCALL:
+
+    #define __NR_xyzzy 292
+    __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
+
+To summarize, you need:
+
+ - a COMPAT_SYSCALL_DEFINEn(xyzzy, ...) for the compat entry point
+ - corresponding prototype in include/linux/compat.h
+ - (if needed) 32-bit mapping struct in include/linux/compat.h
+ - instance of __SC_COMP not __SYSCALL in include/uapi/asm-generic/unistd.h
+
+
+Compatibility System Calls (x86)
+--------------------------------
+
+To wire up the x86 architecture of a system call with a compatibility version,
+the entries in the syscall tables need to be adjusted.
+
+First, the entry in arch/x86/entry/syscalls/syscall_32.tbl gets an extra
+column to indicate that a 32-bit userspace program running on a 64-bit kernel
+should hit the compat entry point:
+
+    380   i386     xyzzy     sys_xyzzy    compat_sys_xyzzy
+
+Second, you need to figure out what should happen for the x32 ABI version of
+the new system call.  There's a choice here: the layout of the arguments
+should either match the 64-bit version or the 32-bit version.
+
+If there's a pointer-to-a-pointer involved, the decision is easy: x32 is
+ILP32, so the layout should match the 32-bit version, and the entry in
+arch/x86/entry/syscalls/syscall_64.tbl is split so that x32 programs hit the
+compatibility wrapper:
+
+    333   64       xyzzy     sys_xyzzy
+    ...
+    555   x32      xyzzy     compat_sys_xyzzy
+
+If no pointers are involved, then it is preferable to re-use the 64-bit system
+call for the x32 ABI (and consequently the entry in
+arch/x86/entry/syscalls/syscall_64.tbl is unchanged).
+
+In either case, you should check that the types involved in your argument
+layout do indeed map exactly from x32 (-mx32) to either the 32-bit (-m32) or
+64-bit (-m64) equivalents.
+
+
+System Calls Returning Elsewhere
+--------------------------------
+
+For most system calls, once the system call is complete the user program
+continues exactly where it left off -- at the next instruction, with the
+stack the same and most of the registers the same as before the system call,
+and with the same virtual memory space.
+
+However, a few system calls do things differently.  They might return to a
+different location (rt_sigreturn) or change the memory space (fork/vfork/clone)
+or even architecture (execve/execveat) of the program.
+
+To allow for this, the kernel implementation of the system call may need to
+save and restore additional registers to the kernel stack, allowing complete
+control of where and how execution continues after the system call.
+
+This is arch-specific, but typically involves defining assembly entry points
+that save/restore additional registers and invoke the real system call entry
+point.
+
+For x86_64, this is implemented as a stub_xyzzy entry point in
+arch/x86/entry/entry_64.S, and the entry in the syscall table
+(arch/x86/entry/syscalls/syscall_64.tbl) is adjusted to match:
+
+    333   common   xyzzy     stub_xyzzy
+
+The equivalent for 32-bit programs running on a 64-bit kernel is normally
+called stub32_xyzzy and implemented in arch/x86/entry/entry_64_compat.S,
+with the corresponding syscall table adjustment in
+arch/x86/entry/syscalls/syscall_32.tbl:
+
+    380   i386     xyzzy     sys_xyzzy    stub32_xyzzy
+
+If the system call needs a compatibility layer (as in the previous section)
+then the stub32_ version needs to call on to the compat_sys_ version of the
+system call rather than the native 64-bit version.  Also, if the x32 ABI
+implementation is not common with the x86_64 version, then its syscall
+table will also need to invoke a stub that calls on to the compat_sys_
+version.
+
+For completeness, it's also nice to set up a mapping so that user-mode Linux
+still works -- its syscall table will reference stub_xyzzy, but the UML build
+doesn't include arch/x86/entry/entry_64.S implementation (because UML
+simulates registers etc).  Fixing this is as simple as adding a #define to
+arch/x86/um/sys_call_table_64.c:
+
+    #define stub_xyzzy sys_xyzzy
+
+
+Other Details
+-------------
+
+Most of the kernel treats system calls in a generic way, but there is the
+occasional exception that may need updating for your particular system call.
+
+The audit subsystem is one such special case; it includes (arch-specific)
+functions that classify some special types of system call -- specifically
+file open (open/openat), program execution (execve/exeveat) or socket
+multiplexor (socketcall) operations. If your new system call is analogous to
+one of these, then the audit system should be updated.
+
+More generally, if there is an existing system call that is analogous to your
+new system call, it's worth doing a kernel-wide grep for the existing system
+call to check there are no other special cases.
+
+
+Testing
+-------
+
+A new system call should obviously be tested; it is also useful to provide
+reviewers with a demonstration of how user space programs will use the system
+call.  A good way to combine these aims is to include a simple self-test
+program in a new directory under tools/testing/selftests/.
+
+For a new system call, there will obviously be no libc wrapper function and so
+the test will need to invoke it using syscall(); also, if the system call
+involves a new userspace-visible structure, the corresponding header will need
+to be installed to compile the test.
+
+Make sure the selftest runs successfully on all supported architectures.  For
+example, check that it works when compiled as an x86_64 (-m64), x86_32 (-m32)
+and x32 (-mx32) ABI program.
+
+For more extensive and thorough testing of new functionality, you should also
+consider adding tests to the Linux Test Project, or to the xfstests project
+for filesystem-related changes.
+ - https://linux-test-project.github.io/
+ - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git
+
+
+Man Page
+--------
+
+All new system calls should come with a complete man page, ideally using groff
+markup, but plain text will do.  If groff is used, it's helpful to include a
+pre-rendered ASCII version of the man page in the cover email for the
+patchset, for the convenience of reviewers.
+
+The man page should be cc'ed to linux-man@vger.kernel.org
+For more details, see https://www.kernel.org/doc/man-pages/patches.html
+
+References and Sources
+----------------------
+
+ - LWN article from Michael Kerrisk on use of flags argument in system calls:
+   https://lwn.net/Articles/585415/
+ - LWN article from Michael Kerrisk on how to handle unknown flags in a system
+   call: https://lwn.net/Articles/588444/
+ - LWN article from Jake Edge describing constraints on 64-bit system call
+   arguments: https://lwn.net/Articles/311630/
+ - Pair of LWN articles from David Drysdale that describe the system call
+   implementation paths in detail for v3.14:
+    - https://lwn.net/Articles/604287/
+    - https://lwn.net/Articles/604515/
+ - Architecture-specific requirements for system calls are discussed in the
+   syscall(2) man-page:
+   http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
+ - Collated emails from Linus Torvalds discussing the problems with ioctl():
+   http://yarchive.net/comp/linux/ioctl.html
+ - "How to not invent kernel interfaces", Arnd Bergmann,
+   http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
+ - LWN article from Michael Kerrisk on avoiding new uses of CAP_SYS_ADMIN:
+   https://lwn.net/Articles/486306/
+ - Recommendation from Andrew Morton that all related information for a new
+   system call should come in the same email thread:
+   https://lkml.org/lkml/2014/7/24/641
+ - Recommendation from Michael Kerrisk that a new system call should come with
+   a man page: https://lkml.org/lkml/2014/6/13/309
+ - Suggestion from Thomas Gleixner that x86 wire-up should be in a separate
+   commit: https://lkml.org/lkml/2014/11/19/254
+ - Suggestion from Greg Kroah-Hartman that it's good for new system calls to
+   come with a man-page & selftest: https://lkml.org/lkml/2014/3/19/710
+ - Discussion from Michael Kerrisk of new system call vs. prctl(2) extension:
+   https://lkml.org/lkml/2014/6/3/411
+ - Suggestion from Ingo Molnar that system calls that involve multiple
+   arguments should encapsulate those arguments in a struct, which includes a
+   size field for future extensibility: https://lkml.org/lkml/2015/7/30/117
+ - Numbering oddities arising from (re-)use of O_* numbering space flags:
+    - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
+      check")
+    - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
+      conflict")
+    - commit bb458c644a59 ("Safer ABI for O_TMPFILE")
+ - Discussion from Matthew Wilcox about restrictions on 64-bit arguments:
+   https://lkml.org/lkml/2008/12/12/187
+ - Recommendation from Greg Kroah-Hartman that unknown flags should be
+   policed: https://lkml.org/lkml/2014/7/17/577
+ - Recommendation from Linus Torvalds that x32 system calls should prefer
+   compatibility with 64-bit versions rather than 32-bit versions:
+   https://lkml.org/lkml/2011/8/31/244
index b96ead9a6919abeac69ab8dabc886120ccc83c3c..df8d4fb85939c82a712e74b6d3987e2598262468 100644 (file)
@@ -15,6 +15,7 @@ executing kernel.
 
 
 1. Non-Secure mode
+
 Address:      sysram_ns_base_addr
 Offset        Value                                        Purpose
 =============================================================================
@@ -28,6 +29,7 @@ Offset        Value                                        Purpose
 
 
 2. Secure mode
+
 Address:      sysram_base_addr
 Offset        Value                                        Purpose
 =============================================================================
@@ -40,14 +42,25 @@ Offset        Value                                        Purpose
 Address:      pmu_base_addr
 Offset        Value                                        Purpose
 =============================================================================
-0x0800        exynos_cpu_resume                            AFTR
+0x0800        exynos_cpu_resume                            AFTR, suspend
+0x0800        mcpm_entry_point (Exynos542x with MCPM)      AFTR, suspend
+0x0804        0xfcba0d10 (Magic cookie)                    AFTR
+0x0804        0x00000bad (Magic cookie)                    System suspend
 0x0814        exynos4_secondary_startup (Exynos4210 r1.1)  Secondary CPU boot
 0x0818        0xfcba0d10 (Magic cookie, Exynos4210 r1.1)   AFTR
 0x081C        exynos_cpu_resume (Exynos4210 r1.1)          AFTR
 
 
 3. Other (regardless of secure/non-secure mode)
+
 Address:      pmu_base_addr
 Offset        Value                           Purpose
 =============================================================================
 0x0908        Non-zero (only Exynos3250)      Secondary CPU boot up indicator
+
+
+4. Glossary
+
+AFTR - ARM Off Top Running, a low power mode, Cortex cores and many other
+modules are power gated, except the TOP modules
+MCPM - Multi-Cluster Power Management
diff --git a/Documentation/arm/keystone/Overview.txt b/Documentation/arm/keystone/Overview.txt
new file mode 100644 (file)
index 0000000..f17bc4c
--- /dev/null
@@ -0,0 +1,73 @@
+               TI Keystone Linux Overview
+               --------------------------
+
+Introduction
+------------
+Keystone range of SoCs are based on ARM Cortex-A15 MPCore Processors
+and c66x DSP cores. This document describes essential information required
+for users to run Linux on Keystone based EVMs from Texas Instruments.
+
+Following SoCs  & EVMs are currently supported:-
+
+------------ K2HK SoC and EVM --------------------------------------------------
+
+a.k.a Keystone 2 Hawking/Kepler SoC
+TCI6636K2H & TCI6636K2K: See documentation at
+       http://www.ti.com/product/tci6638k2k
+       http://www.ti.com/product/tci6638k2h
+
+EVM:
+http://www.advantech.com/Support/TI-EVM/EVMK2HX_sd.aspx
+
+------------ K2E SoC and EVM ---------------------------------------------------
+
+a.k.a Keystone 2 Edison SoC
+K2E  -  66AK2E05: See documentation at
+       http://www.ti.com/product/66AK2E05/technicaldocuments
+
+EVM:
+https://www.einfochips.com/index.php/partnerships/texas-instruments/k2e-evm.html
+
+------------ K2L SoC and EVM ---------------------------------------------------
+
+a.k.a Keystone 2 Lamarr SoC
+K2L  -  TCI6630K2L: See documentation at
+       http://www.ti.com/product/TCI6630K2L/technicaldocuments
+EVM:
+https://www.einfochips.com/index.php/partnerships/texas-instruments/k2l-evm.html
+
+Configuration
+-------------
+
+All of the K2 SoCs/EVMs share a common defconfig, keystone_defconfig and same
+image is used to boot on individual EVMs. The platform configuration is
+specified through DTS. Following are the DTS used:-
+       K2HK EVM : k2hk-evm.dts
+       K2E EVM  : k2e-evm.dts
+       K2L EVM  : k2l-evm.dts
+
+The device tree documentation for the keystone machines are located at
+        Documentation/devicetree/bindings/arm/keystone/keystone.txt
+
+Known issues & workaround
+-------------------------
+
+Some of the device drivers used on keystone are re-used from that from
+DaVinci and other TI SoCs. These device drivers may use clock APIs directly.
+Some of the keystone specific drivers such as netcp uses run time power
+management API instead to enable clock. As this API has limitations on
+keystone, following workaround is needed to boot Linux.
+
+   Add 'clk_ignore_unused' to the bootargs env variable in u-boot. Otherwise
+   clock frameworks will try to disable clocks that are unused and disable
+   the hardware. This is because netcp related power domain and clock
+   domains are enabled in u-boot as run time power management API currently
+   doesn't enable clocks for netcp due to a limitation. This workaround is
+   expected to be removed in the future when proper API support becomes
+   available. Until then, this work around is needed.
+
+
+Document Author
+---------------
+Murali Karicheri <m-karicheri2@ti.com>
+Copyright 2015 Texas Instruments
index f463bdc37f885c80d4614d6c9ab729c739e298d5..5c4bc4d01d0c32939af28b3c0044f1700231d4a1 100644 (file)
@@ -71,12 +71,8 @@ the operations defined in clk.h:
                long            (*round_rate)(struct clk_hw *hw,
                                                unsigned long rate,
                                                unsigned long *parent_rate);
-               long            (*determine_rate)(struct clk_hw *hw,
-                                               unsigned long rate,
-                                               unsigned long min_rate,
-                                               unsigned long max_rate,
-                                               unsigned long *best_parent_rate,
-                                               struct clk_hw **best_parent_clk);
+               int             (*determine_rate)(struct clk_hw *hw,
+                                                 struct clk_rate_request *req);
                int             (*set_parent)(struct clk_hw *hw, u8 index);
                u8              (*get_parent)(struct clk_hw *hw);
                int             (*set_rate)(struct clk_hw *hw,
index 424ac8cbfa08283712309e8cfca1fc822c98d3a0..dd998b9c04333a9e0ec714df73ac89e87e4ea3c4 100644 (file)
@@ -87,7 +87,7 @@ One interrupt per TC channel in a TC block:
 
 RSTC Reset Controller required properties:
 - compatible: Should be "atmel,<chip>-rstc".
-  <chip> can be "at91sam9260" or "at91sam9g45"
+  <chip> can be "at91sam9260" or "at91sam9g45" or "sama5d3"
 - reg: Should contain registers location and length
 
 Example:
index 65a6db2271a2276475db90f0d26f461d8d7e7b58..62938eb9697f120425a4a0b8c7183a32ce449b72 100644 (file)
@@ -17,6 +17,7 @@ its hardware characteristcs.
                - "arm,coresight-tmc", "arm,primecell";
                - "arm,coresight-funnel", "arm,primecell";
                - "arm,coresight-etm3x", "arm,primecell";
+               - "arm,coresight-etm4x", "arm,primecell";
                - "qcom,coresight-replicator1x", "arm,primecell";
 
        * reg: physical base address and length of the register
index d6b794cef0b8b9907ab5a055a6502180b4350148..91e6e5c478d006245c5a88e7ae7e304d6fa7f097 100644 (file)
@@ -199,6 +199,7 @@ nodes to be present and contain the properties described below.
                            "qcom,kpss-acc-v1"
                            "qcom,kpss-acc-v2"
                            "rockchip,rk3066-smp"
+                           "ste,dbx500-smp"
 
        - cpu-release-addr
                Usage: required for systems that have an "enable-method"
index c431c67524d610bed3103dcce5434aff78b78e91..c733e28e18e5896cb6fa5ba4ff988a82c225780c 100644 (file)
@@ -127,6 +127,24 @@ Example:
                #clock-cells = <1>;
        };
 
+
+Hisilicon Hi6220 SRAM controller
+
+Required properties:
+- compatible : "hisilicon,hi6220-sramctrl", "syscon"
+- reg : Register address and size
+
+Hisilicon's SoCs use sram for multiple purpose; on Hi6220 there have several
+SRAM banks for power management, modem, security, etc. Further, use "syscon"
+managing the common sram which can be shared by multiple modules.
+
+Example:
+       /*for Hi6220*/
+       sram: sram@fff80000 {
+               compatible = "hisilicon,hi6220-sramctrl", "syscon";
+               reg = <0x0 0xfff80000 0x0 0x12000>;
+       };
+
 -----------------------------------------------------------------------
 Hisilicon HiP01 system controller
 
diff --git a/Documentation/devicetree/bindings/arm/sp810.txt b/Documentation/devicetree/bindings/arm/sp810.txt
new file mode 100644 (file)
index 0000000..6808fb5
--- /dev/null
@@ -0,0 +1,46 @@
+SP810 System Controller
+-----------------------
+
+Required properties:
+
+- compatible:  standard compatible string for a Primecell peripheral,
+               see Documentation/devicetree/bindings/arm/primecell.txt
+               for more details
+               should be: "arm,sp810", "arm,primecell"
+
+- reg:         standard registers property, physical address and size
+               of the control registers
+
+- clock-names: from the common clock bindings, for more details see
+               Documentation/devicetree/bindings/clock/clock-bindings.txt;
+               should be: "refclk", "timclk", "apb_pclk"
+
+- clocks:      from the common clock bindings, phandle and clock
+               specifier pairs for the entries of clock-names property
+
+- #clock-cells: from the common clock bindings;
+               should be: <1>
+
+- clock-output-names: from the common clock bindings;
+               should be: "timerclken0", "timerclken1", "timerclken2", "timerclken3"
+
+- assigned-clocks: from the common clock binding;
+               should be: clock specifier for each output clock of this
+               provider node
+
+- assigned-clock-parents: from the common clock binding;
+               should be: phandle of input clock listed in clocks
+               property with the highest frequency
+
+Example:
+       v2m_sysctl: sysctl@020000 {
+               compatible = "arm,sp810", "arm,primecell";
+               reg = <0x020000 0x1000>;
+               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+               clock-names = "refclk", "timclk", "apb_pclk";
+               #clock-cells = <1>;
+               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+               assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
+               assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
+
+       };
diff --git a/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt b/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt
new file mode 100644 (file)
index 0000000..2be1e03
--- /dev/null
@@ -0,0 +1,19 @@
+Binding for simple gpio clock multiplexer.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "gpio-mux-clock".
+- clocks: list of two references to parent clocks.
+- #clock-cells : from common clock binding; shall be set to 0.
+- select-gpios : GPIO reference for selecting the parent clock.
+
+Example:
+       clock {
+               compatible = "gpio-mux-clock";
+               clocks = <&parentclk1>, <&parentclk2>;
+               #clock-cells = <0>;
+               select-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
+       };
index 259e30af959768cbbedaeca27648589a9746871d..e4d5feaebc292c7944f32fe5484c2839444f7658 100644 (file)
@@ -15,19 +15,36 @@ Required Properties:
        - "hisilicon,hi6220-sysctrl"
        - "hisilicon,hi6220-mediactrl"
        - "hisilicon,hi6220-pmctrl"
+       - "hisilicon,hi6220-stub-clk"
 
 - reg: physical base address of the controller and length of memory mapped
   region.
 
 - #clock-cells: should be 1.
 
-For example:
+Optional Properties:
+
+- hisilicon,hi6220-clk-sram: phandle to the syscon managing the SoC internal sram;
+  the driver need use the sram to pass parameters for frequency change.
+
+- mboxes: use the label reference for the mailbox as the first parameter, the
+  second parameter is the channel number.
+
+Example 1:
        sys_ctrl: sys_ctrl@f7030000 {
                compatible = "hisilicon,hi6220-sysctrl", "syscon";
                reg = <0x0 0xf7030000 0x0 0x2000>;
                #clock-cells = <1>;
        };
 
+Example 2:
+       stub_clock: stub_clock {
+               compatible = "hisilicon,hi6220-stub-clk";
+               hisilicon,hi6220-clk-sram = <&sram>;
+               #clock-cells = <1>;
+               mboxes = <&mailbox 1>;
+       };
+
 Each clock is assigned an identifier and client nodes use this identifier
 to specify the clock which they consume.
 
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
new file mode 100644 (file)
index 0000000..ee7e5fd
--- /dev/null
@@ -0,0 +1,79 @@
+NVIDIA Tegra124 DFLL FCPU clocksource
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The DFLL IP block on Tegra is a root clocksource designed for clocking
+the fast CPU cluster. It consists of a free-running voltage controlled
+oscillator connected to the CPU voltage rail (VDD_CPU), and a closed loop
+control module that will automatically adjust the VDD_CPU voltage by
+communicating with an off-chip PMIC either via an I2C bus or via PWM signals.
+Currently only the I2C mode is supported by these bindings.
+
+Required properties:
+- compatible : should be "nvidia,tegra124-dfll"
+- reg : Defines the following set of registers, in the order listed:
+        - registers for the DFLL control logic.
+        - registers for the I2C output logic.
+        - registers for the integrated I2C master controller.
+        - look-up table RAM for voltage register values.
+- interrupts: Should contain the DFLL block interrupt.
+- clocks: Must contain an entry for each entry in clock-names.
+  See clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - soc: Clock source for the DFLL control logic.
+  - ref: The closed loop reference clock
+  - i2c: Clock source for the integrated I2C master.
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - dvco: Reset control for the DFLL DVCO.
+- #clock-cells: Must be 0.
+- clock-output-names: Name of the clock output.
+- vdd-cpu-supply: Regulator for the CPU voltage rail that the DFLL
+  hardware will start controlling. The regulator will be queried for
+  the I2C register, control values and supported voltages.
+
+Required properties for the control loop parameters:
+- nvidia,sample-rate: Sample rate of the DFLL control loop.
+- nvidia,droop-ctrl: See the register CL_DVFS_DROOP_CTRL in the TRM.
+- nvidia,force-mode: See the field DFLL_PARAMS_FORCE_MODE in the TRM.
+- nvidia,cf: Numeric value, see the field DFLL_PARAMS_CF_PARAM in the TRM.
+- nvidia,ci: Numeric value, see the field DFLL_PARAMS_CI_PARAM in the TRM.
+- nvidia,cg: Numeric value, see the field DFLL_PARAMS_CG_PARAM in the TRM.
+
+Optional properties for the control loop parameters:
+- nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM.
+
+Required properties for I2C mode:
+- nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode.
+
+Example:
+
+clock@0,70110000 {
+        compatible = "nvidia,tegra124-dfll";
+        reg = <0 0x70110000 0 0x100>, /* DFLL control */
+              <0 0x70110000 0 0x100>, /* I2C output control */
+              <0 0x70110100 0 0x100>, /* Integrated I2C controller */
+              <0 0x70110200 0 0x100>; /* Look-up table RAM */
+        interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>,
+                 <&tegra_car TEGRA124_CLK_DFLL_REF>,
+                 <&tegra_car TEGRA124_CLK_I2C5>;
+        clock-names = "soc", "ref", "i2c";
+        resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
+        reset-names = "dvco";
+        #clock-cells = <0>;
+        clock-output-names = "dfllCPU_out";
+        vdd-cpu-supply = <&vdd_cpu>;
+        status = "okay";
+
+        nvidia,sample-rate = <12500>;
+        nvidia,droop-ctrl = <0x00000f00>;
+        nvidia,force-mode = <1>;
+        nvidia,cf = <10>;
+        nvidia,ci = <0>;
+        nvidia,cg = <2>;
+
+        nvidia,i2c-fs-rate = <400000>;
+};
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
new file mode 100644 (file)
index 0000000..7c8bbcf
--- /dev/null
@@ -0,0 +1,61 @@
+* Rockchip RK3368 Clock and Reset Unit
+
+The RK3368 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3368-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing, pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3368-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_gmac" - external GMAC clock - optional
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+ - "ext_vip" - external VIP clock - optional,
+ - "usbotg_out" - output clock of the pll in the otg phy
+
+Example: Clock controller node:
+
+       cru: clock-controller@ff760000 {
+               compatible = "rockchip,rk3368-cru";
+               reg = <0x0 0xff760000 0x0 0x1000>;
+               rockchip,grf = <&grf>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+       uart0: serial@10124000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x10124000 0x400>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <1>;
+               clocks = <&cru SCLK_UART0>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ux500.txt b/Documentation/devicetree/bindings/clock/ux500.txt
new file mode 100644 (file)
index 0000000..e52bd4b
--- /dev/null
@@ -0,0 +1,64 @@
+Clock bindings for ST-Ericsson Ux500 clocks
+
+Required properties :
+- compatible : shall contain only one of the following:
+  "stericsson,u8500-clks"
+  "stericsson,u8540-clks"
+  "stericsson,u9540-clks"
+- reg : shall contain base register location and length for
+  CLKRST1, 2, 3, 5, and 6 in an array. Note the absence of
+  CLKRST4, which does not exist.
+
+Required subnodes:
+- prcmu-clock: a subnode with one clock cell for PRCMU (power,
+  reset, control unit) clocks. The cell indicates which PRCMU
+  clock in the prcmu-clock node the consumer wants to use.
+- prcc-periph-clock: a subnode with two clock cells for
+  PRCC (programmable reset- and clock controller) peripheral clocks.
+  The first cell indicates which PRCC block the consumer
+  wants to use, possible values are 1, 2, 3, 5, 6. The second
+  cell indicates which clock inside the PRCC block it wants,
+  possible values are 0 thru 31.
+- prcc-kernel-clock: a subnode with two clock cells for
+  PRCC (programmable reset- and clock controller) kernel clocks
+  The first cell indicates which PRCC block the consumer
+  wants to use, possible values are 1, 2, 3, 5, 6. The second
+  cell indicates which clock inside the PRCC block it wants,
+  possible values are 0 thru 31.
+- rtc32k-clock: a subnode with zero clock cells for the 32kHz
+  RTC clock.
+- smp-twd-clock: a subnode for the ARM SMP Timer Watchdog cluster
+  with zero clock cells.
+
+Example:
+
+clocks {
+       compatible = "stericsson,u8500-clks";
+       /*
+        * Registers for the CLKRST block on peripheral
+        * groups 1, 2, 3, 5, 6,
+        */
+       reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
+           <0x8000f000 0x1000>, <0xa03ff000 0x1000>,
+           <0xa03cf000 0x1000>;
+
+       prcmu_clk: prcmu-clock {
+               #clock-cells = <1>;
+       };
+
+       prcc_pclk: prcc-periph-clock {
+               #clock-cells = <2>;
+       };
+
+       prcc_kclk: prcc-kernel-clock {
+               #clock-cells = <2>;
+       };
+
+       rtc_clk: rtc32k-clock {
+               #clock-cells = <0>;
+       };
+
+       smp_twd_clk: smp-twd-clock {
+               #clock-cells = <0>;
+       };
+};
index e4022776ac6e361c47a6564b4d03477835571d0d..100307304766e0e6c0e5205824e1b8e031fd2b6f 100644 (file)
@@ -106,6 +106,18 @@ PROPERTIES
           to the interrupt parent to which the child domain
           is being mapped.
 
+   - clocks
+      Usage: required if SEC 4.0 requires explicit enablement of clocks
+      Value type: <prop_encoded-array>
+      Definition:  A list of phandle and clock specifier pairs describing
+          the clocks required for enabling and disabling SEC 4.0.
+
+   - clock-names
+      Usage: required if SEC 4.0 requires explicit enablement of clocks
+      Value type: <string>
+      Definition: A list of clock name strings in the same order as the
+          clocks property.
+
    Note: All other standard properties (see the ePAPR) are allowed
    but are optional.
 
@@ -120,6 +132,11 @@ EXAMPLE
                ranges = <0 0x300000 0x10000>;
                interrupt-parent = <&mpic>;
                interrupts = <92 2>;
+               clocks = <&clks IMX6QDL_CLK_CAAM_MEM>,
+                        <&clks IMX6QDL_CLK_CAAM_ACLK>,
+                        <&clks IMX6QDL_CLK_CAAM_IPG>,
+                        <&clks IMX6QDL_CLK_EIM_SLOW>;
+               clock-names = "mem", "aclk", "ipg", "emi_slow";
        };
 
 =====================================================================
diff --git a/Documentation/devicetree/bindings/crypto/sun4i-ss.txt b/Documentation/devicetree/bindings/crypto/sun4i-ss.txt
new file mode 100644 (file)
index 0000000..5d38e9b
--- /dev/null
@@ -0,0 +1,23 @@
+* Allwinner Security System found on A20 SoC
+
+Required properties:
+- compatible : Should be "allwinner,sun4i-a10-crypto".
+- reg: Should contain the Security System register location and length.
+- interrupts: Should contain the IRQ line for the Security System.
+- clocks : List of clock specifiers, corresponding to ahb and ss.
+- clock-names : Name of the functional clock, should be
+       * "ahb" : AHB gating clock
+       * "mod" : SS controller clock
+
+Optional properties:
+ - resets : phandle + reset specifier pair
+ - reset-names : must contain "ahb"
+
+Example:
+       crypto: crypto-engine@01c15000 {
+               compatible = "allwinner,sun4i-a10-crypto";
+               reg = <0x01c15000 0x1000>;
+               interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&ahb_gates 5>, <&ss_clk>;
+               clock-names = "ahb", "mod";
+       };
index 45414bbcd9455b13620e9923f0dec048995c82cb..f61d5af44a27f20d21479c9920081906440674a3 100644 (file)
@@ -10,8 +10,11 @@ Required Properties:
 
 Optional Properties:
  - ti,wakeup : To enable the wakeup comparator in probe
- - ti,enable-id-detection: Perform ID detection.
+ - ti,enable-id-detection: Perform ID detection. If id-gpio is specified
+               it performs id-detection using GPIO else using OTG core.
  - ti,enable-vbus-detection: Perform VBUS detection.
+ - id-gpio: gpio for GPIO ID detection. See gpio binding.
+ - debounce-delay-ms: debounce delay for GPIO ID pin in milliseconds.
 
 palmas-usb {
        compatible = "ti,twl6035-usb", "ti,palmas-usb";
diff --git a/Documentation/devicetree/bindings/hwmon/lm70.txt b/Documentation/devicetree/bindings/hwmon/lm70.txt
new file mode 100644 (file)
index 0000000..e7fd921
--- /dev/null
@@ -0,0 +1,21 @@
+* LM70/TMP121/LM71/LM74 thermometer.
+
+Required properties:
+- compatible: one of
+               "ti,lm70"
+               "ti,tmp121"
+               "ti,lm71"
+               "ti,lm74"
+
+See Documentation/devicetree/bindings/spi/spi-bus.txt for more required and
+optional properties.
+
+Example:
+
+spi_master {
+       temperature-sensor@0 {
+               compatible = "ti,lm70";
+               reg = <0>;
+               spi-max-frequency = <1000000>;
+       };
+};
index ed2f09dc2483daece7a3962e51f5e4c9088820d6..a7afbf60bb9c0315126892663f5b3863dffe50de 100644 (file)
@@ -3,10 +3,16 @@ ltc2978
 Required properties:
 - compatible: should contain one of:
   * "lltc,ltc2974"
+  * "lltc,ltc2975"
   * "lltc,ltc2977"
   * "lltc,ltc2978"
+  * "lltc,ltc2980"
   * "lltc,ltc3880"
+  * "lltc,ltc3882"
   * "lltc,ltc3883"
+  * "lltc,ltc3886"
+  * "lltc,ltc3887"
+  * "lltc,ltm2987"
   * "lltc,ltm4676"
 - reg: I2C slave address
 
@@ -17,10 +23,10 @@ Optional properties:
   standard binding for regulators; see regulator.txt.
 
 Valid names of regulators depend on number of supplies supported per device:
-  * ltc2974 : vout0 - vout3
-  * ltc2977 : vout0 - vout7
+  * ltc2974, ltc2975 : vout0 - vout3
+  * ltc2977, ltc2980, ltm2987 : vout0 - vout7
   * ltc2978 : vout0 - vout7
-  * ltc3880 : vout0 - vout1
+  * ltc3880, ltc3882, ltc3886 : vout0 - vout1
   * ltc3883 : vout0
   * ltm4676 : vout0 - vout1
 
index b85184391b7839df4425a9888a3acc448a9c4d0a..2a1f3af30155d0f3a88d0c20ab4fc6711ded2ad1 100644 (file)
@@ -18,6 +18,7 @@ Required properties:
                                "mcp3202"
                                "mcp3204"
                                "mcp3208"
+                               "mcp3301"
 
 
 Examples:
index 3eb40e20c1433753c355efe147137b2748e60ac4..1aad0514e6474be4171e854ae5265d872cc7c89c 100644 (file)
@@ -17,6 +17,11 @@ Recommended properties:
   - Frequency in normal mode (ADLPC=0, ADHSC=0)
   - Frequency in high-speed mode (ADLPC=0, ADHSC=1)
   - Frequency in low-power mode (ADLPC=1, ADHSC=0)
+- min-sample-time: Minimum sampling time in nanoseconds. This value has
+  to be chosen according to the conversion mode and the connected analog
+  source resistance (R_as) and capacitance (C_as). Refer the datasheet's
+  operating requirements. A safe default across a wide range of R_as and
+  C_as as well as conversion modes is 1000ns.
 
 Example:
 adc0: adc@4003b000 {
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt b/Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt
new file mode 100644 (file)
index 0000000..a01235c
--- /dev/null
@@ -0,0 +1,13 @@
+* MEMSIC MMC35240 magnetometer sensor
+
+Required properties:
+
+  - compatible : should be "memsic,mmc35240"
+  - reg : the I2C address of the magnetometer
+
+Example:
+
+mmc35240@30 {
+        compatible = "memsic,mmc35240";
+        reg = <0x30>;
+};
index 8a6be3bdf2671e8b6f9edbfb9407cb3513e51659..d3ccdb190c53b581f347ef2eb8444fcb3ac84592 100644 (file)
@@ -35,6 +35,7 @@ Accelerometers:
 - st,lsm303dl-accel
 - st,lsm303dlm-accel
 - st,lsm330-accel
+- st,lsm303agr-accel
 
 Gyroscopes:
 - st,l3g4200d-gyro
@@ -46,6 +47,7 @@ Gyroscopes:
 - st,lsm330-gyro
 
 Magnetometers:
+- st,lsm303agr-magn
 - st,lsm303dlh-magn
 - st,lsm303dlhc-magn
 - st,lsm303dlm-magn
index 747c53805eecf8e12bff3c18992d0c2a3f48e83b..68419843e32fc83c28ba7ecb5b0a25c2f4c2efb4 100644 (file)
@@ -29,14 +29,23 @@ Optional properties for child nodes:
      "ide-disk" - LED indicates disk activity
      "timer" - LED flashes at a fixed, configurable rate
 
-- max-microamp : maximum intensity in microamperes of the LED
-                (torch LED for flash devices)
-- flash-max-microamp : maximum intensity in microamperes of the
-                       flash LED; it is mandatory if the LED should
-                      support the flash mode
-- flash-timeout-us : timeout in microseconds after which the flash
-                     LED is turned off
+- led-max-microamp : Maximum LED supply current in microamperes. This property
+                     can be made mandatory for the board configurations
+                     introducing a risk of hardware damage in case an excessive
+                     current is set.
+                     For flash LED controllers with configurable current this
+                     property is mandatory for the LEDs in the non-flash modes
+                     (e.g. torch or indicator).
 
+Required properties for flash LED child nodes:
+- flash-max-microamp : Maximum flash LED supply current in microamperes.
+- flash-max-timeout-us : Maximum timeout in microseconds after which the flash
+                         LED is turned off.
+
+For controllers that have no configurable current the flash-max-microamp
+property can be omitted.
+For controllers that have no configurable timeout the flash-max-timeout-us
+property can be omitted.
 
 Examples:
 
@@ -49,7 +58,7 @@ system-status {
 camera-flash {
        label = "Flash";
        led-sources = <0>, <1>;
-       max-microamp = <50000>;
+       led-max-microamp = <50000>;
        flash-max-microamp = <320000>;
-       flash-timeout-us = <500000>;
+       flash-max-timeout-us = <500000>;
 };
index aef3aca34d2d4272dbf49440bd32712a87e38c29..9f81258a5b6e9035835c0cb230559a5a6e7a68f0 100644 (file)
@@ -8,6 +8,9 @@ Each LED is represented as a sub-node of the ns2-leds device.
 Required sub-node properties:
 - cmd-gpio: Command LED GPIO. See OF device-tree GPIO specification.
 - slow-gpio: Slow LED GPIO. See OF device-tree GPIO specification.
+- modes-map: A mapping between LED modes (off, on or SATA activity blinking) and
+  the corresponding cmd-gpio/slow-gpio values. All the GPIO values combinations
+  should be given in order to avoid having an unknown mode at driver probe time.
 
 Optional sub-node properties:
 - label: Name for this LED. If omitted, the label is taken from the node name.
@@ -15,6 +18,8 @@ Optional sub-node properties:
 
 Example:
 
+#include <dt-bindings/leds/leds-ns2.h>
+
 ns2-leds {
        compatible = "lacie,ns2-leds";
 
@@ -22,5 +27,9 @@ ns2-leds {
                label = "ns2:blue:sata";
                slow-gpio = <&gpio0 29 0>;
                cmd-gpio = <&gpio0 30 0>;
+               modes-map = <NS_V2_LED_OFF  0 1
+                            NS_V2_LED_ON   1 0
+                            NS_V2_LED_ON   0 0
+                            NS_V2_LED_SATA 1 1>;
        };
 };
index 9e6e2592e5c88d0eace16144f9521a7b3e60dc9d..4ca6aab4273a1491b7f148cdccbe4ffd181a07b6 100644 (file)
@@ -24,6 +24,10 @@ Optional properties:
 - vcc10-supply: The input supply for LDO_REG6
 - vcc11-supply: The input supply for LDO_REG8
 - vcc12-supply: The input supply for SWITCH_REG2
+- dvs-gpios:  buck1/2 can be controlled by gpio dvs, this is GPIO specifiers
+  for 2 host gpio's used for dvs. The format of the gpio specifier depends in
+  the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
+  very quickly with no slow ramp time.
 
 Regulators: All the regulators of RK808 to be instantiated shall be
 listed in a child node named 'regulators'. Each regulator is represented
@@ -55,7 +59,9 @@ Example:
                interrupt-parent = <&gpio0>;
                interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
                pinctrl-names = "default";
-               pinctrl-0 = <&pmic_int>;
+               pinctrl-0 = <&pmic_int &dvs_1 &dvs_2>;
+               dvs-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>,
+                           <&gpio7 15 GPIO_ACTIVE_HIGH>;
                reg = <0x1b>;
                rockchip,system-power-controller;
                wakeup-source;
similarity index 78%
rename from Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
rename to Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
index fabdf64a5737cc637b59f5612df2f82310619e3a..d543ed3f5363251d0c22b5ddac8a5b078605de93 100644 (file)
@@ -4,6 +4,10 @@ Required properties:
 - compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
 - reg: Should contain registers location and length
 
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
 Example for sun4i:
        sid@01c23800 {
                compatible = "allwinner,sun4i-a10-sid";
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt
new file mode 100644 (file)
index 0000000..b52bc11
--- /dev/null
@@ -0,0 +1,80 @@
+= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
+
+This binding is intended to represent the location of hardware
+configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+On a significant proportion of boards, the manufacturer has stored
+some data on NVMEM, for the OS to be able to retrieve these information
+and act upon it. Obviously, the OS has to know about where to retrieve
+these data from, and where they are stored on the storage device.
+
+This document is here to document this.
+
+= Data providers =
+Contains bindings specific to provider drivers and data cells as children
+of this node.
+
+Optional properties:
+ read-only: Mark the provider as read only.
+
+= Data cells =
+These are the child nodes of the provider which contain data cell
+information like offset and size in nvmem provider.
+
+Required properties:
+reg:   specifies the offset in byte within the storage device.
+
+Optional properties:
+
+bits:  Is pair of bit location and number of bits, which specifies offset
+       in bit and number of bits within the address range specified by reg property.
+       Offset takes values from 0-7.
+
+For example:
+
+       /* Provider */
+       qfprom: qfprom@00700000 {
+               ...
+
+               /* Data cells */
+               tsens_calibration: calib@404 {
+                       reg = <0x404 0x10>;
+               };
+
+               tsens_calibration_bckp: calib_bckp@504 {
+                       reg = <0x504 0x11>;
+                       bits = <6 128>
+               };
+
+               pvs_version: pvs-version@6 {
+                       reg = <0x6 0x2>
+                       bits = <7 2>
+               };
+
+               speed_bin: speed-bin@c{
+                       reg = <0xc 0x1>;
+                       bits = <2 3>;
+
+               };
+               ...
+       };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells/providers.
+
+Required-properties:
+nvmem-cells: list of phandle to the nvmem data cells.
+nvmem-cell-names: names for the each nvmem-cells specified. Required if
+       nvmem-cells is used.
+
+Optional-properties:
+nvmem  : list of phandles to nvmem providers.
+nvmem-names: names for the each nvmem provider. required if nvmem is used.
+
+For example:
+
+       tsens {
+               ...
+               nvmem-cells = <&tsens_calibration>;
+               nvmem-cell-names = "calibration";
+       };
diff --git a/Documentation/devicetree/bindings/nvmem/qfprom.txt b/Documentation/devicetree/bindings/nvmem/qfprom.txt
new file mode 100644 (file)
index 0000000..4ad68b7
--- /dev/null
@@ -0,0 +1,35 @@
+= Qualcomm QFPROM device tree bindings =
+
+This binding is intended to represent QFPROM which is found in most QCOM SOCs.
+
+Required properties:
+- compatible: should be "qcom,qfprom"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+       qfprom: qfprom@00700000 {
+               compatible      = "qcom,qfprom";
+               reg             = <0x00700000 0x8000>;
+               ...
+               /* Data cells */
+               tsens_calibration: calib@404 {
+                       reg = <0x4404 0x10>;
+               };
+       };
+
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+       tsens {
+               ...
+               nvmem-cells = <&tsens_calibration>;
+               nvmem-cell-names = "calibration";
+       };
index 3d217911b3133ef35e762e6abc45e1180b7656e0..60e25161f35181bfd026b48519f43666d33f091e 100644 (file)
@@ -23,6 +23,9 @@ PCIe Designware Controller
    interrupt-map-mask,
    interrupt-map : as specified in ../designware-pcie.txt
 
+Optional Property:
+ - gpios : Should be added if a gpio line is required to drive PERST# line
+
 Example:
 axi {
        compatible = "simple-bus";
diff --git a/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt b/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt
new file mode 100644 (file)
index 0000000..bd61b46
--- /dev/null
@@ -0,0 +1,26 @@
+NXP LPC18xx/43xx internal USB OTG PHY binding
+---------------------------------------------
+
+This file contains documentation for the internal USB OTG PHY found
+in NXP LPC18xx and LPC43xx SoCs.
+
+Required properties:
+- compatible   : must be "nxp,lpc1850-usb-otg-phy"
+- clocks       : must be exactly one entry
+See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- #phy-cells   : must be 0 for this phy
+See: Documentation/devicetree/bindings/phy/phy-bindings.txt
+
+The phy node must be a child of the creg syscon node.
+
+Example:
+creg: syscon@40043000 {
+       compatible = "nxp,lpc1850-creg", "syscon", "simple-mfd";
+       reg = <0x40043000 0x1000>;
+
+       usb0_otg_phy: phy@004 {
+               compatible = "nxp,lpc1850-usb-otg-phy";
+               clocks = <&ccu1 CLK_USB0>;
+               #phy-cells = <0>;
+       };
+};
index 16528b9eb561eca291ed8ee9f32017ff162f2fb4..0cebf745451760d103097ee73e5160b285610d81 100644 (file)
@@ -7,6 +7,8 @@ Required properties:
   * allwinner,sun5i-a13-usb-phy
   * allwinner,sun6i-a31-usb-phy
   * allwinner,sun7i-a20-usb-phy
+  * allwinner,sun8i-a23-usb-phy
+  * allwinner,sun8i-a33-usb-phy
 - reg : a list of offset + length pairs
 - reg-names :
   * "phy_ctrl"
@@ -17,12 +19,21 @@ Required properties:
 - clock-names :
   * "usb_phy" for sun4i, sun5i or sun7i
   * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
+  * "usb0_phy", "usb1_phy" for sun8i
 - resets : a list of phandle + reset specifier pairs
 - reset-names :
   * "usb0_reset"
   * "usb1_reset"
   * "usb2_reset" for sun4i, sun6i or sun7i
 
+Optional properties:
+- usb0_id_det-gpios : gpio phandle for reading the otg id pin value
+- usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus
+- usb0_vbus_power-supply: power-supply phandle for usb0 vbus presence detect
+- usb0_vbus-supply : regulator phandle for controller usb0 vbus
+- usb1_vbus-supply : regulator phandle for controller usb1 vbus
+- usb2_vbus-supply : regulator phandle for controller usb2 vbus
+
 Example:
        usbphy: phy@0x01c13400 {
                #phy-cells = <1>;
@@ -32,6 +43,13 @@ Example:
                reg-names = "phy_ctrl", "pmu1", "pmu2";
                clocks = <&usb_clk 8>;
                clock-names = "usb_phy";
-               resets = <&usb_clk 1>, <&usb_clk 2>;
-               reset-names = "usb1_reset", "usb2_reset";
+               resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>;
+               reset-names = "usb0_reset", "usb1_reset", "usb2_reset";
+               pinctrl-names = "default";
+               pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+               usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */
+               usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */
+               usb0_vbus-supply = <&reg_usb0_vbus>;
+               usb1_vbus-supply = <&reg_usb1_vbus>;
+               usb2_vbus-supply = <&reg_usb2_vbus>;
        };
diff --git a/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt b/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt
new file mode 100644 (file)
index 0000000..0e6d875
--- /dev/null
@@ -0,0 +1,48 @@
+Qualcomm Coincell Charger:
+
+The hardware block controls charging for a coincell or capacitor that is
+used to provide power backup for certain features of the power management
+IC (PMIC)
+
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: must be: "qcom,pm8941-coincell"
+
+- reg:
+       Usage: required
+       Value type: <u32>
+       Definition: base address of the coincell charger registers
+
+- qcom,rset-ohms:
+       Usage: required
+       Value type: <u32>
+       Definition: resistance (in ohms) for current-limiting resistor
+               must be one of: 800, 1200, 1700, 2100
+
+- qcom,vset-millivolts:
+       Usage: required
+       Value type: <u32>
+       Definition: voltage (in millivolts) to apply for charging
+               must be one of: 2500, 3000, 3100, 3200
+
+- qcom,charger-disable:
+       Usage: optional
+       Value type: <boolean>
+       Definition: definining this property disables charging
+
+This charger is a sub-node of one of the 8941 PMIC blocks, and is specified
+as a child node in DTS of that node.  See ../mfd/qcom,spmi-pmic.txt and
+../mfd/qcom-pm8xxx.txt
+
+Example:
+
+       pm8941@0 {
+               coincell@2800 {
+                       compatible = "qcom,pm8941-coincell";
+                       reg = <0x2800>;
+
+                       qcom,rset-ohms = <2100>;
+                       qcom,vset-millivolts = <3000>;
+               };
+       };
index 8832e8798912b5047f6a4250417b5923cbaf2a07..647817527c88f682b8ec939514334074f097b172 100644 (file)
@@ -6,14 +6,14 @@ PSC in UART mode
 For PSC in UART mode the needed PSC serial devices
 are specified by fsl,mpc5121-psc-uart nodes in the
 fsl,mpc5121-immr SoC node. Additionally the PSC FIFO
-Controller node fsl,mpc5121-psc-fifo is requered there:
+Controller node fsl,mpc5121-psc-fifo is required there:
 
-fsl,mpc5121-psc-uart nodes
+fsl,mpc512x-psc-uart nodes
 --------------------------
 
 Required properties :
- - compatible : Should contain "fsl,mpc5121-psc-uart" and "fsl,mpc5121-psc"
- - cell-index : Index of the PSC in hardware
+ - compatible : Should contain "fsl,<soc>-psc-uart" and "fsl,<soc>-psc"
+   Supported <soc>s: mpc5121, mpc5125
  - reg : Offset and length of the register set for the PSC device
  - interrupts : <a b> where a is the interrupt number of the
    PSC FIFO Controller and b is a field that represents an
@@ -25,12 +25,21 @@ Recommended properties :
  - fsl,rx-fifo-size : the size of the RX fifo slice (a multiple of 4)
  - fsl,tx-fifo-size : the size of the TX fifo slice (a multiple of 4)
 
+PSC in SPI mode
+---------------
 
-fsl,mpc5121-psc-fifo node
+Similar to the UART mode a PSC can be operated in SPI mode. The compatible used
+for that is fsl,mpc5121-psc-spi. It requires a fsl,mpc5121-psc-fifo as well.
+The required and recommended properties are identical to the
+fsl,mpc5121-psc-uart nodes, just use spi instead of uart in the compatible
+string.
+
+fsl,mpc512x-psc-fifo node
 -------------------------
 
 Required properties :
- - compatible : Should be "fsl,mpc5121-psc-fifo"
+ - compatible : Should be "fsl,<soc>-psc-fifo"
+   Supported <soc>s: mpc5121, mpc5125
  - reg : Offset and length of the register set for the PSC
          FIFO Controller
  - interrupts : <a b> where a is the interrupt number of the
@@ -39,6 +48,9 @@ Required properties :
  - interrupt-parent : the phandle for the interrupt controller that
    services interrupts for this device.
 
+Recommended properties :
+ - clocks : specifies the clock needed to operate the fifo controller
+ - clock-names : name(s) for the clock(s) listed in clocks
 
 Example for a board using PSC0 and PSC1 devices in serial mode:
 
index 3297c53cb9152395c310693034e33dc3ee26f95e..7aa9b1fa6b21ca18edfd6ad42ea49cad486ffa92 100644 (file)
@@ -5,6 +5,10 @@ Required properties:
 - compatible:  must be "dlg,da9210"
 - reg:         the i2c slave address of the regulator. It should be 0x68.
 
+Optional properties:
+
+- interrupts:  a reference to the DA9210 interrupt, if available.
+
 Any standard regulator properties can be used to configure the single da9210
 DCDC.
 
index eb618907c7dee35446ae8b2153cf566e91cdb689..c620493e8dbe4cfa150a8ad787705cce8fce00d5 100644 (file)
@@ -1,7 +1,7 @@
-* Dialog Semiconductor DA9211/DA9213 Voltage Regulator
+* Dialog Semiconductor DA9211/DA9213/DA9215 Voltage Regulator
 
 Required properties:
-- compatible: "dlg,da9211" or "dlg,da9213".
+- compatible: "dlg,da9211" or "dlg,da9213" or "dlg,da9215"
 - reg: I2C slave address, usually 0x68.
 - interrupts: the interrupt outputs of the controller
 - regulators: A node that houses a sub-node for each regulator within the
@@ -66,3 +66,31 @@ Example 2) DA9213
                        };
                };
        };
+
+
+Example 3) DA9215
+       pmic: da9215@68 {
+               compatible = "dlg,da9215";
+               reg = <0x68>;
+               interrupts = <3 27>;
+
+               regulators {
+                       BUCKA {
+                               regulator-name = "VBUCKA";
+                               regulator-min-microvolt = < 300000>;
+                               regulator-max-microvolt = <1570000>;
+                               regulator-min-microamp  = <4000000>;
+                               regulator-max-microamp  = <7000000>;
+                               enable-gpios = <&gpio 27 0>;
+                       };
+                       BUCKB {
+                               regulator-name = "VBUCKB";
+                               regulator-min-microvolt = < 300000>;
+                               regulator-max-microvolt = <1570000>;
+                               regulator-min-microamp  = <4000000>;
+                               regulator-max-microamp  = <7000000>;
+                               enable-gpios = <&gpio 17 0>;
+                       };
+               };
+       };
+
index 55efb24e5683c429776308e364c996b500f92134..f80ea2fe27e693edfaa387f9dda0ae9c8e32d669 100644 (file)
@@ -25,6 +25,12 @@ Optional properties:
 -maxim,enable-frequency-shift: boolean, enable 9% frequency shift.
 -maxim,enable-bias-control: boolean, enable bias control. By enabling this
                startup delay can be reduce to 20us from 220us.
+-maxim,enable-etr: boolean, enable Enhanced Transient Response.
+-maxim,enable-high-etr-sensitivity: boolean, Enhanced transient response
+               circuit is enabled and set for high sensitivity. If this
+               property is available then etr will be enable default.
+
+Enhanced transient response (ETR) will affect the configuration of CKADV.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/regulator/mt6311-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6311-regulator.txt
new file mode 100644 (file)
index 0000000..02649d8
--- /dev/null
@@ -0,0 +1,35 @@
+Mediatek MT6311 Regulator Driver
+
+Required properties:
+- compatible: "mediatek,mt6311-regulator"
+- reg: I2C slave address, usually 0x6b.
+- regulators: List of regulators provided by this controller. It is named
+  to VDVFS and VBIASN.
+  The definition for each of these nodes is defined using the standard binding
+  for regulators at Documentation/devicetree/bindings/regulator/regulator.txt.
+
+The valid names for regulators are:
+BUCK:
+  VDVFS
+LDO:
+  VBIASN
+
+Example:
+       mt6311: pmic@6b {
+               compatible = "mediatek,mt6311-regulator";
+               reg = <0x6b>;
+
+               regulators {
+                       mt6311_vcpu_reg: VDVFS {
+                               regulator-name = "VDVFS";
+                               regulator-min-microvolt = < 600000>;
+                               regulator-max-microvolt = <1400000>;
+                               regulator-ramp-delay = <10000>;
+                       };
+                       mt6311_ldo_reg: VBIASN {
+                               regulator-name = "VBIASN";
+                               regulator-min-microvolt = <200000>;
+                               regulator-max-microvolt = <800000>;
+                       };
+               };
+       };
index ce91f61feb12554e0d62d84ebe93d13e9e6fbf59..ed936f0f34f28446e5151e238b7bf31161658b0c 100644 (file)
@@ -1,27 +1,68 @@
-pwm regulator bindings
+Bindings for the Generic PWM Regulator
+======================================
+
+Currently supports 2 modes of operation:
+
+Voltage Table:         When in this mode, a voltage table (See below) of
+                       predefined voltage <=> duty-cycle values must be
+                       provided via DT. Limitations are that the regulator can
+                       only operate at the voltages supplied in the table.
+                       Intermediary duty-cycle values which would normally
+                       allow finer grained voltage selection are ignored and
+                       rendered useless.  Although more control is given to
+                       the user if the assumptions made in continuous-voltage
+                       mode do not reign true.
+
+Continuous Voltage:    This mode uses the regulator's maximum and minimum
+                       supplied voltages specified in the
+                       regulator-{min,max}-microvolt properties to calculate
+                       appropriate duty-cycle values.  This allows for a much
+                       more fine grained solution when compared with
+                       voltage-table mode above.  This solution does make an
+                       assumption that a %50 duty-cycle value will cause the
+                       regulator voltage to run at half way between the
+                       supplied max_uV and min_uV values.
 
 Required properties:
-- compatible: Should be "pwm-regulator"
-- pwms: OF device-tree PWM specification (see PWM binding pwm.txt)
-- voltage-table: voltage and duty table, include 2 members in each set of
-  brackets, first one is voltage(unit: uv), the next is duty(unit: percent)
+--------------------
+- compatible:          Should be "pwm-regulator"
+
+- pwms:                        PWM specification (See: ../pwm/pwm.txt)
+
+Only required for Voltage Table Mode:
+- voltage-table:       Voltage and Duty-Cycle table consisting of 2 cells
+                           First cell is voltage in microvolts (uV)
+                           Second cell is duty-cycle in percent (%)
+
+NB: To be clear, if voltage-table is provided, then the device will be used
+in Voltage Table Mode.  If no voltage-table is provided, then the device will
+be used in Continuous Voltage Mode.
 
-Any property defined as part of the core regulator binding defined in
-regulator.txt can also be used.
+Any property defined as part of the core regulator binding can also be used.
+(See: ../regulator/regulator.txt)
 
-Example:
+Continuous Voltage Example:
        pwm_regulator {
                compatible = "pwm-regulator;
                pwms = <&pwm1 0 8448 0>;
+               regulator-min-microvolt = <1016000>;
+               regulator-max-microvolt = <1114000>;
+               regulator-name = "vdd_logic";
+       };
 
+Voltage Table Example:
+       pwm_regulator {
+               compatible = "pwm-regulator;
+               pwms = <&pwm1 0 8448 0>;
+               regulator-min-microvolt = <1016000>;
+               regulator-max-microvolt = <1114000>;
+               regulator-name = "vdd_logic";
+
+                             /* Voltage Duty-Cycle */
                voltage-table = <1114000 0>,
                                <1095000 10>,
                                <1076000 20>,
                                <1056000 30>,
                                <1036000 40>,
                                <1016000 50>;
-
-               regulator-min-microvolt = <1016000>;
-               regulator-max-microvolt = <1114000>;
-               regulator-name = "vdd_logic";
        };
index 75b4604bad07c047dc817ef19305b1e5c68d7be1..d00bfd8624a500eb797aac8273f8fc5f1df3c785 100644 (file)
@@ -91,13 +91,65 @@ see regulator.txt - with additional custom properties described below:
 - regulator-initial-mode:
        Usage: optional
        Value type: <u32>
-       Descrption: 1 = Set initial mode to high power mode (HPM), also referred
-                   to as NPM.  HPM consumes more ground current than LPM, but
+       Description: 2 = Set initial mode to auto mode (automatically select
+                   between HPM and LPM); not available on boost type
+                   regulators.
+
+                   1 = Set initial mode to high power mode (HPM), also referred
+                   to as NPM. HPM consumes more ground current than LPM, but
                    it can source significantly higher load current. HPM is not
                    available on boost type regulators. For voltage switch type
                    regulators, HPM implies that over current protection and
-                   soft start are active all the time. 0 = Set initial mode to
-                   low power mode (LPM).
+                   soft start are active all the time.
+
+                   0 = Set initial mode to low power mode (LPM).
+
+- qcom,ocp-max-retries:
+       Usage: optional
+       Value type: <u32>
+       Description: Maximum number of times to try toggling a voltage switch
+                    off and back on as a result of consecutive over current
+                    events.
+
+- qcom,ocp-retry-delay:
+       Usage: optional
+       Value type: <u32>
+       Description: Time to delay in milliseconds between each voltage switch
+                    toggle after an over current event takes place.
+
+- qcom,pin-ctrl-enable:
+       Usage: optional
+       Value type: <u32>
+       Description: Bit mask specifying which hardware pins should be used to
+                    enable the regulator, if any; supported bits are:
+                       0 = ignore all hardware enable signals
+                       BIT(0) = follow HW0_EN signal
+                       BIT(1) = follow HW1_EN signal
+                       BIT(2) = follow HW2_EN signal
+                       BIT(3) = follow HW3_EN signal
+
+- qcom,pin-ctrl-hpm:
+       Usage: optional
+       Value type: <u32>
+       Description: Bit mask specifying which hardware pins should be used to
+                    force the regulator into high power mode, if any;
+                    supported bits are:
+                       0 = ignore all hardware enable signals
+                       BIT(0) = follow HW0_EN signal
+                       BIT(1) = follow HW1_EN signal
+                       BIT(2) = follow HW2_EN signal
+                       BIT(3) = follow HW3_EN signal
+                       BIT(4) = follow PMIC awake state
+
+- qcom,vs-soft-start-strength:
+       Usage: optional
+       Value type: <u32>
+       Description: This property sets the soft start strength for voltage
+                    switch type regulators; supported values are:
+                       0 = 0.05 uA
+                       1 = 0.25 uA
+                       2 = 0.55 uA
+                       3 = 0.75 uA
 
 Example:
 
index db88feb28c0313bc9914eb2bcb4fc33dde264295..24bd422cecd5857c7fcf07403f5b600fd6310f3c 100644 (file)
@@ -42,6 +42,7 @@ Optional properties:
 - regulator-system-load: Load in uA present on regulator that is not captured by
   any consumer request.
 - regulator-pull-down: Enable pull down resistor when the regulator is disabled.
+- regulator-over-current-protection: Enable over current protection.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
index 90787aa2e648c55a91df5a71b9b10d7f4f7ae7c7..e6e6142e33ac8187f71822ab33467bd1da9c155b 100644 (file)
@@ -22,6 +22,8 @@ Optional properties:
                memory peripheral interface and USART DMA channel ID, FIFO configuration.
                Refer to dma.txt and atmel-dma.txt for details.
        - dma-names: "rx" for RX channel, "tx" for TX channel.
+- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
+  capable USARTs.
 
 <chip> compatible description:
 - at91rm9200:  legacy USART support
@@ -57,4 +59,5 @@ Example:
                dmas = <&dma0 2 0x3>,
                       <&dma0 2 0x204>;
                dma-names = "tx", "rx";
+               atmel,fifo-size = <32>;
        };
index ebcbb62c0a764061fd2c09a28937bdfd999c5517..51b3c9e80ad960e27efdc53ee0b85bab431185a4 100644 (file)
@@ -6,7 +6,7 @@ Required properties:
 - interrupts: device interrupt
 
 Optional properties:
-- {dtr,dsr,ri,cd}-gpios: specify a GPIO for DTR/DSR/RI/CD
+- {dtr,dsr,rng,dcd}-gpios: specify a GPIO for DTR/DSR/RI/DCD
   line respectively.
 
 Example:
@@ -16,4 +16,8 @@ serial@b00260000 {
        reg = <0xb0026000 0x1000>;
        interrupts = <68>;
        status = "disabled";
+       dtr-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>;
+       dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>;
+       rng-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>;
+       dcd-gpios = <&sysgpio 3 GPIO_ACTIVE_LOW>;
 };
index 54c2a155c78323a70f9dc66eb62457eba1143232..7a71b5de77d69b12f58a4d0d26b559fe7fa078fc 100644 (file)
@@ -4,6 +4,9 @@ Required properties:
 - compatible : should be "ti,omap2-uart" for OMAP2 controllers
 - compatible : should be "ti,omap3-uart" for OMAP3 controllers
 - compatible : should be "ti,omap4-uart" for OMAP4 controllers
+- compatible : should be "ti,am4372-uart" for AM437x controllers
+- compatible : should be "ti,am3352-uart" for AM335x controllers
+- compatible : should be "ti,dra742-uart" for DRA7x controllers
 - reg : address and length of the register space
 - interrupts or interrupts-extended : Should contain the uart interrupt
                                       specifier or both the interrupt
index bd99193e87b9ea2b68d2b81945e4d27a144f9950..204b311e04001075eb6ed3b03807087cebea12e2 100644 (file)
@@ -10,6 +10,8 @@ Required properties:
 Optional properties:
 - cs-gpios : Specifies the gpio pis to be used for chipselects.
 - num-cs : The number of chipselects. If omitted, this will default to 4.
+- reg-io-width : The I/O register width (in bytes) implemented by this
+  device.  Supported values are 2 or 4 (the default).
 
 Child nodes as per the generic SPI binding.
 
index 12ecfe9e359956566b95ede24005d2a18844c52c..d1e914adcf6e104856aae9ac023fc57a21292c5b 100644 (file)
@@ -12,6 +12,8 @@ Required properties:
 - compatible:
        - "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family
        - "ti,da830-spi" for SPI used similar to that on DA8xx SoC family
+       - "ti,keystone-spi" for SPI used similar to that on Keystone2 SoC
+               family
 - reg: Offset and length of SPI controller register space
 - num-cs: Number of chip selects. This includes internal as well as
        GPIO chip selects.
index e02fbf18c82cecad21a355cfacd3ae84c1676ac9..494db6012d02f29b3e17aec0f91f0ea6b0b65a28 100644 (file)
@@ -21,6 +21,7 @@ Required properties:
 Optional properties:
 - img,supports-quad-mode: Should be set if the interface supports quad mode
   SPI transfers.
+- spfi-max-frequency: Maximum speed supported by the spfi block.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
new file mode 100644 (file)
index 0000000..dcefc43
--- /dev/null
@@ -0,0 +1,51 @@
+Binding for MTK SPI controller
+
+Required properties:
+- compatible: should be one of the following.
+    - mediatek,mt8173-spi: for mt8173 platforms
+    - mediatek,mt8135-spi: for mt8135 platforms
+    - mediatek,mt6589-spi: for mt6589 platforms
+
+- #address-cells: should be 1.
+
+- #size-cells: should be 0.
+
+- reg: Address and length of the register set for the device
+
+- interrupts: Should contain spi interrupt
+
+- clocks: phandles to input clocks.
+  The first should be <&topckgen CLK_TOP_SPI_SEL>.
+  The second should be one of the following.
+   -  <&clk26m>: specify parent clock 26MHZ.
+   -  <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ.
+                                     It's the default one.
+   -  <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ.
+   -  <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ.
+   -  <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ.
+
+- clock-names: shall be "spi-clk" for the controller clock, and
+  "parent-clk" for the parent clock.
+
+Optional properties:
+- mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi
+  controller used, this value should be 0~3, only required for MT8173.
+    0: specify GPIO69,70,71,72 for spi pins.
+    1: specify GPIO102,103,104,105 for spi pins.
+    2: specify GPIO128,129,130,131 for spi pins.
+    3: specify GPIO5,6,7,8 for spi pins.
+
+Example:
+
+- SoC Specific Portion:
+spi: spi@1100a000 {
+       compatible = "mediatek,mt8173-spi";
+       #address-cells = <1>;
+       #size-cells = <0>;
+       reg = <0 0x1100a000 0 0x1000>;
+       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
+       clocks = <&topckgen CLK_TOP_SPI_SEL>, <&topckgen CLK_TOP_SYSPLL3_D2>;
+       clock-names = "spi-clk", "parent-clk";
+       mediatek,pad-select = <0>;
+       status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/spi/spi-xlp.txt b/Documentation/devicetree/bindings/spi/spi-xlp.txt
new file mode 100644 (file)
index 0000000..40e82d5
--- /dev/null
@@ -0,0 +1,39 @@
+SPI Master controller for Netlogic XLP MIPS64 SOCs
+==================================================
+
+Currently this SPI controller driver is supported for the following
+Netlogic XLP SoCs:
+       XLP832, XLP316, XLP208, XLP980, XLP532
+
+Required properties:
+- compatible           : Should be "netlogic,xlp832-spi".
+- #address-cells       : Number of cells required to define a chip select address
+                         on the SPI bus.
+- #size-cells          : Should be zero.
+- reg                  : Should contain register location and length.
+- clocks               : Phandle of the spi clock
+- interrupts           : Interrupt number used by this controller.
+- interrupt-parent     : Phandle of the parent interrupt controller.
+
+SPI slave nodes must be children of the SPI master node and can contain
+properties described in Documentation/devicetree/bindings/spi/spi-bus.txt.
+
+Example:
+
+       spi: xlp_spi@3a100 {
+               compatible = "netlogic,xlp832-spi";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0 0x3a100 0x100>;
+               clocks = <&spi_clk>;
+               interrupts = <34>;
+               interrupt-parent = <&pic>;
+
+               spi_nor@1 {
+                       compatible = "spansion,s25sl12801";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <1>;      /* Chip Select */
+                       spi-max-frequency = <40000000>;
+               };
+};
index 3075377875745b91874cbad53a0c307a32d0deed..555fb117d4facd8dc8e7b60c84500d873b44f1cd 100644 (file)
@@ -1,4 +1,4 @@
-* Freescale i.MX28 LRADC device driver
+* Freescale MXS LRADC device driver
 
 Required properties:
 - compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
new file mode 100644 (file)
index 0000000..862cd7c
--- /dev/null
@@ -0,0 +1,29 @@
+Allwinner sun4i A10 musb DRC/OTG controller
+-------------------------------------------
+
+Required properties:
+ - compatible      : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb"
+                     or "allwinner,sun8i-a33-musb"
+ - reg             : mmio address range of the musb controller
+ - clocks          : clock specifier for the musb controller ahb gate clock
+ - reset           : reset specifier for the ahb reset (A31 and newer only)
+ - interrupts      : interrupt to which the musb controller is connected
+ - interrupt-names : must be "mc"
+ - phys            : phy specifier for the otg phy
+ - phy-names       : must be "usb"
+ - dr_mode         : Dual-Role mode must be "host" or "otg"
+ - extcon          : extcon specifier for the otg phy
+
+Example:
+
+       usb_otg: usb@01c13000 {
+               compatible = "allwinner,sun4i-a10-musb";
+               reg = <0x01c13000 0x0400>;
+               clocks = <&ahb_gates 0>;
+               interrupts = <38>;
+               interrupt-names = "mc";
+               phys = <&usbphy 0>;
+               phy-names = "usb";
+               extcon = <&usbphy 0>;
+               status = "disabled";
+       };
index 553e2fae3a76f5be43b6fa2bfc00b18756892b44..d71ef07bca5d1a3505ecab53f0b84bc8e5d12fc1 100644 (file)
@@ -30,6 +30,21 @@ Optional properties:
   argument that indicate usb controller index
 - disable-over-current: (FSL only) disable over current detect
 - external-vbus-divider: (FSL only) enables off-chip resistor divider for Vbus
+- itc-setting: interrupt threshold control register control, the setting
+  should be aligned with ITC bits at register USBCMD.
+- ahb-burst-config: it is vendor dependent, the required value should be
+  aligned with AHBBRST at SBUSCFG, the range is from 0x0 to 0x7. This
+  property is used to change AHB burst configuration, check the chipidea
+  spec for meaning of each value. If this property is not existed, it
+  will use the reset value.
+- tx-burst-size-dword: it is vendor dependent, the tx burst size in dword
+  (4 bytes), This register represents the maximum length of a the burst
+  in 32-bit words while moving data from system memory to the USB
+  bus, changing this value takes effect only the SBUSCFG.AHBBRST is 0.
+- rx-burst-size-dword: it is vendor dependent, the rx burst size in dword
+  (4 bytes), This register represents the maximum length of a the burst
+  in 32-bit words while moving data from the USB bus to system memory,
+  changing this value takes effect only the SBUSCFG.AHBBRST is 0.
 
 Example:
 
@@ -41,4 +56,9 @@ Example:
                phys = <&usb_phy0>;
                phy-names = "usb-phy";
                vbus-supply = <&reg_usb0_vbus>;
+               gadget-itc-setting = <0x4>; /* 4 micro-frames */
+                /* Incremental burst of unspecified length */
+               ahb-burst-config = <0x0>;
+               tx-burst-size-dword = <0x10>; /* 64 bytes */
+               rx-burst-size-dword = <0x10>;
        };
index 477d5bb5e51cf9089e900650279373fe89e37812..bba825711873f30d47b6cafa1ee941df57d73c7e 100644 (file)
@@ -11,6 +11,19 @@ Optional properties:
                        "peripheral" and "otg". In case this attribute isn't
                        passed via DT, USB DRD controllers should default to
                        OTG.
+ - otg-rev: tells usb driver the release number of the OTG and EH supplement
+                       with which the device and its descriptors are compliant,
+                       in binary-coded decimal (i.e. 2.0 is 0200H). This
+                       property is used if any real OTG features(HNP/SRP/ADP)
+                       is enabled, if ADP is required, otg-rev should be
+                       0x0200 or above.
+ - hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP
+                       is the basic function of real OTG except you want it
+                       to be a srp-capable only B device.
+ - srp-disable: tells OTG controllers we want to disable OTG SRP, SRP is
+                       optional for OTG device.
+ - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
+                       optional for OTG device.
 
 This is an attribute to a USB controller such as:
 
@@ -21,4 +34,6 @@ dwc3@4a030000 {
        usb-phy = <&usb2_phy>, <&usb3,phy>;
        maximum-speed = "super-speed";
        dr_mode = "otg";
+       otg-rev = <0x0200>;
+       adp-disable;
 };
index bd8d9e7530290a91ec161f68f305c180981bf8fe..8654a3ec23e481127260d36706a5611b9b49576a 100644 (file)
@@ -52,6 +52,10 @@ Required properties:
 Optional properties:
 - dr_mode:      One of "host", "peripheral" or "otg". Defaults to "otg"
 
+- switch-gpio:  A phandle + gpio-specifier pair. Some boards are using Dual
+                SPDT USB Switch, witch is cotrolled by GPIO to de/multiplex
+                D+/D- USB lines between connectors.
+
 - qcom,phy-init-sequence: PHY configuration sequence values. This is related to Device
                 Mode Eye Diagram test. Start address at which these values will be
                 written is ULPI_EXT_VENDOR_SPECIFIC. Value of -1 is reserved as
diff --git a/Documentation/devicetree/bindings/usb/qcom,usb-8x16-phy.txt b/Documentation/devicetree/bindings/usb/qcom,usb-8x16-phy.txt
new file mode 100644 (file)
index 0000000..2cb2168
--- /dev/null
@@ -0,0 +1,76 @@
+Qualcomm's APQ8016/MSM8916 USB transceiver controller
+
+- compatible:
+    Usage: required
+    Value type: <string>
+    Definition: Should contain "qcom,usb-8x16-phy".
+
+- reg:
+    Usage: required
+    Value type: <prop-encoded-array>
+    Definition: USB PHY base address and length of the register map
+
+- clocks:
+    Usage: required
+    Value type: <prop-encoded-array>
+    Definition: See clock-bindings.txt section "consumers". List of
+                two clock specifiers for interface and core controller
+                clocks.
+
+- clock-names:
+    Usage: required
+    Value type: <string>
+    Definition: Must contain "iface" and "core" strings.
+
+- vddcx-supply:
+    Usage: required
+    Value type: <phandle>
+    Definition: phandle to the regulator VDCCX supply node.
+
+- v1p8-supply:
+    Usage: required
+    Value type: <phandle>
+    Definition: phandle to the regulator 1.8V supply node.
+
+- v3p3-supply:
+    Usage: required
+    Value type: <phandle>
+    Definition: phandle to the regulator 3.3V supply node.
+
+- resets:
+    Usage: required
+    Value type: <prop-encoded-array>
+    Definition: See reset.txt section "consumers". PHY reset specifier.
+
+- reset-names:
+    Usage: required
+    Value type: <string>
+    Definition: Must contain "phy" string.
+
+- switch-gpio:
+    Usage: optional
+    Value type: <prop-encoded-array>
+    Definition: Some boards are using Dual SPDT USB Switch, witch is
+                controlled by GPIO to de/multiplex D+/D- USB lines
+                between connectors.
+
+Example:
+       usb_phy: phy@78d9000 {
+               compatible = "qcom,usb-8x16-phy";
+               reg = <0x78d9000 0x400>;
+
+               vddcx-supply = <&pm8916_s1_corner>;
+               v1p8-supply = <&pm8916_l7>;
+               v3p3-supply = <&pm8916_l13>;
+
+               clocks = <&gcc GCC_USB_HS_AHB_CLK>,
+                            <&gcc GCC_USB_HS_SYSTEM_CLK>;
+               clock-names = "iface", "core";
+
+               resets = <&gcc GCC_USB2A_PHY_BCR>;
+               reset-names = "phy";
+
+               // D+/D- lines: 1 - Routed to HUB, 0 - Device connector
+               switch-gpio = <&pm8916_gpios 4 GPIO_ACTIVE_HIGH>;
+       };
+
index c7d49b8855593b2a75e263363a9360e905f50773..3fa450881ecb8e294a74d17766538804489fe9fd 100644 (file)
@@ -93,7 +93,7 @@ Evolution (GUI)
 Some people use this successfully for patches.
 
 When composing mail select: Preformat
-  from Format->Heading->Preformatted (Ctrl-7)
+  from Format->Paragraph Style->Preformatted (Ctrl-7)
   or the toolbar
 
 Then use:
diff --git a/Documentation/fb/sm712fb.txt b/Documentation/fb/sm712fb.txt
new file mode 100644 (file)
index 0000000..c388442
--- /dev/null
@@ -0,0 +1,31 @@
+What is sm712fb?
+=================
+
+This is a graphics framebuffer driver for Silicon Motion SM712 based processors.
+
+How to use it?
+==============
+
+Switching modes is done using the video=sm712fb:... boot parameter.
+
+If you want, for example, enable a resolution of 1280x1024x24bpp you should
+pass to the kernel this command line: "video=sm712fb:0x31B".
+
+You should not compile-in vesafb.
+
+Currently supported video modes are:
+
+[Graphic modes]
+
+bpp | 640x480  800x600  1024x768  1280x1024
+----+--------------------------------------------
+  8 | 0x301    0x303    0x305    0x307
+ 16 | 0x311    0x314    0x317    0x31A
+ 24 | 0x312    0x315    0x318    0x31B
+
+Missing Features
+================
+(alias TODO list)
+
+       * 2D acceleratrion
+       * dual-head support
index d11cc2f8077b9ea6e4284419fd40121c13d0d1c2..c772b47e7ef06e0b8f06538d32ea883343d51081 100644 (file)
@@ -61,7 +61,7 @@ Options with (*) are default options and will not show in the mount options.
 
        check_int enables the integrity checker module, which examines all
        block write requests to ensure on-disk consistency, at a large
-       memory and CPU cost.  
+       memory and CPU cost.
 
        check_int_data includes extent data in the integrity checks, and
        implies the check_int option.
@@ -113,7 +113,7 @@ Options with (*) are default options and will not show in the mount options.
        Disable/enable debugging option to be more verbose in some ENOSPC conditions.
 
   fatal_errors=<action>
-       Action to take when encountering a fatal error: 
+       Action to take when encountering a fatal error:
          "bug" - BUG() on a fatal error.  This is the default.
          "panic" - panic() on a fatal error.
 
@@ -132,10 +132,10 @@ Options with (*) are default options and will not show in the mount options.
 
   max_inline=<bytes>
        Specify the maximum amount of space, in bytes, that can be inlined in
-       a metadata B-tree leaf.  The value is specified in bytes, optionally 
+       a metadata B-tree leaf.  The value is specified in bytes, optionally
        with a K, M, or G suffix, case insensitive.  In practice, this value
        is limited by the root sector size, with some space unavailable due
-       to leaf headers.  For a 4k sectorsize, max inline data is ~3900 bytes.
+       to leaf headers.  For a 4k sector size, max inline data is ~3900 bytes.
 
   metadata_ratio=<value>
        Specify that 1 metadata chunk should be allocated after every <value>
@@ -170,7 +170,7 @@ Options with (*) are default options and will not show in the mount options.
 
   recovery
        Enable autorecovery attempts if a bad tree root is found at mount time.
-       Currently this scans a list of several previous tree roots and tries to 
+       Currently this scans a list of several previous tree roots and tries to
        use the first readable.
 
   rescan_uuid_tree
@@ -194,7 +194,7 @@ Options with (*) are default options and will not show in the mount options.
   ssd_spread
        Options to control ssd allocation schemes.  By default, BTRFS will
        enable or disable ssd allocation heuristics depending on whether a
-       rotational or nonrotational disk is in use.  The ssd and nossd options
+       rotational or non-rotational disk is in use.  The ssd and nossd options
        can override this autodetection.
 
        The ssd_spread mount option attempts to allocate into big chunks
@@ -216,13 +216,13 @@ Options with (*) are default options and will not show in the mount options.
        This allows mounting of subvolumes which are not in the root of the mounted
        filesystem.
        You can use "btrfs subvolume show " to see the object ID for a subvolume.
-       
+
   thread_pool=<number>
        The number of worker threads to allocate.  The default number is equal
        to the number of CPUs + 2, or 8, whichever is smaller.
 
   user_subvol_rm_allowed
-       Allow subvolumes to be deleted by a non-root user. Use with caution. 
+       Allow subvolumes to be deleted by a non-root user. Use with caution.
 
 MAILING LIST
 ============
index 88ab81c79109435052eae5c8e2567435c6aa3cfb..463f595733e8876b5bb1fa65c8d7151e8ece7fd5 100644 (file)
@@ -51,6 +51,17 @@ operations should be provided; others can be included as needed.  Again,
 the return value will be a dentry pointer to the created file, NULL for
 error, or ERR_PTR(-ENODEV) if debugfs support is missing.
 
+Create a file with an initial size, the following function can be used
+instead:
+
+    struct dentry *debugfs_create_file_size(const char *name, umode_t mode,
+                               struct dentry *parent, void *data,
+                               const struct file_operations *fops,
+                               loff_t file_size);
+
+file_size is the initial file size. The other parameters are the same
+as the function debugfs_create_file.
+
 In a number of cases, the creation of a set of file operations is not
 actually necessary; the debugfs code provides a number of helper functions
 for simple situations.  Files containing a single integer value can be
@@ -100,6 +111,14 @@ A read on the resulting file will yield either Y (for non-zero values) or
 N, followed by a newline.  If written to, it will accept either upper- or
 lower-case values, or 1 or 0.  Any other input will be silently ignored.
 
+Also, atomic_t values can be placed in debugfs with:
+
+    struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
+                               struct dentry *parent, atomic_t *value)
+
+A read of this file will get atomic_t values, and a write of this file
+will set atomic_t values.
+
 Another option is exporting a block of arbitrary binary data, with
 this structure and function:
 
@@ -147,6 +166,27 @@ The "base" argument may be 0, but you may want to build the reg32 array
 using __stringify, and a number of register names (macros) are actually
 byte offsets over a base for the register block.
 
+If you want to dump an u32 array in debugfs, you can create file with:
+
+    struct dentry *debugfs_create_u32_array(const char *name, umode_t mode,
+                       struct dentry *parent,
+                       u32 *array, u32 elements);
+
+The "array" argument provides data, and the "elements" argument is
+the number of elements in the array. Note: Once array is created its
+size can not be changed.
+
+There is a helper function to create device related seq_file:
+
+   struct dentry *debugfs_create_devm_seqfile(struct device *dev,
+                               const char *name,
+                               struct dentry *parent,
+                               int (*read_fn)(struct seq_file *s,
+                                       void *data));
+
+The "dev" argument is the device related to this debugfs file, and
+the "read_fn" is a function pointer which to be called to print the
+seq_file content.
 
 There are a couple of other directory-oriented helper functions:
 
index b35a64b82f9e8371d42fcf893354d02c07c6c229..9494afb9476a4b667224fe220fa4ca5ee16ac9ba 100644 (file)
@@ -212,7 +212,10 @@ Other notes:
 - show() methods should return the number of bytes printed into the
   buffer. This is the return value of scnprintf().
 
-- show() should always use scnprintf().
+- show() must not use snprintf() when formatting the value to be
+  returned to user space. If you can guarantee that an overflow
+  will never happen you can use sprintf() otherwise you must use
+  scnprintf().
 
 - store() should return the number of bytes used from the buffer. If the
   entire buffer has been used, just return the count argument.
index 15b4a20d5062f4e3872135557f6740da6c9408cf..d697229e3c18e2571f4846eb8801094daf52eb2e 100644 (file)
@@ -14,6 +14,10 @@ Supported chips:
     Prefix: 'adm1276'
     Addresses scanned: -
     Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
+  * Analog Devices ADM1293/ADM1294
+    Prefix: 'adm1293', 'adm1294'
+    Addresses scanned: -
+    Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/ADM1293_1294.pdf
 
 Author: Guenter Roeck <linux@roeck-us.net>
 
@@ -22,12 +26,12 @@ Description
 -----------
 
 This driver supports hardware montoring for Analog Devices ADM1075, ADM1275,
-and ADM1276 Hot-Swap Controller and Digital Power Monitor.
+ADM1276, ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors.
 
-ADM1075, ADM1275, and ADM1276 are hot-swap controllers that allow a circuit
-board to be removed from or inserted into a live backplane. They also feature
-current and voltage readback via an integrated 12-bit analog-to-digital
-converter (ADC), accessed using a PMBus interface.
+ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 are hot-swap controllers that
+allow a circuit board to be removed from or inserted into a live backplane.
+They also feature current and voltage readback via an integrated 12
+bit analog-to-digital converter (ADC), accessed using a PMBus interface.
 
 The driver is a client driver to the core PMBus driver. Please see
 Documentation/hwmon/pmbus for details on PMBus client drivers.
@@ -58,16 +62,16 @@ Sysfs entries
 The following attributes are supported. Limits are read-write, history reset
 attributes are write-only, all other attributes are read-only.
 
-in1_label              "vin1" or "vout1" depending on chip variant and
-                       configuration. On ADM1075, vout1 reports the voltage on
-                       the VAUX pin.
-in1_input              Measured voltage.
-in1_min                        Minimum Voltage.
-in1_max                        Maximum voltage.
-in1_min_alarm          Voltage low alarm.
-in1_max_alarm          Voltage high alarm.
-in1_highest            Historical maximum voltage.
-in1_reset_history      Write any value to reset history.
+inX_label              "vin1" or "vout1" depending on chip variant and
+                       configuration. On ADM1075, ADM1293, and ADM1294,
+                       vout1 reports the voltage on the VAUX pin.
+inX_input              Measured voltage.
+inX_min                        Minimum Voltage.
+inX_max                        Maximum voltage.
+inX_min_alarm          Voltage low alarm.
+inX_max_alarm          Voltage high alarm.
+inX_highest            Historical maximum voltage.
+inX_reset_history      Write any value to reset history.
 
 curr1_label            "iout1"
 curr1_input            Measured current.
@@ -86,7 +90,9 @@ curr1_reset_history   Write any value to reset history.
 
 power1_label           "pin1"
 power1_input           Input power.
+power1_input_lowest    Lowest observed input power. ADM1293 and ADM1294 only.
+power1_input_highest   Highest observed input power.
 power1_reset_history   Write any value to reset history.
 
-                       Power attributes are supported on ADM1075 and ADM1276
-                       only.
+                       Power attributes are supported on ADM1075, ADM1276,
+                       ADM1293, and ADM1294.
index 80654813d04afdf1e76d8388c8c51a1fb31ae825..e2b1b69eebea85dc0c4bef2b0a337dc1ce239ab6 100644 (file)
@@ -3,12 +3,13 @@ Kernel driver fam15h_power
 
 Supported chips:
 * AMD Family 15h Processors
+* AMD Family 16h Processors
 
   Prefix: 'fam15h_power'
   Addresses scanned: PCI space
   Datasheets:
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
-    (not yet published)
+  BIOS and Kernel Developer's Guide (BKDG) For AMD Family 16h Processors
 
 Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
 
@@ -16,10 +17,11 @@ Description
 -----------
 
 This driver permits reading of registers providing power information
-of AMD Family 15h processors.
+of AMD Family 15h and 16h processors.
 
-For AMD Family 15h processors the following power values can be
-calculated using different processor northbridge function registers:
+For AMD Family 15h and 16h processors the following power values can
+be calculated using different processor northbridge function
+registers:
 
 * BasePwrWatts: Specifies in watts the maximum amount of power
   consumed by the processor for NB and logic external to the core.
index e87294878334d92af5af6420a8eae3d4222aaafc..733296d654493ed98a91f51bb7935fd05d1c65c2 100644 (file)
@@ -38,6 +38,10 @@ Supported chips:
     Prefix: 'it8728'
     Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Not publicly available
+  * IT8732F
+    Prefix: 'it8732'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
   * IT8771E
     Prefix: 'it8771'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -111,9 +115,9 @@ Description
 -----------
 
 This driver implements support for the IT8603E, IT8620E, IT8623E, IT8705F,
-IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
-IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and SiS950
-chips.
+IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F,
+IT8758E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and
+SiS950 chips.
 
 These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
 joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -137,10 +141,10 @@ The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E and later IT8712F revisions
 have support for 2 additional fans. The additional fans are supported by the
 driver.
 
-The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8781F, IT8782F, IT8783E/F,
-and late IT8712F and IT8705F also have optional 16-bit tachometer counters
-for fans 1 to 3. This is better (no more fan clock divider mess) but not
-compatible with the older chips and revisions. The 16-bit tachometer mode
+The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F,
+IT8783E/F, and late IT8712F and IT8705F also have optional 16-bit tachometer
+counters for fans 1 to 3. This is better (no more fan clock divider mess) but
+not compatible with the older chips and revisions. The 16-bit tachometer mode
 is enabled by the driver when one of the above chips is detected.
 
 The IT8726F is just bit enhanced IT8716F with additional hardware
@@ -159,6 +163,9 @@ IT8728F. It only supports 16-bit fan mode.
 
 The IT8790E supports up to 3 fans. 16-bit fan mode is always enabled.
 
+The IT8732F supports a closed-loop mode for fan control, but this is not
+currently implemented by the driver.
+
 Temperatures are measured in degrees Celsius. An alarm is triggered once
 when the Overtemperature Shutdown limit is crossed.
 
@@ -173,12 +180,14 @@ is done.
 Voltage sensors (also known as IN sensors) report their values in volts. An
 alarm is triggered if the voltage has crossed a programmable minimum or
 maximum limit. Note that minimum in this case always means 'closest to
-zero'; this is important for negative voltage measurements. All voltage
-inputs can measure voltages between 0 and 4.08 volts, with a resolution of
-0.016 volt (except IT8603E, IT8721F/IT8758E and IT8728F: 0.012 volt.) The
-battery voltage in8 does not have limit registers.
-
-On the IT8603E, IT8721F/IT8758E, IT8781F, IT8782F, and IT8783E/F, some
+zero'; this is important for negative voltage measurements. On most chips, all
+voltage inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.  IT8603E, IT8721F/IT8758E and IT8728F can measure between 0 and
+3.06 volts, with a resolution of 0.012 volt.  IT8732F can measure between 0 and
+2.8 volts with a resolution of 0.0109 volt.  The battery voltage in8 does not
+have limit registers.
+
+On the IT8603E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F, and IT8783E/F, some
 voltage inputs are internal and scaled inside the chip:
 * in3 (optional)
 * in7 (optional for IT8781F, IT8782F, and IT8783E/F)
index 686c078bb0e08192b6cba325c9f33638c1c0667c..9a49d3c90cd1a7f2a28b19f0850cdc2bd00dbbae 100644 (file)
@@ -6,6 +6,10 @@ Supported chips:
     Prefix: 'ltc2974'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc2974
+  * Linear Technology LTC2975
+    Prefix: 'ltc2975'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc2975
   * Linear Technology LTC2977
     Prefix: 'ltc2977'
     Addresses scanned: -
@@ -15,14 +19,38 @@ Supported chips:
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc2978
               http://www.linear.com/product/ltc2978a
+  * Linear Technology LTC2980
+    Prefix: 'ltc2980'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc2980
   * Linear Technology LTC3880
     Prefix: 'ltc3880'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc3880
+  * Linear Technology LTC3882
+    Prefix: 'ltc3882'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc3882
   * Linear Technology LTC3883
     Prefix: 'ltc3883'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc3883
+  * Linear Technology LTC3886
+    Prefix: 'ltc3886'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc3886
+  * Linear Technology LTC3887
+    Prefix: 'ltc3887'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc3887
+  * Linear Technology LTM2987
+    Prefix: 'ltm2987'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltm2987
+  * Linear Technology LTM4675
+    Prefix: 'ltm4675'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltm4675
   * Linear Technology LTM4676
     Prefix: 'ltm4676'
     Addresses scanned: -
@@ -34,11 +62,20 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
-monitor. LTC2977 is a pin compatible replacement for LTC2978. LTC3880 is a dual
-output poly-phase step-down DC/DC controller. LTC3883 is a single phase
-step-down DC/DC controller. LTM4676 is a dual 13A or single 26A uModule
-regulator.
+LTC2974 and LTC2975 are quad digital power supply managers.
+LTC2978 is an octal power supply monitor.
+LTC2977 is a pin compatible replacement for LTC2978.
+LTC2980 is a 16-channel Power System Manager, consisting of two LTC2977
+in a single die. The chip is instantiated and reported as two separate chips
+on two different I2C bus addresses.
+LTC3880, LTC3882, LTC3886, and LTC3887 are dual output poly-phase step-down
+DC/DC controllers.
+LTC3883 is a single phase step-down DC/DC controller.
+LTM2987 is a 16-channel Power System Manager with two LTC2977 plus
+additional components on a single die. The chip is instantiated and reported
+as two separate chips on two different I2C bus addresses.
+LTM4675 is a dual 9A or single 18A Î¼Module regulator
+LTM4676 is a dual 13A or single 26A uModule regulator.
 
 
 Usage Notes
@@ -61,26 +98,32 @@ in1_label           "vin"
 in1_input              Measured input voltage.
 in1_min                        Minimum input voltage.
 in1_max                        Maximum input voltage.
-                       LTC2974, LTC2977, and LTC2978 only.
+                       LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
+                       LTM2987 only.
 in1_lcrit              Critical minimum input voltage.
-                       LTC2974, LTC2977, and LTC2978 only.
+                       LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
+                       LTM2987 only.
 in1_crit               Critical maximum input voltage.
 in1_min_alarm          Input voltage low alarm.
 in1_max_alarm          Input voltage high alarm.
-                       LTC2974, LTC2977, and LTC2978 only.
+                       LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
+                       LTM2987 only.
 in1_lcrit_alarm                Input voltage critical low alarm.
-                       LTC2974, LTC2977, and LTC2978 only.
+                       LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
+                       LTM2987 only.
 in1_crit_alarm         Input voltage critical high alarm.
 in1_lowest             Lowest input voltage.
-                       LTC2974, LTC2977, and LTC2978 only.
+                       LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
+                       LTM2987 only.
 in1_highest            Highest input voltage.
 in1_reset_history      Reset input voltage history.
 
 in[N]_label            "vout[1-8]".
-                       LTC2974: N=2-5
-                       LTC2977: N=2-9
+                       LTC2974, LTC2975: N=2-5
+                       LTC2977, LTC2980, LTM2987: N=2-9
                        LTC2978: N=2-9
-                       LTC3880, LTM4676: N=2-3
+                       LTC3880, LTC3882, LTC23886 LTC3887, LTM4675, LTM4676:
+                               N=2-3
                        LTC3883: N=2
 in[N]_input            Measured output voltage.
 in[N]_min              Minimum output voltage.
@@ -91,67 +134,78 @@ in[N]_min_alarm            Output voltage low alarm.
 in[N]_max_alarm                Output voltage high alarm.
 in[N]_lcrit_alarm      Output voltage critical low alarm.
 in[N]_crit_alarm       Output voltage critical high alarm.
-in[N]_lowest           Lowest output voltage. LTC2974 and LTC2978 only.
+in[N]_lowest           Lowest output voltage. LTC2974, LTC2975,
+                       and LTC2978 only.
 in[N]_highest          Highest output voltage.
 in[N]_reset_history    Reset output voltage history.
 
 temp[N]_input          Measured temperature.
-                       On LTC2974, temp[1-4] report external temperatures,
-                       and temp5 reports the chip temperature.
-                       On LTC2977 and LTC2978, only one temperature measurement
-                       is supported and reports the chip temperature.
-                       On LTC3880 and LTM4676, temp1 and temp2 report external
-                       temperatures, and temp3 reports the chip temperature.
+                       On LTC2974 and LTC2975, temp[1-4] report external
+                       temperatures, and temp5 reports the chip temperature.
+                       On LTC2977, LTC2980, LTC2978, and LTM2987, only one
+                       temperature measurement is supported and reports
+                       the chip temperature.
+                       On LTC3880, LTC3882, LTC3887, LTM4675, and LTM4676,
+                       temp1 and temp2 report external temperatures, and temp3
+                       reports the chip temperature.
                        On LTC3883, temp1 reports an external temperature,
                        and temp2 reports the chip temperature.
-temp[N]_min            Mimimum temperature. LTC2974, LCT2977, and LTC2978 only.
+temp[N]_min            Mimimum temperature. LTC2974, LCT2977, LTM2980, LTC2978,
+                       and LTM2987 only.
 temp[N]_max            Maximum temperature.
 temp[N]_lcrit          Critical low temperature.
 temp[N]_crit           Critical high temperature.
 temp[N]_min_alarm      Temperature low alarm.
-                       LTC2974, LTC2977, and LTC2978 only.
+                       LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
+                       LTM2987 only.
 temp[N]_max_alarm      Temperature high alarm.
 temp[N]_lcrit_alarm    Temperature critical low alarm.
 temp[N]_crit_alarm     Temperature critical high alarm.
 temp[N]_lowest         Lowest measured temperature.
-                       LTC2974, LTC2977, and LTC2978 only.
-                       Not supported for chip temperature sensor on LTC2974.
+                       LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
+                       LTM2987 only.
+                       Not supported for chip temperature sensor on LTC2974 and
+                       LTC2975.
 temp[N]_highest                Highest measured temperature. Not supported for chip
-                       temperature sensor on LTC2974.
+                       temperature sensor on LTC2974 and LTC2975.
 temp[N]_reset_history  Reset temperature history. Not supported for chip
-                       temperature sensor on LTC2974.
+                       temperature sensor on LTC2974 and LTC2975.
 
-power1_label           "pin". LTC3883 only.
+power1_label           "pin". LTC3883 and LTC3886 only.
 power1_input           Measured input power.
 
 power[N]_label         "pout[1-4]".
-                       LTC2974: N=1-4
-                       LTC2977: Not supported
+                       LTC2974, LTC2975: N=1-4
+                       LTC2977, LTC2980, LTM2987: Not supported
                        LTC2978: Not supported
-                       LTC3880, LTM4676: N=1-2
+                       LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
+                               N=1-2
                        LTC3883: N=2
 power[N]_input         Measured output power.
 
-curr1_label            "iin". LTC3880, LTC3883, and LTM4676 only.
+curr1_label            "iin". LTC3880, LTC3883, LTC3886, LTC3887, LTM4675,
+                       and LTM4676 only.
 curr1_input            Measured input current.
 curr1_max              Maximum input current.
 curr1_max_alarm                Input current high alarm.
-curr1_highest          Highest input current. LTC3883 only.
-curr1_reset_history    Reset input current history. LTC3883 only.
+curr1_highest          Highest input current. LTC3883 and LTC3886 only.
+curr1_reset_history    Reset input current history. LTC3883 and LTC3886 only.
 
 curr[N]_label          "iout[1-4]".
-                       LTC2974: N=1-4
-                       LTC2977: not supported
+                       LTC2974, LTC2975: N=1-4
+                       LTC2977, LTC2980, LTM2987: not supported
                        LTC2978: not supported
-                       LTC3880, LTM4676: N=2-3
+                       LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
+                               N=2-3
                        LTC3883: N=2
 curr[N]_input          Measured output current.
 curr[N]_max            Maximum output current.
 curr[N]_crit           Critical high output current.
-curr[N]_lcrit          Critical low output current. LTC2974 only.
+curr[N]_lcrit          Critical low output current. LTC2974 and LTC2975 only.
 curr[N]_max_alarm      Output current high alarm.
 curr[N]_crit_alarm     Output current critical high alarm.
-curr[N]_lcrit_alarm    Output current critical low alarm. LTC2974 only.
-curr[N]_lowest         Lowest output current. LTC2974 only.
+curr[N]_lcrit_alarm    Output current critical low alarm.
+                       LTC2974 and LTC2975 only.
+curr[N]_lowest         Lowest output current. LTC2974 and LTC2975 only.
 curr[N]_highest                Highest output current.
 curr[N]_reset_history  Reset output current history.
diff --git a/Documentation/hwmon/max20751 b/Documentation/hwmon/max20751
new file mode 100644 (file)
index 0000000..f9fa25e
--- /dev/null
@@ -0,0 +1,77 @@
+Kernel driver max20751
+======================
+
+Supported chips:
+  * maxim MAX20751
+    Prefix: 'max20751'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX20751.pdf
+    Application note: http://pdfserv.maximintegrated.com/en/an/AN5941.pdf
+
+Author: Guenter Roeck <linux@roeck-us.net>
+
+
+Description
+-----------
+
+This driver supports MAX20751 Multiphase Master with PMBus Interface
+and Internal Buck Converter.
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported.
+
+in1_label              "vin1"
+in1_input              Measured voltage.
+in1_min                        Minimum input voltage.
+in1_max                        Maximum input voltage.
+in1_lcrit              Critical minimum input voltage.
+in1_crit               Critical maximum input voltage.
+in1_min_alarm          Input voltage low alarm.
+in1_lcrit_alarm                Input voltage critical low alarm.
+in1_min_alarm          Input voltage low alarm.
+in1_max_alarm          Input voltage high alarm.
+
+in2_label              "vout1"
+in2_input              Measured voltage.
+in2_min                        Minimum output voltage.
+in2_max                        Maximum output voltage.
+in2_lcrit              Critical minimum output voltage.
+in2_crit               Critical maximum output voltage.
+in2_min_alarm          Output voltage low alarm.
+in2_lcrit_alarm                Output voltage critical low alarm.
+in2_min_alarm          Output voltage low alarm.
+in2_max_alarm          Output voltage high alarm.
+
+curr1_input            Measured output current.
+curr1_label            "iout1"
+curr1_max              Maximum output current.
+curr1_alarm            Current high alarm.
+
+temp1_input            Measured temperature.
+temp1_max              Maximum temperature.
+temp1_crit             Critical high temperature.
+temp1_max_alarm                Chip temperature high alarm.
+temp1_crit_alarm       Chip temperature critical high alarm.
+
+power1_input           Output power.
+power1_label           "pout1"
index 2e00f5e344bc83b4c3c6a41abdb1b803e3473855..5438deb6be0207e1f2c4665c7ffed97f66afb175 100644 (file)
@@ -17,8 +17,7 @@ This driver implements support for the Nuvoton NCT7802Y hardware monitoring
 chip. NCT7802Y supports 6 temperature sensors, 5 voltage sensors, and 3 fan
 speed sensors.
 
-The chip also supports intelligent fan speed control. This functionality is
-not currently supported by the driver.
+Smart Fanâ„¢ speed control is available via pwmX_auto_point attributes.
 
 Tested Boards and BIOS Versions
 -------------------------------
index a3557da8f5b4eaf8f9b0524290cd2a3905f94b19..b397675e876d4daa7dae76ca0bef2e1559a0f1da 100644 (file)
@@ -23,11 +23,15 @@ Supported chips:
        http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
        http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
        http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
-  * Texas Instruments TPS40400
-    Prefixes: 'tps40400'
+  * Texas Instruments TPS40400, TPS544B20, TPS544B25, TPS544C20, TPS544C25
+    Prefixes: 'tps40400', 'tps544b20', 'tps544b25', 'tps544c20', 'tps544c25'
     Addresses scanned: -
     Datasheets:
        http://www.ti.com/lit/gpn/tps40400
+       http://www.ti.com/lit/gpn/tps544b20
+       http://www.ti.com/lit/gpn/tps544b25
+       http://www.ti.com/lit/gpn/tps544c20
+       http://www.ti.com/lit/gpn/tps544c25
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
index 611c52267d24812423821a9f062a407414f86e36..141f847c76488b61c5ca05503c221a970a3f3396 100644 (file)
@@ -124,6 +124,8 @@ Code  Seq#(hex)     Include File            Comments
 'H'    00-7F   linux/hiddev.h          conflict!
 'H'    00-0F   linux/hidraw.h          conflict!
 'H'    01      linux/mei.h             conflict!
+'H'    02      linux/mei.h             conflict!
+'H'    03      linux/mei.h             conflict!
 'H'    00-0F   sound/asound.h          conflict!
 'H'    20-40   sound/asound_fm.h       conflict!
 'H'    80-8F   sound/sfnt_info.h       conflict!
index acbc1a3d0d91f44a2b5beb101fe9e95e0e146e51..78f69cdc9b3fbcec6f32beb179eb4c8732883d5a 100644 (file)
@@ -128,7 +128,7 @@ are:
   special place-holders for where the extracted documentation should
   go.
 
-- scripts/basic/docproc.c
+- scripts/docproc.c
 
   This is a program for converting SGML template files into SGML
   files. When a file is referenced it is searched for symbols
index 01b5b68a237a8b7b77f8614a73639963f6ba167f..b09dc2c05fdf017394be5d655d1c9cb5e24bc260 100644 (file)
@@ -910,6 +910,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Disable PIN 1 of APIC timer
                        Can be useful to work around chipset bugs.
 
+       dis_ucode_ldr   [X86] Disable the microcode loader.
+
        dma_debug=off   If the kernel is compiled with DMA_API_DEBUG support,
                        this option disables the debugging code at boot.
 
index 1092ad9578da10d21b6f6f9f164060afbd70b260..7ed371c852046b3dd5d993db1815d00a9d8f4bc0 100644 (file)
@@ -51,8 +51,7 @@ struct demo_client {
  */
 static void message_from_remote(struct mbox_client *cl, void *mssg)
 {
-       struct demo_client *dc = container_of(mbox_client,
-                                               struct demo_client, cl);
+       struct demo_client *dc = container_of(cl, struct demo_client, cl);
        if (dc->async) {
                if (is_an_ack(mssg)) {
                        /* An ACK to our last sample sent */
@@ -68,8 +67,7 @@ static void message_from_remote(struct mbox_client *cl, void *mssg)
 
 static void sample_sent(struct mbox_client *cl, void *mssg, int r)
 {
-       struct demo_client *dc = container_of(mbox_client,
-                                               struct demo_client, cl);
+       struct demo_client *dc = container_of(cl, struct demo_client, cl);
        complete(&dc->c);
 }
 
diff --git a/Documentation/men-chameleon-bus.txt b/Documentation/men-chameleon-bus.txt
new file mode 100644 (file)
index 0000000..30ded73
--- /dev/null
@@ -0,0 +1,163 @@
+                               MEN Chameleon Bus
+                               =================
+
+Table of Contents
+=================
+1 Introduction
+    1.1 Scope of this Document
+    1.2 Limitations of the current implementation
+2 Architecture
+    2.1 MEN Chameleon Bus
+    2.2 Carrier Devices
+    2.3 Parser
+3 Resource handling
+    3.1 Memory Resources
+    3.2 IRQs
+4 Writing an MCB driver
+    4.1 The driver structure
+    4.2 Probing and attaching
+    4.3 Initializing the driver
+
+
+1 Introduction
+===============
+  This document describes the architecture and implementation of the MEN
+  Chameleon Bus (called MCB throughout this document).
+
+1.1 Scope of this Document
+---------------------------
+  This document is intended to be a short overview of the current
+  implementation and does by no means describe the complete possibilities of MCB
+  based devices.
+
+1.2 Limitations of the current implementation
+----------------------------------------------
+  The current implementation is limited to PCI and PCIe based carrier devices
+  that only use a single memory resource and share the PCI legacy IRQ.  Not
+  implemented are:
+  - Multi-resource MCB devices like the VME Controller or M-Module carrier.
+  - MCB devices that need another MCB device, like SRAM for a DMA Controller's
+    buffer descriptors or a video controller's video memory.
+  - A per-carrier IRQ domain for carrier devices that have one (or more) IRQs
+    per MCB device like PCIe based carriers with MSI or MSI-X support.
+
+2 Architecture
+===============
+  MCB is divided into 3 functional blocks:
+  - The MEN Chameleon Bus itself,
+  - drivers for MCB Carrier Devices and
+  - the parser for the Chameleon table.
+
+2.1 MEN Chameleon Bus
+----------------------
+   The MEN Chameleon Bus is an artificial bus system that attaches to a so
+   called Chameleon FPGA device found on some hardware produced my MEN Mikro
+   Elektronik GmbH. These devices are multi-function devices implemented in a
+   single FPGA and usually attached via some sort of PCI or PCIe link. Each
+   FPGA contains a header section describing the content of the FPGA. The
+   header lists the device id, PCI BAR, offset from the beginning of the PCI
+   BAR, size in the FPGA, interrupt number and some other properties currently
+   not handled by the MCB implementation.
+
+2.2 Carrier Devices
+--------------------
+   A carrier device is just an abstraction for the real world physical bus the
+   Chameleon FPGA is attached to. Some IP Core drivers may need to interact with
+   properties of the carrier device (like querying the IRQ number of a PCI
+   device). To provide abstraction from the real hardware bus, an MCB carrier
+   device provides callback methods to translate the driver's MCB function calls
+   to hardware related function calls. For example a carrier device may
+   implement the get_irq() method which can be translated into a hardware bus
+   query for the IRQ number the device should use.
+
+2.3 Parser
+-----------
+   The parser reads the first 512 bytes of a Chameleon device and parses the
+   Chameleon table. Currently the parser only supports the Chameleon v2 variant
+   of the Chameleon table but can easily be adopted to support an older or
+   possible future variant. While parsing the table's entries new MCB devices
+   are allocated and their resources are assigned according to the resource
+   assignment in the Chameleon table. After resource assignment is finished, the
+   MCB devices are registered at the MCB and thus at the driver core of the
+   Linux kernel.
+
+3 Resource handling
+====================
+  The current implementation assigns exactly one memory and one IRQ resource
+  per MCB device. But this is likely going to change in the future.
+
+3.1 Memory Resources
+---------------------
+   Each MCB device has exactly one memory resource, which can be requested from
+   the MCB bus. This memory resource is the physical address of the MCB device
+   inside the carrier and is intended to be passed to ioremap() and friends. It
+   is already requested from the kernel by calling request_mem_region().
+
+3.2 IRQs
+---------
+   Each MCB device has exactly one IRQ resource, which can be requested from the
+   MCB bus. If a carrier device driver implements the ->get_irq() callback
+   method, the IRQ number assigned by the carrier device will be returned,
+   otherwise the IRQ number inside the Chameleon table will be returned. This
+   number is suitable to be passed to request_irq().
+
+4 Writing an MCB driver
+=======================
+
+4.1 The driver structure
+-------------------------
+    Each MCB driver has a structure to identify the device driver as well as
+    device ids which identify the IP Core inside the FPGA. The driver structure
+    also contains callback methods which get executed on driver probe and
+    removal from the system.
+
+
+  static const struct mcb_device_id foo_ids[] = {
+          { .device = 0x123 },
+          { }
+  };
+  MODULE_DEVICE_TABLE(mcb, foo_ids);
+
+  static struct mcb_driver foo_driver = {
+          driver = {
+                  .name = "foo-bar",
+                  .owner = THIS_MODULE,
+          },
+          .probe = foo_probe,
+          .remove = foo_remove,
+          .id_table = foo_ids,
+  };
+
+4.2 Probing and attaching
+--------------------------
+   When a driver is loaded and the MCB devices it services are found, the MCB
+   core will call the driver's probe callback method. When the driver is removed
+   from the system, the MCB core will call the driver's remove callback method.
+
+
+  static init foo_probe(struct mcb_device *mdev, const struct mcb_device_id *id);
+  static void foo_remove(struct mcb_device *mdev);
+
+4.3 Initializing the driver
+----------------------------
+   When the kernel is booted or your foo driver module is inserted, you have to
+   perform driver initialization. Usually it is enough to register your driver
+   module at the MCB core.
+
+
+  static int __init foo_init(void)
+  {
+          return mcb_register_driver(&foo_driver);
+  }
+  module_init(foo_init);
+
+  static void __exit foo_exit(void)
+  {
+          mcb_unregister_driver(&foo_driver);
+  }
+  module_exit(foo_exit);
+
+   The module_mcb_driver() macro can be used to reduce the above code.
+
+
+  module_mcb_driver(foo_driver);
index 8d47501bba0acb1a767ac9bd16c481e41a546287..91c1fa34f48b4a5a662bb14b2d422437795fd474 100644 (file)
@@ -96,7 +96,7 @@ A code snippet for an application communicating with Intel AMTHI client:
 IOCTL
 =====
 
-The Intel MEI Driver supports the following IOCTL command:
+The Intel MEI Driver supports the following IOCTL commands:
        IOCTL_MEI_CONNECT_CLIENT        Connect to firmware Feature (client).
 
        usage:
@@ -125,6 +125,49 @@ The Intel MEI Driver supports the following IOCTL command:
         data that can be sent or received. (e.g. if MTU=2K, can send
         requests up to bytes 2k and received responses up to 2k bytes).
 
+       IOCTL_MEI_NOTIFY_SET: enable or disable event notifications
+
+       Usage:
+               uint32_t enable;
+               ioctl(fd, IOCTL_MEI_NOTIFY_SET, &enable);
+
+       Inputs:
+               uint32_t enable = 1;
+               or
+               uint32_t enable[disable] = 0;
+
+       Error returns:
+               EINVAL  Wrong IOCTL Number
+               ENODEV  Device  is not initialized or the client not connected
+               ENOMEM  Unable to allocate memory to client internal data.
+               EFAULT  Fatal Error (e.g. Unable to access user input data)
+               EOPNOTSUPP if the device doesn't support the feature
+
+       Notes:
+       The client must be connected in order to enable notification events
+
+
+       IOCTL_MEI_NOTIFY_GET : retrieve event
+
+       Usage:
+               uint32_t event;
+               ioctl(fd, IOCTL_MEI_NOTIFY_GET, &event);
+
+       Outputs:
+               1 - if an event is pending
+               0 - if there is no even pending
+
+       Error returns:
+               EINVAL  Wrong IOCTL Number
+               ENODEV  Device is not initialized or the client not connected
+               ENOMEM  Unable to allocate memory to client internal data.
+               EFAULT  Fatal Error (e.g. Unable to access user input data)
+               EOPNOTSUPP if the device doesn't support the feature
+
+       Notes:
+       The client must be connected and event notification has to be enabled
+       in order to receive an event
+
 
 Intel ME Applications
 =====================
index b48d4a1494113c9842b45de8f299f20ecc96c620..fd1a1aad49a9c5251e464cdc382119135c4cdd9b 100644 (file)
@@ -510,7 +510,7 @@ solution for a couple of reasons:
 
   4.1.2 RAW socket option CAN_RAW_ERR_FILTER
 
-  As described in chapter 3.4 the CAN interface driver can generate so
+  As described in chapter 3.3 the CAN interface driver can generate so
   called Error Message Frames that can optionally be passed to the user
   application in the same way as other CAN frames. The possible
   errors are divided into different error classes that may be filtered
@@ -1152,7 +1152,7 @@ solution for a couple of reasons:
     $ ip link set canX type can restart
 
   Note that a restart will also create a CAN error message frame (see
-  also chapter 3.4).
+  also chapter 3.3).
 
   6.6 CAN FD (flexible data rate) driver support
 
diff --git a/Documentation/nvmem/nvmem.txt b/Documentation/nvmem/nvmem.txt
new file mode 100644 (file)
index 0000000..dbd40d8
--- /dev/null
@@ -0,0 +1,152 @@
+                           NVMEM SUBSYSTEM
+         Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+This document explains the NVMEM Framework along with the APIs provided,
+and how to use it.
+
+1. Introduction
+===============
+*NVMEM* is the abbreviation for Non Volatile Memory layer. It is used to
+retrieve configuration of SOC or Device specific data from non volatile
+memories like eeprom, efuses and so on.
+
+Before this framework existed, NVMEM drivers like eeprom were stored in
+drivers/misc, where they all had to duplicate pretty much the same code to
+register a sysfs file, allow in-kernel users to access the content of the
+devices they were driving, etc.
+
+This was also a problem as far as other in-kernel users were involved, since
+the solutions used were pretty much different from one driver to another, there
+was a rather big abstraction leak.
+
+This framework aims at solve these problems. It also introduces DT
+representation for consumer devices to go get the data they require (MAC
+Addresses, SoC/Revision ID, part numbers, and so on) from the NVMEMs. This
+framework is based on regmap, so that most of the abstraction available in
+regmap can be reused, across multiple types of buses.
+
+NVMEM Providers
++++++++++++++++
+
+NVMEM provider refers to an entity that implements methods to initialize, read
+and write the non-volatile memory.
+
+2. Registering/Unregistering the NVMEM provider
+===============================================
+
+A NVMEM provider can register with NVMEM core by supplying relevant
+nvmem configuration to nvmem_register(), on success core would return a valid
+nvmem_device pointer.
+
+nvmem_unregister(nvmem) is used to unregister a previously registered provider.
+
+For example, a simple qfprom case:
+
+static struct nvmem_config econfig = {
+       .name = "qfprom",
+       .owner = THIS_MODULE,
+};
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+       ...
+       econfig.dev = &pdev->dev;
+       nvmem = nvmem_register(&econfig);
+       ...
+}
+
+It is mandatory that the NVMEM provider has a regmap associated with its
+struct device. Failure to do would return error code from nvmem_register().
+
+NVMEM Consumers
++++++++++++++++
+
+NVMEM consumers are the entities which make use of the NVMEM provider to
+read from and to NVMEM.
+
+3. NVMEM cell based consumer APIs
+=================================
+
+NVMEM cells are the data entries/fields in the NVMEM.
+The NVMEM framework provides 3 APIs to read/write NVMEM cells.
+
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+*nvmem_cell_get() apis will get a reference to nvmem cell for a given id,
+and nvmem_cell_read/write() can then read or write to the cell.
+Once the usage of the cell is finished the consumer should call *nvmem_cell_put()
+to free all the allocation memory for the cell.
+
+4. Direct NVMEM device based consumer APIs
+==========================================
+
+In some instances it is necessary to directly read/write the NVMEM.
+To facilitate such consumers NVMEM framework provides below apis.
+
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+                                          const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+                     size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+                      size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+                          struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+                           struct nvmem_cell_info *info, void *buf);
+
+Before the consumers can read/write NVMEM directly, it should get hold
+of nvmem_controller from one of the *nvmem_device_get() api.
+
+The difference between these apis and cell based apis is that these apis always
+take nvmem_device as parameter.
+
+5. Releasing a reference to the NVMEM
+=====================================
+
+When a consumers no longer needs the NVMEM, it has to release the reference
+to the NVMEM it has obtained using the APIs mentioned in the above section.
+The NVMEM framework provides 2 APIs to release a reference to the NVMEM.
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+
+Both these APIs are used to release a reference to the NVMEM and
+devm_nvmem_cell_put and devm_nvmem_device_put destroys the devres associated
+with this NVMEM.
+
+Userspace
++++++++++
+
+6. Userspace binary interface
+==============================
+
+Userspace can read/write the raw NVMEM file located at
+/sys/bus/nvmem/devices/*/nvmem
+
+ex:
+
+hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
+
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+*
+00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+...
+*
+0001000
+
+7. DeviceTree Binding
+=====================
+
+See Documentation/devicetree/bindings/nvmem/nvmem.txt
index 2850df3bf957b2460fbd22bb74af20161b613367..2fc909502db59d2f795ab5e9db92b98714e32dcf 100644 (file)
@@ -72,7 +72,7 @@ More details follow:
                                         |
                                         v
                            Disable regular cpu hotplug
-                        by setting cpu_hotplug_disabled=1
+                        by increasing cpu_hotplug_disabled
                                         |
                                         v
                             Release cpu_add_remove_lock
@@ -89,7 +89,7 @@ Resuming back is likewise, with the counterparts being (in the order of
 execution during resume):
 * enable_nonboot_cpus() which involves:
    |  Acquire cpu_add_remove_lock
-   |  Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug
+   |  Decrease cpu_hotplug_disabled, thereby enabling regular cpu hotplug
    |  Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop]
    |  Release cpu_add_remove_lock
    v
@@ -120,7 +120,7 @@ after the entire cycle is complete (i.e., suspend + resume).
                            Acquire cpu_add_remove_lock
                                         |
                                         v
-                          If cpu_hotplug_disabled is 1
+                          If cpu_hotplug_disabled > 0
                                 return gracefully
                                         |
                                         |
index 2a230d01cd8ce30265c4135bfd461afccbdaf18d..205c1b81625c3175aa4cb99865e1033d181dd19b 100644 (file)
@@ -133,7 +133,7 @@ User API
     The following file operations are supported on both slave and
     master devices.
 
-    A userspace library libcxl is avaliable here:
+    A userspace library libcxl is available here:
        https://github.com/ibm-capi/libcxl
     This provides a C interface to this kernel API.
 
index 1ff4400c57b3deccf1ab1764f70dfed952027e93..ece300c64f760928afb0589e641a1bd5f1d72014 100644 (file)
@@ -4,7 +4,7 @@
 DSCR register in powerpc allows user to have some control of prefetch of data
 stream in the processor. Please refer to the ISA documents or related manual
 for more detailed information regarding how to use this DSCR to attain this
-control of the pefetches . This document here provides an overview of kernel
+control of the prefetches . This document here provides an overview of kernel
 support for DSCR, related kernel objects, it's functionalities and exported
 user interface.
 
@@ -44,7 +44,7 @@ user interface.
        value into every CPU's DSCR register right away and updates the current
        thread's DSCR value as well.
 
-       Changing the CPU specif DSCR default value in the sysfs does exactly
+       Changing the CPU specific DSCR default value in the sysfs does exactly
        the same thing as above but unlike the global one above, it just changes
        stuff for that particular CPU instead for all the CPUs on the system.
 
@@ -62,7 +62,7 @@ user interface.
 
        Accessing DSCR through user level SPR (0x03) from user space will first
        create a facility unavailable exception. Inside this exception handler
-       all mfspr isntruction based read attempts will get emulated and returned
+       all mfspr instruction based read attempts will get emulated and returned
        where as the first mtspr instruction based write attempts will enable
        the DSCR facility for the next time around (both for read and write) by
        setting DSCR facility in the FSCR register.
index 2031ddb33d097d4d78496caadbf16f74481839c3..e7ac24aec4ff0807d15e4be7c7941c1efda01e14 100644 (file)
@@ -117,7 +117,7 @@ specific been defined.  This table describes the structure.
 Extended Modes
 
 This is a double word bit array (64 bits) that defines special functionality
-which has an impact on the softwarew drivers.  Each bit has its own impact
+which has an impact on the software drivers.  Each bit has its own impact
 and has special instructions for the s/w associated with it.  This structure is
 described in this table:
 
index c508cceeee7d0358f7e7165e0c0d50b07a01a005..7cb7264ad598868a3dc8893a7700f322bb29c6f5 100644 (file)
@@ -125,7 +125,7 @@ The same function may also run the defined echo function
 (pps_ktimer_echo(), passing to it the "ptr" pointer) if the user
 asked for that... etc..
 
-Please see the file drivers/pps/clients/ktimer.c for example code.
+Please see the file drivers/pps/clients/pps-ktimer.c for example code.
 
 
 SYSFS support
index 10c874ebdfe5293a0da287ac2037a46904f23bc4..9189535f6cd298fd5b6e7b9967a4bf681197a8d2 100644 (file)
@@ -16,8 +16,6 @@ Debugging390.txt
        - hints for debugging on s390 systems.
 driver-model.txt
        - information on s390 devices and the driver model.
-kvm.txt
-       - ioctl calls to /dev/kvm on s390.
 monreader.txt
        - information on accessing the z/VM monitor stream from Linux.
 qeth.txt
diff --git a/Documentation/s390/kvm.txt b/Documentation/s390/kvm.txt
deleted file mode 100644 (file)
index 85f3280..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-*** BIG FAT WARNING ***
-The kvm module is currently in EXPERIMENTAL state for s390. This means that
-the interface to the module is not yet considered to remain stable. Thus, be
-prepared that we keep breaking your userspace application and guest
-compatibility over and over again until we feel happy with the result. Make sure
-your guest kernel, your host kernel, and your userspace launcher are in a
-consistent state.
-
-This Documentation describes the unique ioctl calls to /dev/kvm, the resulting
-kvm-vm file descriptors, and the kvm-vcpu file descriptors that differ from x86.
-
-1. ioctl calls to /dev/kvm
-KVM does support the following ioctls on s390 that are common with other
-architectures and do behave the same:
-KVM_GET_API_VERSION
-KVM_CREATE_VM          (*) see note
-KVM_CHECK_EXTENSION
-KVM_GET_VCPU_MMAP_SIZE
-
-Notes:
-* KVM_CREATE_VM may fail on s390, if the calling process has multiple
-threads and has not called KVM_S390_ENABLE_SIE before.
-
-In addition, on s390 the following architecture specific ioctls are supported:
-ioctl:         KVM_S390_ENABLE_SIE
-args:          none
-see also:      include/linux/kvm.h
-This call causes the kernel to switch on PGSTE in the user page table. This
-operation is needed in order to run a virtual machine, and it requires the
-calling process to be single-threaded. Note that the first call to KVM_CREATE_VM
-will implicitly try to switch on PGSTE if the user process has not called
-KVM_S390_ENABLE_SIE before. User processes that want to launch multiple threads
-before creating a virtual machine have to call KVM_S390_ENABLE_SIE, or will
-observe an error calling KVM_CREATE_VM. Switching on PGSTE is a one-time
-operation, is not reversible, and will persist over the entire lifetime of
-the calling process. It does not have any user-visible effect other than a small
-performance penalty.
-
-2. ioctl calls to the kvm-vm file descriptor
-KVM does support the following ioctls on s390 that are common with other
-architectures and do behave the same:
-KVM_CREATE_VCPU
-KVM_SET_USER_MEMORY_REGION      (*) see note
-KVM_GET_DIRTY_LOG              (**) see note
-
-Notes:
-*  kvm does only allow exactly one memory slot on s390, which has to start
-   at guest absolute address zero and at a user address that is aligned on any
-   page boundary. This hardware "limitation" allows us to have a few unique
-   optimizations. The memory slot doesn't have to be filled
-   with memory actually, it may contain sparse holes. That said, with different
-   user memory layout this does still allow a large flexibility when
-   doing the guest memory setup.
-** KVM_GET_DIRTY_LOG doesn't work properly yet. The user will receive an empty
-log. This ioctl call is only needed for guest migration, and we intend to
-implement this one in the future.
-
-In addition, on s390 the following architecture specific ioctls for the kvm-vm
-file descriptor are supported:
-ioctl:         KVM_S390_INTERRUPT
-args:          struct kvm_s390_interrupt *
-see also:      include/linux/kvm.h
-This ioctl is used to submit a floating interrupt for a virtual machine.
-Floating interrupts may be delivered to any virtual cpu in the configuration.
-Only some interrupt types defined in include/linux/kvm.h make sense when
-submitted as floating interrupts. The following interrupts are not considered
-to be useful as floating interrupts, and a call to inject them will result in
--EINVAL error code: program interrupts and interprocessor signals. Valid
-floating interrupts are:
-KVM_S390_INT_VIRTIO
-KVM_S390_INT_SERVICE
-
-3. ioctl calls to the kvm-vcpu file descriptor
-KVM does support the following ioctls on s390 that are common with other
-architectures and do behave the same:
-KVM_RUN
-KVM_GET_REGS
-KVM_SET_REGS
-KVM_GET_SREGS
-KVM_SET_SREGS
-KVM_GET_FPU
-KVM_SET_FPU
-
-In addition, on s390 the following architecture specific ioctls for the
-kvm-vcpu file descriptor are supported:
-ioctl:         KVM_S390_INTERRUPT
-args:          struct kvm_s390_interrupt *
-see also:      include/linux/kvm.h
-This ioctl is used to submit an interrupt for a specific virtual cpu.
-Only some interrupt types defined in include/linux/kvm.h make sense when
-submitted for a specific cpu. The following interrupts are not considered
-to be useful, and a call to inject them will result in -EINVAL error code:
-service processor calls and virtio interrupts. Valid interrupt types are:
-KVM_S390_PROGRAM_INT
-KVM_S390_SIGP_STOP
-KVM_S390_RESTART
-KVM_S390_SIGP_SET_PREFIX
-KVM_S390_INT_EMERGENCY
-
-ioctl:         KVM_S390_STORE_STATUS
-args:          unsigned long
-see also:      include/linux/kvm.h
-This ioctl stores the state of the cpu at the guest real address given as
-argument, unless one of the following values defined in include/linux/kvm.h
-is given as argument:
-KVM_S390_STORE_STATUS_NOADDR - the CPU stores its status to the save area in
-absolute lowcore as defined by the principles of operation
-KVM_S390_STORE_STATUS_PREFIXED - the CPU stores its status to the save area in
-its prefix page just like the dump tool that comes with zipl. This is useful
-to create a system dump for use with lkcdutils or crash.
-
-ioctl:         KVM_S390_SET_INITIAL_PSW
-args:          struct kvm_s390_psw *
-see also:      include/linux/kvm.h
-This ioctl can be used to set the processor status word (psw) of a stopped cpu
-prior to running it with KVM_RUN. Note that this call is not required to modify
-the psw during sie intercepts that fall back to userspace because struct kvm_run
-does contain the psw, and this value is evaluated during reentry of KVM_RUN
-after the intercept exit was recognized.
-
-ioctl:         KVM_S390_INITIAL_RESET
-args:          none
-see also:      include/linux/kvm.h
-This ioctl can be used to perform an initial cpu reset as defined by the
-principles of operation. The target cpu has to be in stopped state.
index 9832ec52f859a2f4e3c99b0767ef957a59a97bf1..9c3f2f8054b5f90411b341a6e39a4b060c78804a 100644 (file)
@@ -225,11 +225,11 @@ with your system.  To disable them, echo 4 (bit 3) into drop_caches.
 extfrag_threshold
 
 This parameter affects whether the kernel will compact memory or direct
-reclaim to satisfy a high-order allocation. /proc/extfrag_index shows what
-the fragmentation index for each order is in each zone in the system. Values
-tending towards 0 imply allocations would fail due to lack of memory,
-values towards 1000 imply failures are due to fragmentation and -1 implies
-that the allocation will succeed as long as watermarks are met.
+reclaim to satisfy a high-order allocation. The extfrag/extfrag_index file in
+debugfs shows what the fragmentation index for each order is in each zone in
+the system. Values tending towards 0 imply allocations would fail due to lack
+of memory, values towards 1000 imply failures are due to fragmentation and -1
+implies that the allocation will succeed as long as watermarks are met.
 
 The kernel will not compact memory in a zone if the
 fragmentation index is <= extfrag_threshold. The default value is 500.
index 77d14d51a670a523a14ec9b4581f66d720ba3e76..0a5c3290e7324f09ab01dac65f6825d22e35ea09 100644 (file)
@@ -15,7 +15,7 @@ HW assisted tracing is becoming increasingly useful when dealing with systems
 that have many SoCs and other components like GPU and DMA engines.  ARM has
 developed a HW assisted tracing solution by means of different components, each
 being added to a design at synthesis time to cater to specific tracing needs.
-Compoments are generally categorised as source, link and sinks and are
+Components are generally categorised as source, link and sinks and are
 (usually) discovered using the AMBA bus.
 
 "Sources" generate a compressed stream representing the processor instruction
@@ -138,7 +138,7 @@ void coresight_unregister(struct coresight_device *csdev);
 
 The registering function is taking a "struct coresight_device *csdev" and
 register the device with the core framework.  The unregister function takes
-a reference to a "strut coresight_device", obtained at registration time.
+a reference to a "struct coresight_device", obtained at registration time.
 
 If everything goes well during the registration process the new devices will
 show up under /sys/bus/coresight/devices, as showns here for a TC2 platform:
index 592678009c15c393d59b9ce190b6a96057486160..b24d3ef89166bc16f228e97aceb6f300063edc2a 100644 (file)
@@ -237,9 +237,7 @@ Testing the LOOPBACK function
 -----------------------------
 
 device: run the gadget
-host: test-usb
-
-http://www.linux-usb.org/usbtest/testusb.c
+host: test-usb (tools/usb/testusb.c)
 
 8. MASS STORAGE function
 ========================
@@ -586,9 +584,8 @@ Testing the SOURCESINK function
 -------------------------------
 
 device: run the gadget
-host: test-usb
+host: test-usb (tools/usb/testusb.c)
 
-http://www.linux-usb.org/usbtest/testusb.c
 
 16. UAC1 function
 =================
index b5f83911732a4a2af39873db9a851bf6d296dd07..4a15c90bc11d93d362b0397899091d048992a545 100644 (file)
@@ -521,10 +521,10 @@ enabling hardware LPM, the host can automatically put the device into
 lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
 which state device can enter and resume very quickly.
 
-The user interface for controlling USB2 hardware LPM is located in the
+The user interface for controlling hardware LPM is located in the
 power/ subdirectory of each USB device's sysfs directory, that is, in
 /sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
-relevant attribute files is usb2_hardware_lpm.
+relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
 
        power/usb2_hardware_lpm
 
@@ -537,6 +537,17 @@ relevant attribute files is usb2_hardware_lpm.
                can write y/Y/1 or n/N/0 to the file to enable/disable
                USB2 hardware LPM manually. This is for test purpose mainly.
 
+       power/usb3_hardware_lpm
+
+               When a USB 3.0 lpm-capable device is plugged in to a
+               xHCI host which supports link PM, it will check if U1
+               and U2 exit latencies have been set in the BOS
+               descriptor; if the check is is passed and the host
+               supports USB3 hardware LPM, USB3 hardware LPM will be
+               enabled for the device and this file will be created.
+               The file holds a string value (enable or disable)
+               indicating whether or not USB3 hardware LPM is
+               enabled for the device.
 
        USB Port Power Control
        ----------------------
index a7926a90156f64172897ca5a9ae562f7975701a7..a4ebcb712375478e9bb60a7652d49f4d46b9c978 100644 (file)
@@ -3277,6 +3277,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
                struct {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
+#define KVM_SYSTEM_EVENT_CRASH          3
                        __u32 type;
                        __u64 flags;
                } system_event;
@@ -3296,6 +3297,10 @@ Valid values for 'type' are:
   KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
    As with SHUTDOWN, userspace can choose to ignore the request, or
    to schedule the reset to occur in the future and may call KVM_RUN again.
+  KVM_SYSTEM_EVENT_CRASH -- the guest crash occurred and the guest
+   has requested a crash condition maintenance. Userspace can choose
+   to ignore the request, or to gather VM memory core dump and/or
+   reset/shutdown of the VM.
 
                /* Fix the size of the union. */
                char padding[256];
index 0f3a6c20194326e9880bfea3c9ee78d0c8c89e65..9a0aa4d3a866938170c1b652577c9ed9d69aab29 100644 (file)
@@ -16,7 +16,7 @@ associated with each CPU.  These stacks are only used while the kernel
 is in control on that CPU; when a CPU returns to user space the
 specialized stacks contain no useful data.  The main CPU stacks are:
 
-* Interrupt stack.  IRQSTACKSIZE
+* Interrupt stack.  IRQ_STACK_SIZE
 
   Used for external hardware interrupts.  If this is the first external
   hardware interrupt (i.e. not a nested hardware interrupt) then the
index 20f3735fbda7e9d036c4780a2414fcb85a83cf9d..963233fc721bc37d49c626e11d650c728ff3120e 100644 (file)
@@ -556,6 +556,12 @@ S: Maintained
 F:     Documentation/i2c/busses/i2c-ali1563
 F:     drivers/i2c/busses/i2c-ali1563.c
 
+ALLWINNER SECURITY SYSTEM
+M:     Corentin Labbe <clabbe.montjoie@gmail.com>
+L:     linux-crypto@vger.kernel.org
+S:     Maintained
+F:     drivers/crypto/sunxi-ss/
+
 ALPHA PORT
 M:     Richard Henderson <rth@twiddle.net>
 M:     Ivan Kokshaysky <ink@jurassic.park.msu.ru>
@@ -3454,6 +3460,7 @@ X:        Documentation/devicetree/
 X:     Documentation/acpi
 X:     Documentation/power
 X:     Documentation/spi
+X:     Documentation/DocBook/media
 T:     git git://git.lwn.net/linux-2.6.git docs-next
 
 DOUBLETALK DRIVER
@@ -3587,6 +3594,15 @@ S:       Maintained
 F:     drivers/gpu/drm/rockchip/
 F:     Documentation/devicetree/bindings/video/rockchip*
 
+DRM DRIVERS FOR STI
+M:     Benjamin Gaignard <benjamin.gaignard@linaro.org>
+M:     Vincent Abriou <vincent.abriou@st.com>
+L:     dri-devel@lists.freedesktop.org
+T:     git http://git.linaro.org/people/benjamin.gaignard/kernel.git
+S:     Maintained
+F:     drivers/gpu/drm/sti
+F:     Documentation/devicetree/bindings/gpu/st,stih4xx.txt
+
 DSBR100 USB FM RADIO DRIVER
 M:     Alexey Klimov <klimov.linux@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -4957,6 +4973,7 @@ F:        drivers/scsi/storvsc_drv.c
 F:     drivers/video/fbdev/hyperv_fb.c
 F:     include/linux/hyperv.h
 F:     tools/hv/
+F:     Documentation/ABI/stable/sysfs-bus-vmbus
 
 I2C OVER PARALLEL PORT
 M:     Jean Delvare <jdelvare@suse.com>
@@ -5067,9 +5084,21 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
 S:     Maintained
 F:     arch/ia64/
 
+IBM Power VMX Cryptographic instructions
+M:     Leonidas S. Barbosa <leosilva@linux.vnet.ibm.com>
+M:     Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
+L:     linux-crypto@vger.kernel.org
+S:     Supported
+F:     drivers/crypto/vmx/Makefile
+F:     drivers/crypto/vmx/Kconfig
+F:     drivers/crypto/vmx/vmx.c
+F:     drivers/crypto/vmx/aes*
+F:     drivers/crypto/vmx/ghash*
+F:     drivers/crypto/vmx/ppc-xlate.pl
+
 IBM Power in-Nest Crypto Acceleration
-M:     Marcelo Henrique Cerri <mhcerri@linux.vnet.ibm.com>
-M:     Fionnuala Gunter <fin@linux.vnet.ibm.com>
+M:     Leonidas S. Barbosa <leosilva@linux.vnet.ibm.com>
+M:     Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
 L:     linux-crypto@vger.kernel.org
 S:     Supported
 F:     drivers/crypto/nx/Makefile
@@ -5081,7 +5110,7 @@ F:        drivers/crypto/nx/nx_csbcpb.h
 F:     drivers/crypto/nx/nx_debugfs.h
 
 IBM Power 842 compression accelerator
-M:     Dan Streetman <ddstreet@us.ibm.com>
+M:     Dan Streetman <ddstreet@ieee.org>
 S:     Supported
 F:     drivers/crypto/nx/Makefile
 F:     drivers/crypto/nx/Kconfig
@@ -5840,6 +5869,7 @@ S:        Odd Fixes
 
 KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
 M:     "J. Bruce Fields" <bfields@fieldses.org>
+M:     Jeff Layton <jlayton@poochiereds.net>
 L:     linux-nfs@vger.kernel.org
 W:     http://nfs.sourceforge.net/
 S:     Supported
@@ -5896,7 +5926,6 @@ F:        arch/powerpc/kvm/
 KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
 M:     Christian Borntraeger <borntraeger@de.ibm.com>
 M:     Cornelia Huck <cornelia.huck@de.ibm.com>
-M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -6031,11 +6060,10 @@ F:      Documentation/scsi/53c700.txt
 F:     drivers/scsi/53c700*
 
 LED SUBSYSTEM
-M:     Bryan Wu <cooloney@gmail.com>
 M:     Richard Purdie <rpurdie@rpsys.net>
 M:     Jacek Anaszewski <j.anaszewski@samsung.com>
 L:     linux-leds@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git
 S:     Maintained
 F:     drivers/leds/
 F:     include/linux/leds.h
@@ -6539,6 +6567,13 @@ S:       Maintained
 F:     Documentation/hwmon/max16065
 F:     drivers/hwmon/max16065.c
 
+MAX20751 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/max20751
+F:     drivers/hwmon/max20751.c
+
 MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
 M:     "Hans J. Koch" <hjk@hansjkoch.de>
 L:     lm-sensors@lm-sensors.org
@@ -6683,6 +6718,7 @@ M:        Johannes Thumshirn <morbidrsa@gmail.com>
 S:     Maintained
 F:     drivers/mcb/
 F:     include/linux/mcb.h
+F:     Documentation/men-chameleon-bus.txt
 
 MEN F21BMC (Board Management Controller)
 M:     Andreas Werner <andreas.werner@men.de>
@@ -7288,6 +7324,15 @@ S:       Supported
 F:     drivers/block/nvme*
 F:     include/linux/nvme.h
 
+NVMEM FRAMEWORK
+M:     Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+M:     Maxime Ripard <maxime.ripard@free-electrons.com>
+S:     Maintained
+F:     drivers/nvmem/
+F:     Documentation/devicetree/bindings/nvmem/
+F:     include/linux/nvmem-consumer.h
+F:     include/linux/nvmem-provider.h
+
 NXP-NCI NFC DRIVER
 M:     Clément Perrochaud <clement.perrochaud@effinnov.com>
 R:     Charles Gorand <charles.gorand@effinnov.com>
@@ -8074,6 +8119,7 @@ T:        git git://git.infradead.org/battery-2.6.git
 S:     Maintained
 F:     include/linux/power_supply.h
 F:     drivers/power/
+X:     drivers/power/avs/
 
 PNP SUPPORT
 M:     "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
@@ -8698,7 +8744,6 @@ F:        drivers/video/fbdev/savage/
 S390
 M:     Martin Schwidefsky <schwidefsky@de.ibm.com>
 M:     Heiko Carstens <heiko.carstens@de.ibm.com>
-M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -8726,7 +8771,6 @@ F:        block/partitions/ibm.c
 
 S390 NETWORK DRIVERS
 M:     Ursula Braun <ursula.braun@de.ibm.com>
-M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -8743,7 +8787,6 @@ F:        drivers/pci/hotplug/s390_pci_hpc.c
 
 S390 ZCRYPT DRIVER
 M:     Ingo Tuchscherer <ingo.tuchscherer@de.ibm.com>
-M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -8751,7 +8794,6 @@ F:        drivers/s390/crypto/
 
 S390 ZFCP DRIVER
 M:     Steffen Maier <maier@linux.vnet.ibm.com>
-M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -8759,7 +8801,6 @@ F:        drivers/s390/scsi/zfcp_*
 
 S390 IUCV NETWORK LAYER
 M:     Ursula Braun <ursula.braun@de.ibm.com>
-M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -9328,6 +9369,15 @@ S:       Maintained
 F:     drivers/media/i2c/ov2659.c
 F:     include/media/ov2659.h
 
+SILICON MOTION SM712 FRAME BUFFER DRIVER
+M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+M:     Teddy Wang <teddy.wang@siliconmotion.com>
+M:     Sudip Mukherjee <sudip@vectorindia.org>
+L:     linux-fbdev@vger.kernel.org
+S:     Maintained
+F:     drivers/video/fbdev/sm712*
+F:     Documentation/fb/sm712fb.txt
+
 SIS 190 ETHERNET DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
@@ -9725,11 +9775,6 @@ W:       http://wiki.laptop.org/go/DCON
 S:     Maintained
 F:     drivers/staging/olpc_dcon/
 
-STAGING - OZMO DEVICES USB OVER WIFI DRIVER
-M:     Shigekatsu Tateno <shigekatsu.tateno@atmel.com>
-S:     Maintained
-F:     drivers/staging/ozwpan/
-
 STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER
 M:     Willy Tarreau <willy@meta-x.org>
 S:     Odd Fixes
@@ -9748,14 +9793,6 @@ L:       linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/staging/rtl8723au/
 
-STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
-M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
-M:     Teddy Wang <teddy.wang@siliconmotion.com>
-M:     Sudip Mukherjee <sudip@vectorindia.org>
-L:     linux-fbdev@vger.kernel.org
-S:     Maintained
-F:     drivers/staging/sm7xxfb/
-
 STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
 M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 M:     Teddy Wang <teddy.wang@siliconmotion.com>
index 35b4c196c171306f8ce66791eb6f91f57fbbb215..c3615937df3891f8418db7a05656c9969954ee80 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION =
 NAME = Hurr durr I'ma sheep
 
 # *DOCUMENTATION*
diff --git a/README b/README
index 69c68fb4a10908a4f8d1986c6fdad2ec7b3c397b..a326a6a6a46f194203371603cfbe94b4b72a2a1b 100644 (file)
--- a/README
+++ b/README
@@ -161,7 +161,7 @@ CONFIGURING the kernel:
 
      "make xconfig"     X windows (Qt) based configuration tool.
 
-     "make gconfig"     X windows (Gtk) based configuration tool.
+     "make gconfig"     X windows (GTK+) based configuration tool.
 
      "make oldconfig"   Default all questions based on the contents of
                         your existing ./.config file and asking about
index bf9e9d3b379218b74aa2bf6506d62f7978f71abd..f515a4dbf7a0621e902fc488ef0108ac34d60b4c 100644 (file)
@@ -3,6 +3,7 @@ config ALPHA
        default y
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
+       select ARCH_USE_CMPXCHG_LOCKREF
        select HAVE_AOUT
        select HAVE_IDE
        select HAVE_OPROFILE
index 37b570d01202e4ee62d5dcc11af345f1805e81a0..fed9c6f44c191295d36f4ab8a9a9352883a1c5b1 100644 (file)
 #define arch_spin_unlock_wait(x) \
                do { cpu_relax(); } while ((x)->lock)
 
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+        return lock.lock == 0;
+}
+
 static inline void arch_spin_unlock(arch_spinlock_t * lock)
 {
        mb();
index 82f738e5d54cb85f5b77c21304fd590d1e5bbbc5..cded02c890aacb5b32813332b61df3b4523fbd05 100644 (file)
@@ -242,12 +242,7 @@ pci_restore_srm_config(void)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dev = bus->self;
-
-       if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
-                  (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-               pci_read_bridge_bases(bus);
-       } 
+       struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                pdev_save_srm_config(dev);
index 07ab3d203916732337f909ec5f903db4c7bb1294..7451b447cc2d2cb8cc68a9bf59f125f2dd2ce347 100644 (file)
@@ -312,6 +312,9 @@ INSTALL_TARGETS     = zinstall uinstall install
 
 PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS)
 
+bootpImage uImage: zImage
+zImage: Image
+
 $(BOOT_TARGETS): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
index 21fcc440fc1a9d886d408701a705ad4daabd2325..b76f9a2ce05d827c29c8dd47fc80bf219e44be22 100644 (file)
                };
 
                uart0: serial@44e09000 {
-                       compatible = "ti,omap3-uart";
+                       compatible = "ti,am3352-uart", "ti,omap3-uart";
                        ti,hwmods = "uart1";
                        clock-frequency = <48000000>;
                        reg = <0x44e09000 0x2000>;
                };
 
                uart1: serial@48022000 {
-                       compatible = "ti,omap3-uart";
+                       compatible = "ti,am3352-uart", "ti,omap3-uart";
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                        reg = <0x48022000 0x2000>;
                };
 
                uart2: serial@48024000 {
-                       compatible = "ti,omap3-uart";
+                       compatible = "ti,am3352-uart", "ti,omap3-uart";
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                        reg = <0x48024000 0x2000>;
                };
 
                uart3: serial@481a6000 {
-                       compatible = "ti,omap3-uart";
+                       compatible = "ti,am3352-uart", "ti,omap3-uart";
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                        reg = <0x481a6000 0x2000>;
                };
 
                uart4: serial@481a8000 {
-                       compatible = "ti,omap3-uart";
+                       compatible = "ti,am3352-uart", "ti,omap3-uart";
                        ti,hwmods = "uart5";
                        clock-frequency = <48000000>;
                        reg = <0x481a8000 0x2000>;
                };
 
                uart5: serial@481aa000 {
-                       compatible = "ti,omap3-uart";
+                       compatible = "ti,am3352-uart", "ti,omap3-uart";
                        ti,hwmods = "uart6";
                        clock-frequency = <48000000>;
                        reg = <0x481aa000 0x2000>;
index a63bf78191ea5a57093e97f1d1fc95d904695816..f9a4b317ed2fc4d6c40fcd13d6422ecb6787fb74 100644 (file)
                };
        };
 };
+
+&pcie1 {
+       gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
+};
index 4a0718ccf68e3fe6c262c81596e35c0ec2bfd697..b058b314687490ab3902512283f2e14cf4188fd5 100644 (file)
                                ranges = <0 0x2000 0x2000>;
 
                                scm_conf: scm_conf@0 {
-                                       compatible = "syscon";
+                                       compatible = "syscon", "simple-bus";
                                        reg = <0x0 0x1400>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
                        #address-cells = <1>;
                        ranges = <0x51000000 0x51000000 0x3000
                                  0x0        0x20000000 0x10000000>;
-                       pcie@51000000 {
+                       pcie1: pcie@51000000 {
                                compatible = "ti,dra7-pcie";
                                reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>;
                                reg-names = "rc_dbics", "ti_conf", "config";
                };
 
                uart1: serial@4806a000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x4806a000 0x100>;
                        interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart1";
                };
 
                uart2: serial@4806c000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x4806c000 0x100>;
                        interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart2";
                };
 
                uart3: serial@48020000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x48020000 0x100>;
                        interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart3";
                };
 
                uart4: serial@4806e000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x4806e000 0x100>;
                        interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart4";
                };
 
                uart5: serial@48066000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x48066000 0x100>;
                        interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart5";
                };
 
                uart6: serial@48068000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x48068000 0x100>;
                        interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart6";
                };
 
                uart7: serial@48420000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x48420000 0x100>;
                        interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart7";
                };
 
                uart8: serial@48422000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x48422000 0x100>;
                        interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart8";
                };
 
                uart9: serial@48424000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x48424000 0x100>;
                        interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart9";
                };
 
                uart10: serial@4ae2b000 {
-                       compatible = "ti,omap4-uart";
+                       compatible = "ti,dra742-uart", "ti,omap4-uart";
                        reg = <0x4ae2b000 0x100>;
                        interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart10";
index e6d13592080d7c701056c2f6a73326aa11e715b5..10d0b26c93f1dac3974df73f1ae11e2a1f535484 100644 (file)
                        interrupt-names = "msi";
                        #interrupt-cells = <1>;
                        interrupt-map-mask = <0 0 0 0x7>;
-                       interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
-                                       <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
-                                       <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
-                                       <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-map = <0 0 0 1 &gpc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
                                 <&clks IMX6QDL_CLK_LVDS1_GATE>,
                                 <&clks IMX6QDL_CLK_PCIE_REF_125M>;
                        reg = <0x02100000 0x100000>;
                        ranges;
 
-                       caam@02100000 {
-                               reg = <0x02100000 0x40000>;
-                               interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>,
-                                            <0 106 IRQ_TYPE_LEVEL_HIGH>;
+                       crypto: caam@2100000 {
+                               compatible = "fsl,sec-v4.0";
+                               fsl,sec-era = <4>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x2100000 0x10000>;
+                               ranges = <0 0x2100000 0x10000>;
+                               interrupt-parent = <&intc>;
+                               clocks = <&clks IMX6QDL_CLK_CAAM_MEM>,
+                                        <&clks IMX6QDL_CLK_CAAM_ACLK>,
+                                        <&clks IMX6QDL_CLK_CAAM_IPG>,
+                                        <&clks IMX6QDL_CLK_EIM_SLOW>;
+                               clock-names = "mem", "aclk", "ipg", "emi_slow";
+
+                               sec_jr0: jr0@1000 {
+                                       compatible = "fsl,sec-v4.0-job-ring";
+                                       reg = <0x1000 0x1000>;
+                                       interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               sec_jr1: jr1@2000 {
+                                       compatible = "fsl,sec-v4.0-job-ring";
+                                       reg = <0x2000 0x1000>;
+                                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+                               };
                        };
 
                        aipstz@0217c000 { /* AIPSTZ2 */
index 708175d59b9c31085877da68ad378765fe701369..e6223d8e79af72d1964cdd09946a77d32dce28fc 100644 (file)
                        reg = <0x02100000 0x100000>;
                        ranges;
 
+                       crypto: caam@2100000 {
+                               compatible = "fsl,sec-v4.0";
+                               fsl,sec-era = <4>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x2100000 0x10000>;
+                               ranges = <0 0x2100000 0x10000>;
+                               interrupt-parent = <&intc>;
+                               clocks = <&clks IMX6SX_CLK_CAAM_MEM>,
+                                        <&clks IMX6SX_CLK_CAAM_ACLK>,
+                                        <&clks IMX6SX_CLK_CAAM_IPG>,
+                                        <&clks IMX6SX_CLK_EIM_SLOW>;
+                               clock-names = "mem", "aclk", "ipg", "emi_slow";
+
+                               sec_jr0: jr0@1000 {
+                                       compatible = "fsl,sec-v4.0-job-ring";
+                                       reg = <0x1000 0x1000>;
+                                       interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               sec_jr1: jr1@2000 {
+                                       compatible = "fsl,sec-v4.0-job-ring";
+                                       reg = <0x2000 0x1000>;
+                                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+                       };
+
                        usbotg1: usb@02184000 {
                                compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
                                reg = <0x02184000 0x200>;
index 1b6494fbdb91b9301c607652efbd9a9fb34a9f36..675fb8e492c6aa0478a6d5df01b30fbe1e281b7d 100644 (file)
                                        <GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
                        };
                };
+
+               mdio: mdio@24200f00 {
+                       compatible      = "ti,keystone_mdio", "ti,davinci_mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x24200f00 0x100>;
+                       status = "disabled";
+                       clocks = <&clkcpgmac>;
+                       clock-names = "fck";
+                       bus_freq        = <2500000>;
+               };
                /include/ "k2e-netcp.dtsi"
        };
 };
-
-&mdio {
-       reg = <0x24200f00 0x100>;
-};
index ae6472407b2277012096d733bb80951592555d03..d0810a5f296857394397c7f1c60bffa0011bb6e1 100644 (file)
                        #gpio-cells = <2>;
                        gpio,syscon-dev = <&devctrl 0x25c>;
                };
+
+               mdio: mdio@02090300 {
+                       compatible      = "ti,keystone_mdio", "ti,davinci_mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x02090300 0x100>;
+                       status = "disabled";
+                       clocks = <&clkcpgmac>;
+                       clock-names = "fck";
+                       bus_freq        = <2500000>;
+               };
                /include/ "k2hk-netcp.dtsi"
        };
 };
index 0e007483615e4f097bb747a2d882b2e2d3a030aa..49fd414f680c93ab50cf0dae72d2e9261181da21 100644 (file)
@@ -29,7 +29,6 @@
        };
 
        soc {
-
                /include/ "k2l-clocks.dtsi"
 
                uart2: serial@02348400 {
                        #gpio-cells = <2>;
                        gpio,syscon-dev = <&devctrl 0x24c>;
                };
+
+               mdio: mdio@26200f00 {
+                       compatible      = "ti,keystone_mdio", "ti,davinci_mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x26200f00 0x100>;
+                       status = "disabled";
+                       clocks = <&clkcpgmac>;
+                       clock-names = "fck";
+                       bus_freq        = <2500000>;
+               };
                /include/ "k2l-netcp.dtsi"
        };
 };
        /* Pin muxed. Enabled and configured by Bootloader */
        status = "disabled";
 };
-
-&mdio {
-       reg = <0x26200f00 0x100>;
-};
index e7a6f6deabb6c0d89d4ca1e2c2ae63639249d010..72816d65f7ec3fcf5d7c47ce792ae57db369754b 100644 (file)
                                  1 0 0x21000A00 0x00000100>;
                };
 
-               mdio: mdio@02090300 {
-                       compatible      = "ti,keystone_mdio", "ti,davinci_mdio";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg             = <0x02090300 0x100>;
-                       status = "disabled";
-                       clocks = <&clkpa>;
-                       clock-names = "fck";
-                       bus_freq        = <2500000>;
-               };
-
                kirq0: keystone_irq@26202a0 {
                        compatible = "ti,keystone-irq";
                        interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
index 6b7856025001b376d575d133ace4e040a59ebddc..e1c25c35e9ce86a381558ba7cd610f81458697ef 100644 (file)
@@ -10,6 +10,7 @@
 
 /dts-v1/;
 
+#include <dt-bindings/leds/leds-ns2.h>
 #include "kirkwood-netxbig.dtsi"
 
 / {
                        label = "d2net_v2:blue:sata";
                        slow-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
                        cmd-gpio = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+                       modes-map = <NS_V2_LED_OFF  1 0
+                                    NS_V2_LED_ON   0 1
+                                    NS_V2_LED_ON   1 1
+                                    NS_V2_LED_SATA 0 0>;
                };
        };
 
index da674bbd49a8642524f89995102b86c7ec9f7bc0..4121674abd1c35fbca7212def1e08af3061317e2 100644 (file)
@@ -1,5 +1,6 @@
 /dts-v1/;
 
+#include <dt-bindings/leds/leds-ns2.h>
 #include "kirkwood-ns2-common.dtsi"
 
 / {
                        label = "ns2:blue:sata";
                        slow-gpio = <&gpio0 29 0>;
                        cmd-gpio = <&gpio0 30 0>;
+                       modes-map = <NS_V2_LED_OFF  1 0
+                                    NS_V2_LED_ON   0 1
+                                    NS_V2_LED_ON   1 1
+                                    NS_V2_LED_SATA 0 0>;
                };
        };
 };
index 53368d1022ccd6fbffc2ad86037a73f870f694bb..190189d235e60151bfd46b7835cce645a9c951d4 100644 (file)
@@ -1,5 +1,6 @@
 /dts-v1/;
 
+#include <dt-bindings/leds/leds-ns2.h>
 #include "kirkwood-ns2-common.dtsi"
 
 / {
                        label = "ns2:blue:sata";
                        slow-gpio = <&gpio0 29 0>;
                        cmd-gpio = <&gpio0 30 0>;
+                       modes-map = <NS_V2_LED_OFF  1 0
+                                    NS_V2_LED_ON   0 1
+                                    NS_V2_LED_ON   1 1
+                                    NS_V2_LED_SATA 0 0>;
                };
        };
 };
index 72c78d0b1116112cb224676073c57d534359a6b5..55cc41d9c80c2184d2580e43b5075b05113a8480 100644 (file)
@@ -1,5 +1,6 @@
 /dts-v1/;
 
+#include <dt-bindings/leds/leds-ns2.h>
 #include "kirkwood-ns2-common.dtsi"
 
 / {
                        label = "ns2:blue:sata";
                        slow-gpio = <&gpio0 29 0>;
                        cmd-gpio = <&gpio0 30 0>;
+                       modes-map = <NS_V2_LED_OFF  1 0
+                                    NS_V2_LED_ON   0 1
+                                    NS_V2_LED_ON   1 1
+                                    NS_V2_LED_SATA 0 0>;
                };
        };
 };
index c441bf62c09fcfa9cab080b00eeb0e76129c31d0..9935f3ec29b4f6b026e580a3ce7cb9d3ac181115 100644 (file)
@@ -1,5 +1,6 @@
 /dts-v1/;
 
+#include <dt-bindings/leds/leds-ns2.h>
 #include "kirkwood-ns2-common.dtsi"
 
 / {
                        label = "ns2:blue:sata";
                        slow-gpio = <&gpio0 29 0>;
                        cmd-gpio = <&gpio0 30 0>;
+                       modes-map = <NS_V2_LED_OFF  1 0
+                                    NS_V2_LED_ON   0 1
+                                    NS_V2_LED_ON   1 1
+                                    NS_V2_LED_SATA 0 0>;
                };
        };
 };
index 11a7963be0035a002fa77c2bec6809b34444e584..2390f387c27163bb76e918bb73e26966bee7fb48 100644 (file)
@@ -51,7 +51,8 @@
                                };
 
                                scm_conf: scm_conf@270 {
-                                       compatible = "syscon";
+                                       compatible = "syscon",
+                                                    "simple-bus";
                                        reg = <0x270 0x240>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
index 7d31c6ff246f47b14afd5eeb332d01a955faef35..abc4473e6f8a17e51d5e66416be089ab24d7b472 100644 (file)
                                };
 
                                omap4_padconf_global: omap4_padconf_global@5a0 {
-                                       compatible = "syscon";
+                                       compatible = "syscon",
+                                                    "simple-bus";
                                        reg = <0x5a0 0x170>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
index c8fd648a7108515def0e9492936fd3760f156579..b1a1263e600168291091a963f9f56aefc87fd59e 100644 (file)
                                };
 
                                omap5_padconf_global: omap5_padconf_global@5a0 {
-                                       compatible = "syscon";
+                                       compatible = "syscon",
+                                                    "simple-bus";
                                        reg = <0x5a0 0xec>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
index bd35b0674ff6894cd6518046d049b385e038a624..9bc72a3356e45ea7c79d43daf9eae826342e8f52 100644 (file)
                status = "ok";
        };
 };
+
+&spmi_bus {
+       pm8941@0 {
+               coincell@2800 {
+                       status = "ok";
+                       qcom,rset-ohms = <2100>;
+                       qcom,vset-millivolts = <3000>;
+               };
+       };
+};
index aa774e685018a58d2fdebd408af6aed6e849a0f0..968f1043d4f599ce9438f61f094834c484e9e22d 100644 (file)
                        interrupts = <0x0 0x36 0x0 IRQ_TYPE_EDGE_RISING>;
                        qcom,external-resistor-micro-ohms = <10000>;
                };
+
+               coincell@2800 {
+                       compatible = "qcom,pm8941-coincell";
+                       reg = <0x2800>;
+                       status = "disabled";
+               };
        };
 
        usid1: pm8941@1 {
index a75f3289e653ab2973e2d7dd1cb12c8a12724451..c5fbde3afcf6fc482aa4d1f521b3c138c20608e1 100644 (file)
 #include "skeleton.dtsi"
 
 / {
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               enable-method = "ste,dbx500-smp";
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                       };
+               };
+               CPU0: cpu@300 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0x300>;
+               };
+               CPU1: cpu@301 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0x301>;
+               };
+       };
+
        soc {
                #address-cells = <1>;
                #size-cells = <1>;
                interrupt-parent = <&intc>;
                ranges;
 
-               cpus {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       cpu-map {
-                               cluster0 {
-                                       core0 {
-                                               cpu = <&CPU0>;
-                                       };
-                                       core1 {
-                                               cpu = <&CPU1>;
-                                       };
-                               };
-                       };
-                       CPU0: cpu@0 {
-                               device_type = "cpu";
-                               compatible = "arm,cortex-a9";
-                               reg = <0>;
-                       };
-                       CPU1: cpu@1 {
-                               device_type = "cpu";
-                               compatible = "arm,cortex-a9";
-                               reg = <1>;
-                       };
-               };
-
                ptm@801ae000 {
                        compatible = "arm,coresight-etm3x", "arm,primecell";
                        reg = <0x801ae000 0x1000>;
 
                clocks {
                        compatible = "stericsson,u8500-clks";
+                       /*
+                        * Registers for the CLKRST block on peripheral
+                        * groups 1, 2, 3, 5, 6,
+                        */
+                       reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>,
+                           <0x8000f000 0x1000>, <0xa03ff000 0x1000>,
+                           <0xa03cf000 0x1000>;
 
                        prcmu_clk: prcmu-clock {
                                #clock-cells = <1>;
index 61c03d1fe5303301a7ee44f1069c3865da958313..adaa57b7a9437035445bde2e14fe958c85b5ab97 100644 (file)
                        compatible = "allwinner,sun4i-a10-axi-gates-clk";
                        reg = <0x01c2005c 0x4>;
                        clocks = <&axi>;
+                       clock-indices = <0>;
                        clock-output-names = "axi_dram";
                };
 
                        compatible = "allwinner,sun4i-a10-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>,
+                                       <4>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <11>, <12>,
+                                       <13>, <14>, <16>,
+                                       <17>, <18>, <20>,
+                                       <21>, <22>, <23>,
+                                       <24>, <25>, <26>,
+                                       <32>, <33>, <34>,
+                                       <35>, <36>, <37>,
+                                       <40>, <41>, <43>,
+                                       <44>, <45>,
+                                       <46>, <47>,
+                                       <50>, <52>;
                        clock-output-names = "ahb_usb0", "ahb_ehci0",
-                               "ahb_ohci0", "ahb_ehci1", "ahb_ohci1", "ahb_ss",
-                               "ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1",
-                               "ahb_mmc2", "ahb_mmc3", "ahb_ms", "ahb_nand",
-                               "ahb_sdram", "ahb_ace", "ahb_emac", "ahb_ts",
-                               "ahb_spi0", "ahb_spi1", "ahb_spi2", "ahb_spi3",
-                               "ahb_pata", "ahb_sata", "ahb_gps", "ahb_ve",
-                               "ahb_tvd", "ahb_tve0", "ahb_tve1", "ahb_lcd0",
-                               "ahb_lcd1", "ahb_csi0", "ahb_csi1", "ahb_hdmi",
-                               "ahb_de_be0", "ahb_de_be1", "ahb_de_fe0",
-                               "ahb_de_fe1", "ahb_mp", "ahb_mali400";
+                                            "ahb_ohci0", "ahb_ehci1",
+                                            "ahb_ohci1", "ahb_ss", "ahb_dma",
+                                            "ahb_bist", "ahb_mmc0", "ahb_mmc1",
+                                            "ahb_mmc2", "ahb_mmc3", "ahb_ms",
+                                            "ahb_nand", "ahb_sdram", "ahb_ace",
+                                            "ahb_emac", "ahb_ts", "ahb_spi0",
+                                            "ahb_spi1", "ahb_spi2", "ahb_spi3",
+                                            "ahb_pata", "ahb_sata", "ahb_gps",
+                                            "ahb_ve", "ahb_tvd", "ahb_tve0",
+                                            "ahb_tve1", "ahb_lcd0", "ahb_lcd1",
+                                            "ahb_csi0", "ahb_csi1", "ahb_hdmi",
+                                            "ahb_de_be0", "ahb_de_be1",
+                                            "ahb_de_fe0", "ahb_de_fe1",
+                                            "ahb_mp", "ahb_mali400";
                };
 
                apb0: apb0@01c20054 {
                        compatible = "allwinner,sun4i-a10-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>,
+                                       <5>, <6>,
+                                       <7>, <10>;
                        clock-output-names = "apb0_codec", "apb0_spdif",
-                               "apb0_ac97", "apb0_iis", "apb0_pio", "apb0_ir0",
-                               "apb0_ir1", "apb0_keypad";
+                                            "apb0_ac97", "apb0_iis",
+                                            "apb0_pio", "apb0_ir0",
+                                            "apb0_ir1", "apb0_keypad";
                };
 
                apb1: clk@01c20058 {
                        compatible = "allwinner,sun4i-a10-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <4>,
+                                       <5>, <6>,
+                                       <7>, <16>,
+                                       <17>, <18>,
+                                       <19>, <20>,
+                                       <21>, <22>,
+                                       <23>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
-                               "apb1_i2c2", "apb1_can", "apb1_scr",
-                               "apb1_ps20", "apb1_ps21", "apb1_uart0",
-                               "apb1_uart1", "apb1_uart2", "apb1_uart3",
-                               "apb1_uart4", "apb1_uart5", "apb1_uart6",
-                               "apb1_uart7";
+                                            "apb1_i2c2", "apb1_can",
+                                            "apb1_scr", "apb1_ps20",
+                                            "apb1_ps21", "apb1_uart0",
+                                            "apb1_uart1", "apb1_uart2",
+                                            "apb1_uart3", "apb1_uart4",
+                                            "apb1_uart5", "apb1_uart6",
+                                            "apb1_uart7";
                };
 
                nand_clk: clk@01c20080 {
                        status = "disabled";
                };
 
+               crypto: crypto-engine@01c15000 {
+                       compatible = "allwinner,sun4i-a10-crypto";
+                       reg = <0x01c15000 0x1000>;
+                       interrupts = <86>;
+                       clocks = <&ahb_gates 5>, <&ss_clk>;
+                       clock-names = "ahb", "mod";
+               };
+
                spi2: spi@01c17000 {
                        compatible = "allwinner,sun4i-a10-spi";
                        reg = <0x01c17000 0x1000>;
index f11efb722bbb025cc7f0d5b7b22524e3bc060c45..a513b416a80773c970105920cecd8878d46a2dfc 100644 (file)
                        compatible = "allwinner,sun5i-a10s-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <13>,
+                                       <14>, <17>, <18>,
+                                       <20>, <21>, <22>,
+                                       <26>, <28>, <32>,
+                                       <34>, <36>, <40>,
+                                       <43>, <44>,
+                                       <46>, <51>,
+                                       <52>;
                        clock-output-names = "ahb_usbotg", "ahb_ehci",
                                             "ahb_ohci", "ahb_ss", "ahb_dma",
                                             "ahb_bist", "ahb_mmc0", "ahb_mmc1",
                        compatible = "allwinner,sun5i-a10s-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <3>,
+                                       <5>, <6>,
+                                       <10>;
                        clock-output-names = "apb0_codec", "apb0_iis",
                                             "apb0_pio", "apb0_ir",
                                             "apb0_keypad";
                        compatible = "allwinner,sun5i-a10s-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <16>,
+                                       <17>, <18>,
+                                       <19>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
-                               "apb1_i2c2", "apb1_uart0", "apb1_uart1",
-                               "apb1_uart2", "apb1_uart3";
+                                            "apb1_i2c2", "apb1_uart0",
+                                            "apb1_uart1", "apb1_uart2",
+                                            "apb1_uart3";
                };
        };
 
index 976d4faa2179ace0c60d6adc269deb226c314e15..f3631c9c6fa2616e8b5ef209df59ca9ac9ee0ad3 100644 (file)
                        compatible = "allwinner,sun5i-a13-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <5>, <6>,
+                                       <7>, <8>, <9>,
+                                       <10>, <13>,
+                                       <14>, <20>,
+                                       <21>, <22>,
+                                       <28>, <32>, <36>,
+                                       <40>, <44>,
+                                       <46>, <51>,
+                                       <52>;
                        clock-output-names = "ahb_usbotg", "ahb_ehci",
                                             "ahb_ohci", "ahb_ss", "ahb_dma",
                                             "ahb_bist", "ahb_mmc0", "ahb_mmc1",
                        compatible = "allwinner,sun5i-a13-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <5>,
+                                       <6>;
                        clock-output-names = "apb0_codec", "apb0_pio",
                                             "apb0_ir";
                };
                        compatible = "allwinner,sun5i-a13-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <17>,
+                                       <19>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
-                               "apb1_i2c2", "apb1_uart1", "apb1_uart3";
+                                            "apb1_i2c2", "apb1_uart1",
+                                            "apb1_uart3";
                };
        };
 };
index 54b0978304344104d94d7d4e79a3117986563204..427c0e7289fa3d44d05c281d8c5f0860501f7a77 100644 (file)
                        compatible = "allwinner,sun4i-a10-axi-gates-clk";
                        reg = <0x01c2005c 0x4>;
                        clocks = <&axi>;
+                       clock-indices = <0>;
                        clock-output-names = "axi_dram";
                };
 
index 008047a018cf2b645cc85136c194be665376c5ef..e4d3484d97bd055f2bb1fe848049918f8d3e24e8 100644 (file)
                        compatible = "allwinner,sun6i-a31-ahb1-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb1>;
+                       clock-indices = <1>, <5>,
+                                       <6>, <8>, <9>,
+                                       <10>, <11>, <12>,
+                                       <13>, <14>,
+                                       <17>, <18>, <19>,
+                                       <20>, <21>, <22>,
+                                       <23>, <24>, <26>,
+                                       <27>, <29>,
+                                       <30>, <31>, <32>,
+                                       <36>, <37>, <40>,
+                                       <43>, <44>, <45>,
+                                       <46>, <47>, <50>,
+                                       <52>, <55>, <56>,
+                                       <57>, <58>;
                        clock-output-names = "ahb1_mipidsi", "ahb1_ss",
                                        "ahb1_dma", "ahb1_mmc0", "ahb1_mmc1",
                                        "ahb1_mmc2", "ahb1_mmc3", "ahb1_nand1",
                        compatible = "allwinner,sun6i-a31-apb1-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <4>,
+                                       <5>, <12>,
+                                       <13>;
                        clock-output-names = "apb1_codec", "apb1_digital_mic",
                                        "apb1_pio", "apb1_daudio0",
                                        "apb1_daudio1";
                        compatible = "allwinner,sun6i-a31-apb2-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb2>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <16>,
+                                       <17>, <18>, <19>,
+                                       <20>, <21>;
                        clock-output-names = "apb2_i2c0", "apb2_i2c1",
                                             "apb2_i2c2", "apb2_i2c3",
                                             "apb2_uart0", "apb2_uart1",
                                             "mmc3_sample";
                };
 
+               ss_clk: clk@01c2009c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mod0-clk";
+                       reg = <0x01c2009c 0x4>;
+                       clocks = <&osc24M>, <&pll6 0>;
+                       clock-output-names = "ss";
+               };
+
                spi0_clk: clk@01c200a0 {
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        compatible = "allwinner,sun6i-a31-usb-clk";
                        reg = <0x01c200cc 0x4>;
                        clocks = <&osc24M>;
+                       clock-indices = <8>, <9>, <10>,
+                                       <16>, <17>,
+                                       <18>;
                        clock-output-names = "usb_phy0", "usb_phy1", "usb_phy2",
                                             "usb_ohci0", "usb_ohci1",
                                             "usb_ohci2";
                        #size-cells = <0>;
                };
 
+               crypto: crypto-engine@01c15000 {
+                       compatible = "allwinner,sun4i-a10-crypto";
+                       reg = <0x01c15000 0x1000>;
+                       interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ahb1_gates 5>, <&ss_clk>;
+                       clock-names = "ahb", "mod";
+                       resets = <&ahb1_rst 5>;
+                       reset-names = "ahb";
+               };
+
                timer@01c60000 {
                        compatible = "allwinner,sun6i-a31-hstimer",
                                     "allwinner,sun7i-a20-hstimer";
index 6a63f30c9a699d0e4620aac31f64247ad9c1f95b..d3b2f26417aae78c59d8eeebbf8f4b28c4855d6d 100644 (file)
                        compatible = "allwinner,sun7i-a20-ahb-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <5>, <6>, <7>, <8>,
+                                       <9>, <10>, <11>, <12>,
+                                       <13>, <14>, <16>,
+                                       <17>, <18>, <20>, <21>,
+                                       <22>, <23>, <25>,
+                                       <28>, <32>, <33>, <34>,
+                                       <35>, <36>, <37>, <40>,
+                                       <41>, <42>, <43>,
+                                       <44>, <45>, <46>,
+                                       <47>, <49>, <50>,
+                                       <52>;
                        clock-output-names = "ahb_usb0", "ahb_ehci0",
                                "ahb_ohci0", "ahb_ehci1", "ahb_ohci1",
                                "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0",
                        compatible = "allwinner,sun7i-a20-apb0-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb0>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <5>, <6>, <7>,
+                                       <8>, <10>;
                        clock-output-names = "apb0_codec", "apb0_spdif",
                                "apb0_ac97", "apb0_iis0", "apb0_iis1",
                                "apb0_pio", "apb0_ir0", "apb0_ir1",
                        compatible = "allwinner,sun7i-a20-apb1-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <5>, <6>, <7>,
+                                       <15>, <16>, <17>,
+                                       <18>, <19>, <20>,
+                                       <21>, <22>, <23>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
                                "apb1_i2c2", "apb1_i2c3", "apb1_can",
                                "apb1_scr", "apb1_ps20", "apb1_ps21",
                        status = "disabled";
                };
 
+               crypto: crypto-engine@01c15000 {
+                       compatible = "allwinner,sun4i-a10-crypto";
+                       reg = <0x01c15000 0x1000>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ahb_gates 5>, <&ss_clk>;
+                       clock-names = "ahb", "mod";
+               };
+
                spi2: spi@01c17000 {
                        compatible = "allwinner,sun4i-a10-spi";
                        reg = <0x01c17000 0x1000>;
index 7abd0ae3143d74e1f9ba9b2638fc55353a306d7c..c318c770b6c1533b0afe7de02747c05153bbe68a 100644 (file)
                        compatible = "allwinner,sun8i-a23-ahb1-gates-clk";
                        reg = <0x01c20060 0x8>;
                        clocks = <&ahb1>;
+                       clock-indices = <1>, <6>,
+                                       <8>, <9>, <10>,
+                                       <13>, <14>,
+                                       <19>, <20>,
+                                       <21>, <24>, <26>,
+                                       <29>, <32>, <36>,
+                                       <40>, <44>, <46>,
+                                       <52>, <54>,
+                                       <57>;
                        clock-output-names = "ahb1_mipidsi", "ahb1_dma",
                                        "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2",
                                        "ahb1_nand", "ahb1_sdram",
                        compatible = "allwinner,sun8i-a23-apb1-gates-clk";
                        reg = <0x01c20068 0x4>;
                        clocks = <&apb1>;
+                       clock-indices = <0>, <5>,
+                                       <12>, <13>;
                        clock-output-names = "apb1_codec", "apb1_pio",
                                        "apb1_daudio0", "apb1_daudio1";
                };
                        compatible = "allwinner,sun8i-a23-apb2-gates-clk";
                        reg = <0x01c2006c 0x4>;
                        clocks = <&apb2>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <16>,
+                                       <17>, <18>,
+                                       <19>, <20>;
                        clock-output-names = "apb2_i2c0", "apb2_i2c1",
                                        "apb2_i2c2", "apb2_uart0",
                                        "apb2_uart1", "apb2_uart2",
index a43ad779ee2f68546a26da570f19ba601c2dc15b..5908e3dcf9658544e1f45b38d0fcd46a6c3a58a6 100644 (file)
                        compatible = "allwinner,sun9i-a80-ahb0-gates-clk";
                        reg = <0x06000580 0x4>;
                        clocks = <&ahb0>;
-                       clock-indices = <0>, <1>, <3>, <5>, <8>, <12>, <13>,
-                                       <14>, <15>, <16>, <18>, <20>, <21>,
-                                       <22>, <23>;
+                       clock-indices = <0>, <1>, <3>,
+                                       <5>, <8>, <12>,
+                                       <13>, <14>,
+                                       <15>, <16>, <18>,
+                                       <20>, <21>, <22>,
+                                       <23>;
                        clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu",
                                        "ahb0_ss", "ahb0_sd", "ahb0_nand1",
                                        "ahb0_nand0", "ahb0_sdram",
                        compatible = "allwinner,sun9i-a80-ahb1-gates-clk";
                        reg = <0x06000584 0x4>;
                        clocks = <&ahb1>;
-                       clock-indices = <0>, <1>, <17>, <21>, <22>, <23>, <24>;
+                       clock-indices = <0>, <1>,
+                                       <17>, <21>,
+                                       <22>, <23>,
+                                       <24>;
                        clock-output-names = "ahb1_usbotg", "ahb1_usbhci",
                                        "ahb1_gmac", "ahb1_msgbox",
                                        "ahb1_spinlock", "ahb1_hstimer",
                        compatible = "allwinner,sun9i-a80-ahb2-gates-clk";
                        reg = <0x06000588 0x4>;
                        clocks = <&ahb2>;
-                       clock-indices = <0>, <1>, <2>, <4>, <5>, <7>, <8>,
-                                       <11>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <4>, <5>,
+                                       <7>, <8>, <11>;
                        clock-output-names = "ahb2_lcd0", "ahb2_lcd1",
                                        "ahb2_edp", "ahb2_csi", "ahb2_hdmi",
                                        "ahb2_de", "ahb2_mp", "ahb2_mipi_dsi";
                        compatible = "allwinner,sun9i-a80-apb0-gates-clk";
                        reg = <0x06000590 0x4>;
                        clocks = <&apb0>;
-                       clock-indices = <1>, <5>, <11>, <12>, <13>, <15>,
-                                       <17>, <18>, <19>;
+                       clock-indices = <1>, <5>,
+                                       <11>, <12>, <13>,
+                                       <15>, <17>, <18>,
+                                       <19>;
                        clock-output-names = "apb0_spdif", "apb0_pio",
                                        "apb0_ac97", "apb0_i2s0", "apb0_i2s1",
                                        "apb0_lradc", "apb0_gpadc", "apb0_twd",
                        compatible = "allwinner,sun9i-a80-apb1-gates-clk";
                        reg = <0x06000594 0x4>;
                        clocks = <&apb1>;
-                       clock-indices = <0>, <1>, <2>, <3>, <4>,
-                                       <16>, <17>, <18>, <19>, <20>, <21>;
+                       clock-indices = <0>, <1>,
+                                       <2>, <3>, <4>,
+                                       <16>, <17>,
+                                       <18>, <19>,
+                                       <20>, <21>;
                        clock-output-names = "apb1_i2c0", "apb1_i2c1",
                                        "apb1_i2c2", "apb1_i2c3", "apb1_i2c4",
                                        "apb1_uart0", "apb1_uart1",
index b47863d49ac6aaf192f4feac7111f0b7e8d21488..7569b391704e0fbd2c3c91a9a7b051a717daf9a4 100644 (file)
@@ -354,8 +354,7 @@ CONFIG_PROVE_LOCKING=y
 # CONFIG_FTRACE is not set
 # CONFIG_ARM_UNWIND is not set
 CONFIG_SECURITYFS=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_T10DIF=y
 CONFIG_CRC7=m
index 6231d36b3635260cf0f2a7185182099ce844ccb9..31e1f538df7dee529af3cf36a30fd941314de95c 100644 (file)
@@ -1 +1,3 @@
 aesbs-core.S
+sha256-core.S
+sha512-core.S
index 28b9bb35949e08a93bdcf940d125cedbe6c55b63..8857d2869a5f8cb0d76a8efb021d3bd2304fe3e1 100644 (file)
@@ -19,9 +19,7 @@ struct pci_bus;
 struct device;
 
 struct hw_pci {
-#ifdef CONFIG_PCI_MSI
        struct msi_controller *msi_ctrl;
-#endif
        struct pci_ops  *ops;
        int             nr_controllers;
        void            **private_data;
@@ -42,9 +40,6 @@ struct hw_pci {
  * Per-controller structure
  */
 struct pci_sys_data {
-#ifdef CONFIG_PCI_MSI
-       struct msi_controller *msi_ctrl;
-#endif
        struct list_head node;
        int             busnr;          /* primary bus number                   */
        u64             mem_offset;     /* bus->cpu memory mapping offset       */
index fcbbbb1b9e9578b64371785385b6074e256ff26d..874e1823f8036fd9915c63e8b95561e96c0152b7 100644 (file)
 
 static int debug_pci;
 
-#ifdef CONFIG_PCI_MSI
-struct msi_controller *pcibios_msi_controller(struct pci_dev *dev)
-{
-       struct pci_sys_data *sysdata = dev->bus->sysdata;
-
-       return sysdata->msi_ctrl;
-}
-#endif
-
 /*
  * We can't use pci_get_device() here since we are
  * called from interrupt context.
@@ -459,12 +450,9 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 
        for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
                sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
-               if (!sys)
-                       panic("PCI: unable to allocate sys data!");
+               if (WARN(!sys, "PCI: unable to allocate sys data!"))
+                       break;
 
-#ifdef CONFIG_PCI_MSI
-               sys->msi_ctrl = hw->msi_ctrl;
-#endif
                sys->busnr   = busnr;
                sys->swizzle = hw->swizzle;
                sys->map_irq = hw->map_irq;
@@ -486,11 +474,14 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
                        if (hw->scan)
                                sys->bus = hw->scan(nr, sys);
                        else
-                               sys->bus = pci_scan_root_bus(parent, sys->busnr,
-                                               hw->ops, sys, &sys->resources);
+                               sys->bus = pci_scan_root_bus_msi(parent,
+                                       sys->busnr, hw->ops, sys,
+                                       &sys->resources, hw->msi_ctrl);
 
-                       if (!sys->bus)
-                               panic("PCI: unable to scan bus!");
+                       if (WARN(!sys->bus, "PCI: unable to scan bus!")) {
+                               kfree(sys);
+                               break;
+                       }
 
                        busnr = sys->bus->busn_res.end + 1;
 
@@ -521,6 +512,8 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
                struct pci_bus *bus = sys->bus;
 
                if (!pci_has_flag(PCI_PROBE_ONLY)) {
+                       struct pci_bus *child;
+
                        /*
                         * Size the bridge windows.
                         */
@@ -530,25 +523,15 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
                         * Assign resources.
                         */
                        pci_bus_assign_resources(bus);
-               }
 
+                       list_for_each_entry(child, &bus->children, node)
+                               pcie_bus_configure_settings(child);
+               }
                /*
                 * Tell drivers about devices found.
                 */
                pci_bus_add_devices(bus);
        }
-
-       list_for_each_entry(sys, &head, node) {
-               struct pci_bus *bus = sys->bus;
-
-               /* Configure PCI Express settings */
-               if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
-                       struct pci_bus *child;
-
-                       list_for_each_entry(child, &bus->children, node)
-                               pcie_bus_configure_settings(child);
-               }
-       }
 }
 
 #ifndef CONFIG_PCI_HOST_ITE8152
index 92828a1dec80c1c33d051d9b76063727598495d5..b48dd4f37f8067e781ee3e135ed7aff27940371f 100644 (file)
@@ -61,6 +61,7 @@ work_pending:
        movlt   scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE)
        ldmia   sp, {r0 - r6}                   @ have to reload r0 - r6
        b       local_restart                   @ ... and off we go
+ENDPROC(ret_fast_syscall)
 
 /*
  * "slow" syscall return path.  "why" tells us if this was a real syscall.
index bd755d97e459d77ff05cc8a1264f336c58c1b598..29e2991465cb27b579f729deec65e2293a0a04b5 100644 (file)
@@ -399,6 +399,9 @@ ENTRY(secondary_startup)
        sub     lr, r4, r5                      @ mmu has been enabled
        add     r3, r7, lr
        ldrd    r4, [r3, #0]                    @ get secondary_data.pgdir
+ARM_BE8(eor    r4, r4, r5)                     @ Swap r5 and r4 in BE:
+ARM_BE8(eor    r5, r4, r5)                     @ it can be done in 3 steps
+ARM_BE8(eor    r4, r4, r5)                     @ without using a temp reg.
        ldr     r8, [r3, #8]                    @ get secondary_data.swapper_pg_dir
        badr    lr, __enable_mmu                @ return address
        mov     r13, r12                        @ __secondary_switched address
index efe17dd9b9218b7ef16299700a0f2a6d74ca61c1..54a5aeab988d3526657b8e3089942ca8cfe4fe5e 100644 (file)
@@ -296,7 +296,6 @@ static bool tk_is_cntvct(const struct timekeeper *tk)
  */
 void update_vsyscall(struct timekeeper *tk)
 {
-       struct timespec xtime_coarse;
        struct timespec64 *wtm = &tk->wall_to_monotonic;
 
        if (!cntvct_ok) {
@@ -308,10 +307,10 @@ void update_vsyscall(struct timekeeper *tk)
 
        vdso_write_begin(vdso_data);
 
-       xtime_coarse = __current_kernel_time();
        vdso_data->tk_is_cntvct                 = tk_is_cntvct(tk);
-       vdso_data->xtime_coarse_sec             = xtime_coarse.tv_sec;
-       vdso_data->xtime_coarse_nsec            = xtime_coarse.tv_nsec;
+       vdso_data->xtime_coarse_sec             = tk->xtime_sec;
+       vdso_data->xtime_coarse_nsec            = (u32)(tk->tkr_mono.xtime_nsec >>
+                                                       tk->tkr_mono.shift);
        vdso_data->wtm_clock_sec                = wtm->tv_sec;
        vdso_data->wtm_clock_nsec               = wtm->tv_nsec;
 
index 3e58d710013c3ad9b377fc76e6dad58f377e88a7..4b39af2dfda9963345afe18c89131c1056a90b41 100644 (file)
@@ -96,7 +96,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
        }
 
        /* the mmap semaphore is taken only if not in an atomic context */
-       atomic = in_atomic();
+       atomic = faulthandler_disabled();
 
        if (!atomic)
                down_read(&current->mm->mmap_sem);
index eaf58f88ef5dcd262a862e96b0656b03a31cf8b3..685826c4a710b16e11f21a400480b516ed8c09d9 100644 (file)
@@ -8,7 +8,6 @@
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
index ddfdd820e6f2b99f6bfa80a51a287255794d74d5..29e08aac8294aa06233b916c130aa0740a6d897f 100644 (file)
@@ -1010,11 +1010,13 @@ static struct davinci_spi_platform_data da8xx_spi_pdata[] = {
                .version        = SPI_VERSION_2,
                .intr_line      = 1,
                .dma_event_q    = EVENTQ_0,
+               .prescaler_limit = 2,
        },
        [1] = {
                .version        = SPI_VERSION_2,
                .intr_line      = 1,
                .dma_event_q    = EVENTQ_0,
+               .prescaler_limit = 2,
        },
 };
 
index 9cbeda798584d236bfbc9db0f6b4abbc2d420b90..567dc56fe8cded405dc05dffb01605cc0316d9dd 100644 (file)
@@ -411,6 +411,7 @@ static struct davinci_spi_platform_data dm355_spi0_pdata = {
        .num_chipselect = 2,
        .cshold_bug     = true,
        .dma_event_q    = EVENTQ_1,
+       .prescaler_limit = 1,
 };
 static struct platform_device dm355_spi0_device = {
        .name = "spi_davinci",
index e3a3c54b6832e4bf35410564411e5235cb54c566..6a890a8486d0032462490144065e8c6e140b8833 100644 (file)
@@ -646,6 +646,7 @@ static struct davinci_spi_platform_data dm365_spi0_pdata = {
        .version        = SPI_VERSION_1,
        .num_chipselect = 2,
        .dma_event_q    = EVENTQ_3,
+       .prescaler_limit = 1,
 };
 
 static struct resource dm365_spi0_resources[] = {
index 6001f1c9d136f45fabd7d61e97638855d0beb46a..4a87e86dec45d1546153ca0ebb7310bbd5f82d93 100644 (file)
@@ -146,9 +146,8 @@ static __init int exynos4_pm_init_power_domain(void)
                pd->base = of_iomap(np, 0);
                if (!pd->base) {
                        pr_warn("%s: failed to map memory\n", __func__);
-                       kfree(pd->pd.name);
+                       kfree_const(pd->pd.name);
                        kfree(pd);
-                       of_node_put(np);
                        continue;
                }
 
index c6bd7c7bd4aa4949203505247f0fd9db21ea0c5b..8cc62150116a779b48e15b71b4937af154075415 100644 (file)
@@ -11,7 +11,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
 
index edea697e8253d601ce2323a0a99c1083d1e9ff93..e283939a216fb188c0fa9ccaaa08b70eb18ff7ef 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_clock.h>
 #include <linux/platform_device.h>
-#include <linux/clk-provider.h>
 #include <linux/of.h>
 
 static struct dev_pm_domain keystone_pm_domain = {
index afee9083ad92bc6d16bb7b29ef5f86f811351847..9f739f3cad4c7e584391c0e8f79ec27376d5fa4c 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
index 903c85be28972e6e7d28aaf9459f5bc87b4ac87c..7892c7d3b6f4b005c9416dbcd108bfab6ead2b3c 100644 (file)
@@ -12,8 +12,7 @@ obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \
 
 hwmod-common                           = omap_hwmod.o omap_hwmod_reset.o \
                                          omap_hwmod_common_data.o
-clock-common                           = clock.o clock_common_data.o \
-                                         clkt_dpll.o clkt_clksel.o
+clock-common                           = clock.o
 secure-common                          = omap-smc.o omap-secure.o
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
@@ -182,24 +181,17 @@ obj-$(CONFIG_SOC_DRA7XX)          += $(clockdomain-common)
 obj-$(CONFIG_SOC_DRA7XX)               += clockdomains7xx_data.o
 
 # Clock framework
-obj-$(CONFIG_ARCH_OMAP2)               += $(clock-common) clock2xxx.o
+obj-$(CONFIG_ARCH_OMAP2)               += $(clock-common)
 obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_dpllcore.o
 obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_virt_prcm_set.o
-obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_dpll.o clkt_iclk.o
-obj-$(CONFIG_SOC_OMAP2430)             += clock2430.o
-obj-$(CONFIG_ARCH_OMAP3)               += $(clock-common) clock3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)               += clock34xx.o clkt34xx_dpll3m2.o
-obj-$(CONFIG_ARCH_OMAP3)               += clock3517.o clock36xx.o
-obj-$(CONFIG_ARCH_OMAP3)               += dpll3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)               += clkt_iclk.o
+obj-$(CONFIG_ARCH_OMAP2)               += clkt2xxx_dpll.o
+obj-$(CONFIG_ARCH_OMAP3)               += $(clock-common)
+obj-$(CONFIG_ARCH_OMAP3)               += clkt34xx_dpll3m2.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(clock-common)
-obj-$(CONFIG_ARCH_OMAP4)               += dpll3xxx.o dpll44xx.o
-obj-$(CONFIG_SOC_AM33XX)               += $(clock-common) dpll3xxx.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clock-common)
 obj-$(CONFIG_SOC_OMAP5)                        += $(clock-common)
-obj-$(CONFIG_SOC_OMAP5)                        += dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_DRA7XX)               += $(clock-common)
-obj-$(CONFIG_SOC_DRA7XX)               += dpll3xxx.o dpll44xx.o
-obj-$(CONFIG_SOC_AM43XX)               += $(clock-common) dpll3xxx.o
+obj-$(CONFIG_SOC_AM43XX)               += $(clock-common)
 
 # OMAP2 clock rate set data (old "OPP" data)
 obj-$(CONFIG_SOC_OMAP2420)             += opp2420_data.o
index eb69acf21014e023184baac01b8821c528b7ed56..3f6521313c93337a791963003339218d9adf3f10 100644 (file)
 
 #include "clock.h"
 #include "clock3xxx.h"
-#include "clock34xx.h"
 #include "sdrc.h"
 #include "sram.h"
 
 #define CYCLES_PER_MHZ                 1000000
 
+struct clk *sdrc_ick_p, *arm_fck_p;
+
 /*
  * CORE DPLL (DPLL3) M2 divider rate programming functions
  *
@@ -60,12 +61,14 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!clk || !rate)
                return -EINVAL;
 
-       validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
+       new_div = DIV_ROUND_UP(parent_rate, rate);
+       validrate = parent_rate / new_div;
+
        if (validrate != rate)
                return -EINVAL;
 
-       sdrcrate = __clk_get_rate(sdrc_ick_p);
-       clkrate = __clk_get_rate(hw->clk);
+       sdrcrate = clk_get_rate(sdrc_ick_p);
+       clkrate = clk_hw_get_rate(hw);
        if (rate > clkrate)
                sdrcrate <<= ((rate / clkrate) >> 1);
        else
@@ -83,7 +86,7 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
        /*
         * XXX This only needs to be done when the CPU frequency changes
         */
-       _mpurate = __clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
+       _mpurate = clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
        c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
        c += 1;  /* for safety */
        c *= SDRC_MPURATE_LOOPS;
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
deleted file mode 100644 (file)
index 7ee2610..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * clkt_clksel.c - OMAP2/3/4 clksel clock functions
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * 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.
- *
- *
- * clksel clocks are clocks that do not have a fixed parent, or that
- * can divide their parent's rate, or possibly both at the same time, based
- * on the contents of a hardware register bitfield.
- *
- * All of the various mux and divider settings can be encoded into
- * struct clksel* data structures, and then these can be autogenerated
- * from some hardware database for each new chip generation.  This
- * should avoid the need to write, review, and validate a lot of new
- * clock code for each new chip, since it can be exported from the SoC
- * design flow.  This is now done on OMAP4.
- *
- * The fusion of mux and divider clocks is a software creation.  In
- * hardware reality, the multiplexer (parent selection) and the
- * divider exist separately.  XXX At some point these clksel clocks
- * should be split into "divider" clocks and "mux" clocks to better
- * match the hardware.
- *
- * (The name "clksel" comes from the name of the corresponding
- * register field in the OMAP2/3 family of SoCs.)
- *
- * XXX Currently these clocks are only used in the OMAP2/3/4 code, but
- * many of the OMAP1 clocks should be convertible to use this
- * mechanism.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/bug.h>
-
-#include "clock.h"
-
-/* Private functions */
-
-/**
- * _get_clksel_by_parent() - return clksel struct for a given clk & parent
- * @clk: OMAP struct clk ptr to inspect
- * @src_clk: OMAP struct clk ptr of the parent clk to search for
- *
- * Scan the struct clksel array associated with the clock to find
- * the element associated with the supplied parent clock address.
- * Returns a pointer to the struct clksel on success or NULL on error.
- */
-static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
-                                                 struct clk *src_clk)
-{
-       const struct clksel *clks;
-
-       if (!src_clk)
-               return NULL;
-
-       for (clks = clk->clksel; clks->parent; clks++)
-               if (clks->parent == src_clk)
-                       break; /* Found the requested parent */
-
-       if (!clks->parent) {
-               /* This indicates a data problem */
-               WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
-                    __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
-               return NULL;
-       }
-
-       return clks;
-}
-
-/**
- * _write_clksel_reg() - program a clock's clksel register in hardware
- * @clk: struct clk * to program
- * @v: clksel bitfield value to program (with LSB at bit 0)
- *
- * Shift the clksel register bitfield value @v to its appropriate
- * location in the clksel register and write it in.  This function
- * will ensure that the write to the clksel_reg reaches its
- * destination before returning -- important since PRM and CM register
- * accesses can be quite slow compared to ARM cycles -- but does not
- * take into account any time the hardware might take to switch the
- * clock source.
- */
-static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
-{
-       u32 v;
-
-       v = omap2_clk_readl(clk, clk->clksel_reg);
-       v &= ~clk->clksel_mask;
-       v |= field_val << __ffs(clk->clksel_mask);
-       omap2_clk_writel(v, clk, clk->clksel_reg);
-
-       v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */
-}
-
-/**
- * _clksel_to_divisor() - turn clksel field value into integer divider
- * @clk: OMAP struct clk to use
- * @field_val: register field value to find
- *
- * Given a struct clk of a rate-selectable clksel clock, and a register field
- * value to search for, find the corresponding clock divisor.  The register
- * field value should be pre-masked and shifted down so the LSB is at bit 0
- * before calling.  Returns 0 on error or returns the actual integer divisor
- * upon success.
- */
-static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
-{
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       struct clk *parent;
-
-       parent = __clk_get_parent(clk->hw.clk);
-
-       clks = _get_clksel_by_parent(clk, parent);
-       if (!clks)
-               return 0;
-
-       for (clkr = clks->rates; clkr->div; clkr++) {
-               if (!(clkr->flags & cpu_mask))
-                       continue;
-
-               if (clkr->val == field_val)
-                       break;
-       }
-
-       if (!clkr->div) {
-               /* This indicates a data error */
-               WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
-                    __clk_get_name(clk->hw.clk), field_val,
-                    __clk_get_name(parent));
-               return 0;
-       }
-
-       return clkr->div;
-}
-
-/**
- * _divisor_to_clksel() - turn clksel integer divisor into a field value
- * @clk: OMAP struct clk to use
- * @div: integer divisor to search for
- *
- * Given a struct clk of a rate-selectable clksel clock, and a clock
- * divisor, find the corresponding register field value.  Returns the
- * register field value _before_ left-shifting (i.e., LSB is at bit
- * 0); or returns 0xFFFFFFFF (~0) upon error.
- */
-static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
-{
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       struct clk *parent;
-
-       /* should never happen */
-       WARN_ON(div == 0);
-
-       parent = __clk_get_parent(clk->hw.clk);
-       clks = _get_clksel_by_parent(clk, parent);
-       if (!clks)
-               return ~0;
-
-       for (clkr = clks->rates; clkr->div; clkr++) {
-               if (!(clkr->flags & cpu_mask))
-                       continue;
-
-               if (clkr->div == div)
-                       break;
-       }
-
-       if (!clkr->div) {
-               pr_err("clock: %s: could not find divisor %d for parent %s\n",
-                      __clk_get_name(clk->hw.clk), div,
-                      __clk_get_name(parent));
-               return ~0;
-       }
-
-       return clkr->val;
-}
-
-/**
- * _read_divisor() - get current divisor applied to parent clock (from hdwr)
- * @clk: OMAP struct clk to use.
- *
- * Read the current divisor register value for @clk that is programmed
- * into the hardware, convert it into the actual divisor value, and
- * return it; or return 0 on error.
- */
-static u32 _read_divisor(struct clk_hw_omap *clk)
-{
-       u32 v;
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return 0;
-
-       v = omap2_clk_readl(clk, clk->clksel_reg);
-       v &= clk->clksel_mask;
-       v >>= __ffs(clk->clksel_mask);
-
-       return _clksel_to_divisor(clk, v);
-}
-
-/* Public functions */
-
-/**
- * omap2_clksel_round_rate_div() - find divisor for the given clock and rate
- * @clk: OMAP struct clk to use
- * @target_rate: desired clock rate
- * @new_div: ptr to where we should store the divisor
- *
- * Finds 'best' divider value in an array based on the source and target
- * rates.  The divider array must be sorted with smallest divider first.
- * This function is also used by the DPLL3 M2 divider code.
- *
- * Returns the rounded clock rate or returns 0xffffffff on error.
- */
-u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
-                                                unsigned long target_rate,
-                               u32 *new_div)
-{
-       unsigned long test_rate;
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       u32 last_div = 0;
-       struct clk *parent;
-       unsigned long parent_rate;
-       const char *clk_name;
-
-       parent = __clk_get_parent(clk->hw.clk);
-       clk_name = __clk_get_name(clk->hw.clk);
-       parent_rate = __clk_get_rate(parent);
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return ~0;
-
-       pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
-                clk_name, target_rate);
-
-       *new_div = 1;
-
-       clks = _get_clksel_by_parent(clk, parent);
-       if (!clks)
-               return ~0;
-
-       for (clkr = clks->rates; clkr->div; clkr++) {
-               if (!(clkr->flags & cpu_mask))
-                       continue;
-
-               /* Sanity check */
-               if (clkr->div <= last_div)
-                       pr_err("clock: %s: clksel_rate table not sorted\n",
-                              clk_name);
-
-               last_div = clkr->div;
-
-               test_rate = parent_rate / clkr->div;
-
-               if (test_rate <= target_rate)
-                       break; /* found it */
-       }
-
-       if (!clkr->div) {
-               pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
-                      clk_name, target_rate, __clk_get_name(parent));
-               return ~0;
-       }
-
-       *new_div = clkr->div;
-
-       pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
-                (parent_rate / clkr->div));
-
-       return parent_rate / clkr->div;
-}
-
-/*
- * Clocktype interface functions to the OMAP clock code
- * (i.e., those used in struct clk field function pointers, etc.)
- */
-
-/**
- * omap2_clksel_find_parent_index() - return the array index of the current
- * hardware parent of @hw
- * @hw: struct clk_hw * to find the current hardware parent of
- *
- * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
- * clk_hw_omap record representing a source-selectable hardware clock,
- * read the hardware register and determine what its parent is
- * currently set to.  Intended to be called only by the common clock
- * framework struct clk_hw_ops.get_parent function pointer.  Return
- * the array index of this parent clock upon success -- there is no
- * way to return an error, so if we encounter an error, just WARN()
- * and pretend that we know that we're doing.
- */
-u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       const struct clksel *clks;
-       const struct clksel_rate *clkr;
-       u32 r, found = 0;
-       struct clk *parent;
-       const char *clk_name;
-       int ret = 0, f = 0;
-
-       parent = __clk_get_parent(hw->clk);
-       clk_name = __clk_get_name(hw->clk);
-
-       /* XXX should be able to return an error */
-       WARN((!clk->clksel || !clk->clksel_mask),
-            "clock: %s: attempt to call on a non-clksel clock", clk_name);
-
-       r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask;
-       r >>= __ffs(clk->clksel_mask);
-
-       for (clks = clk->clksel; clks->parent && !found; clks++) {
-               for (clkr = clks->rates; clkr->div && !found; clkr++) {
-                       if (!(clkr->flags & cpu_mask))
-                               continue;
-
-                       if (clkr->val == r) {
-                               found = 1;
-                               ret = f;
-                       }
-               }
-               f++;
-       }
-
-       /* This indicates a data error */
-       WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
-            clk_name, r);
-
-       return ret;
-}
-
-
-/**
- * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
- * @clk: struct clk *
- *
- * This function is intended to be called only by the clock framework.
- * Each clksel clock should have its struct clk .recalc field set to this
- * function.  Returns the clock's current rate, based on its parent's rate
- * and its current divisor setting in the hardware.
- */
-unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
-{
-       unsigned long rate;
-       u32 div = 0;
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-
-       if (!parent_rate)
-               return 0;
-
-       div = _read_divisor(clk);
-       if (!div)
-               rate = parent_rate;
-       else
-               rate = parent_rate / div;
-
-       pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
-                __clk_get_name(hw->clk), rate, div);
-
-       return rate;
-}
-
-/**
- * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
- * @clk: OMAP struct clk to use
- * @target_rate: desired clock rate
- *
- * This function is intended to be called only by the clock framework.
- * Finds best target rate based on the source clock and possible dividers.
- * rates. The divider array must be sorted with smallest divider first.
- *
- * Returns the rounded clock rate or returns 0xffffffff on error.
- */
-long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                       unsigned long *parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 new_div;
-
-       return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
-}
-
-/**
- * omap2_clksel_set_rate() - program clock rate in hardware
- * @clk: struct clk * to program rate
- * @rate: target rate to program
- *
- * This function is intended to be called only by the clock framework.
- * Program @clk's rate to @rate in the hardware.  The clock can be
- * either enabled or disabled when this happens, although if the clock
- * is enabled, some downstream devices may glitch or behave
- * unpredictably when the clock rate is changed - this depends on the
- * hardware. This function does not currently check the usecount of
- * the clock, so if multiple drivers are using the clock, and the rate
- * is changed, they will all be affected without any notification.
- * Returns -EINVAL upon error, or 0 upon success.
- */
-int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 field_val, validrate, new_div = 0;
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return -EINVAL;
-
-       validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
-       if (validrate != rate)
-               return -EINVAL;
-
-       field_val = _divisor_to_clksel(clk, new_div);
-       if (field_val == ~0)
-               return -EINVAL;
-
-       _write_clksel_reg(clk, field_val);
-
-       pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
-                __clk_get_rate(hw->clk));
-
-       return 0;
-}
-
-/*
- * Clksel parent setting function - not passed in struct clk function
- * pointer - instead, the OMAP clock code currently assumes that any
- * parent-setting clock is a clksel clock, and calls
- * omap2_clksel_set_parent() by default
- */
-
-/**
- * omap2_clksel_set_parent() - change a clock's parent clock
- * @clk: struct clk * of the child clock
- * @new_parent: struct clk * of the new parent clock
- *
- * This function is intended to be called only by the clock framework.
- * Change the parent clock of clock @clk to @new_parent.  This is
- * intended to be used while @clk is disabled.  This function does not
- * currently check the usecount of the clock, so if multiple drivers
- * are using the clock, and the parent is changed, they will all be
- * affected without any notification.  Returns -EINVAL upon error, or
- * 0 upon success.
- */
-int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-
-       if (!clk->clksel || !clk->clksel_mask)
-               return -EINVAL;
-
-       _write_clksel_reg(clk, field_val);
-       return 0;
-}
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
deleted file mode 100644 (file)
index 55eb579..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * OMAP2/3 interface clock control
- *
- * Copyright (C) 2011 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-
-#include "clock.h"
-
-/* Register offsets */
-#define CM_AUTOIDLE                    0x30
-#define CM_ICLKEN                      0x10
-
-/* Private functions */
-
-/* XXX */
-void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
-{
-       u32 v;
-       void __iomem *r;
-
-       r = (__force void __iomem *)
-               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
-
-       v = omap2_clk_readl(clk, r);
-       v |= (1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, r);
-}
-
-/* XXX */
-void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
-{
-       u32 v;
-       void __iomem *r;
-
-       r = (__force void __iomem *)
-               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
-
-       v = omap2_clk_readl(clk, r);
-       v &= ~(1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, r);
-}
-
-/* Public data */
-
-const struct clk_hw_omap_ops clkhwops_iclk = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-};
-
-const struct clk_hw_omap_ops clkhwops_iclk_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap2_clk_dflt_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-
-
index a699d716930746d4f37bd603be865b248d5986bc..acb60ed172730a12b06f36a02c3175d848d7369c 100644 (file)
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
-#include <linux/regmap.h>
 #include <linux/of_address.h>
-#include <linux/bootmem.h>
 #include <asm/cpu.h>
 
 #include <trace/events/power.h>
 #include "cm-regbits-34xx.h"
 #include "common.h"
 
-/*
- * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
- * for a module to indicate that it is no longer in idle
- */
-#define MAX_MODULE_ENABLE_WAIT         100000
-
 u16 cpu_mask;
 
-/*
- * Clock features setup. Used instead of CPU type checks.
- */
-struct ti_clk_features ti_clk_features;
-
 /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
 #define OMAP3430_DPLL_FINT_BAND1_MIN   750000
 #define OMAP3430_DPLL_FINT_BAND1_MAX   2100000
@@ -66,119 +54,24 @@ struct ti_clk_features ti_clk_features;
 #define OMAP3PLUS_DPLL_FINT_MIN                32000
 #define OMAP3PLUS_DPLL_FINT_MAX                52000000
 
-/*
- * clkdm_control: if true, then when a clock is enabled in the
- * hardware, its clockdomain will first be enabled; and when a clock
- * is disabled in the hardware, its clockdomain will be disabled
- * afterwards.
- */
-static bool clkdm_control = true;
-
-static LIST_HEAD(clk_hw_omap_clocks);
-
-struct clk_iomap {
-       struct regmap *regmap;
-       void __iomem *mem;
-};
-
-static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
-
-static void clk_memmap_writel(u32 val, void __iomem *reg)
-{
-       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-       struct clk_iomap *io = clk_memmaps[r->index];
-
-       if (io->regmap)
-               regmap_write(io->regmap, r->offset, val);
-       else
-               writel_relaxed(val, io->mem + r->offset);
-}
-
-static u32 clk_memmap_readl(void __iomem *reg)
-{
-       u32 val;
-       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-       struct clk_iomap *io = clk_memmaps[r->index];
-
-       if (io->regmap)
-               regmap_read(io->regmap, r->offset, &val);
-       else
-               val = readl_relaxed(io->mem + r->offset);
-
-       return val;
-}
-
-void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
-{
-       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
-               writel_relaxed(val, reg);
-       else
-               clk_memmap_writel(val, reg);
-}
-
-u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
-{
-       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
-               return readl_relaxed(reg);
-       else
-               return clk_memmap_readl(reg);
-}
-
 static struct ti_clk_ll_ops omap_clk_ll_ops = {
-       .clk_readl = clk_memmap_readl,
-       .clk_writel = clk_memmap_writel,
+       .clkdm_clk_enable = clkdm_clk_enable,
+       .clkdm_clk_disable = clkdm_clk_disable,
+       .cm_wait_module_ready = omap_cm_wait_module_ready,
+       .cm_split_idlest_reg = cm_split_idlest_reg,
 };
 
 /**
- * omap2_clk_provider_init - initialize a clock provider
- * @match_table: DT device table to match for devices to init
- * @np: device node pointer for the this clock provider
- * @index: index for the clock provider
- + @syscon: syscon regmap pointer
- * @mem: iomem pointer for the clock provider memory area, only used if
- *      syscon is not provided
+ * omap2_clk_setup_ll_ops - setup clock driver low-level ops
  *
- * Initializes a clock provider module (CM/PRM etc.), registering
- * the memory mapping at specified index and initializing the
- * low level driver infrastructure. Returns 0 in success.
+ * Sets up clock driver low-level platform ops. These are needed
+ * for register accesses and various other misc platform operations.
+ * Returns 0 on success, -EBUSY if low level ops have been registered
+ * already.
  */
-int __init omap2_clk_provider_init(struct device_node *np, int index,
-                                  struct regmap *syscon, void __iomem *mem)
+int __init omap2_clk_setup_ll_ops(void)
 {
-       struct clk_iomap *io;
-
-       ti_clk_ll_ops = &omap_clk_ll_ops;
-
-       io = kzalloc(sizeof(*io), GFP_KERNEL);
-
-       io->regmap = syscon;
-       io->mem = mem;
-
-       clk_memmaps[index] = io;
-
-       ti_dt_clk_init_provider(np, index);
-
-       return 0;
-}
-
-/**
- * omap2_clk_legacy_provider_init - initialize a legacy clock provider
- * @index: index for the clock provider
- * @mem: iomem pointer for the clock provider memory area
- *
- * Initializes a legacy clock provider memory mapping.
- */
-void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
-{
-       struct clk_iomap *io;
-
-       ti_clk_ll_ops = &omap_clk_ll_ops;
-
-       io = memblock_virt_alloc(sizeof(*io), 0);
-
-       io->mem = mem;
-
-       clk_memmaps[index] = io;
+       return ti_clk_setup_ll_ops(&omap_clk_ll_ops);
 }
 
 /*
@@ -187,77 +80,6 @@ void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
 
 /* Private functions */
 
-
-/**
- * _wait_idlest_generic - wait for a module to leave the idle state
- * @clk: module clock to wait for (needed for register offsets)
- * @reg: virtual address of module IDLEST register
- * @mask: value to mask against to determine if the module is active
- * @idlest: idle state indicator (0 or 1) for the clock
- * @name: name of the clock (for printk)
- *
- * Wait for a module to leave idle, where its idle-status register is
- * not inside the CM module.  Returns 1 if the module left idle
- * promptly, or 0 if the module did not leave idle before the timeout
- * elapsed.  XXX Deprecated - should be moved into drivers for the
- * individual IP block that the IDLEST register exists in.
- */
-static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
-                               u32 mask, u8 idlest, const char *name)
-{
-       int i = 0, ena = 0;
-
-       ena = (idlest) ? 0 : mask;
-
-       omap_test_timeout(((omap2_clk_readl(clk, reg) & mask) == ena),
-                         MAX_MODULE_ENABLE_WAIT, i);
-
-       if (i < MAX_MODULE_ENABLE_WAIT)
-               pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
-                        name, i);
-       else
-               pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
-                      name, MAX_MODULE_ENABLE_WAIT);
-
-       return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
-};
-
-/**
- * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
- * @clk: struct clk * belonging to the module
- *
- * If the necessary clocks for the OMAP hardware IP block that
- * corresponds to clock @clk are enabled, then wait for the module to
- * indicate readiness (i.e., to leave IDLE).  This code does not
- * belong in the clock code and will be moved in the medium term to
- * module-dependent code.  No return value.
- */
-static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
-{
-       void __iomem *companion_reg, *idlest_reg;
-       u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
-       s16 prcm_mod;
-       int r;
-
-       /* Not all modules have multiple clocks that their IDLEST depends on */
-       if (clk->ops->find_companion) {
-               clk->ops->find_companion(clk, &companion_reg, &other_bit);
-               if (!(omap2_clk_readl(clk, companion_reg) & (1 << other_bit)))
-                       return;
-       }
-
-       clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
-       r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
-       if (r) {
-               /* IDLEST register not in the CM module */
-               _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
-                                    idlest_val, __clk_get_name(clk->hw.clk));
-       } else {
-               omap_cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
-                                         idlest_bit);
-       };
-}
-
 /* Public functions */
 
 /**
@@ -290,279 +112,6 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
        }
 }
 
-/**
- * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
- *
- * Prevent the OMAP clock code from calling into the clockdomain code
- * when a hardware clock in that clockdomain is enabled or disabled.
- * Intended to be called at init time from omap*_clk_init().  No
- * return value.
- */
-void __init omap2_clk_disable_clkdm_control(void)
-{
-       clkdm_control = false;
-}
-
-/**
- * omap2_clk_dflt_find_companion - find companion clock to @clk
- * @clk: struct clk * to find the companion clock of
- * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
- * @other_bit: u8 ** to return the companion clock bit shift in
- *
- * Note: We don't need special code here for INVERT_ENABLE for the
- * time being since INVERT_ENABLE only applies to clocks enabled by
- * CM_CLKEN_PLL
- *
- * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
- * just a matter of XORing the bits.
- *
- * Some clocks don't have companion clocks.  For example, modules with
- * only an interface clock (such as MAILBOXES) don't have a companion
- * clock.  Right now, this code relies on the hardware exporting a bit
- * in the correct companion register that indicates that the
- * nonexistent 'companion clock' is active.  Future patches will
- * associate this type of code with per-module data structures to
- * avoid this issue, and remove the casts.  No return value.
- */
-void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
-                       void __iomem **other_reg, u8 *other_bit)
-{
-       u32 r;
-
-       /*
-        * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
-        * it's just a matter of XORing the bits.
-        */
-       r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
-
-       *other_reg = (__force void __iomem *)r;
-       *other_bit = clk->enable_bit;
-}
-
-/**
- * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
- * @clk: struct clk * to find IDLEST info for
- * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
- * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
- * @idlest_val: u8 * to return the idle status indicator
- *
- * Return the CM_IDLEST register address and bit shift corresponding
- * to the module that "owns" this clock.  This default code assumes
- * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
- * the IDLEST register address ID corresponds to the CM_*CLKEN
- * register address ID (e.g., that CM_FCLKEN2 corresponds to
- * CM_IDLEST2).  This is not true for all modules.  No return value.
- */
-void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
-               void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = clk->enable_bit;
-
-       /*
-        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
-        * 34xx reverses this, just to keep us on our toes
-        * AM35xx uses both, depending on the module.
-        */
-       *idlest_val = ti_clk_features.cm_idlest_val;
-}
-
-/**
- * omap2_dflt_clk_enable - enable a clock in the hardware
- * @hw: struct clk_hw * of the clock to enable
- *
- * Enable the clock @hw in the hardware.  We first call into the OMAP
- * clockdomain code to "enable" the corresponding clockdomain if this
- * is the first enabled user of the clockdomain.  Then program the
- * hardware to enable the clock.  Then wait for the IP block that uses
- * this clock to leave idle (if applicable).  Returns the error value
- * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
- * if @hw has a null clock enable_reg, or zero upon success.
- */
-int omap2_dflt_clk_enable(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-       u32 v;
-       int ret = 0;
-
-       clk = to_clk_hw_omap(hw);
-
-       if (clkdm_control && clk->clkdm) {
-               ret = clkdm_clk_enable(clk->clkdm, hw->clk);
-               if (ret) {
-                       WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
-                            __func__, __clk_get_name(hw->clk),
-                            clk->clkdm->name, ret);
-                       return ret;
-               }
-       }
-
-       if (unlikely(clk->enable_reg == NULL)) {
-               pr_err("%s: %s missing enable_reg\n", __func__,
-                      __clk_get_name(hw->clk));
-               ret = -EINVAL;
-               goto err;
-       }
-
-       /* FIXME should not have INVERT_ENABLE bit here */
-       v = omap2_clk_readl(clk, clk->enable_reg);
-       if (clk->flags & INVERT_ENABLE)
-               v &= ~(1 << clk->enable_bit);
-       else
-               v |= (1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, clk->enable_reg);
-       v = omap2_clk_readl(clk, clk->enable_reg); /* OCP barrier */
-
-       if (clk->ops && clk->ops->find_idlest)
-               _omap2_module_wait_ready(clk);
-
-       return 0;
-
-err:
-       if (clkdm_control && clk->clkdm)
-               clkdm_clk_disable(clk->clkdm, hw->clk);
-       return ret;
-}
-
-/**
- * omap2_dflt_clk_disable - disable a clock in the hardware
- * @hw: struct clk_hw * of the clock to disable
- *
- * Disable the clock @hw in the hardware, and call into the OMAP
- * clockdomain code to "disable" the corresponding clockdomain if all
- * clocks/hwmods in that clockdomain are now disabled.  No return
- * value.
- */
-void omap2_dflt_clk_disable(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-       u32 v;
-
-       clk = to_clk_hw_omap(hw);
-       if (!clk->enable_reg) {
-               /*
-                * 'independent' here refers to a clock which is not
-                * controlled by its parent.
-                */
-               pr_err("%s: independent clock %s has no enable_reg\n",
-                      __func__, __clk_get_name(hw->clk));
-               return;
-       }
-
-       v = omap2_clk_readl(clk, clk->enable_reg);
-       if (clk->flags & INVERT_ENABLE)
-               v |= (1 << clk->enable_bit);
-       else
-               v &= ~(1 << clk->enable_bit);
-       omap2_clk_writel(v, clk, clk->enable_reg);
-       /* No OCP barrier needed here since it is a disable operation */
-
-       if (clkdm_control && clk->clkdm)
-               clkdm_clk_disable(clk->clkdm, hw->clk);
-}
-
-/**
- * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
- * @hw: struct clk_hw * of the clock being enabled
- *
- * Increment the usecount of the clockdomain of the clock pointed to
- * by @hw; if the usecount is 1, the clockdomain will be "enabled."
- * Only needed for clocks that don't use omap2_dflt_clk_enable() as
- * their enable function pointer.  Passes along the return value of
- * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
- * clockdomain, or 0 if clock framework-based clockdomain control is
- * not implemented.
- */
-int omap2_clkops_enable_clkdm(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-       int ret = 0;
-
-       clk = to_clk_hw_omap(hw);
-
-       if (unlikely(!clk->clkdm)) {
-               pr_err("%s: %s: no clkdm set ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-               return -EINVAL;
-       }
-
-       if (unlikely(clk->enable_reg))
-               pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-
-       if (!clkdm_control) {
-               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
-                      __func__, __clk_get_name(hw->clk));
-               return 0;
-       }
-
-       ret = clkdm_clk_enable(clk->clkdm, hw->clk);
-       WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
-            __func__, __clk_get_name(hw->clk), clk->clkdm->name, ret);
-
-       return ret;
-}
-
-/**
- * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
- * @hw: struct clk_hw * of the clock being disabled
- *
- * Decrement the usecount of the clockdomain of the clock pointed to
- * by @hw; if the usecount is 0, the clockdomain will be "disabled."
- * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
- * disable function pointer.  No return value.
- */
-void omap2_clkops_disable_clkdm(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk;
-
-       clk = to_clk_hw_omap(hw);
-
-       if (unlikely(!clk->clkdm)) {
-               pr_err("%s: %s: no clkdm set ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-               return;
-       }
-
-       if (unlikely(clk->enable_reg))
-               pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
-                      __clk_get_name(hw->clk));
-
-       if (!clkdm_control) {
-               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
-                      __func__, __clk_get_name(hw->clk));
-               return;
-       }
-
-       clkdm_clk_disable(clk->clkdm, hw->clk);
-}
-
-/**
- * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
- * @hw: struct clk_hw * to check
- *
- * Return 1 if the clock represented by @hw is enabled in the
- * hardware, or 0 otherwise.  Intended for use in the struct
- * clk_ops.is_enabled function pointer.
- */
-int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       u32 v;
-
-       v = omap2_clk_readl(clk, clk->enable_reg);
-
-       if (clk->flags & INVERT_ENABLE)
-               v ^= BIT(clk->enable_bit);
-
-       v &= BIT(clk->enable_bit);
-
-       return v ? 1 : 0;
-}
-
 static int __initdata mpurate;
 
 /*
@@ -583,178 +132,6 @@ static int __init omap_clk_setup(char *str)
 }
 __setup("mpurate=", omap_clk_setup);
 
-/**
- * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
- * @clk: struct clk * to initialize
- *
- * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
- * temporarily for autoidle handling, until this support can be
- * integrated into the common clock framework code in some way.  No
- * return value.
- */
-void omap2_init_clk_hw_omap_clocks(struct clk *clk)
-{
-       struct clk_hw_omap *c;
-
-       if (__clk_get_flags(clk) & CLK_IS_BASIC)
-               return;
-
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       list_add(&c->node, &clk_hw_omap_clocks);
-}
-
-/**
- * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
- * support it
- *
- * Enable clock autoidle on all OMAP clocks that have allow_idle
- * function pointers associated with them.  This function is intended
- * to be temporary until support for this is added to the common clock
- * code.  Returns 0.
- */
-int omap2_clk_enable_autoidle_all(void)
-{
-       struct clk_hw_omap *c;
-
-       list_for_each_entry(c, &clk_hw_omap_clocks, node)
-               if (c->ops && c->ops->allow_idle)
-                       c->ops->allow_idle(c);
-
-       of_ti_clk_allow_autoidle_all();
-
-       return 0;
-}
-
-/**
- * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
- * support it
- *
- * Disable clock autoidle on all OMAP clocks that have allow_idle
- * function pointers associated with them.  This function is intended
- * to be temporary until support for this is added to the common clock
- * code.  Returns 0.
- */
-int omap2_clk_disable_autoidle_all(void)
-{
-       struct clk_hw_omap *c;
-
-       list_for_each_entry(c, &clk_hw_omap_clocks, node)
-               if (c->ops && c->ops->deny_idle)
-                       c->ops->deny_idle(c);
-
-       of_ti_clk_deny_autoidle_all();
-
-       return 0;
-}
-
-/**
- * omap2_clk_deny_idle - disable autoidle on an OMAP clock
- * @clk: struct clk * to disable autoidle for
- *
- * Disable autoidle on an OMAP clock.
- */
-int omap2_clk_deny_idle(struct clk *clk)
-{
-       struct clk_hw_omap *c;
-
-       if (__clk_get_flags(clk) & CLK_IS_BASIC)
-               return -EINVAL;
-
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       if (c->ops && c->ops->deny_idle)
-               c->ops->deny_idle(c);
-       return 0;
-}
-
-/**
- * omap2_clk_allow_idle - enable autoidle on an OMAP clock
- * @clk: struct clk * to enable autoidle for
- *
- * Enable autoidle on an OMAP clock.
- */
-int omap2_clk_allow_idle(struct clk *clk)
-{
-       struct clk_hw_omap *c;
-
-       if (__clk_get_flags(clk) & CLK_IS_BASIC)
-               return -EINVAL;
-
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       if (c->ops && c->ops->allow_idle)
-               c->ops->allow_idle(c);
-       return 0;
-}
-
-/**
- * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
- * @clk_names: ptr to an array of strings of clock names to enable
- * @num_clocks: number of clock names in @clk_names
- *
- * Prepare and enable a list of clocks, named by @clk_names.  No
- * return value. XXX Deprecated; only needed until these clocks are
- * properly claimed and enabled by the drivers or core code that uses
- * them.  XXX What code disables & calls clk_put on these clocks?
- */
-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
-{
-       struct clk *init_clk;
-       int i;
-
-       for (i = 0; i < num_clocks; i++) {
-               init_clk = clk_get(NULL, clk_names[i]);
-               if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
-                               clk_names[i]))
-                       continue;
-               clk_prepare_enable(init_clk);
-       }
-}
-
-const struct clk_hw_omap_ops clkhwops_wait = {
-       .find_idlest    = omap2_clk_dflt_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-/**
- * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
- * @mpurate_ck_name: clk name of the clock to change rate
- *
- * Change the ARM MPU clock rate to the rate specified on the command
- * line, if one was specified.  @mpurate_ck_name should be
- * "virt_prcm_set" on OMAP2xxx and "dpll1_ck" on OMAP34xx/OMAP36xx.
- * XXX Does not handle voltage scaling - on OMAP2xxx this is currently
- * handled by the virt_prcm_set clock, but this should be handled by
- * the OPP layer.  XXX This is intended to be handled by the OPP layer
- * code in the near future and should be removed from the clock code.
- * Returns -EINVAL if 'mpurate' is zero or if clk_set_rate() rejects
- * the rate, -ENOENT if the struct clk referred to by @mpurate_ck_name
- * cannot be found, or 0 upon success.
- */
-int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
-{
-       struct clk *mpurate_ck;
-       int r;
-
-       if (!mpurate)
-               return -EINVAL;
-
-       mpurate_ck = clk_get(NULL, mpurate_ck_name);
-       if (WARN(IS_ERR(mpurate_ck), "Failed to get %s.\n", mpurate_ck_name))
-               return -ENOENT;
-
-       r = clk_set_rate(mpurate_ck, mpurate);
-       if (r < 0) {
-               WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
-                    mpurate_ck_name, mpurate, r);
-               clk_put(mpurate_ck);
-               return -EINVAL;
-       }
-
-       calibrate_delay();
-       clk_put(mpurate_ck);
-
-       return 0;
-}
-
 /**
  * omap2_clk_print_new_rates - print summary of current clock tree rates
  * @hfclkin_ck_name: clk name for the off-chip HF oscillator
@@ -801,29 +178,30 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
  */
 void __init ti_clk_init_features(void)
 {
+       struct ti_clk_features features = { 0 };
        /* Fint setup for DPLLs */
        if (cpu_is_omap3430()) {
-               ti_clk_features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
-               ti_clk_features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
-               ti_clk_features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
-               ti_clk_features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
+               features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+               features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+               features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
+               features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
        } else {
-               ti_clk_features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
-               ti_clk_features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+               features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+               features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
        }
 
        /* Bypass value setup for DPLLs */
        if (cpu_is_omap24xx()) {
-               ti_clk_features.dpll_bypass_vals |=
+               features.dpll_bypass_vals |=
                        (1 << OMAP2XXX_EN_DPLL_LPBYPASS) |
                        (1 << OMAP2XXX_EN_DPLL_FRBYPASS);
        } else if (cpu_is_omap34xx()) {
-               ti_clk_features.dpll_bypass_vals |=
+               features.dpll_bypass_vals |=
                        (1 << OMAP3XXX_EN_DPLL_LPBYPASS) |
                        (1 << OMAP3XXX_EN_DPLL_FRBYPASS);
        } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() ||
                   soc_is_omap54xx() || soc_is_dra7xx()) {
-               ti_clk_features.dpll_bypass_vals |=
+               features.dpll_bypass_vals |=
                        (1 << OMAP4XXX_EN_DPLL_LPBYPASS) |
                        (1 << OMAP4XXX_EN_DPLL_FRBYPASS) |
                        (1 << OMAP4XXX_EN_DPLL_MNBYPASS);
@@ -831,7 +209,7 @@ void __init ti_clk_init_features(void)
 
        /* Jitter correction only available on OMAP343X */
        if (cpu_is_omap343x())
-               ti_clk_features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
+               features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
 
        /* Idlest value for interface clocks.
         * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
@@ -839,11 +217,13 @@ void __init ti_clk_init_features(void)
         * AM35xx uses both, depending on the module.
         */
        if (cpu_is_omap24xx())
-               ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
+               features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
        else if (cpu_is_omap34xx())
-               ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
+               features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
 
        /* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
        if (omap_rev() == OMAP3430_REV_ES1_0)
-               ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
+               features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
+
+       ti_clk_setup_features(&features);
 }
index 652ed0ab86ec022cffdb55271e3c1e9fb6a78e0c..67da640ba1c747a57bc5e3da47603c275ae068a2 100644 (file)
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
-struct omap_clk {
-       u16                             cpu;
-       struct clk_lookup               lk;
-};
-
-#define CLK(dev, con, ck)              \
-       {                               \
-               .lk = {                 \
-                       .dev_id = dev,  \
-                       .con_id = con,  \
-                       .clk = ck,      \
-               },                      \
-       }
-
-struct clockdomain;
-
-#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)     \
-       static struct clk_core _name##_core = {                 \
-               .name = #_name,                                 \
-               .hw = &_name##_hw.hw,                           \
-               .parent_names = _parent_array_name,             \
-               .num_parents = ARRAY_SIZE(_parent_array_name),  \
-               .ops = &_clkops_name,                           \
-       };                                                      \
-       static struct clk _name = {                             \
-               .core = &_name##_core,                          \
-       };
-
-#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name,     \
-                               _clkops_name, _flags)           \
-       static struct clk_core _name##_core = {                 \
-               .name = #_name,                                 \
-               .hw = &_name##_hw.hw,                           \
-               .parent_names = _parent_array_name,             \
-               .num_parents = ARRAY_SIZE(_parent_array_name),  \
-               .ops = &_clkops_name,                           \
-               .flags = _flags,                                \
-       };                                                      \
-       static struct clk _name = {                             \
-               .core = &_name##_core,                          \
-       };
-
-#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name)          \
-       static struct clk_hw_omap _name##_hw = {                \
-               .hw = {                                         \
-                       .clk = &_name,                          \
-               },                                              \
-               .clkdm_name = _clkdm_name,                      \
-       };
-
-#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel,       \
-                           _clksel_reg, _clksel_mask,          \
-                           _parent_names, _ops)                \
-       static struct clk _name;                                \
-       static struct clk_hw_omap _name##_hw = {                \
-               .hw = {                                         \
-                       .clk = &_name,                          \
-               },                                              \
-               .clksel         = _clksel,                      \
-               .clksel_reg     = _clksel_reg,                  \
-               .clksel_mask    = _clksel_mask,                 \
-               .clkdm_name     = _clkdm_name,                  \
-       };                                                      \
-       DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
-
-#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel,  \
-                                _clksel_reg, _clksel_mask,     \
-                                _enable_reg, _enable_bit,      \
-                                _hwops, _parent_names, _ops)   \
-       static struct clk _name;                                \
-       static struct clk_hw_omap _name##_hw = {                \
-               .hw = {                                         \
-                       .clk = &_name,                          \
-               },                                              \
-               .ops            = _hwops,                       \
-               .enable_reg     = _enable_reg,                  \
-               .enable_bit     = _enable_bit,                  \
-               .clksel         = _clksel,                      \
-               .clksel_reg     = _clksel_reg,                  \
-               .clksel_mask    = _clksel_mask,                 \
-               .clkdm_name     = _clkdm_name,                  \
-       };                                                      \
-       DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
-
 /* struct clksel_rate.flags possibilities */
 #define RATE_IN_242X           (1 << 0)
 #define RATE_IN_243X           (1 << 1)
@@ -127,38 +43,6 @@ struct clockdomain;
 /* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
 #define RATE_IN_3430ES2PLUS_36XX       (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
 
-
-/**
- * struct clksel_rate - register bitfield values corresponding to clk divisors
- * @val: register bitfield value (shifted to bit 0)
- * @div: clock divisor corresponding to @val
- * @flags: (see "struct clksel_rate.flags possibilities" above)
- *
- * @val should match the value of a read from struct clk.clksel_reg
- * AND'ed with struct clk.clksel_mask, shifted right to bit 0.
- *
- * @div is the divisor that should be applied to the parent clock's rate
- * to produce the current clock's rate.
- */
-struct clksel_rate {
-       u32                     val;
-       u8                      div;
-       u16                     flags;
-};
-
-/**
- * struct clksel - available parent clocks, and a pointer to their divisors
- * @parent: struct clk * to a possible parent clock
- * @rates: available divisors for this parent clock
- *
- * A struct clksel is always associated with one or more struct clks
- * and one or more struct clksel_rates.
- */
-struct clksel {
-       struct clk               *parent;
-       const struct clksel_rate *rates;
-};
-
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K               0x0
 #define CORE_CLK_SRC_DPLL              0x1
@@ -180,105 +64,18 @@ struct clksel {
 #define OMAP4XXX_EN_DPLL_FRBYPASS              0x6
 #define OMAP4XXX_EN_DPLL_LOCKED                        0x7
 
-u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
-void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
-void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
-void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
-void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
-
-void __init omap2_clk_disable_clkdm_control(void);
-
-/* clkt_clksel.c public functions */
-u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
-                               unsigned long target_rate,
-                               u32 *new_div);
-u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
-unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
-long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                               unsigned long *parent_rate);
-int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate);
-int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
-
-/* clkt_iclk.c public functions */
-extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
-extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
-
-unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
-
-void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
-                                  void __iomem **other_reg,
-                                  u8 *other_bit);
-void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
-                               void __iomem **idlest_reg,
-                               u8 *idlest_bit, u8 *idlest_val);
-int omap2_clk_enable_autoidle_all(void);
-int omap2_clk_allow_idle(struct clk *clk);
-int omap2_clk_deny_idle(struct clk *clk);
-int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
                               const char *core_ck_name,
                               const char *mpu_ck_name);
 
-u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg);
-void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
-
 extern u16 cpu_mask;
 
-/*
- * Clock features setup. Used instead of CPU type checks.
- */
-struct ti_clk_features {
-       u32 flags;
-       long fint_min;
-       long fint_max;
-       long fint_band1_max;
-       long fint_band2_min;
-       u8 dpll_bypass_vals;
-       u8 cm_idlest_val;
-};
-
-#define TI_CLK_DPLL_HAS_FREQSEL                (1 << 0)
-#define TI_CLK_DPLL4_DENY_REPROGRAM    (1 << 1)
-
-extern struct ti_clk_features ti_clk_features;
-
 extern const struct clkops clkops_omap2_dflt_wait;
 extern const struct clkops clkops_omap2_dflt;
 
 extern struct clk_functions omap2_clk_functions;
 
-extern const struct clksel_rate gpt_32k_rates[];
-extern const struct clksel_rate gpt_sys_rates[];
-extern const struct clksel_rate gfx_l3_rates[];
-extern const struct clksel_rate dsp_ick_rates[];
-
-extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
-extern const struct clk_hw_omap_ops clkhwops_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
-extern const struct clk_hw_omap_ops clkhwops_apll54;
-extern const struct clk_hw_omap_ops clkhwops_apll96;
-
-/* clksel_rate blocks shared between OMAP44xx and AM33xx */
-extern const struct clksel_rate div_1_0_rates[];
-extern const struct clksel_rate div3_1to4_rates[];
-extern const struct clksel_rate div_1_1_rates[];
-extern const struct clksel_rate div_1_2_rates[];
-extern const struct clksel_rate div_1_3_rates[];
-extern const struct clksel_rate div_1_4_rates[];
-extern const struct clksel_rate div31_1to31_rates[];
-
-extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
-extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
-
-struct regmap;
-
-int __init omap2_clk_provider_init(struct device_node *np, int index,
-                                  struct regmap *syscon, void __iomem *mem);
-void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem);
+int __init omap2_clk_setup_ll_ops(void);
 
 void __init ti_clk_init_features(void);
 #endif
diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
deleted file mode 100644 (file)
index cef0c8d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * clock2430.c - OMAP2430-specific clock integration code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "cm2xxx.h"
-#include "cm-regbits-24xx.h"
-
-/**
- * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
- * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
- * passes back the correct CM_IDLEST register address for I2CHS
- * modules.  No return value.
- */
-static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
-                                          void __iomem **idlest_reg,
-                                          u8 *idlest_bit,
-                                          u8 *idlest_val)
-{
-       *idlest_reg = OMAP2430_CM_REGADDR(CORE_MOD, CM_IDLEST);
-       *idlest_bit = clk->enable_bit;
-       *idlest_val = OMAP24XX_CM_IDLEST_VAL;
-}
-
-/* 2430 I2CHS has non-standard IDLEST register */
-const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
-       .find_idlest    = omap2430_clk_i2chs_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c
deleted file mode 100644 (file)
index b870f6a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * clock2xxx.c - OMAP2xxx-specific clock integration code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "cm.h"
-#include "cm-regbits-24xx.h"
-
-struct clk_hw *dclk_hw;
-/*
- * Omap24xx specific clock functions
- */
-
-/*
- * Switch the MPU rate if specified on cmdline.  We cannot do this
- * early until cmdline is parsed.  XXX This should be removed from the
- * clock code and handled by the OPP layer code in the near future.
- */
-static int __init omap2xxx_clk_arch_init(void)
-{
-       int ret;
-
-       if (!cpu_is_omap24xx())
-               return 0;
-
-       ret = omap2_clk_switch_mpurate_at_boot("virt_prcm_set");
-       if (!ret)
-               omap2_clk_print_new_rates("sys_ck", "dpll_ck", "mpu_ck");
-
-       return ret;
-}
-
-omap_arch_initcall(omap2xxx_clk_arch_init);
-
-
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
deleted file mode 100644 (file)
index 4596468..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * OMAP3-specific clock framework functions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- *
- * Paul Walmsley
- * Jouni Högander
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
- * Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock34xx.h"
-#include "cm3xxx.h"
-#include "cm-regbits-34xx.h"
-
-/**
- * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
- * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
- * @idlest_reg and @idlest_bit.  No return value.
- */
-static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
-                                           u8 *idlest_bit,
-                                           u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
-       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-/**
- * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
- * target IDLEST bits.  For our purposes, we are concerned with the
- * target IDLEST bits, which exist at a different bit position than
- * the *CLKEN bit position for these modules (DSS and USBHOST) (The
- * default find_idlest code assumes that they are at the same
- * position.)  No return value.
- */
-static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
-                                                   void __iomem **idlest_reg,
-                                                   u8 *idlest_bit,
-                                                   u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       /* USBHOST_IDLE has same shift */
-       *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
-       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-/**
- * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
- * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
- * @idlest_reg and @idlest_bit.  No return value.
- */
-static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
-                                                void __iomem **idlest_reg,
-                                                u8 *idlest_bit,
-                                                u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
-
-const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
-       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
deleted file mode 100644 (file)
index 084ba71..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * OMAP34xx clock function prototypes and macros
- *
- * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
-
-extern const struct clkops clkops_omap3430es2_ssi_wait;
-extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
-extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
-extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
-extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
-extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
-
-#endif
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
deleted file mode 100644 (file)
index 4d79ae2..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * OMAP3517/3505-specific clock framework functions
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2011 Nokia Corporation
- *
- * Ranjith Lohithakshan
- * Paul Walmsley
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
- * Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock3517.h"
-#include "cm3xxx.h"
-#include "cm-regbits-34xx.h"
-
-/*
- * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
- * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
- * at an offset of 4 from ICK enable bit.
- */
-#define AM35XX_IPSS_ICK_MASK                   0xF
-#define AM35XX_IPSS_ICK_EN_ACK_OFFSET          0x4
-#define AM35XX_IPSS_ICK_FCK_OFFSET             0x8
-#define AM35XX_IPSS_CLK_IDLEST_VAL             0
-
-/**
- * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The interface clocks on AM35xx IPSS reflects the clock idle status
- * in the enable register itsel at a bit offset of 4 from the enable
- * bit. A value of 1 indicates that clock is enabled.
- */
-static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
-                                           u8 *idlest_bit,
-                                           u8 *idlest_val)
-{
-       *idlest_reg = (__force void __iomem *)(clk->enable_reg);
-       *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
-       *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
-}
-
-/**
- * am35xx_clk_find_companion - find companion clock to @clk
- * @clk: struct clk * to find the companion clock of
- * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
- * @other_bit: u8 ** to return the companion clock bit shift in
- *
- * Some clocks don't have companion clocks.  For example, modules with
- * only an interface clock (such as HECC) don't have a companion
- * clock.  Right now, this code relies on the hardware exporting a bit
- * in the correct companion register that indicates that the
- * nonexistent 'companion clock' is active.  Future patches will
- * associate this type of code with per-module data structures to
- * avoid this issue, and remove the casts.  No return value.
- */
-static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
-                                     void __iomem **other_reg,
-                                     u8 *other_bit)
-{
-       *other_reg = (__force void __iomem *)(clk->enable_reg);
-       if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
-               *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
-       else
-               *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
-}
-const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
-       .find_idlest    = am35xx_clk_find_idlest,
-       .find_companion = am35xx_clk_find_companion,
-};
-
-/**
- * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
- * @clk: struct clk * being enabled
- * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
- * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
- * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
- *
- * The IPSS target CM_IDLEST bit is at a different shift from the
- * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
- * and @idlest_bit.  No return value.
- */
-static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
-                                           u8 *idlest_bit,
-                                           u8 *idlest_val)
-{
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
-       *idlest_bit = AM35XX_ST_IPSS_SHIFT;
-       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
-}
-
-const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
-       .allow_idle     = omap2_clkt_iclk_allow_idle,
-       .deny_idle      = omap2_clkt_iclk_deny_idle,
-       .find_idlest    = am35xx_clk_ipss_find_idlest,
-       .find_companion = omap2_clk_dflt_find_companion,
-};
diff --git a/arch/arm/mach-omap2/clock3517.h b/arch/arm/mach-omap2/clock3517.h
deleted file mode 100644 (file)
index ca5e5a6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * OMAP3517/3505 clock function prototypes and macros
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
-
-extern const struct clkops clkops_am35xx_ipss_module_wait;
-extern const struct clkops clkops_am35xx_ipss_wait;
-
-#endif
diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c
deleted file mode 100644 (file)
index 91ccb96..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * OMAP36xx-specific clkops
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- *
- * Mike Turquette
- * Vijaykumar GN
- * Paul Walmsley
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
- * Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock36xx.h"
-#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
-
-/**
- * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering
- *         from HSDivider PWRDN problem Implements Errata ID: i556.
- * @clk: DPLL output struct clk
- *
- * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
- * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
- * valueafter their respective PWRDN bits are set.  Any dummy write
- * (Any other value different from the Read value) to the
- * corresponding CM_CLKSEL register will refresh the dividers.
- */
-int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
-{
-       struct clk_divider *parent;
-       struct clk_hw *parent_hw;
-       u32 dummy_v, orig_v;
-       struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
-       int ret;
-
-       /* Clear PWRDN bit of HSDIVIDER */
-       ret = omap2_dflt_clk_enable(clk);
-
-       parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
-       parent = to_clk_divider(parent_hw);
-
-       /* Restore the dividers */
-       if (!ret) {
-               orig_v = omap2_clk_readl(omap_clk, parent->reg);
-               dummy_v = orig_v;
-
-               /* Write any other value different from the Read value */
-               dummy_v ^= (1 << parent->shift);
-               omap2_clk_writel(dummy_v, omap_clk, parent->reg);
-
-               /* Write the original divider */
-               omap2_clk_writel(orig_v, omap_clk, parent->reg);
-       }
-
-       return ret;
-}
diff --git a/arch/arm/mach-omap2/clock36xx.h b/arch/arm/mach-omap2/clock36xx.h
deleted file mode 100644 (file)
index 945bb7f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * OMAP36xx clock function prototypes and macros
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
-
-extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
-
-#endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
deleted file mode 100644 (file)
index a9e86db..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * OMAP3-specific clock framework functions
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
- *
- * Paul Walmsley
- * Jouni Högander
- *
- * Parts of this code are based on code written by
- * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "clock.h"
-#include "clock3xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-34xx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-34xx.h"
-
-/*
- * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
- * that are sourced by DPLL5, and both of these require this clock
- * to be at 120 MHz for proper operation.
- */
-#define DPLL5_FREQ_FOR_USBHOST         120000000
-
-/* needed by omap3_core_dpll_m2_set_rate() */
-struct clk *sdrc_ick_p, *arm_fck_p;
-
-/**
- * omap3_dpll4_set_rate - set rate for omap3 per-dpll
- * @hw: clock to change
- * @rate: target rate for clock
- * @parent_rate: rate of the parent clock
- *
- * Check if the current SoC supports the per-dpll reprogram operation
- * or not, and then do the rate change if supported. Returns -EINVAL
- * if not supported, 0 for success, and potential error codes from the
- * clock rate change.
- */
-int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate)
-{
-       /*
-        * According to the 12-5 CDP code from TI, "Limitation 2.5"
-        * on 3430ES1 prevents us from changing DPLL multipliers or dividers
-        * on DPLL4.
-        */
-       if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
-               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
-               return -EINVAL;
-       }
-
-       return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
-}
-
-/**
- * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
- * @hw: clock to change
- * @rate: target rate for clock
- * @parent_rate: rate of the parent clock
- * @index: parent index, 0 - reference clock, 1 - bypass clock
- *
- * Check if the current SoC support the per-dpll reprogram operation
- * or not, and then do the rate + parent change if supported. Returns
- * -EINVAL if not supported, 0 for success, and potential error codes
- * from the clock rate change.
- */
-int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
-                                   unsigned long parent_rate, u8 index)
-{
-       if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
-               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
-               return -EINVAL;
-       }
-
-       return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
-                                                     index);
-}
-
-void __init omap3_clk_lock_dpll5(void)
-{
-       struct clk *dpll5_clk;
-       struct clk *dpll5_m2_clk;
-
-       dpll5_clk = clk_get(NULL, "dpll5_ck");
-       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
-       clk_prepare_enable(dpll5_clk);
-
-       /* Program dpll5_m2_clk divider for no division */
-       dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
-       clk_prepare_enable(dpll5_m2_clk);
-       clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
-
-       clk_disable_unprepare(dpll5_m2_clk);
-       clk_disable_unprepare(dpll5_clk);
-       return;
-}
-
-/* Common clock code */
-
-/*
- * Switch the MPU rate if specified on cmdline.  We cannot do this
- * early until cmdline is parsed.  XXX This should be removed from the
- * clock code and handled by the OPP layer code in the near future.
- */
-static int __init omap3xxx_clk_arch_init(void)
-{
-       int ret;
-
-       if (!cpu_is_omap34xx())
-               return 0;
-
-       ret = omap2_clk_switch_mpurate_at_boot("dpll1_ck");
-       if (!ret)
-               omap2_clk_print_new_rates("osc_sys_ck", "core_ck", "arm_fck");
-
-       return ret;
-}
-
-omap_arch_initcall(omap3xxx_clk_arch_init);
-
-
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
deleted file mode 100644 (file)
index 287a46f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * OMAP4 clock function prototypes and macros
- *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
-
-/*
- * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
- *    set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
- *    vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
- */
-#define OMAP4430_REGM4XEN_MULT 4
-
-int omap4xxx_clk_init(void);
-
-#endif
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
deleted file mode 100644 (file)
index 61b60df..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *  linux/arch/arm/mach-omap2/clock_common_data.c
- *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2009 Nokia Corporation
- *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
- *
- * 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 file contains clock data that is common to both the OMAP2xxx and
- * OMAP3xxx clock definition files.
- */
-
-#include "clock.h"
-
-/* clksel_rate data common to 24xx/343x */
-const struct clksel_rate gpt_32k_rates[] = {
-        { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-        { .div = 0 }
-};
-
-const struct clksel_rate gpt_sys_rates[] = {
-        { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-        { .div = 0 }
-};
-
-const struct clksel_rate gfx_l3_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-       { .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_3XXX },
-       { .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_3XXX },
-       { .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_3XXX },
-       { .div = 0 }
-};
-
-const struct clksel_rate dsp_ick_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_24XX },
-       { .div = 2, .val = 2, .flags = RATE_IN_24XX },
-       { .div = 3, .val = 3, .flags = RATE_IN_243X },
-       { .div = 0 },
-};
-
-
-/* clksel_rate blocks shared between OMAP44xx and AM33xx */
-
-const struct clksel_rate div_1_0_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div3_1to4_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
-       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 4, .val = 2, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_1_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_2_rates[] = {
-       { .div = 1, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_3_rates[] = {
-       { .div = 1, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div_1_4_rates[] = {
-       { .div = 1, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
-
-const struct clksel_rate div31_1to31_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 2, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 3, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 4, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 5, .val = 5, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 6, .val = 6, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 7, .val = 7, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 8, .val = 8, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 9, .val = 9, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 10, .val = 10, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 11, .val = 11, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 12, .val = 12, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 13, .val = 13, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 14, .val = 14, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 15, .val = 15, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 16, .val = 16, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 17, .val = 17, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 18, .val = 18, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 19, .val = 19, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 20, .val = 20, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 21, .val = 21, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 22, .val = 22, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 23, .val = 23, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 24, .val = 24, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 25, .val = 25, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 26, .val = 26, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 27, .val = 27, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 28, .val = 28, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 29, .val = 29, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 30, .val = 30, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
-       { .div = 0 },
-};
index 820dde8b5b0453f96a6a3c53a4db8e4c3c9abca6..a253aafbb9a29fe3a7350ca959095e3e78b836d4 100644 (file)
@@ -37,7 +37,6 @@
 #include "clock.h"
 #include "clock2xxx.h"
 #include "clock3xxx.h"
-#include "clock44xx.h"
 #include "omap-pm.h"
 #include "sdrc.h"
 #include "control.h"
@@ -723,6 +722,8 @@ int __init omap_clk_init(void)
 
        ti_clk_init_features();
 
+       omap2_clk_setup_ll_ops();
+
        if (of_have_populated_dt()) {
                ret = omap_control_init();
                if (ret)
index 8e52621b5a6bf3ab42ddef8a5c3db79c3391fcf1..e1d2e991d17a31fc15f1c44616c9b4b7f9de3a84 100644 (file)
@@ -392,6 +392,7 @@ static struct irq_chip wakeupgen_chip = {
        .irq_mask               = wakeupgen_mask,
        .irq_unmask             = wakeupgen_unmask,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .irq_set_type           = irq_chip_set_type_parent,
        .flags                  = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
index 486cc4ded1906670c053f110bb09aeee34ea7fa3..6ef9e6341d96ba13e31c6a3cd0e1b3fc54cf1db9 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
index b1aad7e1426c62e9a394b72a09dfc48ab361f348..2a1a4180d5d0f5901e8fdbaab5d25339b581be01 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/sysfs.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/irq.h>
 #include <linux/time.h>
index 79f033b1ddff2f24c96327c5822a19951983855d..d0871786dd8ac7ebebc93a1b71a2410b4483d9a4 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/of_platform.h>
 #include <linux/cpu.h>
 #include <linux/mbus.h>
-#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <asm/system_misc.h>
 #include <asm/mach/arch.h>
index 16547f2641a32d343bb8ea44adfdf106ad781f49..25d6676f8d6e80d1e75cea63b662de8a7e8ef61c 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
index 5d1a318f1302c53b37b6fa896f24c03ac247404b..0fa4c5f8b1beb31abfa6f26745143a1693a8725c 100644 (file)
@@ -8,6 +8,7 @@ menuconfig ARCH_TEGRA
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
        select PINCTRL
+       select PM_OPP
        select ARCH_HAS_RESET_CONTROLLER
        select RESET_CONTROLLER
        select SOC_BUS
index e31d3d61c9988a645bf081f7462fffaee3db67dd..b316e18a76aa1d14ba5d7ce5bc7a77f9fc8bb930 100644 (file)
@@ -72,21 +72,12 @@ void __init ux500_init_irq(void)
         * Init clocks here so that they are available for system timer
         * initialization.
         */
-       if (cpu_is_u8500_family()) {
-               u8500_of_clk_init(U8500_CLKRST1_BASE,
-                                 U8500_CLKRST2_BASE,
-                                 U8500_CLKRST3_BASE,
-                                 U8500_CLKRST5_BASE,
-                                 U8500_CLKRST6_BASE);
-       } else if (cpu_is_u9540()) {
-               u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
-                              U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
-                              U8500_CLKRST6_BASE);
-       } else if (cpu_is_u8540()) {
-               u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
-                              U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
-                              U8500_CLKRST6_BASE);
-       }
+       if (cpu_is_u8500_family())
+               u8500_clk_init();
+       else if (cpu_is_u9540())
+               u9540_clk_init();
+       else if (cpu_is_u8540())
+               u8540_clk_init();
 }
 
 static const char * __init ux500_get_machine(void)
index 9d259d94e429c4cc493542ad4cf238a513b13743..1160434eece0509c3797733b49e8fcb1262e42e7 100644 (file)
@@ -14,7 +14,7 @@ VDSO_LDFLAGS += -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 VDSO_LDFLAGS += -nostdlib -shared
 VDSO_LDFLAGS += $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
 VDSO_LDFLAGS += $(call cc-ldoption, -Wl$(comma)--build-id)
-VDSO_LDFLAGS += $(call cc-option, -fuse-ld=bfd)
+VDSO_LDFLAGS += $(call cc-ldoption, -fuse-ld=bfd)
 
 obj-$(CONFIG_VDSO) += vdso.o
 extra-$(CONFIG_VDSO) += vdso.lds
index 58093edeea2e5b7513321ff5ddfcb305ac873638..d831bc2ac204b9ab19b98859f135c0386864db35 100644 (file)
                                0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
                        ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000   /* io */
-                                 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */
+                                 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xf0 0x00000000 0xf0 0x00000000 0x10 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg = < 0x00 0x1f2c0000 0x0 0x00010000   /* Controller registers */
                                0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */
+                       ranges = <0x01000000 0x00 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0xd1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xd8 0x00000000 0xd8 0x00000000 0x08 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg =  < 0x00 0x1f2d0000 0x0 0x00010000   /* Controller registers */
                                 0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */
+                       ranges = <0x01000000 0x00 0x00000000 0x90 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0x91 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0x94 0x00000000 0x94 0x00000000 0x04 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg = < 0x00 0x1f500000 0x0 0x00010000   /* Controller registers */
                                0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000   /* io   */
-                                 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem  */
+                       ranges = <0x01000000 0x00 0x00000000 0xa0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0xa1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xb0 0x00000000 0xb0 0x00000000 0x10 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg = < 0x00 0x1f510000 0x0 0x00010000   /* Controller registers */
                                0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */
+                       ranges = <0x01000000 0x00 0x00000000 0xc0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0xc1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xc8 0x00000000 0xc8 0x00000000 0x08 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
index 3303e8a7b837c9fc033da5a94206af4bb0594ba5..f4bf2f2a014cdccf0838f01f4ba1f452d65b43f6 100644 (file)
@@ -124,7 +124,7 @@ static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
 
        ce_aes_ccm_auth_data(mac, (u8 *)&ltag, ltag.len, &macp, ctx->key_enc,
                             num_rounds(ctx));
-       scatterwalk_start(&walk, req->assoc);
+       scatterwalk_start(&walk, req->src);
 
        do {
                u32 n = scatterwalk_clamp(&walk, len);
@@ -151,6 +151,10 @@ static int ccm_encrypt(struct aead_request *req)
        struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
        struct blkcipher_desc desc = { .info = req->iv };
        struct blkcipher_walk walk;
+       struct scatterlist srcbuf[2];
+       struct scatterlist dstbuf[2];
+       struct scatterlist *src;
+       struct scatterlist *dst;
        u8 __aligned(8) mac[AES_BLOCK_SIZE];
        u8 buf[AES_BLOCK_SIZE];
        u32 len = req->cryptlen;
@@ -168,7 +172,12 @@ static int ccm_encrypt(struct aead_request *req)
        /* preserve the original iv for the final round */
        memcpy(buf, req->iv, AES_BLOCK_SIZE);
 
-       blkcipher_walk_init(&walk, req->dst, req->src, len);
+       src = scatterwalk_ffwd(srcbuf, req->src, req->assoclen);
+       dst = src;
+       if (req->src != req->dst)
+               dst = scatterwalk_ffwd(dstbuf, req->dst, req->assoclen);
+
+       blkcipher_walk_init(&walk, dst, src, len);
        err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
                                             AES_BLOCK_SIZE);
 
@@ -194,7 +203,7 @@ static int ccm_encrypt(struct aead_request *req)
                return err;
 
        /* copy authtag to end of dst */
-       scatterwalk_map_and_copy(mac, req->dst, req->cryptlen,
+       scatterwalk_map_and_copy(mac, dst, req->cryptlen,
                                 crypto_aead_authsize(aead), 1);
 
        return 0;
@@ -207,6 +216,10 @@ static int ccm_decrypt(struct aead_request *req)
        unsigned int authsize = crypto_aead_authsize(aead);
        struct blkcipher_desc desc = { .info = req->iv };
        struct blkcipher_walk walk;
+       struct scatterlist srcbuf[2];
+       struct scatterlist dstbuf[2];
+       struct scatterlist *src;
+       struct scatterlist *dst;
        u8 __aligned(8) mac[AES_BLOCK_SIZE];
        u8 buf[AES_BLOCK_SIZE];
        u32 len = req->cryptlen - authsize;
@@ -224,7 +237,12 @@ static int ccm_decrypt(struct aead_request *req)
        /* preserve the original iv for the final round */
        memcpy(buf, req->iv, AES_BLOCK_SIZE);
 
-       blkcipher_walk_init(&walk, req->dst, req->src, len);
+       src = scatterwalk_ffwd(srcbuf, req->src, req->assoclen);
+       dst = src;
+       if (req->src != req->dst)
+               dst = scatterwalk_ffwd(dstbuf, req->dst, req->assoclen);
+
+       blkcipher_walk_init(&walk, dst, src, len);
        err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
                                             AES_BLOCK_SIZE);
 
@@ -250,44 +268,42 @@ static int ccm_decrypt(struct aead_request *req)
                return err;
 
        /* compare calculated auth tag with the stored one */
-       scatterwalk_map_and_copy(buf, req->src, req->cryptlen - authsize,
+       scatterwalk_map_and_copy(buf, src, req->cryptlen - authsize,
                                 authsize, 0);
 
-       if (memcmp(mac, buf, authsize))
+       if (crypto_memneq(mac, buf, authsize))
                return -EBADMSG;
        return 0;
 }
 
-static struct crypto_alg ccm_aes_alg = {
-       .cra_name               = "ccm(aes)",
-       .cra_driver_name        = "ccm-aes-ce",
-       .cra_priority           = 300,
-       .cra_flags              = CRYPTO_ALG_TYPE_AEAD,
-       .cra_blocksize          = 1,
-       .cra_ctxsize            = sizeof(struct crypto_aes_ctx),
-       .cra_alignmask          = 7,
-       .cra_type               = &crypto_aead_type,
-       .cra_module             = THIS_MODULE,
-       .cra_aead = {
-               .ivsize         = AES_BLOCK_SIZE,
-               .maxauthsize    = AES_BLOCK_SIZE,
-               .setkey         = ccm_setkey,
-               .setauthsize    = ccm_setauthsize,
-               .encrypt        = ccm_encrypt,
-               .decrypt        = ccm_decrypt,
-       }
+static struct aead_alg ccm_aes_alg = {
+       .base = {
+               .cra_name               = "ccm(aes)",
+               .cra_driver_name        = "ccm-aes-ce",
+               .cra_priority           = 300,
+               .cra_blocksize          = 1,
+               .cra_ctxsize            = sizeof(struct crypto_aes_ctx),
+               .cra_alignmask          = 7,
+               .cra_module             = THIS_MODULE,
+       },
+       .ivsize         = AES_BLOCK_SIZE,
+       .maxauthsize    = AES_BLOCK_SIZE,
+       .setkey         = ccm_setkey,
+       .setauthsize    = ccm_setauthsize,
+       .encrypt        = ccm_encrypt,
+       .decrypt        = ccm_decrypt,
 };
 
 static int __init aes_mod_init(void)
 {
        if (!(elf_hwcap & HWCAP_AES))
                return -ENODEV;
-       return crypto_register_alg(&ccm_aes_alg);
+       return crypto_register_aead(&ccm_aes_alg);
 }
 
 static void __exit aes_mod_exit(void)
 {
-       crypto_unregister_alg(&ccm_aes_alg);
+       crypto_unregister_aead(&ccm_aes_alg);
 }
 
 module_init(aes_mod_init);
index f3067d4d4e35711680376372395667efdc45ad07..926ae8d9abc5f7ff66449d1eec168b8973da6118 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/kexec.h>
 #include <linux/crash_dump.h>
 #include <linux/root_dev.h>
-#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
index ec37ab3f524f303419d2cc3a82b79c119e61de1d..97bc68f4c689f28eac7188f5e0b792b5293c37da 100644 (file)
@@ -199,16 +199,15 @@ up_fail:
  */
 void update_vsyscall(struct timekeeper *tk)
 {
-       struct timespec xtime_coarse;
        u32 use_syscall = strcmp(tk->tkr_mono.clock->name, "arch_sys_counter");
 
        ++vdso_data->tb_seq_count;
        smp_wmb();
 
-       xtime_coarse = __current_kernel_time();
        vdso_data->use_syscall                  = use_syscall;
-       vdso_data->xtime_coarse_sec             = xtime_coarse.tv_sec;
-       vdso_data->xtime_coarse_nsec            = xtime_coarse.tv_nsec;
+       vdso_data->xtime_coarse_sec             = tk->xtime_sec;
+       vdso_data->xtime_coarse_nsec            = tk->tkr_mono.xtime_nsec >>
+                                                       tk->tkr_mono.shift;
        vdso_data->wtm_clock_sec                = tk->wall_to_monotonic.tv_sec;
        vdso_data->wtm_clock_nsec               = tk->wall_to_monotonic.tv_nsec;
 
index f02530e726f693ef85df8796b1a01843c3dd2df2..85c57158dcd96a83d80ce99c2c557b371c275984 100644 (file)
@@ -168,8 +168,8 @@ void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
 {
        if (!(vcpu->arch.hcr_el2 & HCR_RW))
                inject_abt32(vcpu, false, addr);
-
-       inject_abt64(vcpu, false, addr);
+       else
+               inject_abt64(vcpu, false, addr);
 }
 
 /**
@@ -184,8 +184,8 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
 {
        if (!(vcpu->arch.hcr_el2 & HCR_RW))
                inject_abt32(vcpu, true, addr);
-
-       inject_abt64(vcpu, true, addr);
+       else
+               inject_abt64(vcpu, true, addr);
 }
 
 /**
@@ -198,6 +198,6 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
 {
        if (!(vcpu->arch.hcr_el2 & HCR_RW))
                inject_undef32(vcpu);
-
-       inject_undef64(vcpu);
+       else
+               inject_undef64(vcpu);
 }
index 0635bd6c2af392fc372b0e02002b1a669a88e33c..34bb4b13e079811f79e76598119c272625f774db 100644 (file)
@@ -175,14 +175,6 @@ static void __init pcibios_assign_resources(void)
                        if (!r->start && r->end)
                                pci_assign_resource(dev, idx);
                }
-
-               if (pci_probe & PCI_ASSIGN_ROMS) {
-                       r = &dev->resource[PCI_ROM_RESOURCE];
-                       r->end -= r->start;
-                       r->start = 0;
-                       if (r->end)
-                               pci_assign_resource(dev, PCI_ROM_RESOURCE);
-               }
        }
 }
 
index a7e487fe76edeaf7cf36846e779481535e13eb5e..d51992ff5a61b601a98b69d59af4f0f469e268ea 100644 (file)
 #define DBG(x...)
 #endif
 
-#define PCI_PROBE_BIOS         0x0001
-#define PCI_PROBE_CONF1                0x0002
-#define PCI_PROBE_CONF2                0x0004
-#define PCI_NO_CHECKS          0x0400
-#define PCI_ASSIGN_ROMS                0x1000
-#define PCI_BIOS_IRQ_SCAN      0x2000
-#define PCI_ASSIGN_ALL_BUSSES  0x4000
-
 extern unsigned int __nongpreldata pci_probe;
 
 /* pci-frv.c */
index f211839e2cae18f4d71999ec41ad8ed2a8ff1bca..f9c86c475bbdafdbd37771c6834d7376b25673ec 100644 (file)
@@ -294,8 +294,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
 #endif
 
-       pci_read_bridge_bases(bus);
-
        if (bus->number == 0) {
                struct pci_dev *dev;
                list_for_each_entry(dev, &bus->devices, bus_list) {
index 7cc3be9fa7c65a0dd700dfd30c04cc7be822922d..d89b6013c9412c7f2ef5d72a3a5f9710f7544d3e 100644 (file)
@@ -533,10 +533,9 @@ void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
-       if (b->self) {
-               pci_read_bridge_bases(b);
+       if (b->self)
                pcibios_fixup_bridge_resources(b->self);
-       }
+
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
        platform_pci_fixup_bus(b);
index 753a6237f99a30a81ac842d7540be5c9ecdc9819..0b6b40d37b95b5acd2f0561a82f12b3859b35880 100644 (file)
@@ -57,7 +57,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -91,6 +91,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -287,7 +288,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -320,7 +320,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -345,6 +344,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -355,6 +355,7 @@ CONFIG_ARIADNE=y
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -363,6 +364,7 @@ CONFIG_HYDRA=y
 CONFIG_APNE=y
 CONFIG_ZORRO8390=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -448,6 +450,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -536,6 +539,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -543,6 +547,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -571,14 +576,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 1f93dcaf02e514719093af817e017037705979fa..eeb3a8991fc411e952cd6a20b3e44602b80f38e0 100644 (file)
@@ -55,7 +55,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -89,6 +89,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -279,7 +280,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -302,7 +302,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -327,17 +326,20 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -406,6 +408,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -494,6 +497,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -501,6 +505,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -529,14 +534,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 831b8b8b92ad3619b0e50d83ed6da092627c3305..3a7006654ce97c9df5bd521d66af5c29c61171fb 100644 (file)
@@ -55,7 +55,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -89,6 +89,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -283,7 +284,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -311,7 +311,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -336,6 +335,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -343,11 +343,13 @@ CONFIG_ATARILANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -428,6 +430,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -516,6 +519,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -523,6 +527,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -551,14 +556,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 91fd187c16d59f6e8685aa55e8accf8f1a14a39c..0586b323a673791fff0661eb5804347bc7ad16fb 100644 (file)
@@ -53,7 +53,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -87,6 +87,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -277,7 +278,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -301,7 +301,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -326,17 +325,20 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 CONFIG_BVME6000_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -399,6 +401,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 9d4934f1d2c3b8c995339eb5f9766594db367d25..ad1dbce07aa4b532fdb49fe515db2f2a19c37aa7 100644 (file)
@@ -55,7 +55,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -89,6 +89,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -279,7 +280,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -302,7 +302,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -327,6 +326,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -334,11 +334,13 @@ CONFIG_HPLANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -408,6 +410,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -496,6 +499,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -503,6 +507,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -531,14 +536,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 72bc187ca995ad5910a82b0f4b0f8c5f847b21ee..b44acacaecf41f43bae326e63318c3c8c7e7d0f8 100644 (file)
@@ -54,7 +54,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -88,6 +88,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -282,7 +283,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -311,7 +311,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -343,6 +342,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -351,12 +351,14 @@ CONFIG_MACMACE=y
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MAC89x0=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_MACSONIC=y
 CONFIG_MAC8390=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -430,6 +432,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -518,6 +521,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -525,6 +529,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -553,14 +558,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 8fb65535597fd13f3bec6769e37493311d4f99fd..8afca3753db1f8f52245f2b4265c35f74268ae5e 100644 (file)
@@ -64,7 +64,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -98,6 +98,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -301,7 +302,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -344,7 +344,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -376,6 +375,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -391,6 +391,7 @@ CONFIG_MACMACE=y
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MAC89x0=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_HP is not set
 CONFIG_BVME6000_NET=y
 CONFIG_MVME16x_NET=y
@@ -403,6 +404,7 @@ CONFIG_NE2000=y
 CONFIG_APNE=y
 CONFIG_ZORRO8390=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -510,6 +512,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -598,6 +601,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -605,6 +609,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -633,14 +638,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index f34491ec01269ceb35d2deae8d72dc71280ba566..ef00875994d9ac34191f2bd6a572d9c44118ef4d 100644 (file)
@@ -52,7 +52,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -86,6 +86,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -276,7 +277,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -300,7 +300,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -325,6 +324,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -332,11 +332,13 @@ CONFIG_MVME147_NET=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -399,6 +401,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 3d3614d1b041d047fc01a24225ba722f01410000..387c2bd90ff1490a8a1c1fcb08a11753c8b2b6b1 100644 (file)
@@ -53,7 +53,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -87,6 +87,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -277,7 +278,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -301,7 +301,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -326,17 +325,20 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 CONFIG_MVME16x_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -399,6 +401,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 643e9c93bea72697f944fdbe5ce2e3a5e0dd22d5..35355c1bc714000d1e3d44b5a429b97fabeac84a 100644 (file)
@@ -53,7 +53,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -87,6 +87,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -280,7 +281,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -307,7 +307,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -332,6 +331,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -341,12 +341,14 @@ CONFIG_VETH=m
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_EZCHIP 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_MICREL is not set
 CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -421,6 +423,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -509,6 +512,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -516,6 +520,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -544,14 +549,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 8fecc5aa166c3ea77ecdb18ed1edf02f23aa9e58..8442d267b877202e5293c0c5178eb340113e69f8 100644 (file)
@@ -50,7 +50,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -84,6 +84,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -274,7 +275,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -298,7 +298,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -323,17 +322,20 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 CONFIG_SUN3_82586=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -400,6 +402,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@ CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 9902c5bfbdc87685f9e815c72a6d4ec40006dfc8..0e1b542e155582a3685340bf0ce8651fcc5d8948 100644 (file)
@@ -50,7 +50,7 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -84,6 +84,7 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
 CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -274,7 +275,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_DUMMY_IRQ=m
@@ -298,7 +298,6 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
 CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
@@ -323,6 +322,7 @@ CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
+CONFIG_GENEVE=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
@@ -330,11 +330,13 @@ CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
@@ -400,6 +402,7 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
 CONFIG_TMPFS=y
 CONFIG_AFFS_FS=m
 CONFIG_ECRYPT_FS=m
@@ -488,6 +491,7 @@ CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -495,6 +499,7 @@ CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
@@ -523,14 +528,15 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_DRBG_HASH=y
 CONFIG_CRYPTO_DRBG_CTR=y
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_XZ_DEC_TEST=m
index 7ee853e1432b077b92da90623f71d56b8e0d75a5..2a33a9645ad822a3482fc29b7dd28baed5450fb7 100644 (file)
@@ -62,12 +62,10 @@ static int __init init_bootinfo_procfs(void)
        if (!bootinfo_size)
                return -EINVAL;
 
-       bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL);
+       bootinfo_copy = kmemdup(bootinfo_tmp, bootinfo_size, GFP_KERNEL);
        if (!bootinfo_copy)
                return -ENOMEM;
 
-       memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size);
-
        pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
        if (!pde) {
                kfree(bootinfo_copy);
index ae838ed5fcf2535ca5c047a2837adadc434735cd..6b8b75266801aaf25fe509985d2a5edd66ed3e8c 100644 (file)
@@ -863,14 +863,7 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases. This is -not- called when generating the PCI tree from
-        * the OF device-tree.
-        */
-       if (bus->self != NULL)
-               pci_read_bridge_bases(bus);
-
-       /* Now fixup the bus bus */
+       /* Fixup the bus */
        pcibios_setup_bus_self(bus);
 
        /* Now fixup devices on that bus */
index 6e46abe0dac6a9cb054bc690f8fee4c9fed60ed3..bd34f4093cd9f7d565be85dd3950849ebaa264a0 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/slab.h>
@@ -389,12 +390,11 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
        return div1;
 }
 
-static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk,
-                                       int scale, int maxdiv)
+static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req,
+                                int scale, int maxdiv)
 {
-       struct clk *pc, *bpc, *free;
+       struct clk_hw *pc, *bpc, *free;
        long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
        int j;
 
@@ -408,7 +408,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
         * the one that gets closest to but not over the requested rate.
         */
        for (j = 0; j < 7; j++) {
-               pc = clk_get_parent_by_index(hw->clk, j);
+               pc = clk_hw_get_parent_by_index(hw, j);
                if (!pc)
                        break;
 
@@ -416,20 +416,20 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
                 * XXX: we would actually want clk_has_active_children()
                 * but this is a good-enough approximation for now.
                 */
-               if (!__clk_is_prepared(pc)) {
+               if (!clk_hw_is_prepared(pc)) {
                        if (!free)
                                free = pc;
                }
 
-               pr = clk_get_rate(pc);
-               if (pr < rate)
+               pr = clk_hw_get_rate(pc);
+               if (pr < req->rate)
                        continue;
 
                /* what can hardware actually provide */
-               tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+               tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
                nr = pr / tdv;
-               diff = rate - nr;
-               if (nr > rate)
+               diff = req->rate - nr;
+               if (nr > req->rate)
                        continue;
 
                if (diff < lastdiff) {
@@ -448,15 +448,16 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
         */
        if (lastdiff && free) {
                for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
-                       tpr = rate * j;
+                       tpr = req->rate * j;
                        if (tpr < 0)
                                break;
-                       pr = clk_round_rate(free, tpr);
+                       pr = clk_hw_round_rate(free, tpr);
 
-                       tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+                       tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
+                                              NULL);
                        nr = pr / tdv;
-                       diff = rate - nr;
-                       if (nr > rate)
+                       diff = req->rate - nr;
+                       if (nr > req->rate)
                                continue;
                        if (diff < lastdiff) {
                                lastdiff = diff;
@@ -469,9 +470,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
                }
        }
 
-       *best_parent_rate = bpr;
-       *best_parent_clk = __clk_get_hw(bpc);
-       return br;
+       if (br < 0)
+               return br;
+
+       req->best_parent_rate = bpr;
+       req->best_parent_hw = bpc;
+       req->rate = br;
+
+       return 0;
 }
 
 static int alchemy_clk_fgv1_en(struct clk_hw *hw)
@@ -562,14 +568,10 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
        return parent_rate / v;
 }
 
-static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req)
 {
-       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
-                                    best_parent_clk, 2, 512);
+       return alchemy_clk_fgcs_detr(hw, req, 2, 512);
 }
 
 /* Au1000, Au1100, Au15x0, Au12x0 */
@@ -696,11 +698,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
        return t;
 }
 
-static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req)
 {
        struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
        int scale, maxdiv;
@@ -713,8 +712,7 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
                maxdiv = 512;
        }
 
-       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
-                                    best_parent_clk, scale, maxdiv);
+       return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
 }
 
 /* Au1300 larger input mux, no separate disable bit, flexible divider */
@@ -917,17 +915,13 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
-static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int alchemy_clk_csrc_detr(struct clk_hw *hw,
+                                struct clk_rate_request *req)
 {
        struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
        int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
 
-       return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
-                                    best_parent_clk, scale, 4);
+       return alchemy_clk_fgcs_detr(hw, req, scale, 4);
 }
 
 static struct clk_ops alchemy_clkops_csrc = {
index af42e7003f12d025cd31e2a5d167f2f4b158d37a..baa7b6fc0a60b1879976c2d4158f73d01e0ca53b 100644 (file)
@@ -407,7 +407,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    noat
        SAVE_ALL
        FEXPORT(handle_\exception\ext)
-       __BUILD_clear_\clear
+       __build_clear_\clear
        .set    at
        __BUILD_\verbose \exception
        move    a0, sp
index ad4d44635c7601162ca0dd8f1b626df28eeeafb2..a6f6b762c47a4c5a2d395e13a1d564964595abe1 100644 (file)
@@ -80,7 +80,7 @@ syscall_trace_entry:
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
-       daddiu  a1, v0, __NR_64_Linux
+       move    a1, v0
        jal     syscall_trace_enter
 
        bltz    v0, 2f                  # seccomp failed? Skip syscall
index 446cc654da56c5f5fcaad749242dd98d593776e1..4b2010654c463158b7dee80194de736195c04595 100644 (file)
@@ -72,7 +72,7 @@ n32_syscall_trace_entry:
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
-       daddiu  a1, v0, __NR_N32_Linux
+       move    a1, v0
        jal     syscall_trace_enter
 
        bltz    v0, 2f                  # seccomp failed? Skip syscall
index b8a0bf5766f2efb64380ae3dedddca3b4782da03..c6996cf67a5c83e91e465d7d03e25c3ff7d3c89d 100644 (file)
@@ -311,12 +311,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dev = bus->self;
-
-       if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
-           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-               pci_read_bridge_bases(bus);
-       }
 }
 
 EXPORT_SYMBOL(PCIBIOS_MIN_IO);
index b5b036f64275b0fe0176132b74f4715f185f7503..b7ab8378964ce5e9ca55acdd869d249f18a3d49b 100644 (file)
@@ -183,18 +183,16 @@ static int __init pcibios_assign_resources(void)
        struct pci_dev *dev = NULL;
        struct resource *r;
 
-       if (!(pci_probe & PCI_ASSIGN_ROMS)) {
-               /* Try to use BIOS settings for ROMs, otherwise let
-                  pci_assign_unassigned_resources() allocate the new
-                  addresses. */
-               for_each_pci_dev(dev) {
-                       r = &dev->resource[PCI_ROM_RESOURCE];
-                       if (!r->flags || !r->start)
-                               continue;
-                       if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
-                               r->end -= r->start;
-                               r->start = 0;
-                       }
+       /* Try to use BIOS settings for ROMs, otherwise let
+          pci_assign_unassigned_resources() allocate the new
+          addresses. */
+       for_each_pci_dev(dev) {
+               r = &dev->resource[PCI_ROM_RESOURCE];
+               if (!r->flags || !r->start)
+                       continue;
+               if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
+                       r->end -= r->start;
+                       r->start = 0;
                }
        }
 
index 9e17aca5a2a19871d939d697a3688b454fcda578..96c484b12226566999248042c6182eb9a4af66d4 100644 (file)
 #define DBG(x...)
 #endif
 
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-
 extern unsigned int pci_probe;
 
 /* pci-asb2305.c */
index 3dfe2d31c67b20971701cac89565af0531dec878..deaa893efba5969a92aed92e6c230f2e00658e6f 100644 (file)
@@ -324,7 +324,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        struct pci_dev *dev;
 
        if (bus->self) {
-               pci_read_bridge_bases(bus);
                pcibios_fixup_bridge_resources(bus->self);
        }
 
index d0ece257d310527743007a60f01f60cc5f684754..04c7e8fc24c207c7909eecfceac2d8e0cbd2722e 100644 (file)
 
 /* Structure of the hardware registers */
 struct mpc52xx_psc {
-       u8              mode;           /* PSC + 0x00 */
+       union {
+               u8      mode;           /* PSC + 0x00 */
+               u8      mr2;
+       };
        u8              reserved0[3];
        union {                         /* PSC + 0x04 */
                u16     status;
index 58abeda64cb7afa271078497f25e3ae5a8a0e26c..15cca17cba4b9fe47c5598006f9e61214e20295c 100644 (file)
@@ -29,6 +29,7 @@ static inline void save_early_sprs(struct thread_struct *prev) {}
 
 extern void enable_kernel_fp(void);
 extern void enable_kernel_altivec(void);
+extern void enable_kernel_vsx(void);
 extern int emulate_altivec(struct pt_regs *);
 extern void __giveup_vsx(struct task_struct *);
 extern void giveup_vsx(struct task_struct *);
index b9de34d44fcb877c388bcb54c98cc82bfb2ac3f2..02c1d5dcee4d8c10b0bf00d1f466bb1256725767 100644 (file)
@@ -1044,13 +1044,7 @@ void pcibios_set_master(struct pci_dev *dev)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases. This is -not- called when generating the PCI tree from
-        * the OF device-tree.
-        */
-       pci_read_bridge_bases(bus);
-
-       /* Now fixup the bus bus */
+       /* Fixup the bus */
        pcibios_setup_bus_self(bus);
 
        /* Now fixup devices on that bus */
index 42e02a2d570bf70a63f0371b16a39c1aec24bbe3..c8c62c7fc31ce67e6888391d821fbe822e1e1f19 100644 (file)
@@ -126,7 +126,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 {
        struct pci_dev *dev;
        const char *type;
-       struct pci_slot *slot;
 
        dev = pci_alloc_dev(bus);
        if (!dev)
@@ -145,10 +144,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        dev->needs_freset = 0;          /* pcie fundamental reset required */
        set_pcie_port_type(dev);
 
-       list_for_each_entry(slot, &dev->bus->slots, list)
-               if (PCI_SLOT(dev->devfn) == slot->number)
-                       dev->slot = slot;
-
+       pci_dev_assign_slot(dev);
        dev->vendor = get_int_prop(node, "vendor-id", 0xffff);
        dev->device = get_int_prop(node, "device-id", 0xffff);
        dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
@@ -191,6 +187,9 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 
        pci_device_add(dev, bus);
 
+       /* Setup MSI caps & disable MSI/MSI-X interrupts */
+       pci_msi_setup_pci_dev(dev);
+
        return dev;
 }
 EXPORT_SYMBOL(of_create_pci_dev);
index 8005e18d1b40381f6b815890b0d58c99a382b4e8..64e6e9d9e656280d819da7f0c9725026b4bf83a9 100644 (file)
@@ -204,8 +204,6 @@ EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_VSX
-#if 0
-/* not currently used, but some crazy RAID module might want to later */
 void enable_kernel_vsx(void)
 {
        WARN_ON(preemptible());
@@ -220,7 +218,6 @@ void enable_kernel_vsx(void)
 #endif /* CONFIG_SMP */
 }
 EXPORT_SYMBOL(enable_kernel_vsx);
-#endif
 
 void giveup_vsx(struct task_struct *tsk)
 {
index f691bcabd71013e23a09a07bfec61a592e1cd237..c50ea76ba66ceb95c99555f7391b75c0744a1b96 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/device.h>
index 2938934c6518c5c427e6b6e938a9c925b56b8eb4..e256592eb66e515d2305bc12fa40afc9ca4f95de 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_S390_HYPFS_FS)     += hypfs/
 obj-$(CONFIG_APPLDATA_BASE)    += appldata/
 obj-y                          += net/
 obj-$(CONFIG_PCI)              += pci/
+obj-$(CONFIG_NUMA)             += numa/
index b06dc383926846c73e85a6c635ff0fac0a3ddcab..4827870f7a6d8c00925b7d052ed68efda20f364e 100644 (file)
@@ -99,18 +99,22 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
        select ARCH_SAVE_PAGE_KEYS if HIBERNATION
        select ARCH_SUPPORTS_ATOMIC_RMW
+       select ARCH_SUPPORTS_NUMA_BALANCING
        select ARCH_USE_CMPXCHG_LOCKREF
+       select ARCH_WANTS_PROT_NUMA_PROT_NONE
        select ARCH_WANT_IPC_PARSE_VERSION
        select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS2
        select DYNAMIC_FTRACE if FUNCTION_TRACER
        select GENERIC_CLOCKEVENTS
+       select GENERIC_CPU_AUTOPROBE
        select GENERIC_CPU_DEVICES if !SMP
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL
        select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_ARCH_AUDITSYSCALL
+       select HAVE_ARCH_EARLY_PFN_TO_NID
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
@@ -153,6 +157,7 @@ config S390
        select VIRT_CPU_ACCOUNTING
        select VIRT_TO_BUS
 
+
 config SCHED_OMIT_FRAME_POINTER
        def_bool y
 
@@ -385,6 +390,76 @@ config HOTPLUG_CPU
 config SCHED_SMT
        def_bool n
 
+# Some NUMA nodes have memory ranges that span
+# other nodes. Even though a pfn is valid and
+# between a node's start and end pfns, it may not
+# reside on that node. See memmap_init_zone()
+# for details. <- They meant memory holes!
+config NODES_SPAN_OTHER_NODES
+       def_bool NUMA
+
+config NUMA
+       bool "NUMA support"
+       depends on SMP && 64BIT && SCHED_TOPOLOGY
+       default n
+       help
+         Enable NUMA support
+
+         This option adds NUMA support to the kernel.
+
+         An operation mode can be selected by appending
+         numa=<method> to the kernel command line.
+
+         The default behaviour is identical to appending numa=plain to
+         the command line. This will create just one node with all
+         available memory and all CPUs in it.
+
+config NODES_SHIFT
+       int "Maximum NUMA nodes (as a power of 2)"
+       range 1 10
+       depends on NUMA
+       default "4"
+       help
+         Specify the maximum number of NUMA nodes available on the target
+         system. Increases memory reserved to accommodate various tables.
+
+menu "Select NUMA modes"
+       depends on NUMA
+
+config NUMA_EMU
+       bool "NUMA emulation"
+       default y
+       help
+         Numa emulation mode will split the available system memory into
+         equal chunks which then are distributed over the configured number
+         of nodes in a round-robin manner.
+
+         The number of fake nodes is limited by the number of available memory
+         chunks (i.e. memory size / fake size) and the number of supported
+         nodes in the kernel.
+
+         The CPUs are assigned to the nodes in a way that partially respects
+         the original machine topology (if supported by the machine).
+         Fair distribution of the CPUs is not guaranteed.
+
+config EMU_SIZE
+       hex "NUMA emulation memory chunk size"
+       default 0x10000000
+       range 0x400000 0x100000000
+       depends on NUMA_EMU
+       help
+         Select the default size by which the memory is chopped and then
+         assigned to emulated NUMA nodes.
+
+         This can be overridden by specifying
+
+         emu_size=<n>
+
+         on the kernel command line where also suffixes K, M, G, and T are
+         supported.
+
+endmenu
+
 config SCHED_MC
        def_bool n
 
index 667b1bca5681fb0eea922ba892727abe5a31dc81..e8d4423e4f858da28b7658a04d47820b5ecbfb16 100644 (file)
@@ -33,6 +33,8 @@ mflags-$(CONFIG_MARCH_Z196)   := -march=z196
 mflags-$(CONFIG_MARCH_ZEC12)  := -march=zEC12
 mflags-$(CONFIG_MARCH_Z13)   := -march=z13
 
+export CC_FLAGS_MARCH := $(mflags-y)
+
 aflags-y += $(mflags-y)
 cflags-y += $(mflags-y)
 
index 940cbddd9237c833839d244ba59d4f69d608f46b..0c98f1508542c9f900ee2bed1394413b8d5d8d88 100644 (file)
@@ -13,6 +13,7 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_NUMA_BALANCING=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
@@ -50,6 +51,7 @@ CONFIG_LIVEPATCH=y
 CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=256
+CONFIG_NUMA=y
 CONFIG_PREEMPT=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
index d793fec91797ba8d3b27cea97a14f85118dced51..82083e1fbdc4c6cc9f4ad6a2c0cfbfbcd3af1210 100644 (file)
@@ -13,6 +13,7 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_NUMA_BALANCING=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
@@ -49,6 +50,7 @@ CONFIG_DEFAULT_DEADLINE=y
 CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=256
+CONFIG_NUMA=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
index 38a77e9c8aa685b09f9aee9b433a85faafd8b431..c05c9e0821e3bcd956b929c591e41b5445ac9565 100644 (file)
@@ -13,6 +13,8 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_NUMA_BALANCING=y
+# CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
@@ -48,6 +50,7 @@ CONFIG_LIVEPATCH=y
 CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=512
+CONFIG_NUMA=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
index 5566ce80abdbf7c97bec630d480b583b324bf82d..0b9b95f3c7037e6fcad08a5dd6453852c60d4180 100644 (file)
@@ -24,6 +24,7 @@
 #include <crypto/algapi.h>
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/cpufeature.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include "crypt_s390.h"
@@ -976,7 +977,7 @@ static void __exit aes_s390_fini(void)
        crypto_unregister_alg(&aes_alg);
 }
 
-module_init(aes_s390_init);
+module_cpu_feature_match(MSA, aes_s390_init);
 module_exit(aes_s390_fini);
 
 MODULE_ALIAS_CRYPTO("aes-all");
index 9e05cc453a40d5fd946ecf56f1063f2446812695..fba1c10a2dd0330151a368a72a0e251718b7648c 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/cpufeature.h>
 #include <linux/crypto.h>
 #include <crypto/algapi.h>
 #include <crypto/des.h>
@@ -616,7 +617,7 @@ static void __exit des_s390_exit(void)
        crypto_unregister_alg(&des_alg);
 }
 
-module_init(des_s390_init);
+module_cpu_feature_match(MSA, des_s390_init);
 module_exit(des_s390_exit);
 
 MODULE_ALIAS_CRYPTO("des");
index b258110da952d320443d113cdcff38beb14ae432..26e14efd30a794fb7cecd6611c3c4906093982fb 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <crypto/internal/hash.h>
 #include <linux/module.h>
+#include <linux/cpufeature.h>
 
 #include "crypt_s390.h"
 
@@ -158,7 +159,7 @@ static void __exit ghash_mod_exit(void)
        crypto_unregister_shash(&ghash_alg);
 }
 
-module_init(ghash_mod_init);
+module_cpu_feature_match(MSA, ghash_mod_init);
 module_exit(ghash_mod_exit);
 
 MODULE_ALIAS_CRYPTO("ghash");
index 9d5192c9496317d490a338e19a69718ef00741dd..b8045b97f4fbd888c35783b13a2b5b9dc89f353f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
+#include <linux/cpufeature.h>
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <asm/debug.h>
@@ -914,6 +915,5 @@ static void __exit prng_exit(void)
        }
 }
 
-
-module_init(prng_init);
+module_cpu_feature_match(MSA, prng_init);
 module_exit(prng_exit);
index 5b2bee323694b2144c382dd9af85126b81b311a8..9208eadae9f09fe33792e4c735e20d14d0aa2ac8 100644 (file)
@@ -26,6 +26,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/cpufeature.h>
 #include <crypto/sha.h>
 
 #include "crypt_s390.h"
@@ -100,7 +101,7 @@ static void __exit sha1_s390_fini(void)
        crypto_unregister_shash(&alg);
 }
 
-module_init(sha1_s390_init);
+module_cpu_feature_match(MSA, sha1_s390_init);
 module_exit(sha1_s390_fini);
 
 MODULE_ALIAS_CRYPTO("sha1");
index b74ff158108c9421a25b26a02f3a1f1669d1f69d..667888f5c964a118f804efa5575f0f6dc7a5a575 100644 (file)
@@ -16,6 +16,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/cpufeature.h>
 #include <crypto/sha.h>
 
 #include "crypt_s390.h"
@@ -140,7 +141,7 @@ static void __exit sha256_s390_fini(void)
        crypto_unregister_shash(&sha256_alg);
 }
 
-module_init(sha256_s390_init);
+module_cpu_feature_match(MSA, sha256_s390_init);
 module_exit(sha256_s390_fini);
 
 MODULE_ALIAS_CRYPTO("sha256");
index 0c36989ba182b1e411b56c3018ab610622cfe6ff..2ba66b1518f0ea8b84a7cc4da893bd4c9d54aae9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/cpufeature.h>
 
 #include "sha.h"
 #include "crypt_s390.h"
@@ -148,7 +149,7 @@ static void __exit fini(void)
        crypto_unregister_shash(&sha384_alg);
 }
 
-module_init(init);
+module_cpu_feature_match(MSA, init);
 module_exit(fini);
 
 MODULE_LICENSE("GPL");
diff --git a/arch/s390/include/asm/cpufeature.h b/arch/s390/include/asm/cpufeature.h
new file mode 100644 (file)
index 0000000..fa7e69b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Module interface for CPU features
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ */
+
+#ifndef __ASM_S390_CPUFEATURE_H
+#define __ASM_S390_CPUFEATURE_H
+
+#include <asm/elf.h>
+
+/* Hardware features on Linux on z Systems are indicated by facility bits that
+ * are mapped to the so-called machine flags.  Particular machine flags are
+ * then used to define ELF hardware capabilities; most notably hardware flags
+ * that are essential for user space / glibc.
+ *
+ * Restrict the set of exposed CPU features to ELF hardware capabilities for
+ * now.  Additional machine flags can be indicated by values larger than
+ * MAX_ELF_HWCAP_FEATURES.
+ */
+#define MAX_ELF_HWCAP_FEATURES (8 * sizeof(elf_hwcap))
+#define MAX_CPU_FEATURES       MAX_ELF_HWCAP_FEATURES
+
+#define cpu_feature(feat)      ilog2(HWCAP_S390_ ## feat)
+
+int cpu_have_feature(unsigned int nr);
+
+#endif /* __ASM_S390_CPUFEATURE_H */
index d7697ab802f6c94813a27394baa255fa26a93ddc..17a3735768681d98290ab51527efe8eed9fcd57e 100644 (file)
@@ -46,6 +46,8 @@ static inline void __ctl_clear_bit(unsigned int cr, unsigned int bit)
        __ctl_load(reg, cr, cr);
 }
 
+void __ctl_set_vx(void);
+
 void smp_ctl_set_bit(int cr, int bit);
 void smp_ctl_clear_bit(int cr, int bit);
 
index 629b79a93165662b16c66ba5632ddd64850dddd8..f7e5c36688c38573d4b4e708b6e65ac1417f28dc 100644 (file)
@@ -214,6 +214,9 @@ static inline int etr_ptff(void *ptff_block, unsigned int func)
 void etr_switch_to_local(void);
 void etr_sync_check(void);
 
+/* notifier for syncs */
+extern struct atomic_notifier_head s390_epoch_delta_notifier;
+
 /* STP interruption parameter */
 struct stp_irq_parm {
        unsigned int _pad0      : 14;
diff --git a/arch/s390/include/asm/fpu-internal.h b/arch/s390/include/asm/fpu-internal.h
new file mode 100644 (file)
index 0000000..55dc2c0
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * General floating pointer and vector register helpers
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ */
+
+#ifndef _ASM_S390_FPU_INTERNAL_H
+#define _ASM_S390_FPU_INTERNAL_H
+
+#define FPU_USE_VX             1       /* Vector extension is active */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <asm/linkage.h>
+#include <asm/ctl_reg.h>
+#include <asm/sigcontext.h>
+
+struct fpu {
+       __u32 fpc;                      /* Floating-point control */
+       __u32 flags;
+       union {
+               void *regs;
+               freg_t *fprs;           /* Floating-point register save area */
+               __vector128 *vxrs;      /* Vector register save area */
+       };
+};
+
+void save_fpu_regs(void);
+
+#define is_vx_fpu(fpu) (!!((fpu)->flags & FPU_USE_VX))
+#define is_vx_task(tsk) (!!((tsk)->thread.fpu.flags & FPU_USE_VX))
+
+/* VX array structure for address operand constraints in inline assemblies */
+struct vx_array { __vector128 _[__NUM_VXRS]; };
+
+static inline int test_fp_ctl(u32 fpc)
+{
+       u32 orig_fpc;
+       int rc;
+
+       asm volatile(
+               "       efpc    %1\n"
+               "       sfpc    %2\n"
+               "0:     sfpc    %1\n"
+               "       la      %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "=d" (rc), "=d" (orig_fpc)
+               : "d" (fpc), "0" (-EINVAL));
+       return rc;
+}
+
+static inline void save_vx_regs_safe(__vector128 *vxrs)
+{
+       unsigned long cr0, flags;
+
+       flags = arch_local_irq_save();
+       __ctl_store(cr0, 0, 0);
+       __ctl_set_bit(0, 17);
+       __ctl_set_bit(0, 18);
+       asm volatile(
+               "       la      1,%0\n"
+               "       .word   0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */
+               "       .word   0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */
+               : "=Q" (*(struct vx_array *) vxrs) : : "1");
+       __ctl_load(cr0, 0, 0);
+       arch_local_irq_restore(flags);
+}
+
+static inline void convert_vx_to_fp(freg_t *fprs, __vector128 *vxrs)
+{
+       int i;
+
+       for (i = 0; i < __NUM_FPRS; i++)
+               fprs[i] = *(freg_t *)(vxrs + i);
+}
+
+static inline void convert_fp_to_vx(__vector128 *vxrs, freg_t *fprs)
+{
+       int i;
+
+       for (i = 0; i < __NUM_FPRS; i++)
+               *(freg_t *)(vxrs + i) = fprs[i];
+}
+
+static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
+{
+       fpregs->pad = 0;
+       if (is_vx_fpu(fpu))
+               convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
+       else
+               memcpy((freg_t *)&fpregs->fprs, fpu->fprs,
+                      sizeof(fpregs->fprs));
+}
+
+static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
+{
+       if (is_vx_fpu(fpu))
+               convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
+       else
+               memcpy(fpu->fprs, (freg_t *)&fpregs->fprs,
+                      sizeof(fpregs->fprs));
+}
+
+#endif
+
+#endif /* _ASM_S390_FPU_INTERNAL_H */
index 3024acbe1f9d63c935b8c74780227f07e429037c..3d012e071647970ce14ee2eb566649ada4b000e6 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kvm.h>
 #include <asm/debug.h>
 #include <asm/cpu.h>
+#include <asm/fpu-internal.h>
 #include <asm/isc.h>
 
 #define KVM_MAX_VCPUS 64
@@ -258,6 +259,9 @@ struct kvm_vcpu_stat {
        u32 diagnose_10;
        u32 diagnose_44;
        u32 diagnose_9c;
+       u32 diagnose_258;
+       u32 diagnose_308;
+       u32 diagnose_500;
 };
 
 #define PGM_OPERATION                  0x01
@@ -498,10 +502,9 @@ struct kvm_guestdbg_info_arch {
 
 struct kvm_vcpu_arch {
        struct kvm_s390_sie_block *sie_block;
-       s390_fp_regs      host_fpregs;
        unsigned int      host_acrs[NUM_ACRS];
-       s390_fp_regs      guest_fpregs;
-       struct kvm_s390_vregs   *host_vregs;
+       struct fpu        host_fpregs;
+       struct fpu        guest_fpregs;
        struct kvm_s390_local_interrupt local_int;
        struct hrtimer    ckc_timer;
        struct kvm_s390_pgm_info pgm;
@@ -630,7 +633,6 @@ extern char sie_exit;
 
 static inline void kvm_arch_hardware_disable(void) {}
 static inline void kvm_arch_check_processor_compat(void *rtn) {}
-static inline void kvm_arch_exit(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
index fc8a8284778e178773568e97c59a200da0bd1c21..27da78cf416da602a9fb60eac8c7e30b62e900ea 100644 (file)
@@ -6,4 +6,26 @@
 #define __ALIGN .align 4, 0x07
 #define __ALIGN_STR __stringify(__ALIGN)
 
+#ifndef __ASSEMBLY__
+
+/*
+ * Helper macro for exception table entries
+ */
+#define EX_TABLE(_fault, _target)      \
+       ".section __ex_table,\"a\"\n"   \
+       ".align 4\n"                    \
+       ".long  (" #_fault ") - .\n"    \
+       ".long  (" #_target ") - .\n"   \
+       ".previous\n"
+
+#else /* __ASSEMBLY__ */
+
+#define EX_TABLE(_fault, _target)      \
+       .section __ex_table,"a" ;       \
+       .align  4 ;                     \
+       .long   (_fault) - . ;          \
+       .long   (_target) - . ;         \
+       .previous
+
+#endif /* __ASSEMBLY__ */
 #endif
diff --git a/arch/s390/include/asm/mmzone.h b/arch/s390/include/asm/mmzone.h
new file mode 100644 (file)
index 0000000..a9e834e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * NUMA support for s390
+ *
+ * Copyright IBM Corp. 2015
+ */
+
+#ifndef _ASM_S390_MMZONE_H
+#define _ASM_S390_MMZONE_H
+
+#ifdef CONFIG_NUMA
+
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid) (node_data[nid])
+
+#endif /* CONFIG_NUMA */
+#endif /* _ASM_S390_MMZONE_H */
diff --git a/arch/s390/include/asm/numa.h b/arch/s390/include/asm/numa.h
new file mode 100644 (file)
index 0000000..2a0efc6
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * NUMA support for s390
+ *
+ * Declare the NUMA core code structures and functions.
+ *
+ * Copyright IBM Corp. 2015
+ */
+
+#ifndef _ASM_S390_NUMA_H
+#define _ASM_S390_NUMA_H
+
+#ifdef CONFIG_NUMA
+
+#include <linux/numa.h>
+#include <linux/cpumask.h>
+
+void numa_setup(void);
+int numa_pfn_to_nid(unsigned long pfn);
+int __node_distance(int a, int b);
+void numa_update_cpu_topology(void);
+
+extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
+extern int numa_debug_enabled;
+
+#else
+
+static inline void numa_setup(void) { }
+static inline void numa_update_cpu_topology(void) { }
+static inline int numa_pfn_to_nid(unsigned long pfn)
+{
+       return 0;
+}
+
+#endif /* CONFIG_NUMA */
+#endif /* _ASM_S390_NUMA_H */
index a648338c434a46ff8fb2843af14a65eefe3943a3..34d960353a084baa14577f88981b51b6a9e4c866 100644 (file)
@@ -170,7 +170,11 @@ static inline void zpci_exit_slot(struct zpci_dev *zdev) {}
 #endif /* CONFIG_HOTPLUG_PCI_S390 */
 
 /* Helpers */
-struct zpci_dev *get_zdev(struct pci_dev *);
+static inline struct zpci_dev *to_zpci(struct pci_dev *pdev)
+{
+       return pdev->sysdata;
+}
+
 struct zpci_dev *get_zdev_by_fid(u32);
 
 /* DMA */
@@ -188,4 +192,20 @@ void zpci_debug_init_device(struct zpci_dev *);
 void zpci_debug_exit_device(struct zpci_dev *);
 void zpci_debug_info(struct zpci_dev *, struct seq_file *);
 
+#ifdef CONFIG_NUMA
+
+/* Returns the node based on PCI bus */
+static inline int __pcibus_to_node(const struct pci_bus *bus)
+{
+       return NUMA_NO_NODE;
+}
+
+static inline const struct cpumask *
+cpumask_of_pcibus(const struct pci_bus *bus)
+{
+       return cpu_online_mask;
+}
+
+#endif /* CONFIG_NUMA */
+
 #endif
index f66d82798a6a7725f7e3eeeb547d8bb2d433719e..bdb2f51124edeff48399eb007a1bdd90a5c44340 100644 (file)
@@ -576,6 +576,19 @@ static inline int pte_same(pte_t a, pte_t b)
        return pte_val(a) == pte_val(b);
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+static inline int pte_protnone(pte_t pte)
+{
+       return pte_present(pte) && !(pte_val(pte) & _PAGE_READ);
+}
+
+static inline int pmd_protnone(pmd_t pmd)
+{
+       /* pmd_large(pmd) implies pmd_present(pmd) */
+       return pmd_large(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_READ);
+}
+#endif
+
 static inline pgste_t pgste_get_lock(pte_t *ptep)
 {
        unsigned long new = 0;
index dedb6218544b3520d6d592e1a8bdd6938fb35af4..085fb0d3c54e944e2f846a2188136f7f729bef72 100644 (file)
 #define CIF_MCCK_PENDING       0       /* machine check handling is pending */
 #define CIF_ASCE               1       /* user asce needs fixup / uaccess */
 #define CIF_NOHZ_DELAY         2       /* delay HZ disable for a tick */
+#define CIF_FPU                        3       /* restore vector registers */
 
 #define _CIF_MCCK_PENDING      (1<<CIF_MCCK_PENDING)
 #define _CIF_ASCE              (1<<CIF_ASCE)
 #define _CIF_NOHZ_DELAY                (1<<CIF_NOHZ_DELAY)
+#define _CIF_FPU               (1<<CIF_FPU)
 
 #ifndef __ASSEMBLY__
 
@@ -28,6 +30,7 @@
 #include <asm/ptrace.h>
 #include <asm/setup.h>
 #include <asm/runtime_instr.h>
+#include <asm/fpu-internal.h>
 
 static inline void set_cpu_flag(int flag)
 {
@@ -85,7 +88,7 @@ typedef struct {
  * Thread structure
  */
 struct thread_struct {
-       s390_fp_regs fp_regs;
+       struct fpu fpu;                 /* FP and VX register save area */
        unsigned int  acrs[NUM_ACRS];
         unsigned long ksp;              /* kernel stack pointer             */
        mm_segment_t mm_segment;
@@ -101,7 +104,6 @@ struct thread_struct {
        struct runtime_instr_cb *ri_cb;
        int ri_signum;
        unsigned char trap_tdb[256];    /* Transaction abort diagnose block */
-       __vector128 *vxrs;              /* Vector register save area */
 };
 
 /* Flag to disable transactions. */
@@ -230,6 +232,17 @@ static inline void __load_psw_mask (unsigned long mask)
                : "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
 }
 
+/*
+ * Extract current PSW mask
+ */
+static inline unsigned long __extract_psw(void)
+{
+       unsigned int reg1, reg2;
+
+       asm volatile("epsw %0,%1" : "=d" (reg1), "=a" (reg2));
+       return (((unsigned long) reg1) << 32) | ((unsigned long) reg2);
+}
+
 /*
  * Rewind PSW instruction address by specified number of bytes.
  */
@@ -336,25 +349,6 @@ extern void memcpy_absolute(void *, void *, size_t);
        memcpy_absolute(&(dest), &__tmp, sizeof(__tmp));        \
 }
 
-/*
- * Helper macro for exception table entries
- */
-#define EX_TABLE(_fault, _target)      \
-       ".section __ex_table,\"a\"\n"   \
-       ".align 4\n"                    \
-       ".long  (" #_fault ") - .\n"    \
-       ".long  (" #_target ") - .\n"   \
-       ".previous\n"
-
-#else /* __ASSEMBLY__ */
-
-#define EX_TABLE(_fault, _target)      \
-       .section __ex_table,"a" ;       \
-       .align  4 ;                     \
-       .long   (_fault) - . ;          \
-       .long   (_target) - . ;         \
-       .previous
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_S390_PROCESSOR_H */
index f6ff06077631c8ebf4ede37bced142df25dbc7de..821dde5f425d0b3e97fbe32f5496fe968e4899fd 100644 (file)
@@ -79,6 +79,6 @@ int sclp_pci_configure(u32 fid);
 int sclp_pci_deconfigure(u32 fid);
 int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
 void sclp_early_detect(void);
-long _sclp_print_early(const char *);
+int _sclp_print_early(const char *);
 
 #endif /* _ASM_S390_SCLP_H */
index d62e7a69605f8ea5a36d251763538e9c894b50b3..dcadfde32265ad705a3899ef1584f858ae3af704 100644 (file)
 #define __ASM_SWITCH_TO_H
 
 #include <linux/thread_info.h>
+#include <asm/fpu-internal.h>
 #include <asm/ptrace.h>
 
 extern struct task_struct *__switch_to(void *, void *);
 extern void update_cr_regs(struct task_struct *task);
 
-static inline int test_fp_ctl(u32 fpc)
-{
-       u32 orig_fpc;
-       int rc;
-
-       asm volatile(
-               "       efpc    %1\n"
-               "       sfpc    %2\n"
-               "0:     sfpc    %1\n"
-               "       la      %0,0\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "=d" (rc), "=d" (orig_fpc)
-               : "d" (fpc), "0" (-EINVAL));
-       return rc;
-}
-
-static inline void save_fp_ctl(u32 *fpc)
-{
-       asm volatile(
-               "       stfpc   %0\n"
-               : "+Q" (*fpc));
-}
-
-static inline int restore_fp_ctl(u32 *fpc)
-{
-       int rc;
-
-       asm volatile(
-               "       lfpc    %1\n"
-               "0:     la      %0,0\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "=d" (rc) : "Q" (*fpc), "0" (-EINVAL));
-       return rc;
-}
-
-static inline void save_fp_regs(freg_t *fprs)
-{
-       asm volatile("std 0,%0" : "=Q" (fprs[0]));
-       asm volatile("std 2,%0" : "=Q" (fprs[2]));
-       asm volatile("std 4,%0" : "=Q" (fprs[4]));
-       asm volatile("std 6,%0" : "=Q" (fprs[6]));
-       asm volatile("std 1,%0" : "=Q" (fprs[1]));
-       asm volatile("std 3,%0" : "=Q" (fprs[3]));
-       asm volatile("std 5,%0" : "=Q" (fprs[5]));
-       asm volatile("std 7,%0" : "=Q" (fprs[7]));
-       asm volatile("std 8,%0" : "=Q" (fprs[8]));
-       asm volatile("std 9,%0" : "=Q" (fprs[9]));
-       asm volatile("std 10,%0" : "=Q" (fprs[10]));
-       asm volatile("std 11,%0" : "=Q" (fprs[11]));
-       asm volatile("std 12,%0" : "=Q" (fprs[12]));
-       asm volatile("std 13,%0" : "=Q" (fprs[13]));
-       asm volatile("std 14,%0" : "=Q" (fprs[14]));
-       asm volatile("std 15,%0" : "=Q" (fprs[15]));
-}
-
-static inline void restore_fp_regs(freg_t *fprs)
-{
-       asm volatile("ld 0,%0" : : "Q" (fprs[0]));
-       asm volatile("ld 2,%0" : : "Q" (fprs[2]));
-       asm volatile("ld 4,%0" : : "Q" (fprs[4]));
-       asm volatile("ld 6,%0" : : "Q" (fprs[6]));
-       asm volatile("ld 1,%0" : : "Q" (fprs[1]));
-       asm volatile("ld 3,%0" : : "Q" (fprs[3]));
-       asm volatile("ld 5,%0" : : "Q" (fprs[5]));
-       asm volatile("ld 7,%0" : : "Q" (fprs[7]));
-       asm volatile("ld 8,%0" : : "Q" (fprs[8]));
-       asm volatile("ld 9,%0" : : "Q" (fprs[9]));
-       asm volatile("ld 10,%0" : : "Q" (fprs[10]));
-       asm volatile("ld 11,%0" : : "Q" (fprs[11]));
-       asm volatile("ld 12,%0" : : "Q" (fprs[12]));
-       asm volatile("ld 13,%0" : : "Q" (fprs[13]));
-       asm volatile("ld 14,%0" : : "Q" (fprs[14]));
-       asm volatile("ld 15,%0" : : "Q" (fprs[15]));
-}
-
-static inline void save_vx_regs(__vector128 *vxrs)
-{
-       typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
-
-       asm volatile(
-               "       la      1,%0\n"
-               "       .word   0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */
-               "       .word   0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */
-               : "=Q" (*(addrtype *) vxrs) : : "1");
-}
-
-static inline void save_vx_regs_safe(__vector128 *vxrs)
-{
-       unsigned long cr0, flags;
-
-       flags = arch_local_irq_save();
-       __ctl_store(cr0, 0, 0);
-       __ctl_set_bit(0, 17);
-       __ctl_set_bit(0, 18);
-       save_vx_regs(vxrs);
-       __ctl_load(cr0, 0, 0);
-       arch_local_irq_restore(flags);
-}
-
-static inline void restore_vx_regs(__vector128 *vxrs)
-{
-       typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
-
-       asm volatile(
-               "       la      1,%0\n"
-               "       .word   0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */
-               "       .word   0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */
-               : : "Q" (*(addrtype *) vxrs) : "1");
-}
-
-static inline void save_fp_vx_regs(struct task_struct *task)
-{
-       if (task->thread.vxrs)
-               save_vx_regs(task->thread.vxrs);
-       else
-               save_fp_regs(task->thread.fp_regs.fprs);
-}
-
-static inline void restore_fp_vx_regs(struct task_struct *task)
-{
-       if (task->thread.vxrs)
-               restore_vx_regs(task->thread.vxrs);
-       else
-               restore_fp_regs(task->thread.fp_regs.fprs);
-}
-
 static inline void save_access_regs(unsigned int *acrs)
 {
        typedef struct { int _[NUM_ACRS]; } acrstype;
@@ -157,15 +30,13 @@ static inline void restore_access_regs(unsigned int *acrs)
 
 #define switch_to(prev,next,last) do {                                 \
        if (prev->mm) {                                                 \
-               save_fp_ctl(&prev->thread.fp_regs.fpc);                 \
-               save_fp_vx_regs(prev);                                  \
+               save_fpu_regs();                                        \
                save_access_regs(&prev->thread.acrs[0]);                \
                save_ri_cb(prev->thread.ri_cb);                         \
        }                                                               \
        if (next->mm) {                                                 \
                update_cr_regs(next);                                   \
-               restore_fp_ctl(&next->thread.fp_regs.fpc);              \
-               restore_fp_vx_regs(next);                               \
+               set_cpu_flag(CIF_FPU);                                  \
                restore_access_regs(&next->thread.acrs[0]);             \
                restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb);  \
        }                                                               \
index 4990f6c66288582b21ad01295b032cb13da9ee31..27ebde643933a908c1ebb2a75ff723d8d43a65f6 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_S390_TOPOLOGY_H
 
 #include <linux/cpumask.h>
+#include <asm/numa.h>
 
 struct sysinfo_15_1_x;
 struct cpu;
@@ -13,6 +14,7 @@ struct cpu_topology_s390 {
        unsigned short core_id;
        unsigned short socket_id;
        unsigned short book_id;
+       unsigned short node_id;
        cpumask_t thread_mask;
        cpumask_t core_mask;
        cpumask_t book_mask;
@@ -52,6 +54,43 @@ static inline void topology_expect_change(void) { }
 #define POLARIZATION_VM                (2)
 #define POLARIZATION_VH                (3)
 
+#define SD_BOOK_INIT   SD_CPU_INIT
+
+#ifdef CONFIG_NUMA
+
+#define cpu_to_node cpu_to_node
+static inline int cpu_to_node(int cpu)
+{
+       return per_cpu(cpu_topology, cpu).node_id;
+}
+
+/* Returns a pointer to the cpumask of CPUs on node 'node'. */
+#define cpumask_of_node cpumask_of_node
+static inline const struct cpumask *cpumask_of_node(int node)
+{
+       return node_to_cpumask_map[node];
+}
+
+/*
+ * Returns the number of the node containing node 'node'. This
+ * architecture is flat, so it is a pretty simple function!
+ */
+#define parent_node(node) (node)
+
+#define pcibus_to_node(bus) __pcibus_to_node(bus)
+
+#define node_distance(a, b) __node_distance(a, b)
+
+#else /* !CONFIG_NUMA */
+
+#define numa_node_id numa_node_id
+static inline int numa_node_id(void)
+{
+       return 0;
+}
+
+#endif /* CONFIG_NUMA */
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_S390_TOPOLOGY_H */
index 91f56b1d8156dc9a0d7044bcef421df14a983d7f..525cef73b0859379b8789a5d7fec105edc4ce451 100644 (file)
 
 #define __IGNORE_time
 
-/* Ignore NUMA system calls. Not wired up on s390. */
-#define __IGNORE_mbind
-#define __IGNORE_get_mempolicy
-#define __IGNORE_set_mempolicy
-#define __IGNORE_migrate_pages
-#define __IGNORE_move_pages
-
-/* Ignore system calls that are also reachable via sys_socket */
+/* Ignore system calls that are also reachable via sys_socketcall */
 #define __IGNORE_recvmmsg
 #define __IGNORE_sendmmsg
+#define __IGNORE_socket
+#define __IGNORE_socketpair
+#define __IGNORE_bind
+#define __IGNORE_connect
+#define __IGNORE_listen
+#define __IGNORE_accept4
+#define __IGNORE_getsockopt
+#define __IGNORE_setsockopt
+#define __IGNORE_getsockname
+#define __IGNORE_getpeername
+#define __IGNORE_sendto
+#define __IGNORE_sendmsg
+#define __IGNORE_recvfrom
+#define __IGNORE_recvmsg
+#define __IGNORE_shutdown
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
diff --git a/arch/s390/include/asm/vx-insn.h b/arch/s390/include/asm/vx-insn.h
new file mode 100644 (file)
index 0000000..4a31356
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * Support for Vector Instructions
+ *
+ * Assembler macros to generate .byte/.word code for particular
+ * vector instructions that are supported by recent binutils (>= 2.26) only.
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ */
+
+#ifndef __ASM_S390_VX_INSN_H
+#define __ASM_S390_VX_INSN_H
+
+#ifdef __ASSEMBLY__
+
+
+/* Macros to generate vector instruction byte code */
+
+#define REG_NUM_INVALID               255
+
+/* GR_NUM - Retrieve general-purpose register number
+ *
+ * @opd:       Operand to store register number
+ * @r64:       String designation register in the format "%rN"
+ */
+.macro GR_NUM  opd gr
+       \opd = REG_NUM_INVALID
+       .ifc \gr,%r0
+               \opd = 0
+       .endif
+       .ifc \gr,%r1
+               \opd = 1
+       .endif
+       .ifc \gr,%r2
+               \opd = 2
+       .endif
+       .ifc \gr,%r3
+               \opd = 3
+       .endif
+       .ifc \gr,%r4
+               \opd = 4
+       .endif
+       .ifc \gr,%r5
+               \opd = 5
+       .endif
+       .ifc \gr,%r6
+               \opd = 6
+       .endif
+       .ifc \gr,%r7
+               \opd = 7
+       .endif
+       .ifc \gr,%r8
+               \opd = 8
+       .endif
+       .ifc \gr,%r9
+               \opd = 9
+       .endif
+       .ifc \gr,%r10
+               \opd = 10
+       .endif
+       .ifc \gr,%r11
+               \opd = 11
+       .endif
+       .ifc \gr,%r12
+               \opd = 12
+       .endif
+       .ifc \gr,%r13
+               \opd = 13
+       .endif
+       .ifc \gr,%r14
+               \opd = 14
+       .endif
+       .ifc \gr,%r15
+               \opd = 15
+       .endif
+       .if \opd == REG_NUM_INVALID
+               .error "Invalid general-purpose register designation: \gr"
+       .endif
+.endm
+
+/* VX_R() - Macro to encode the VX_NUM into the instruction */
+#define VX_R(v)                (v & 0x0F)
+
+/* VX_NUM - Retrieve vector register number
+ *
+ * @opd:       Operand to store register number
+ * @vxr:       String designation register in the format "%vN"
+ *
+ * The vector register number is used for as input number to the
+ * instruction and, as well as, to compute the RXB field of the
+ * instruction.  To encode the particular vector register number,
+ * use the VX_R(v) macro to extract the instruction opcode.
+ */
+.macro VX_NUM  opd vxr
+       \opd = REG_NUM_INVALID
+       .ifc \vxr,%v0
+               \opd = 0
+       .endif
+       .ifc \vxr,%v1
+               \opd = 1
+       .endif
+       .ifc \vxr,%v2
+               \opd = 2
+       .endif
+       .ifc \vxr,%v3
+               \opd = 3
+       .endif
+       .ifc \vxr,%v4
+               \opd = 4
+       .endif
+       .ifc \vxr,%v5
+               \opd = 5
+       .endif
+       .ifc \vxr,%v6
+               \opd = 6
+       .endif
+       .ifc \vxr,%v7
+               \opd = 7
+       .endif
+       .ifc \vxr,%v8
+               \opd = 8
+       .endif
+       .ifc \vxr,%v9
+               \opd = 9
+       .endif
+       .ifc \vxr,%v10
+               \opd = 10
+       .endif
+       .ifc \vxr,%v11
+               \opd = 11
+       .endif
+       .ifc \vxr,%v12
+               \opd = 12
+       .endif
+       .ifc \vxr,%v13
+               \opd = 13
+       .endif
+       .ifc \vxr,%v14
+               \opd = 14
+       .endif
+       .ifc \vxr,%v15
+               \opd = 15
+       .endif
+       .ifc \vxr,%v16
+               \opd = 16
+       .endif
+       .ifc \vxr,%v17
+               \opd = 17
+       .endif
+       .ifc \vxr,%v18
+               \opd = 18
+       .endif
+       .ifc \vxr,%v19
+               \opd = 19
+       .endif
+       .ifc \vxr,%v20
+               \opd = 20
+       .endif
+       .ifc \vxr,%v21
+               \opd = 21
+       .endif
+       .ifc \vxr,%v22
+               \opd = 22
+       .endif
+       .ifc \vxr,%v23
+               \opd = 23
+       .endif
+       .ifc \vxr,%v24
+               \opd = 24
+       .endif
+       .ifc \vxr,%v25
+               \opd = 25
+       .endif
+       .ifc \vxr,%v26
+               \opd = 26
+       .endif
+       .ifc \vxr,%v27
+               \opd = 27
+       .endif
+       .ifc \vxr,%v28
+               \opd = 28
+       .endif
+       .ifc \vxr,%v29
+               \opd = 29
+       .endif
+       .ifc \vxr,%v30
+               \opd = 30
+       .endif
+       .ifc \vxr,%v31
+               \opd = 31
+       .endif
+       .if \opd == REG_NUM_INVALID
+               .error "Invalid vector register designation: \vxr"
+       .endif
+.endm
+
+/* RXB - Compute most significant bit used vector registers
+ *
+ * @rxb:       Operand to store computed RXB value
+ * @v1:                First vector register designated operand
+ * @v2:                Second vector register designated operand
+ * @v3:                Third vector register designated operand
+ * @v4:                Fourth vector register designated operand
+ */
+.macro RXB     rxb v1 v2=0 v3=0 v4=0
+       \rxb = 0
+       .if \v1 & 0x10
+               \rxb = \rxb | 0x08
+       .endif
+       .if \v2 & 0x10
+               \rxb = \rxb | 0x04
+       .endif
+       .if \v3 & 0x10
+               \rxb = \rxb | 0x02
+       .endif
+       .if \v4 & 0x10
+               \rxb = \rxb | 0x01
+       .endif
+.endm
+
+/* MRXB - Generate Element Size Control and RXB value
+ *
+ * @m:         Element size control
+ * @v1:                First vector register designated operand (for RXB)
+ * @v2:                Second vector register designated operand (for RXB)
+ * @v3:                Third vector register designated operand (for RXB)
+ * @v4:                Fourth vector register designated operand (for RXB)
+ */
+.macro MRXB    m v1 v2=0 v3=0 v4=0
+       rxb = 0
+       RXB     rxb, \v1, \v2, \v3, \v4
+       .byte   (\m << 4) | rxb
+.endm
+
+/* MRXBOPC - Generate Element Size Control, RXB, and final Opcode fields
+ *
+ * @m:         Element size control
+ * @opc:       Opcode
+ * @v1:                First vector register designated operand (for RXB)
+ * @v2:                Second vector register designated operand (for RXB)
+ * @v3:                Third vector register designated operand (for RXB)
+ * @v4:                Fourth vector register designated operand (for RXB)
+ */
+.macro MRXBOPC m opc v1 v2=0 v3=0 v4=0
+       MRXB    \m, \v1, \v2, \v3, \v4
+       .byte   \opc
+.endm
+
+/* Vector support instructions */
+
+/* VECTOR GENERATE BYTE MASK */
+.macro VGBM    vr imm2
+       VX_NUM  v1, \vr
+       .word   (0xE700 | (VX_R(v1) << 4))
+       .word   \imm2
+       MRXBOPC 0, 0x44, v1
+.endm
+.macro VZERO   vxr
+       VGBM    \vxr, 0
+.endm
+.macro VONE    vxr
+       VGBM    \vxr, 0xFFFF
+.endm
+
+/* VECTOR LOAD VR ELEMENT FROM GR */
+.macro VLVG    v, gr, disp, m
+       VX_NUM  v1, \v
+       GR_NUM  b2, "%r0"
+       GR_NUM  r3, \gr
+       .word   0xE700 | (VX_R(v1) << 4) | r3
+       .word   (b2 << 12) | (\disp)
+       MRXBOPC \m, 0x22, v1
+.endm
+.macro VLVGB   v, gr, index, base
+       VLVG    \v, \gr, \index, \base, 0
+.endm
+.macro VLVGH   v, gr, index
+       VLVG    \v, \gr, \index, 1
+.endm
+.macro VLVGF   v, gr, index
+       VLVG    \v, \gr, \index, 2
+.endm
+.macro VLVGG   v, gr, index
+       VLVG    \v, \gr, \index, 3
+.endm
+
+/* VECTOR LOAD */
+.macro VL      v, disp, index="%r0", base
+       VX_NUM  v1, \v
+       GR_NUM  x2, \index
+       GR_NUM  b2, \base
+       .word   0xE700 | (VX_R(v1) << 4) | x2
+       .word   (b2 << 12) | (\disp)
+       MRXBOPC 0, 0x06, v1
+.endm
+
+/* VECTOR LOAD ELEMENT */
+.macro VLEx    vr1, disp, index="%r0", base, m3, opc
+       VX_NUM  v1, \vr1
+       GR_NUM  x2, \index
+       GR_NUM  b2, \base
+       .word   0xE700 | (VX_R(v1) << 4) | x2
+       .word   (b2 << 12) | (\disp)
+       MRXBOPC \m3, \opc, v1
+.endm
+.macro VLEB    vr1, disp, index="%r0", base, m3
+       VLEx    \vr1, \disp, \index, \base, \m3, 0x00
+.endm
+.macro VLEH    vr1, disp, index="%r0", base, m3
+       VLEx    \vr1, \disp, \index, \base, \m3, 0x01
+.endm
+.macro VLEF    vr1, disp, index="%r0", base, m3
+       VLEx    \vr1, \disp, \index, \base, \m3, 0x03
+.endm
+.macro VLEG    vr1, disp, index="%r0", base, m3
+       VLEx    \vr1, \disp, \index, \base, \m3, 0x02
+.endm
+
+/* VECTOR LOAD ELEMENT IMMEDIATE */
+.macro VLEIx   vr1, imm2, m3, opc
+       VX_NUM  v1, \vr1
+       .word   0xE700 | (VX_R(v1) << 4)
+       .word   \imm2
+       MRXBOPC \m3, \opc, v1
+.endm
+.macro VLEIB   vr1, imm2, index
+       VLEIx   \vr1, \imm2, \index, 0x40
+.endm
+.macro VLEIH   vr1, imm2, index
+       VLEIx   \vr1, \imm2, \index, 0x41
+.endm
+.macro VLEIF   vr1, imm2, index
+       VLEIx   \vr1, \imm2, \index, 0x43
+.endm
+.macro VLEIG   vr1, imm2, index
+       VLEIx   \vr1, \imm2, \index, 0x42
+.endm
+
+/* VECTOR LOAD GR FROM VR ELEMENT */
+.macro VLGV    gr, vr, disp, base="%r0", m
+       GR_NUM  r1, \gr
+       GR_NUM  b2, \base
+       VX_NUM  v3, \vr
+       .word   0xE700 | (r1 << 4) | VX_R(v3)
+       .word   (b2 << 12) | (\disp)
+       MRXBOPC \m, 0x21, v3
+.endm
+.macro VLGVB   gr, vr, disp, base="%r0"
+       VLGV    \gr, \vr, \disp, \base, 0
+.endm
+.macro VLGVH   gr, vr, disp, base="%r0"
+       VLGV    \gr, \vr, \disp, \base, 1
+.endm
+.macro VLGVF   gr, vr, disp, base="%r0"
+       VLGV    \gr, \vr, \disp, \base, 2
+.endm
+.macro VLGVG   gr, vr, disp, base="%r0"
+       VLGV    \gr, \vr, \disp, \base, 3
+.endm
+
+/* VECTOR LOAD MULTIPLE */
+.macro VLM     vfrom, vto, disp, base
+       VX_NUM  v1, \vfrom
+       VX_NUM  v3, \vto
+       GR_NUM  b2, \base           /* Base register */
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v3)
+       .word   (b2 << 12) | (\disp)
+       MRXBOPC 0, 0x36, v1, v3
+.endm
+
+/* VECTOR STORE MULTIPLE */
+.macro VSTM    vfrom, vto, disp, base
+       VX_NUM  v1, \vfrom
+       VX_NUM  v3, \vto
+       GR_NUM  b2, \base           /* Base register */
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v3)
+       .word   (b2 << 12) | (\disp)
+       MRXBOPC 0, 0x3E, v1, v3
+.endm
+
+/* VECTOR PERMUTE */
+.macro VPERM   vr1, vr2, vr3, vr4
+       VX_NUM  v1, \vr1
+       VX_NUM  v2, \vr2
+       VX_NUM  v3, \vr3
+       VX_NUM  v4, \vr4
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v2)
+       .word   (VX_R(v3) << 12)
+       MRXBOPC VX_R(v4), 0x8C, v1, v2, v3, v4
+.endm
+
+/* VECTOR UNPACK LOGICAL LOW */
+.macro VUPLL   vr1, vr2, m3
+       VX_NUM  v1, \vr1
+       VX_NUM  v2, \vr2
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v2)
+       .word   0x0000
+       MRXBOPC \m3, 0xD4, v1, v2
+.endm
+.macro VUPLLB  vr1, vr2
+       VUPLL   \vr1, \vr2, 0
+.endm
+.macro VUPLLH  vr1, vr2
+       VUPLL   \vr1, \vr2, 1
+.endm
+.macro VUPLLF  vr1, vr2
+       VUPLL   \vr1, \vr2, 2
+.endm
+
+
+/* Vector integer instructions */
+
+/* VECTOR EXCLUSIVE OR */
+.macro VX      vr1, vr2, vr3
+       VX_NUM  v1, \vr1
+       VX_NUM  v2, \vr2
+       VX_NUM  v3, \vr3
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v2)
+       .word   (VX_R(v3) << 12)
+       MRXBOPC 0, 0x6D, v1, v2, v3
+.endm
+
+/* VECTOR GALOIS FIELD MULTIPLY SUM */
+.macro VGFM    vr1, vr2, vr3, m4
+       VX_NUM  v1, \vr1
+       VX_NUM  v2, \vr2
+       VX_NUM  v3, \vr3
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v2)
+       .word   (VX_R(v3) << 12)
+       MRXBOPC \m4, 0xB4, v1, v2, v3
+.endm
+.macro VGFMB   vr1, vr2, vr3
+       VGFM    \vr1, \vr2, \vr3, 0
+.endm
+.macro VGFMH   vr1, vr2, vr3
+       VGFM    \vr1, \vr2, \vr3, 1
+.endm
+.macro VGFMF   vr1, vr2, vr3
+       VGFM    \vr1, \vr2, \vr3, 2
+.endm
+.macro VGFMG   vr1, vr2, vr3
+       VGFM    \vr1, \vr2, \vr3, 3
+.endm
+
+/* VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE */
+.macro VGFMA   vr1, vr2, vr3, vr4, m5
+       VX_NUM  v1, \vr1
+       VX_NUM  v2, \vr2
+       VX_NUM  v3, \vr3
+       VX_NUM  v4, \vr4
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v2)
+       .word   (VX_R(v3) << 12) | (\m5 << 8)
+       MRXBOPC VX_R(v4), 0xBC, v1, v2, v3, v4
+.endm
+.macro VGFMAB  vr1, vr2, vr3, vr4
+       VGFMA   \vr1, \vr2, \vr3, \vr4, 0
+.endm
+.macro VGFMAH  vr1, vr2, vr3, vr4
+       VGFMA   \vr1, \vr2, \vr3, \vr4, 1
+.endm
+.macro VGFMAF  vr1, vr2, vr3, vr4
+       VGFMA   \vr1, \vr2, \vr3, \vr4, 2
+.endm
+.macro VGFMAG  vr1, vr2, vr3, vr4
+       VGFMA   \vr1, \vr2, \vr3, \vr4, 3
+.endm
+
+/* VECTOR SHIFT RIGHT LOGICAL BY BYTE */
+.macro VSRLB   vr1, vr2, vr3
+       VX_NUM  v1, \vr1
+       VX_NUM  v2, \vr2
+       VX_NUM  v3, \vr3
+       .word   0xE700 | (VX_R(v1) << 4) | VX_R(v2)
+       .word   (VX_R(v3) << 12)
+       MRXBOPC 0, 0x7D, v1, v2, v3
+.endm
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_S390_VX_INSN_H */
index 67878af257a083c531140f74b951019e2a1537e0..59d2bb4e2d0cf0802618d40b88afdaba08c8c963 100644 (file)
 #define __NR_statfs64          265
 #define __NR_fstatfs64         266
 #define __NR_remap_file_pages  267
-/* Number 268 is reserved for new sys_mbind */
-/* Number 269 is reserved for new sys_get_mempolicy */
-/* Number 270 is reserved for new sys_set_mempolicy */
+#define __NR_mbind             268
+#define __NR_get_mempolicy     269
+#define __NR_set_mempolicy     270
 #define __NR_mq_open           271
 #define __NR_mq_unlink         272
 #define __NR_mq_timedsend      273
 #define __NR_inotify_init      284
 #define __NR_inotify_add_watch 285
 #define __NR_inotify_rm_watch  286
-/* Number 287 is reserved for new sys_migrate_pages */
+#define __NR_migrate_pages     287
 #define __NR_openat            288
 #define __NR_mkdirat           289
 #define __NR_mknodat           290
 #define __NR_sync_file_range   307
 #define __NR_tee               308
 #define __NR_vmsplice          309
-/* Number 310 is reserved for new sys_move_pages */
+#define __NR_move_pages                310
 #define __NR_getcpu            311
 #define __NR_epoll_pwait       312
 #define __NR_utimes            313
index ffb87617a36c5992598e9f65bb2c84a06fac457e..b756c6348ac68ec20d9b67269823ab50db61f837 100644 (file)
@@ -28,6 +28,17 @@ CFLAGS_ptrace.o              += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 CFLAGS_sysinfo.o += -w
 
+#
+# Use -march=z900 for sclp.c to be able to print an error message if
+# the kernel is started on a machine which is too old
+#
+CFLAGS_REMOVE_sclp.o = $(CC_FLAGS_FTRACE)
+ifneq ($(CC_FLAGS_MARCH),-march=z900)
+CFLAGS_REMOVE_sclp.o += $(CC_FLAGS_MARCH)
+CFLAGS_sclp.o  += -march=z900
+endif
+GCOV_PROFILE_sclp.o := n
+
 obj-y  := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o
 obj-y  += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
 obj-y  += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
index a2da259d932741614c4f6b78642c491b3829b223..48c9af7a76831ea63ef6ef92760df02f15c1188c 100644 (file)
@@ -28,6 +28,9 @@ int main(void)
        DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
        BLANK();
        DEFINE(__THREAD_ksp, offsetof(struct thread_struct, ksp));
+       DEFINE(__THREAD_FPU_fpc, offsetof(struct thread_struct, fpu.fpc));
+       DEFINE(__THREAD_FPU_flags, offsetof(struct thread_struct, fpu.flags));
+       DEFINE(__THREAD_FPU_regs, offsetof(struct thread_struct, fpu.regs));
        DEFINE(__THREAD_per_cause, offsetof(struct thread_struct, per_event.cause));
        DEFINE(__THREAD_per_address, offsetof(struct thread_struct, per_event.address));
        DEFINE(__THREAD_per_paid, offsetof(struct thread_struct, per_event.paid));
index fe8d6924efaa8f00205c8c2755bdc64f17d0e8ba..eb4664238613a0c7db83e7910ae065a9b584e95b 100644 (file)
@@ -153,33 +153,14 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 /* Store registers needed to create the signal frame */
 static void store_sigregs(void)
 {
-       int i;
-
        save_access_regs(current->thread.acrs);
-       save_fp_ctl(&current->thread.fp_regs.fpc);
-       if (current->thread.vxrs) {
-               save_vx_regs(current->thread.vxrs);
-               for (i = 0; i < __NUM_FPRS; i++)
-                       current->thread.fp_regs.fprs[i] =
-                               *(freg_t *)(current->thread.vxrs + i);
-       } else
-               save_fp_regs(current->thread.fp_regs.fprs);
+       save_fpu_regs();
 }
 
 /* Load registers after signal return */
 static void load_sigregs(void)
 {
-       int i;
-
        restore_access_regs(current->thread.acrs);
-       /* restore_fp_ctl is done in restore_sigregs */
-       if (current->thread.vxrs) {
-               for (i = 0; i < __NUM_FPRS; i++)
-                       *(freg_t *)(current->thread.vxrs + i) =
-                               current->thread.fp_regs.fprs[i];
-               restore_vx_regs(current->thread.vxrs);
-       } else
-               restore_fp_regs(current->thread.fp_regs.fprs);
 }
 
 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
@@ -196,8 +177,7 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
                user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
        memcpy(&user_sregs.regs.acrs, current->thread.acrs,
               sizeof(user_sregs.regs.acrs));
-       memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
-              sizeof(user_sregs.fpregs));
+       fpregs_store((_s390_fp_regs *) &user_sregs.fpregs, &current->thread.fpu);
        if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
                return -EFAULT;
        return 0;
@@ -217,8 +197,8 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI))
                return -EINVAL;
 
-       /* Loading the floating-point-control word can fail. Do that first. */
-       if (restore_fp_ctl(&user_sregs.fpregs.fpc))
+       /* Test the floating-point-control word. */
+       if (test_fp_ctl(user_sregs.fpregs.fpc))
                return -EINVAL;
 
        /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
@@ -235,9 +215,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
                regs->gprs[i] = (__u64) user_sregs.regs.gprs[i];
        memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
               sizeof(current->thread.acrs));
-
-       memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
-              sizeof(current->thread.fp_regs));
+       fpregs_load((_s390_fp_regs *) &user_sregs.fpregs, &current->thread.fpu);
 
        clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
        return 0;
@@ -258,13 +236,13 @@ static int save_sigregs_ext32(struct pt_regs *regs,
                return -EFAULT;
 
        /* Save vector registers to signal stack */
-       if (current->thread.vxrs) {
+       if (is_vx_task(current)) {
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
+                       vxrs[i] = *((__u64 *)(current->thread.fpu.vxrs + i) + 1);
                if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
                                   sizeof(sregs_ext->vxrs_low)) ||
                    __copy_to_user(&sregs_ext->vxrs_high,
-                                  current->thread.vxrs + __NUM_VXRS_LOW,
+                                  current->thread.fpu.vxrs + __NUM_VXRS_LOW,
                                   sizeof(sregs_ext->vxrs_high)))
                        return -EFAULT;
        }
@@ -286,15 +264,15 @@ static int restore_sigregs_ext32(struct pt_regs *regs,
                *(__u32 *)&regs->gprs[i] = gprs_high[i];
 
        /* Restore vector registers from signal stack */
-       if (current->thread.vxrs) {
+       if (is_vx_task(current)) {
                if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
                                     sizeof(sregs_ext->vxrs_low)) ||
-                   __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
+                   __copy_from_user(current->thread.fpu.vxrs + __NUM_VXRS_LOW,
                                     &sregs_ext->vxrs_high,
                                     sizeof(sregs_ext->vxrs_high)))
                        return -EFAULT;
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
+                       *((__u64 *)(current->thread.fpu.vxrs + i) + 1) = vxrs[i];
        }
        return 0;
 }
@@ -308,6 +286,7 @@ COMPAT_SYSCALL_DEFINE0(sigreturn)
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
                goto badframe;
        set_current_blocked(&set);
+       save_fpu_regs();
        if (restore_sigregs32(regs, &frame->sregs))
                goto badframe;
        if (restore_sigregs_ext32(regs, &frame->sregs_ext))
@@ -330,6 +309,7 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
        set_current_blocked(&set);
        if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
+       save_fpu_regs();
        if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
                goto badframe;
        if (restore_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
@@ -472,7 +452,7 @@ static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
         */
        uc_flags = UC_GPRS_HIGH;
        if (MACHINE_HAS_VX) {
-               if (current->thread.vxrs)
+               if (is_vx_task(current))
                        uc_flags |= UC_VXRS;
        } else
                frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
index 84062e7a77dad75c50fa60822255ee2b20b34181..247b7aae4c6de0a332bf0b276b7224de00296307 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/page.h>
 #include <asm/sigp.h>
 #include <asm/irq.h>
+#include <asm/fpu-internal.h>
+#include <asm/vx-insn.h>
 
 __PT_R0      = __PT_GPRS
 __PT_R1      = __PT_GPRS + 8
@@ -46,10 +48,10 @@ _TIF_WORK   = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                   _TIF_UPROBE)
 _TIF_TRACE     = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
                   _TIF_SYSCALL_TRACEPOINT)
-_CIF_WORK      = (_CIF_MCCK_PENDING | _CIF_ASCE)
+_CIF_WORK      = (_CIF_MCCK_PENDING | _CIF_ASCE | _CIF_FPU)
 _PIF_WORK      = (_PIF_PER_TRAP)
 
-#define BASED(name) name-system_call(%r13)
+#define BASED(name) name-cleanup_critical(%r13)
 
        .macro  TRACE_IRQS_ON
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -73,38 +75,6 @@ _PIF_WORK    = (_PIF_PER_TRAP)
 #endif
        .endm
 
-       .macro LPP newpp
-#if IS_ENABLED(CONFIG_KVM)
-       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_LPP
-       jz      .+8
-       .insn   s,0xb2800000,\newpp
-#endif
-       .endm
-
-       .macro  HANDLE_SIE_INTERCEPT scratch,reason
-#if IS_ENABLED(CONFIG_KVM)
-       tmhh    %r8,0x0001              # interrupting from user ?
-       jnz     .+62
-       lgr     \scratch,%r9
-       slg     \scratch,BASED(.Lsie_critical)
-       clg     \scratch,BASED(.Lsie_critical_length)
-       .if     \reason==1
-       # 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 .Lrewind_pad
-       jh      .+42
-       .else
-       jhe     .+42
-       .endif
-       lg      %r14,__SF_EMPTY(%r15)           # get control block pointer
-       LPP     __SF_EMPTY+16(%r15)             # set host id
-       ni      __SIE_PROG0C+3(%r14),0xfe       # no longer in SIE
-       lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
-       larl    %r9,sie_exit                    # skip forward to sie_exit
-       mvi     __SF_EMPTY+31(%r15),\reason     # set exit reason
-#endif
-       .endm
-
        .macro  CHECK_STACK stacksize,savearea
 #ifdef CONFIG_CHECK_STACK
        tml     %r15,\stacksize - CONFIG_STACK_GUARD
@@ -113,7 +83,7 @@ _PIF_WORK    = (_PIF_PER_TRAP)
 #endif
        .endm
 
-       .macro  SWITCH_ASYNC savearea,stack,shift
+       .macro  SWITCH_ASYNC savearea,timer
        tmhh    %r8,0x0001              # interrupting from user ?
        jnz     1f
        lgr     %r14,%r9
@@ -124,26 +94,28 @@ _PIF_WORK  = (_PIF_PER_TRAP)
        brasl   %r14,cleanup_critical
        tmhh    %r8,0x0001              # retest problem state after cleanup
        jnz     1f
-0:     lg      %r14,\stack             # are we already on the target stack?
+0:     lg      %r14,__LC_ASYNC_STACK   # are we already on the async stack?
        slgr    %r14,%r15
-       srag    %r14,%r14,\shift
-       jnz     1f
-       CHECK_STACK 1<<\shift,\savearea
+       srag    %r14,%r14,STACK_SHIFT
+       jnz     2f
+       CHECK_STACK 1<<STACK_SHIFT,\savearea
        aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       j       2f
-1:     lg      %r15,\stack             # load target stack
-2:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
+       j       3f
+1:     LAST_BREAK %r14
+       UPDATE_VTIME %r14,%r15,\timer
+2:     lg      %r15,__LC_ASYNC_STACK   # load async stack
+3:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
        .endm
 
-       .macro UPDATE_VTIME scratch,enter_timer
-       lg      \scratch,__LC_EXIT_TIMER
-       slg     \scratch,\enter_timer
-       alg     \scratch,__LC_USER_TIMER
-       stg     \scratch,__LC_USER_TIMER
-       lg      \scratch,__LC_LAST_UPDATE_TIMER
-       slg     \scratch,__LC_EXIT_TIMER
-       alg     \scratch,__LC_SYSTEM_TIMER
-       stg     \scratch,__LC_SYSTEM_TIMER
+       .macro UPDATE_VTIME w1,w2,enter_timer
+       lg      \w1,__LC_EXIT_TIMER
+       lg      \w2,__LC_LAST_UPDATE_TIMER
+       slg     \w1,\enter_timer
+       slg     \w2,__LC_EXIT_TIMER
+       alg     \w1,__LC_USER_TIMER
+       alg     \w2,__LC_SYSTEM_TIMER
+       stg     \w1,__LC_USER_TIMER
+       stg     \w2,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),\enter_timer
        .endm
 
@@ -197,6 +169,69 @@ ENTRY(__switch_to)
        br      %r14
 
 .L__critical_start:
+
+#if IS_ENABLED(CONFIG_KVM)
+/*
+ * sie64a calling convention:
+ * %r2 pointer to sie control block
+ * %r3 guest register save area
+ */
+ENTRY(sie64a)
+       stmg    %r6,%r14,__SF_GPRS(%r15)        # save kernel registers
+       stg     %r2,__SF_EMPTY(%r15)            # save control block pointer
+       stg     %r3,__SF_EMPTY+8(%r15)          # save guest register save area
+       xc      __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU       # load guest fp/vx registers ?
+       jno     .Lsie_load_guest_gprs
+       brasl   %r14,load_fpu_regs              # load guest fp/vx regs
+.Lsie_load_guest_gprs:
+       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
+       lg      %r14,__LC_GMAP                  # get gmap pointer
+       ltgr    %r14,%r14
+       jz      .Lsie_gmap
+       lctlg   %c1,%c1,__GMAP_ASCE(%r14)       # load primary asce
+.Lsie_gmap:
+       lg      %r14,__SF_EMPTY(%r15)           # get control block pointer
+       oi      __SIE_PROG0C+3(%r14),1          # we are going into SIE now
+       tm      __SIE_PROG20+3(%r14),3          # last exit...
+       jnz     .Lsie_skip
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       jo      .Lsie_skip                      # exit if fp/vx regs changed
+       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_LPP
+       jz      .Lsie_enter
+       .insn   s,0xb2800000,__LC_CURRENT_PID   # set guest id to pid
+.Lsie_enter:
+       sie     0(%r14)
+       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_LPP
+       jz      .Lsie_skip
+       .insn   s,0xb2800000,__SF_EMPTY+16(%r15)# set host id
+.Lsie_skip:
+       ni      __SIE_PROG0C+3(%r14),0xfe       # no longer in SIE
+       lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
+.Lsie_done:
+# 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 between sie64a and .Lsie_done should not cause program
+# interrupts. So lets use a nop (47 00 00 00) as a landing pad.
+# See also .Lcleanup_sie
+.Lrewind_pad:
+       nop     0
+       .globl sie_exit
+sie_exit:
+       lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
+       lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
+       lg      %r2,__SF_EMPTY+24(%r15)         # return exit reason code
+       br      %r14
+.Lsie_fault:
+       lghi    %r14,-EFAULT
+       stg     %r14,__SF_EMPTY+24(%r15)        # set exit reason code
+       j       sie_exit
+
+       EX_TABLE(.Lrewind_pad,.Lsie_fault)
+       EX_TABLE(sie_exit,.Lsie_fault)
+#endif
+
 /*
  * SVC interrupt handler routine. System calls are synchronous events and
  * are executed with interrupts enabled.
@@ -212,9 +247,9 @@ ENTRY(system_call)
 .Lsysc_per:
        lg      %r15,__LC_KERNEL_STACK
        la      %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
-.Lsysc_vtime:
-       UPDATE_VTIME %r13,__LC_SYNC_ENTER_TIMER
        LAST_BREAK %r13
+.Lsysc_vtime:
+       UPDATE_VTIME %r10,%r13,__LC_SYNC_ENTER_TIMER
        stmg    %r0,%r7,__PT_R0(%r11)
        mvc     __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
        mvc     __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
@@ -244,8 +279,6 @@ ENTRY(system_call)
 .Lsysc_return:
        LOCKDEP_SYS_EXIT
 .Lsysc_tif:
-       tm      __PT_PSW+1(%r11),0x01           # returning to user ?
-       jno     .Lsysc_restore
        tm      __PT_FLAGS+7(%r11),_PIF_WORK
        jnz     .Lsysc_work
        tm      __TI_flags+7(%r12),_TIF_WORK
@@ -280,6 +313,8 @@ ENTRY(system_call)
        jo      .Lsysc_sigpending
        tm      __TI_flags+7(%r12),_TIF_NOTIFY_RESUME
        jo      .Lsysc_notify_resume
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       jo      .Lsysc_vxrs
        tm      __LC_CPU_FLAGS+7,_CIF_ASCE
        jo      .Lsysc_uaccess
        j       .Lsysc_return           # beware of critical section cleanup
@@ -306,6 +341,13 @@ ENTRY(system_call)
        lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
        j       .Lsysc_return
 
+#
+# CIF_FPU is set, restore floating-point controls and floating-point registers.
+#
+.Lsysc_vxrs:
+       larl    %r14,.Lsysc_return
+       jg      load_fpu_regs
+
 #
 # _TIF_SIGPENDING is set, call do_signal
 #
@@ -405,28 +447,35 @@ ENTRY(pgm_check_handler)
        stmg    %r8,%r15,__LC_SAVE_AREA_SYNC
        lg      %r10,__LC_LAST_BREAK
        lg      %r12,__LC_THREAD_INFO
-       larl    %r13,system_call
+       larl    %r13,cleanup_critical
        lmg     %r8,%r9,__LC_PGM_OLD_PSW
-       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 ?
-       jnz     0f                      # -> enabled, can't be a double fault
+       jnz     2f                      # -> fault in user space
+#if IS_ENABLED(CONFIG_KVM)
+       # cleanup critical section for sie64a
+       lgr     %r14,%r9
+       slg     %r14,BASED(.Lsie_critical_start)
+       clg     %r14,BASED(.Lsie_critical_length)
+       jhe     0f
+       brasl   %r14,.Lcleanup_sie
+#endif
+0:     tmhh    %r8,0x4000              # PER bit set in old PSW ?
+       jnz     1f                      # -> enabled, can't be a double fault
        tm      __LC_PGM_ILC+3,0x80     # check for per exception
        jnz     .Lpgm_svcper            # -> single stepped svc
-0:     CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
+1:     CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
        aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-       j       2f
-1:     UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER
-       LAST_BREAK %r14
+       j       3f
+2:     LAST_BREAK %r14
+       UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
        lg      %r15,__LC_KERNEL_STACK
        lg      %r14,__TI_task(%r12)
        aghi    %r14,__TASK_thread      # pointer to thread_struct
        lghi    %r13,__LC_PGM_TDB
        tm      __LC_PGM_ILC+2,0x02     # check for transaction abort
-       jz      2f
+       jz      3f
        mvc     __THREAD_trap_tdb(256,%r14),0(%r13)
-2:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
+3:     la      %r11,STACK_FRAME_OVERHEAD(%r15)
        stmg    %r0,%r7,__PT_R0(%r11)
        mvc     __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
        stmg    %r8,%r9,__PT_PSW(%r11)
@@ -435,24 +484,28 @@ ENTRY(pgm_check_handler)
        xc      __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
        stg     %r10,__PT_ARGS(%r11)
        tm      __LC_PGM_ILC+3,0x80     # check for per exception
-       jz      0f
+       jz      4f
        tmhh    %r8,0x0001              # kernel per event ?
        jz      .Lpgm_kprobe
        oi      __PT_FLAGS+7(%r11),_PIF_PER_TRAP
        mvc     __THREAD_per_address(8,%r14),__LC_PER_ADDRESS
        mvc     __THREAD_per_cause(2,%r14),__LC_PER_CODE
        mvc     __THREAD_per_paid(1,%r14),__LC_PER_ACCESS_ID
-0:     REENABLE_IRQS
+4:     REENABLE_IRQS
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        larl    %r1,pgm_check_table
        llgh    %r10,__PT_INT_CODE+2(%r11)
        nill    %r10,0x007f
        sll     %r10,2
-       je      .Lsysc_return
+       je      .Lpgm_return
        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       .Lsysc_return
+.Lpgm_return:
+       LOCKDEP_SYS_EXIT
+       tm      __PT_PSW+1(%r11),0x01   # returning to user ?
+       jno     .Lsysc_restore
+       j       .Lsysc_tif
 
 #
 # PER event in supervisor state, must be kprobes
@@ -462,7 +515,7 @@ ENTRY(pgm_check_handler)
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        lgr     %r2,%r11                # pass pointer to pt_regs
        brasl   %r14,do_per_trap
-       j       .Lsysc_return
+       j       .Lpgm_return
 
 #
 # single stepped system call
@@ -483,15 +536,9 @@ ENTRY(io_int_handler)
        stmg    %r8,%r15,__LC_SAVE_AREA_ASYNC
        lg      %r10,__LC_LAST_BREAK
        lg      %r12,__LC_THREAD_INFO
-       larl    %r13,system_call
+       larl    %r13,cleanup_critical
        lmg     %r8,%r9,__LC_IO_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14,2
-       SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
-       tmhh    %r8,0x0001              # interrupting from user?
-       jz      .Lio_skip
-       UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER
-       LAST_BREAK %r14
-.Lio_skip:
+       SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
        stmg    %r0,%r7,__PT_R0(%r11)
        mvc     __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
        stmg    %r8,%r9,__PT_PSW(%r11)
@@ -587,6 +634,8 @@ ENTRY(io_int_handler)
        jo      .Lio_sigpending
        tm      __TI_flags+7(%r12),_TIF_NOTIFY_RESUME
        jo      .Lio_notify_resume
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       jo      .Lio_vxrs
        tm      __LC_CPU_FLAGS+7,_CIF_ASCE
        jo      .Lio_uaccess
        j       .Lio_return             # beware of critical section cleanup
@@ -608,6 +657,13 @@ ENTRY(io_int_handler)
        lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
        j       .Lio_return
 
+#
+# CIF_FPU is set, restore floating-point controls and floating-point registers.
+#
+.Lio_vxrs:
+       larl    %r14,.Lio_return
+       jg      load_fpu_regs
+
 #
 # _TIF_NEED_RESCHED is set, call schedule
 #
@@ -652,15 +708,9 @@ ENTRY(ext_int_handler)
        stmg    %r8,%r15,__LC_SAVE_AREA_ASYNC
        lg      %r10,__LC_LAST_BREAK
        lg      %r12,__LC_THREAD_INFO
-       larl    %r13,system_call
+       larl    %r13,cleanup_critical
        lmg     %r8,%r9,__LC_EXT_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14,3
-       SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
-       tmhh    %r8,0x0001              # interrupting from user ?
-       jz      .Lext_skip
-       UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER
-       LAST_BREAK %r14
-.Lext_skip:
+       SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
        stmg    %r0,%r7,__PT_R0(%r11)
        mvc     __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
        stmg    %r8,%r9,__PT_PSW(%r11)
@@ -690,6 +740,122 @@ ENTRY(psw_idle)
        br      %r14
 .Lpsw_idle_end:
 
+/* Store floating-point controls and floating-point or vector extension
+ * registers instead.  A critical section cleanup assures that the registers
+ * are stored even if interrupted for some other work. The register %r2
+ * designates a struct fpu to store register contents. If the specified
+ * structure does not contain a register save area, the register store is
+ * omitted (see also comments in arch_dup_task_struct()).
+ *
+ * The CIF_FPU flag is set in any case.  The CIF_FPU triggers a lazy restore
+ * of the register contents at system call or io return.
+ */
+ENTRY(save_fpu_regs)
+       lg      %r2,__LC_CURRENT
+       aghi    %r2,__TASK_thread
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       bor     %r14
+       stfpc   __THREAD_FPU_fpc(%r2)
+.Lsave_fpu_regs_fpc_end:
+       lg      %r3,__THREAD_FPU_regs(%r2)
+       ltgr    %r3,%r3
+       jz      .Lsave_fpu_regs_done      # no save area -> set CIF_FPU
+       tm      __THREAD_FPU_flags+3(%r2),FPU_USE_VX
+       jz      .Lsave_fpu_regs_fp        # no -> store FP regs
+.Lsave_fpu_regs_vx_low:
+       VSTM    %v0,%v15,0,%r3            # vstm 0,15,0(3)
+.Lsave_fpu_regs_vx_high:
+       VSTM    %v16,%v31,256,%r3         # vstm 16,31,256(3)
+       j       .Lsave_fpu_regs_done      # -> set CIF_FPU flag
+.Lsave_fpu_regs_fp:
+       std     0,0(%r3)
+       std     1,8(%r3)
+       std     2,16(%r3)
+       std     3,24(%r3)
+       std     4,32(%r3)
+       std     5,40(%r3)
+       std     6,48(%r3)
+       std     7,56(%r3)
+       std     8,64(%r3)
+       std     9,72(%r3)
+       std     10,80(%r3)
+       std     11,88(%r3)
+       std     12,96(%r3)
+       std     13,104(%r3)
+       std     14,112(%r3)
+       std     15,120(%r3)
+.Lsave_fpu_regs_done:
+       oi      __LC_CPU_FLAGS+7,_CIF_FPU
+       br      %r14
+.Lsave_fpu_regs_end:
+
+/* Load floating-point controls and floating-point or vector extension
+ * registers.  A critical section cleanup assures that the register contents
+ * are loaded even if interrupted for some other work. Depending on the saved
+ * FP/VX state, the vector-enablement control, CR0.46, is either set or cleared.
+ *
+ * There are special calling conventions to fit into sysc and io return work:
+ *     %r15:   <kernel stack>
+ * The function requires:
+ *     %r4 and __SF_EMPTY+32(%r15)
+ */
+load_fpu_regs:
+       lg      %r4,__LC_CURRENT
+       aghi    %r4,__TASK_thread
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       bnor    %r14
+       lfpc    __THREAD_FPU_fpc(%r4)
+       stctg   %c0,%c0,__SF_EMPTY+32(%r15)     # store CR0
+       tm      __THREAD_FPU_flags+3(%r4),FPU_USE_VX    # VX-enabled task ?
+       lg      %r4,__THREAD_FPU_regs(%r4)      # %r4 <- reg save area
+       jz      .Lload_fpu_regs_fp_ctl          # -> no VX, load FP regs
+.Lload_fpu_regs_vx_ctl:
+       tm      __SF_EMPTY+32+5(%r15),2         # test VX control
+       jo      .Lload_fpu_regs_vx
+       oi      __SF_EMPTY+32+5(%r15),2         # set VX control
+       lctlg   %c0,%c0,__SF_EMPTY+32(%r15)
+.Lload_fpu_regs_vx:
+       VLM     %v0,%v15,0,%r4
+.Lload_fpu_regs_vx_high:
+       VLM     %v16,%v31,256,%r4
+       j       .Lload_fpu_regs_done
+.Lload_fpu_regs_fp_ctl:
+       tm      __SF_EMPTY+32+5(%r15),2         # test VX control
+       jz      .Lload_fpu_regs_fp
+       ni      __SF_EMPTY+32+5(%r15),253       # clear VX control
+       lctlg   %c0,%c0,__SF_EMPTY+32(%r15)
+.Lload_fpu_regs_fp:
+       ld      0,0(%r4)
+       ld      1,8(%r4)
+       ld      2,16(%r4)
+       ld      3,24(%r4)
+       ld      4,32(%r4)
+       ld      5,40(%r4)
+       ld      6,48(%r4)
+       ld      7,56(%r4)
+       ld      8,64(%r4)
+       ld      9,72(%r4)
+       ld      10,80(%r4)
+       ld      11,88(%r4)
+       ld      12,96(%r4)
+       ld      13,104(%r4)
+       ld      14,112(%r4)
+       ld      15,120(%r4)
+.Lload_fpu_regs_done:
+       ni      __LC_CPU_FLAGS+7,255-_CIF_FPU
+       br      %r14
+.Lload_fpu_regs_end:
+
+/* Test and set the vector enablement control in CR0.46 */
+ENTRY(__ctl_set_vx)
+       stctg   %c0,%c0,__SF_EMPTY(%r15)
+       tm      __SF_EMPTY+5(%r15),2
+       bor     %r14
+       oi      __SF_EMPTY+5(%r15),2
+       lctlg   %c0,%c0,__SF_EMPTY(%r15)
+       br      %r14
+.L__ctl_set_vx_end:
+
 .L__critical_end:
 
 /*
@@ -702,9 +868,8 @@ ENTRY(mcck_int_handler)
        lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
        lg      %r10,__LC_LAST_BREAK
        lg      %r12,__LC_THREAD_INFO
-       larl    %r13,system_call
+       larl    %r13,cleanup_critical
        lmg     %r8,%r9,__LC_MCK_OLD_PSW
-       HANDLE_SIE_INTERCEPT %r14,4
        tm      __LC_MCCK_CODE,0x80     # system damage?
        jo      .Lmcck_panic            # yes -> rest of mcck code invalid
        lghi    %r14,__LC_CPU_TIMER_SAVE_AREA
@@ -725,11 +890,7 @@ ENTRY(mcck_int_handler)
        mvc     __LC_MCCK_ENTER_TIMER(8),0(%r14)
 3:     tm      __LC_MCCK_CODE+2,0x09   # mwp + ia of old psw valid?
        jno     .Lmcck_panic            # no -> skip cleanup critical
-       SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_PANIC_STACK,PAGE_SHIFT
-       tm      %r8,0x0001              # interrupting from user ?
-       jz      .Lmcck_skip
-       UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER
-       LAST_BREAK %r14
+       SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_MCCK_ENTER_TIMER
 .Lmcck_skip:
        lghi    %r14,__LC_GPREGS_SAVE_AREA+64
        stmg    %r0,%r7,__PT_R0(%r11)
@@ -764,12 +925,8 @@ ENTRY(mcck_int_handler)
        lpswe   __LC_RETURN_MCCK_PSW
 
 .Lmcck_panic:
-       lg      %r14,__LC_PANIC_STACK
-       slgr    %r14,%r15
-       srag    %r14,%r14,PAGE_SHIFT
-       jz      0f
        lg      %r15,__LC_PANIC_STACK
-0:     aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
+       aghi    %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
        j       .Lmcck_skip
 
 #
@@ -819,20 +976,13 @@ stack_overflow:
        jg      kernel_stack_overflow
 #endif
 
-       .align  8
-.Lcleanup_table:
-       .quad   system_call
-       .quad   .Lsysc_do_svc
-       .quad   .Lsysc_tif
-       .quad   .Lsysc_restore
-       .quad   .Lsysc_done
-       .quad   .Lio_tif
-       .quad   .Lio_restore
-       .quad   .Lio_done
-       .quad   psw_idle
-       .quad   .Lpsw_idle_end
-
 cleanup_critical:
+#if IS_ENABLED(CONFIG_KVM)
+       clg     %r9,BASED(.Lcleanup_table_sie)  # .Lsie_gmap
+       jl      0f
+       clg     %r9,BASED(.Lcleanup_table_sie+8)# .Lsie_done
+       jl      .Lcleanup_sie
+#endif
        clg     %r9,BASED(.Lcleanup_table)      # system_call
        jl      0f
        clg     %r9,BASED(.Lcleanup_table+8)    # .Lsysc_do_svc
@@ -853,8 +1003,54 @@ cleanup_critical:
        jl      0f
        clg     %r9,BASED(.Lcleanup_table+72)   # .Lpsw_idle_end
        jl      .Lcleanup_idle
+       clg     %r9,BASED(.Lcleanup_table+80)   # save_fpu_regs
+       jl      0f
+       clg     %r9,BASED(.Lcleanup_table+88)   # .Lsave_fpu_regs_end
+       jl      .Lcleanup_save_fpu_regs
+       clg     %r9,BASED(.Lcleanup_table+96)   # load_fpu_regs
+       jl      0f
+       clg     %r9,BASED(.Lcleanup_table+104)  # .Lload_fpu_regs_end
+       jl      .Lcleanup_load_fpu_regs
+       clg     %r9,BASED(.Lcleanup_table+112)  # __ctl_set_vx
+       jl      0f
+       clg     %r9,BASED(.Lcleanup_table+120)  # .L__ctl_set_vx_end
+       jl      .Lcleanup___ctl_set_vx
 0:     br      %r14
 
+       .align  8
+.Lcleanup_table:
+       .quad   system_call
+       .quad   .Lsysc_do_svc
+       .quad   .Lsysc_tif
+       .quad   .Lsysc_restore
+       .quad   .Lsysc_done
+       .quad   .Lio_tif
+       .quad   .Lio_restore
+       .quad   .Lio_done
+       .quad   psw_idle
+       .quad   .Lpsw_idle_end
+       .quad   save_fpu_regs
+       .quad   .Lsave_fpu_regs_end
+       .quad   load_fpu_regs
+       .quad   .Lload_fpu_regs_end
+       .quad   __ctl_set_vx
+       .quad   .L__ctl_set_vx_end
+
+#if IS_ENABLED(CONFIG_KVM)
+.Lcleanup_table_sie:
+       .quad   .Lsie_gmap
+       .quad   .Lsie_done
+
+.Lcleanup_sie:
+       lg      %r9,__SF_EMPTY(%r15)            # get control block pointer
+       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_LPP
+       jz      0f
+       .insn   s,0xb2800000,__SF_EMPTY+16(%r15)# set host id
+0:     ni      __SIE_PROG0C+3(%r9),0xfe        # no longer in SIE
+       lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
+       larl    %r9,sie_exit                    # skip forward to sie_exit
+       br      %r14
+#endif
 
 .Lcleanup_system_call:
        # check if stpt has been executed
@@ -915,7 +1111,7 @@ cleanup_critical:
        .quad   system_call
        .quad   .Lsysc_stmg
        .quad   .Lsysc_per
-       .quad   .Lsysc_vtime+18
+       .quad   .Lsysc_vtime+36
        .quad   .Lsysc_vtime+42
 
 .Lcleanup_sysc_tif:
@@ -981,6 +1177,145 @@ cleanup_critical:
 .Lcleanup_idle_insn:
        .quad   .Lpsw_idle_lpsw
 
+.Lcleanup_save_fpu_regs:
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       bor     %r14
+       clg     %r9,BASED(.Lcleanup_save_fpu_regs_done)
+       jhe     5f
+       clg     %r9,BASED(.Lcleanup_save_fpu_regs_fp)
+       jhe     4f
+       clg     %r9,BASED(.Lcleanup_save_fpu_regs_vx_high)
+       jhe     3f
+       clg     %r9,BASED(.Lcleanup_save_fpu_regs_vx_low)
+       jhe     2f
+       clg     %r9,BASED(.Lcleanup_save_fpu_fpc_end)
+       jhe     1f
+       lg      %r2,__LC_CURRENT
+0:     # Store floating-point controls
+       stfpc   __THREAD_FPU_fpc(%r2)
+1:     # Load register save area and check if VX is active
+       lg      %r3,__THREAD_FPU_regs(%r2)
+       ltgr    %r3,%r3
+       jz      5f                        # no save area -> set CIF_FPU
+       tm      __THREAD_FPU_flags+3(%r2),FPU_USE_VX
+       jz      4f                        # no VX -> store FP regs
+2:     # Store vector registers (V0-V15)
+       VSTM    %v0,%v15,0,%r3            # vstm 0,15,0(3)
+3:     # Store vector registers (V16-V31)
+       VSTM    %v16,%v31,256,%r3         # vstm 16,31,256(3)
+       j       5f                        # -> done, set CIF_FPU flag
+4:     # Store floating-point registers
+       std     0,0(%r3)
+       std     1,8(%r3)
+       std     2,16(%r3)
+       std     3,24(%r3)
+       std     4,32(%r3)
+       std     5,40(%r3)
+       std     6,48(%r3)
+       std     7,56(%r3)
+       std     8,64(%r3)
+       std     9,72(%r3)
+       std     10,80(%r3)
+       std     11,88(%r3)
+       std     12,96(%r3)
+       std     13,104(%r3)
+       std     14,112(%r3)
+       std     15,120(%r3)
+5:     # Set CIF_FPU flag
+       oi      __LC_CPU_FLAGS+7,_CIF_FPU
+       lg      %r9,48(%r11)            # return from save_fpu_regs
+       br      %r14
+.Lcleanup_save_fpu_fpc_end:
+       .quad   .Lsave_fpu_regs_fpc_end
+.Lcleanup_save_fpu_regs_vx_low:
+       .quad   .Lsave_fpu_regs_vx_low
+.Lcleanup_save_fpu_regs_vx_high:
+       .quad   .Lsave_fpu_regs_vx_high
+.Lcleanup_save_fpu_regs_fp:
+       .quad   .Lsave_fpu_regs_fp
+.Lcleanup_save_fpu_regs_done:
+       .quad   .Lsave_fpu_regs_done
+
+.Lcleanup_load_fpu_regs:
+       tm      __LC_CPU_FLAGS+7,_CIF_FPU
+       bnor    %r14
+       clg     %r9,BASED(.Lcleanup_load_fpu_regs_done)
+       jhe     1f
+       clg     %r9,BASED(.Lcleanup_load_fpu_regs_fp)
+       jhe     2f
+       clg     %r9,BASED(.Lcleanup_load_fpu_regs_fp_ctl)
+       jhe     3f
+       clg     %r9,BASED(.Lcleanup_load_fpu_regs_vx_high)
+       jhe     4f
+       clg     %r9,BASED(.Lcleanup_load_fpu_regs_vx)
+       jhe     5f
+       clg     %r9,BASED(.Lcleanup_load_fpu_regs_vx_ctl)
+       jhe     6f
+       lg      %r4,__LC_CURRENT
+       lfpc    __THREAD_FPU_fpc(%r4)
+       tm      __THREAD_FPU_flags+3(%r4),FPU_USE_VX    # VX-enabled task ?
+       lg      %r4,__THREAD_FPU_regs(%r4)      # %r4 <- reg save area
+       jz      3f                              # -> no VX, load FP regs
+6:     # Set VX-enablement control
+       stctg   %c0,%c0,__SF_EMPTY+32(%r15)     # store CR0
+       tm      __SF_EMPTY+32+5(%r15),2         # test VX control
+       jo      5f
+       oi      __SF_EMPTY+32+5(%r15),2         # set VX control
+       lctlg   %c0,%c0,__SF_EMPTY+32(%r15)
+5:     # Load V0 ..V15 registers
+       VLM     %v0,%v15,0,%r4
+4:     # Load V16..V31 registers
+       VLM     %v16,%v31,256,%r4
+       j       1f
+3:     # Clear VX-enablement control for FP
+       stctg   %c0,%c0,__SF_EMPTY+32(%r15)     # store CR0
+       tm      __SF_EMPTY+32+5(%r15),2         # test VX control
+       jz      2f
+       ni      __SF_EMPTY+32+5(%r15),253       # clear VX control
+       lctlg   %c0,%c0,__SF_EMPTY+32(%r15)
+2:     # Load floating-point registers
+       ld      0,0(%r4)
+       ld      1,8(%r4)
+       ld      2,16(%r4)
+       ld      3,24(%r4)
+       ld      4,32(%r4)
+       ld      5,40(%r4)
+       ld      6,48(%r4)
+       ld      7,56(%r4)
+       ld      8,64(%r4)
+       ld      9,72(%r4)
+       ld      10,80(%r4)
+       ld      11,88(%r4)
+       ld      12,96(%r4)
+       ld      13,104(%r4)
+       ld      14,112(%r4)
+       ld      15,120(%r4)
+1:     # Clear CIF_FPU bit
+       ni      __LC_CPU_FLAGS+7,255-_CIF_FPU
+       lg      %r9,48(%r11)            # return from load_fpu_regs
+       br      %r14
+.Lcleanup_load_fpu_regs_vx_ctl:
+       .quad   .Lload_fpu_regs_vx_ctl
+.Lcleanup_load_fpu_regs_vx:
+       .quad   .Lload_fpu_regs_vx
+.Lcleanup_load_fpu_regs_vx_high:
+       .quad   .Lload_fpu_regs_vx_high
+.Lcleanup_load_fpu_regs_fp_ctl:
+       .quad   .Lload_fpu_regs_fp_ctl
+.Lcleanup_load_fpu_regs_fp:
+       .quad   .Lload_fpu_regs_fp
+.Lcleanup_load_fpu_regs_done:
+       .quad   .Lload_fpu_regs_done
+
+.Lcleanup___ctl_set_vx:
+       stctg   %c0,%c0,__SF_EMPTY(%r15)
+       tm      __SF_EMPTY+5(%r15),2
+       bor     %r14
+       oi      __SF_EMPTY+5(%r15),2
+       lctlg   %c0,%c0,__SF_EMPTY(%r15)
+       lg      %r9,48(%r11)            # return from __ctl_set_vx
+       br      %r14
+
 /*
  * Integer constants
  */
@@ -989,62 +1324,11 @@ cleanup_critical:
        .quad   .L__critical_start
 .Lcritical_length:
        .quad   .L__critical_end - .L__critical_start
-
-
 #if IS_ENABLED(CONFIG_KVM)
-/*
- * sie64a calling convention:
- * %r2 pointer to sie control block
- * %r3 guest register save area
- */
-ENTRY(sie64a)
-       stmg    %r6,%r14,__SF_GPRS(%r15)        # save kernel registers
-       stg     %r2,__SF_EMPTY(%r15)            # save control block pointer
-       stg     %r3,__SF_EMPTY+8(%r15)          # save guest register save area
-       xc      __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason
-       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
-       lg      %r14,__LC_GMAP                  # get gmap pointer
-       ltgr    %r14,%r14
-       jz      .Lsie_gmap
-       lctlg   %c1,%c1,__GMAP_ASCE(%r14)       # load primary asce
-.Lsie_gmap:
-       lg      %r14,__SF_EMPTY(%r15)           # get control block pointer
-       oi      __SIE_PROG0C+3(%r14),1          # we are going into SIE now
-       tm      __SIE_PROG20+3(%r14),3          # last exit...
-       jnz     .Lsie_done
-       LPP     __SF_EMPTY(%r15)                # set guest id
-       sie     0(%r14)
-.Lsie_done:
-       LPP     __SF_EMPTY+16(%r15)             # set host id
-       ni      __SIE_PROG0C+3(%r14),0xfe       # no longer in SIE
-       lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
-# 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 between sie64a and .Lsie_done should not cause program
-# interrupts. So lets use a nop (47 00 00 00) as a landing pad.
-# See also HANDLE_SIE_INTERCEPT
-.Lrewind_pad:
-       nop     0
-       .globl sie_exit
-sie_exit:
-       lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
-       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
-       lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
-       lg      %r2,__SF_EMPTY+24(%r15)         # return exit reason code
-       br      %r14
-.Lsie_fault:
-       lghi    %r14,-EFAULT
-       stg     %r14,__SF_EMPTY+24(%r15)        # set exit reason code
-       j       sie_exit
-
-       .align  8
-.Lsie_critical:
+.Lsie_critical_start:
        .quad   .Lsie_gmap
 .Lsie_critical_length:
        .quad   .Lsie_done - .Lsie_gmap
-
-       EX_TABLE(.Lrewind_pad,.Lsie_fault)
-       EX_TABLE(sie_exit,.Lsie_fault)
 #endif
 
        .section .rodata, "a"
index 59b7c6470567d6d611daa28e310f4c420ffdedaf..1255c6c5353e2404f065545e557fe216e109b127 100644 (file)
@@ -370,6 +370,7 @@ ENTRY(startup_kdump)
        xc      0x200(256),0x200        # partially clear lowcore
        xc      0x300(256),0x300
        xc      0xe00(256),0xe00
+       lctlg   %c0,%c15,0x200(%r0)     # initialize control registers
        stck    __LC_LAST_UPDATE_CLOCK
        spt     6f-.LPG0(%r13)
        mvc     __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
@@ -413,9 +414,9 @@ ENTRY(startup_kdump)
 # followed by the facility words.
 
 #if defined(CONFIG_MARCH_Z13)
-       .long 3, 0xc100eff2, 0xf46ce800, 0x00400000
+       .long 2, 0xc100eff2, 0xf46cc800
 #elif defined(CONFIG_MARCH_ZEC12)
-       .long 3, 0xc100eff2, 0xf46ce800, 0x00400000
+       .long 2, 0xc100eff2, 0xf46cc800
 #elif defined(CONFIG_MARCH_Z196)
        .long 2, 0xc100eff2, 0xf46c0000
 #elif defined(CONFIG_MARCH_Z10)
index a90299600483e4c0780157af6fc2ea460afbd294..c9dac2139f59efcfb101200e96bfd0f143f5e761 100644 (file)
@@ -44,12 +44,9 @@ static void jump_label_bug(struct jump_entry *entry, struct insn *expected,
        unsigned char *ipn = (unsigned char *)new;
 
        pr_emerg("Jump label code mismatch at %pS [%p]\n", ipc, ipc);
-       pr_emerg("Found:    %02x %02x %02x %02x %02x %02x\n",
-                ipc[0], ipc[1], ipc[2], ipc[3], ipc[4], ipc[5]);
-       pr_emerg("Expected: %02x %02x %02x %02x %02x %02x\n",
-                ipe[0], ipe[1], ipe[2], ipe[3], ipe[4], ipe[5]);
-       pr_emerg("New:      %02x %02x %02x %02x %02x %02x\n",
-                ipn[0], ipn[1], ipn[2], ipn[3], ipn[4], ipn[5]);
+       pr_emerg("Found:    %6ph\n", ipc);
+       pr_emerg("Expected: %6ph\n", ipe);
+       pr_emerg("New:      %6ph\n", ipn);
        panic("Corrupted kernel text");
 }
 
index 56b550893593a58a5ab07879a2fa3561cde009d4..0ae6f8e74840d70cacda76f04851d2da1db9f0d3 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/nmi.h>
 #include <asm/crw.h>
 #include <asm/switch_to.h>
+#include <asm/fpu-internal.h>
 #include <asm/ctl_reg.h>
 
 struct mcck_struct {
@@ -164,8 +165,12 @@ static int notrace s390_revalidate_registers(struct mci *mci)
                cr0.val = S390_lowcore.cregs_save_area[0];
                cr0.afp = cr0.vx = 1;
                __ctl_load(cr0.val, 0, 0);
-               restore_vx_regs((__vector128 *)
-                               &S390_lowcore.vector_save_area);
+               asm volatile(
+                       "       la      1,%0\n"
+                       "       .word   0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */
+                       "       .word   0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */
+                       : : "Q" (*(struct vx_array *)
+                                &S390_lowcore.vector_save_area) : "1");
                __ctl_load(S390_lowcore.cregs_save_area[0], 0, 0);
        }
        /* Revalidate access registers */
@@ -358,4 +363,4 @@ static int __init machine_check_init(void)
        ctl_set_bit(14, 24);    /* enable warning MCH */
        return 0;
 }
-arch_initcall(machine_check_init);
+early_initcall(machine_check_init);
index afe05bfb7e008a723388ff6c39f2d83d5693ad65..b973972f6ba5cf8e995a01ef7ba869a4e520b5e8 100644 (file)
@@ -1019,12 +1019,9 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
                break;
        }
 
-       /* The host-program-parameter (hpp) contains the sie control
-        * block that is set by sie64a() in entry64.S.  Check if hpp
-        * refers to a valid control block and set sde_regs flags
-        * accordingly.  This would allow to use hpp values for other
-        * purposes too.
-        * For now, simply use a non-zero value as guest indicator.
+       /* The host-program-parameter (hpp) contains the pid of
+        * the CPU thread as set by sie64a() in entry.S.
+        * If non-zero assume a guest sample.
         */
        if (sfr->basic.hpp)
                sde_regs->in_guest = 1;
index 8f587d871b9f234bed189b9c568746930d1045f3..f2dac9f0799dc04a5bb07c4529bf617e84e82d0c 100644 (file)
@@ -81,8 +81,38 @@ void release_thread(struct task_struct *dead_task)
 
 void arch_release_task_struct(struct task_struct *tsk)
 {
-       if (tsk->thread.vxrs)
-               kfree(tsk->thread.vxrs);
+       /* Free either the floating-point or the vector register save area */
+       kfree(tsk->thread.fpu.regs);
+}
+
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+       *dst = *src;
+
+       /* Set up a new floating-point register save area */
+       dst->thread.fpu.fpc = 0;
+       dst->thread.fpu.flags = 0;      /* Always start with VX disabled */
+       dst->thread.fpu.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
+                                      GFP_KERNEL|__GFP_REPEAT);
+       if (!dst->thread.fpu.fprs)
+               return -ENOMEM;
+
+       /*
+        * Save the floating-point or vector register state of the current
+        * task.  The state is not saved for early kernel threads, for example,
+        * the init_task, which do not have an allocated save area.
+        * The CIF_FPU flag is set in any case to lazy clear or restore a saved
+        * state when switching to a different task or returning to user space.
+        */
+       save_fpu_regs();
+       dst->thread.fpu.fpc = current->thread.fpu.fpc;
+       if (is_vx_task(current))
+               convert_vx_to_fp(dst->thread.fpu.fprs,
+                                current->thread.fpu.vxrs);
+       else
+               memcpy(dst->thread.fpu.fprs, current->thread.fpu.fprs,
+                      sizeof(freg_t) * __NUM_FPRS);
+       return 0;
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
@@ -142,11 +172,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
        p->thread.ri_signum = 0;
        frame->childregs.psw.mask &= ~PSW_MASK_RI;
 
-       /* Save the fpu registers to new thread structure. */
-       save_fp_ctl(&p->thread.fp_regs.fpc);
-       save_fp_regs(p->thread.fp_regs.fprs);
-       p->thread.fp_regs.pad = 0;
-       p->thread.vxrs = NULL;
        /* Set a new TLS ?  */
        if (clone_flags & CLONE_SETTLS) {
                unsigned long tls = frame->childregs.gprs[6];
@@ -162,7 +187,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
 asmlinkage void execve_tail(void)
 {
-       current->thread.fp_regs.fpc = 0;
+       current->thread.fpu.fpc = 0;
        asm volatile("sfpc %0" : : "d" (0));
 }
 
@@ -171,8 +196,15 @@ asmlinkage void execve_tail(void)
  */
 int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
 {
-       save_fp_ctl(&fpregs->fpc);
-       save_fp_regs(fpregs->fprs);
+       save_fpu_regs();
+       fpregs->fpc = current->thread.fpu.fpc;
+       fpregs->pad = 0;
+       if (is_vx_task(current))
+               convert_vx_to_fp((freg_t *)&fpregs->fprs,
+                                current->thread.fpu.vxrs);
+       else
+               memcpy(&fpregs->fprs, current->thread.fpu.fprs,
+                      sizeof(fpregs->fprs));
        return 1;
 }
 EXPORT_SYMBOL(dump_fpu);
index dc488e13b7e35b216335323a68bd6eac422ce172..e6e077ae3990ff93672347e8a801877aa8953f95 100644 (file)
@@ -40,6 +40,15 @@ void cpu_init(void)
        enter_lazy_tlb(&init_mm, current);
 }
 
+/*
+ * cpu_have_feature - Test CPU features on module initialization
+ */
+int cpu_have_feature(unsigned int num)
+{
+       return elf_hwcap & (1UL << num);
+}
+EXPORT_SYMBOL(cpu_have_feature);
+
 /*
  * show_cpuinfo - Get information on one CPU for use by procfs.
  */
index d363c9c322a1b4b7b7eaa1031b7ebb9da7ea4a42..8b1c8e33f184a94f057d35f479145734aafc6ad0 100644 (file)
@@ -45,39 +45,27 @@ void update_cr_regs(struct task_struct *task)
        struct per_regs old, new;
 
        /* Take care of the enable/disable of transactional execution. */
-       if (MACHINE_HAS_TE || MACHINE_HAS_VX) {
+       if (MACHINE_HAS_TE) {
                unsigned long cr, cr_new;
 
                __ctl_store(cr, 0, 0);
-               cr_new = cr;
-               if (MACHINE_HAS_TE) {
-                       /* Set or clear transaction execution TXC bit 8. */
-                       cr_new |= (1UL << 55);
-                       if (task->thread.per_flags & PER_FLAG_NO_TE)
-                               cr_new &= ~(1UL << 55);
-               }
-               if (MACHINE_HAS_VX) {
-                       /* Enable/disable of vector extension */
-                       cr_new &= ~(1UL << 17);
-                       if (task->thread.vxrs)
-                               cr_new |= (1UL << 17);
-               }
+               /* Set or clear transaction execution TXC bit 8. */
+               cr_new = cr | (1UL << 55);
+               if (task->thread.per_flags & PER_FLAG_NO_TE)
+                       cr_new &= ~(1UL << 55);
                if (cr_new != cr)
                        __ctl_load(cr_new, 0, 0);
-               if (MACHINE_HAS_TE) {
-                       /* Set/clear transaction execution TDC bits 62/63. */
-                       __ctl_store(cr, 2, 2);
-                       cr_new = cr & ~3UL;
-                       if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
-                               if (task->thread.per_flags &
-                                   PER_FLAG_TE_ABORT_RAND_TEND)
-                                       cr_new |= 1UL;
-                               else
-                                       cr_new |= 2UL;
-                       }
-                       if (cr_new != cr)
-                               __ctl_load(cr_new, 2, 2);
+               /* Set or clear transaction execution TDC bits 62 and 63. */
+               __ctl_store(cr, 2, 2);
+               cr_new = cr & ~3UL;
+               if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
+                       if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
+                               cr_new |= 1UL;
+                       else
+                               cr_new |= 2UL;
                }
+               if (cr_new != cr)
+                       __ctl_load(cr_new, 2, 2);
        }
        /* Copy user specified PER registers */
        new.control = thread->per_user.control;
@@ -242,21 +230,21 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
                /*
                 * floating point control reg. is in the thread structure
                 */
-               tmp = child->thread.fp_regs.fpc;
+               tmp = child->thread.fpu.fpc;
                tmp <<= BITS_PER_LONG - 32;
 
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (is_vx_task(child))
                        tmp = *(addr_t *)
-                              ((addr_t) child->thread.vxrs + 2*offset);
+                              ((addr_t) child->thread.fpu.vxrs + 2*offset);
                else
                        tmp = *(addr_t *)
-                              ((addr_t) &child->thread.fp_regs.fprs + offset);
+                              ((addr_t) &child->thread.fpu.fprs + offset);
 
        } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
                /*
@@ -387,20 +375,20 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
                if ((unsigned int) data != 0 ||
                    test_fp_ctl(data >> (BITS_PER_LONG - 32)))
                        return -EINVAL;
-               child->thread.fp_regs.fpc = data >> (BITS_PER_LONG - 32);
+               child->thread.fpu.fpc = data >> (BITS_PER_LONG - 32);
 
        } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (is_vx_task(child))
                        *(addr_t *)((addr_t)
-                               child->thread.vxrs + 2*offset) = data;
+                               child->thread.fpu.vxrs + 2*offset) = data;
                else
                        *(addr_t *)((addr_t)
-                               &child->thread.fp_regs.fprs + offset) = data;
+                               &child->thread.fpu.fprs + offset) = data;
 
        } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
                /*
@@ -621,20 +609,20 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
                /*
                 * floating point control reg. is in the thread structure
                 */
-               tmp = child->thread.fp_regs.fpc;
+               tmp = child->thread.fpu.fpc;
 
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (is_vx_task(child))
                        tmp = *(__u32 *)
-                              ((addr_t) child->thread.vxrs + 2*offset);
+                              ((addr_t) child->thread.fpu.vxrs + 2*offset);
                else
                        tmp = *(__u32 *)
-                              ((addr_t) &child->thread.fp_regs.fprs + offset);
+                              ((addr_t) &child->thread.fpu.fprs + offset);
 
        } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
                /*
@@ -746,20 +734,20 @@ static int __poke_user_compat(struct task_struct *child,
                 */
                if (test_fp_ctl(tmp))
                        return -EINVAL;
-               child->thread.fp_regs.fpc = data;
+               child->thread.fpu.fpc = data;
 
        } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
                /*
-                * floating point regs. are either in child->thread.fp_regs
-                * or the child->thread.vxrs array
+                * floating point regs. are either in child->thread.fpu
+                * or the child->thread.fpu.vxrs array
                 */
                offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs;
-               if (child->thread.vxrs)
+               if (is_vx_task(child))
                        *(__u32 *)((addr_t)
-                               child->thread.vxrs + 2*offset) = tmp;
+                               child->thread.fpu.vxrs + 2*offset) = tmp;
                else
                        *(__u32 *)((addr_t)
-                               &child->thread.fp_regs.fprs + offset) = tmp;
+                               &child->thread.fpu.fprs + offset) = tmp;
 
        } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
                /*
@@ -952,18 +940,16 @@ static int s390_fpregs_get(struct task_struct *target,
                           const struct user_regset *regset, unsigned int pos,
                           unsigned int count, void *kbuf, void __user *ubuf)
 {
-       if (target == current) {
-               save_fp_ctl(&target->thread.fp_regs.fpc);
-               save_fp_regs(target->thread.fp_regs.fprs);
-       } else if (target->thread.vxrs) {
-               int i;
+       _s390_fp_regs fp_regs;
+
+       if (target == current)
+               save_fpu_regs();
+
+       fp_regs.fpc = target->thread.fpu.fpc;
+       fpregs_store(&fp_regs, &target->thread.fpu);
 
-               for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       target->thread.fp_regs.fprs[i] =
-                               *(freg_t *)(target->thread.vxrs + i);
-       }
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                  &target->thread.fp_regs, 0, -1);
+                                  &fp_regs, 0, -1);
 }
 
 static int s390_fpregs_set(struct task_struct *target,
@@ -972,41 +958,33 @@ static int s390_fpregs_set(struct task_struct *target,
                           const void __user *ubuf)
 {
        int rc = 0;
+       freg_t fprs[__NUM_FPRS];
 
-       if (target == current) {
-               save_fp_ctl(&target->thread.fp_regs.fpc);
-               save_fp_regs(target->thread.fp_regs.fprs);
-       }
+       if (target == current)
+               save_fpu_regs();
 
        /* If setting FPC, must validate it first. */
        if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
-               u32 ufpc[2] = { target->thread.fp_regs.fpc, 0 };
+               u32 ufpc[2] = { target->thread.fpu.fpc, 0 };
                rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ufpc,
                                        0, offsetof(s390_fp_regs, fprs));
                if (rc)
                        return rc;
                if (ufpc[1] != 0 || test_fp_ctl(ufpc[0]))
                        return -EINVAL;
-               target->thread.fp_regs.fpc = ufpc[0];
+               target->thread.fpu.fpc = ufpc[0];
        }
 
        if (rc == 0 && count > 0)
                rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                       target->thread.fp_regs.fprs,
-                                       offsetof(s390_fp_regs, fprs), -1);
-
-       if (rc == 0) {
-               if (target == current) {
-                       restore_fp_ctl(&target->thread.fp_regs.fpc);
-                       restore_fp_regs(target->thread.fp_regs.fprs);
-               } else if (target->thread.vxrs) {
-                       int i;
-
-                       for (i = 0; i < __NUM_VXRS_LOW; i++)
-                               *(freg_t *)(target->thread.vxrs + i) =
-                                       target->thread.fp_regs.fprs[i];
-               }
-       }
+                                       fprs, offsetof(s390_fp_regs, fprs), -1);
+       if (rc)
+               return rc;
+
+       if (is_vx_task(target))
+               convert_fp_to_vx(target->thread.fpu.vxrs, fprs);
+       else
+               memcpy(target->thread.fpu.fprs, &fprs, sizeof(fprs));
 
        return rc;
 }
@@ -1069,11 +1047,11 @@ static int s390_vxrs_low_get(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (target->thread.vxrs) {
+       if (is_vx_task(target)) {
                if (target == current)
-                       save_vx_regs(target->thread.vxrs);
+                       save_fpu_regs();
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       vxrs[i] = *((__u64 *)(target->thread.vxrs + i) + 1);
+                       vxrs[i] = *((__u64 *)(target->thread.fpu.vxrs + i) + 1);
        } else
                memset(vxrs, 0, sizeof(vxrs));
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
@@ -1089,20 +1067,17 @@ static int s390_vxrs_low_set(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (!target->thread.vxrs) {
+       if (!is_vx_task(target)) {
                rc = alloc_vector_registers(target);
                if (rc)
                        return rc;
        } else if (target == current)
-               save_vx_regs(target->thread.vxrs);
+               save_fpu_regs();
 
        rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
-       if (rc == 0) {
+       if (rc == 0)
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       *((__u64 *)(target->thread.vxrs + i) + 1) = vxrs[i];
-               if (target == current)
-                       restore_vx_regs(target->thread.vxrs);
-       }
+                       *((__u64 *)(target->thread.fpu.vxrs + i) + 1) = vxrs[i];
 
        return rc;
 }
@@ -1116,10 +1091,10 @@ static int s390_vxrs_high_get(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (target->thread.vxrs) {
+       if (is_vx_task(target)) {
                if (target == current)
-                       save_vx_regs(target->thread.vxrs);
-               memcpy(vxrs, target->thread.vxrs + __NUM_VXRS_LOW,
+                       save_fpu_regs();
+               memcpy(vxrs, target->thread.fpu.vxrs + __NUM_VXRS_LOW,
                       sizeof(vxrs));
        } else
                memset(vxrs, 0, sizeof(vxrs));
@@ -1135,18 +1110,15 @@ static int s390_vxrs_high_set(struct task_struct *target,
 
        if (!MACHINE_HAS_VX)
                return -ENODEV;
-       if (!target->thread.vxrs) {
+       if (!is_vx_task(target)) {
                rc = alloc_vector_registers(target);
                if (rc)
                        return rc;
        } else if (target == current)
-               save_vx_regs(target->thread.vxrs);
+               save_fpu_regs();
 
        rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                               target->thread.vxrs + __NUM_VXRS_LOW, 0, -1);
-       if (rc == 0 && target == current)
-               restore_vx_regs(target->thread.vxrs);
-
+                               target->thread.fpu.vxrs + __NUM_VXRS_LOW, 0, -1);
        return rc;
 }
 
index 9f60467938d177ca6e6ffc0a45fa563b518b0693..5090d3dad10b56cef69b754e6ada95fc4e067a53 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/module.h>
 #include <linux/kvm_host.h>
+#include <asm/fpu-internal.h>
 #include <asm/ftrace.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
@@ -8,6 +9,8 @@ EXPORT_SYMBOL(_mcount);
 #if IS_ENABLED(CONFIG_KVM)
 EXPORT_SYMBOL(sie64a);
 EXPORT_SYMBOL(sie_exit);
+EXPORT_SYMBOL(save_fpu_regs);
+EXPORT_SYMBOL(__ctl_set_vx);
 #endif
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
deleted file mode 100644 (file)
index ada0c07..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Mini SCLP driver.
- *
- * Copyright IBM Corp. 2004, 2009
- *
- *   Author(s):        Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
- *             Heiko Carstens <heiko.carstens@de.ibm.com>,
- *
- */
-
-#include <linux/linkage.h>
-#include <asm/irq.h>
-
-LC_EXT_NEW_PSW         = 0x58                  # addr of ext int handler
-LC_EXT_NEW_PSW_64      = 0x1b0                 # addr of ext int handler 64 bit
-LC_EXT_INT_PARAM       = 0x80                  # addr of ext int parameter
-LC_EXT_INT_CODE                = 0x86                  # addr of ext int code
-LC_AR_MODE_ID          = 0xa3
-
-#
-# Subroutine which waits synchronously until either an external interruption
-# or a timeout occurs.
-#
-# Parameters:
-#   R2 = 0 for no timeout, non-zero for timeout in (approximated) seconds
-#
-# Returns:
-#   R2 = 0 on interrupt, 2 on timeout
-#   R3 = external interruption parameter if R2=0
-#
-
-_sclp_wait_int:
-       stm     %r6,%r15,24(%r15)               # save registers
-       basr    %r13,0                          # get base register
-.LbaseS1:
-       ahi     %r15,-96                        # create stack frame
-       la      %r8,LC_EXT_NEW_PSW              # register int handler
-       la      %r9,.LextpswS1-.LbaseS1(%r13)
-       tm      LC_AR_MODE_ID,1
-       jno     .Lesa1
-       la      %r8,LC_EXT_NEW_PSW_64           # register int handler 64 bit
-       la      %r9,.LextpswS1_64-.LbaseS1(%r13)
-.Lesa1:
-       mvc     .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
-       mvc     0(16,%r8),0(%r9)
-       epsw    %r6,%r7                         # set current addressing mode
-       nill    %r6,0x1                         # in new psw (31 or 64 bit mode)
-       nilh    %r7,0x8000
-       stm     %r6,%r7,0(%r8)
-       lhi     %r6,0x0200                      # cr mask for ext int (cr0.54)
-       ltr     %r2,%r2
-       jz      .LsetctS1
-       ahi     %r6,0x0800                      # cr mask for clock int (cr0.52)
-       stck    .LtimeS1-.LbaseS1(%r13)         # initiate timeout
-       al      %r2,.LtimeS1-.LbaseS1(%r13)
-       st      %r2,.LtimeS1-.LbaseS1(%r13)
-       sckc    .LtimeS1-.LbaseS1(%r13)
-
-.LsetctS1:
-       stctl   %c0,%c0,.LctlS1-.LbaseS1(%r13)  # enable required interrupts
-       l       %r0,.LctlS1-.LbaseS1(%r13)
-       lhi     %r1,~(0x200 | 0x800)            # clear old values
-       nr      %r1,%r0
-       or      %r1,%r6                         # set new value
-       st      %r1,.LctlS1-.LbaseS1(%r13)
-       lctl    %c0,%c0,.LctlS1-.LbaseS1(%r13)
-       st      %r0,.LctlS1-.LbaseS1(%r13)
-       lhi     %r2,2                           # return code for timeout
-.LloopS1:
-       lpsw    .LwaitpswS1-.LbaseS1(%r13)      # wait until interrupt
-.LwaitS1:
-       lh      %r7,LC_EXT_INT_CODE
-       chi     %r7,EXT_IRQ_CLK_COMP            # timeout?
-       je      .LtimeoutS1
-       chi     %r7,EXT_IRQ_SERVICE_SIG         # service int?
-       jne     .LloopS1
-       sr      %r2,%r2
-       l       %r3,LC_EXT_INT_PARAM
-.LtimeoutS1:
-       lctl    %c0,%c0,.LctlS1-.LbaseS1(%r13)  # restore interrupt setting
-       # restore old handler
-       mvc     0(16,%r8),.LoldpswS1-.LbaseS1(%r13)
-       lm      %r6,%r15,120(%r15)              # restore registers
-       br      %r14                            # return to caller
-
-       .align  8
-.LoldpswS1:
-       .long   0, 0, 0, 0                      # old ext int PSW
-.LextpswS1:
-       .long   0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
-.LextpswS1_64:
-       .quad   0, .LwaitS1                     # PSW to handle ext int, 64 bit
-.LwaitpswS1:
-       .long   0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
-.LtimeS1:
-       .quad   0                               # current time
-.LctlS1:
-       .long   0                               # CT0 contents
-
-#
-# Subroutine to synchronously issue a service call.
-#
-# Parameters:
-#   R2 = command word
-#   R3 = sccb address
-#
-# Returns:
-#   R2 = 0 on success, 1 on failure
-#   R3 = sccb response code if R2 = 0
-#
-
-_sclp_servc:
-       stm     %r6,%r15,24(%r15)               # save registers
-       ahi     %r15,-96                        # create stack frame
-       lr      %r6,%r2                         # save command word
-       lr      %r7,%r3                         # save sccb address
-.LretryS2:
-       lhi     %r2,1                           # error return code
-       .insn   rre,0xb2200000,%r6,%r7          # servc
-       brc     1,.LendS2                       # exit if not operational
-       brc     8,.LnotbusyS2                   # go on if not busy
-       sr      %r2,%r2                         # wait until no longer busy
-       bras    %r14,_sclp_wait_int
-       j       .LretryS2                       # retry
-.LnotbusyS2:
-       sr      %r2,%r2                         # wait until result
-       bras    %r14,_sclp_wait_int
-       sr      %r2,%r2
-       lh      %r3,6(%r7)
-.LendS2:
-       lm      %r6,%r15,120(%r15)              # restore registers
-       br      %r14
-
-#
-# Subroutine to set up the SCLP interface.
-#
-# Parameters:
-#   R2 = 0 to activate, non-zero to deactivate
-#
-# Returns:
-#   R2 = 0 on success, non-zero on failure
-#
-
-_sclp_setup:
-       stm     %r6,%r15,24(%r15)               # save registers
-       ahi     %r15,-96                        # create stack frame
-       basr    %r13,0                          # get base register
-.LbaseS3:
-       l       %r6,.LsccbS0-.LbaseS3(%r13)     # prepare init mask sccb
-       mvc     0(.LinitendS3-.LinitsccbS3,%r6),.LinitsccbS3-.LbaseS3(%r13)
-       ltr     %r2,%r2                         # initialization?
-       jz      .LdoinitS3                      # go ahead
-       # clear masks
-       xc      .LinitmaskS3-.LinitsccbS3(8,%r6),.LinitmaskS3-.LinitsccbS3(%r6)
-.LdoinitS3:
-       l       %r2,.LwritemaskS3-.LbaseS3(%r13)# get command word
-       lr      %r3,%r6                         # get sccb address
-       bras    %r14,_sclp_servc                # issue service call
-       ltr     %r2,%r2                         # servc successful?
-       jnz     .LerrorS3
-       chi     %r3,0x20                        # write mask successful?
-       jne     .LerrorS3
-       # check masks
-       la      %r2,.LinitmaskS3-.LinitsccbS3(%r6)
-       l       %r1,0(%r2)                      # receive mask ok?
-       n       %r1,12(%r2)
-       cl      %r1,0(%r2)
-       jne     .LerrorS3
-       l       %r1,4(%r2)                      # send mask ok?
-       n       %r1,8(%r2)
-       cl      %r1,4(%r2)
-       sr      %r2,%r2
-       je      .LendS3
-.LerrorS3:
-       lhi     %r2,1                           # error return code
-.LendS3:
-       lm      %r6,%r15,120(%r15)              # restore registers
-       br      %r14
-.LwritemaskS3:
-       .long   0x00780005                      # SCLP command for write mask
-.LinitsccbS3:
-       .word   .LinitendS3-.LinitsccbS3
-       .byte   0,0,0,0
-       .word   0
-       .word   0
-       .word   4
-.LinitmaskS3:
-       .long   0x80000000
-       .long   0x40000000
-       .long   0
-       .long   0
-.LinitendS3:
-
-#
-# Subroutine which prints a given text to the SCLP console.
-#
-# Parameters:
-#   R2 = address of nil-terminated ASCII text
-#
-# Returns:
-#   R2 = 0 on success, 1 on failure
-#
-
-_sclp_print:
-       stm     %r6,%r15,24(%r15)               # save registers
-       ahi     %r15,-96                        # create stack frame
-       basr    %r13,0                          # get base register
-.LbaseS4:
-       l       %r8,.LsccbS0-.LbaseS4(%r13)     # prepare write data sccb
-       mvc     0(.LmtoS4-.LwritesccbS4,%r8),.LwritesccbS4-.LbaseS4(%r13)
-       la      %r7,.LmtoS4-.LwritesccbS4(%r8)  # current mto addr
-       sr      %r0,%r0
-       l       %r10,.Lascebc-.LbaseS4(%r13)    # address of translation table
-.LinitmtoS4:
-       # initialize mto
-       mvc     0(.LmtoendS4-.LmtoS4,%r7),.LmtoS4-.LbaseS4(%r13)
-       lhi     %r6,.LmtoendS4-.LmtoS4          # current mto length
-.LloopS4:
-       ic      %r0,0(%r2)                      # get character
-       ahi     %r2,1
-       ltr     %r0,%r0                         # end of string?
-       jz      .LfinalizemtoS4
-       chi     %r0,0x0a                        # end of line (NL)?
-       jz      .LfinalizemtoS4
-       stc     %r0,0(%r6,%r7)                  # copy to mto
-       la      %r11,0(%r6,%r7)
-       tr      0(1,%r11),0(%r10)               # translate to EBCDIC
-       ahi     %r6,1
-       j       .LloopS4
-.LfinalizemtoS4:
-       sth     %r6,0(%r7)                      # update mto length
-       lh      %r9,.LmdbS4-.LwritesccbS4(%r8)  # update mdb length
-       ar      %r9,%r6
-       sth     %r9,.LmdbS4-.LwritesccbS4(%r8)
-       lh      %r9,.LevbufS4-.LwritesccbS4(%r8)# update evbuf length
-       ar      %r9,%r6
-       sth     %r9,.LevbufS4-.LwritesccbS4(%r8)
-       lh      %r9,0(%r8)                      # update sccb length
-       ar      %r9,%r6
-       sth     %r9,0(%r8)
-       ar      %r7,%r6                         # update current mto address
-       ltr     %r0,%r0                         # more characters?
-       jnz     .LinitmtoS4
-       l       %r2,.LwritedataS4-.LbaseS4(%r13)# write data
-       lr      %r3,%r8
-       bras    %r14,_sclp_servc
-       ltr     %r2,%r2                         # servc successful?
-       jnz     .LendS4
-       chi     %r3,0x20                        # write data successful?
-       je      .LendS4
-       lhi     %r2,1                           # error return code
-.LendS4:
-       lm      %r6,%r15,120(%r15)              # restore registers
-       br      %r14
-
-#
-# Function which prints a given text to the SCLP console.
-#
-# Parameters:
-#   R2 = address of nil-terminated ASCII text
-#
-# Returns:
-#   R2 = 0 on success, 1 on failure
-#
-
-ENTRY(_sclp_print_early)
-       stm     %r6,%r15,24(%r15)               # save registers
-       ahi     %r15,-96                        # create stack frame
-       tm      LC_AR_MODE_ID,1
-       jno     .Lesa2
-       ahi     %r15,-80
-       stmh    %r6,%r15,96(%r15)               # store upper register halves
-       basr    %r13,0
-       lmh     %r0,%r15,.Lzeroes-.(%r13)       # clear upper register halves
-.Lesa2:
-       lr      %r10,%r2                        # save string pointer
-       lhi     %r2,0
-       bras    %r14,_sclp_setup                # enable console
-       ltr     %r2,%r2
-       jnz     .LendS5
-       lr      %r2,%r10
-       bras    %r14,_sclp_print                # print string
-       ltr     %r2,%r2
-       jnz     .LendS5
-       lhi     %r2,1
-       bras    %r14,_sclp_setup                # disable console
-.LendS5:
-       tm      LC_AR_MODE_ID,1
-       jno     .Lesa3
-       lgfr    %r2,%r2                         # sign extend return value
-       lmh     %r6,%r15,96(%r15)               # restore upper register halves
-       ahi     %r15,80
-.Lesa3:
-       lm      %r6,%r15,120(%r15)              # restore registers
-       br      %r14
-.Lzeroes:
-       .fill   64,4,0
-
-.LwritedataS4:
-       .long   0x00760005                      # SCLP command for write data
-.LwritesccbS4:
-       # sccb
-       .word   .LmtoS4-.LwritesccbS4
-       .byte   0
-       .byte   0,0,0
-       .word   0
-
-       # evbuf
-.LevbufS4:
-       .word   .LmtoS4-.LevbufS4
-       .byte   0x02
-       .byte   0
-       .word   0
-
-.LmdbS4:
-       # mdb
-       .word   .LmtoS4-.LmdbS4
-       .word   1
-       .long   0xd4c4c240
-       .long   1
-
-       # go
-.LgoS4:
-       .word   .LmtoS4-.LgoS4
-       .word   1
-       .long   0
-       .byte   0,0,0,0,0,0,0,0
-       .byte   0,0,0
-       .byte   0
-       .byte   0,0,0,0,0,0,0
-       .byte   0
-       .word   0
-       .byte   0,0,0,0,0,0,0,0,0,0
-       .byte   0,0,0,0,0,0,0,0
-       .byte   0,0,0,0,0,0,0,0
-
-.LmtoS4:
-       .word   .LmtoendS4-.LmtoS4
-       .word   4
-       .word   0x1000
-       .byte   0
-       .byte   0,0,0
-.LmtoendS4:
-
-       # Global constants
-.LsccbS0:
-       .long   _sclp_work_area
-.Lascebc:
-       .long   _ascebc
-
-.section .data,"aw",@progbits
-       .balign 4096
-_sclp_work_area:
-       .fill   4096
-.previous
diff --git a/arch/s390/kernel/sclp.c b/arch/s390/kernel/sclp.c
new file mode 100644 (file)
index 0000000..fa0bdff
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *    Copyright IBM Corp. 2015
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#include <linux/kernel.h>
+#include <asm/ebcdic.h>
+#include <asm/irq.h>
+#include <asm/lowcore.h>
+#include <asm/processor.h>
+#include <asm/sclp.h>
+
+static char _sclp_work_area[4096] __aligned(PAGE_SIZE);
+
+static void _sclp_wait_int(void)
+{
+       unsigned long cr0, cr0_new, psw_mask, addr;
+       psw_t psw_ext_save, psw_wait;
+
+       __ctl_store(cr0, 0, 0);
+       cr0_new = cr0 | 0x200;
+       __ctl_load(cr0_new, 0, 0);
+
+       psw_ext_save = S390_lowcore.external_new_psw;
+       psw_mask = __extract_psw() & (PSW_MASK_EA | PSW_MASK_BA);
+       S390_lowcore.external_new_psw.mask = psw_mask;
+       psw_wait.mask = psw_mask | PSW_MASK_EXT | PSW_MASK_WAIT;
+       S390_lowcore.ext_int_code = 0;
+
+       do {
+               asm volatile(
+                       "       larl    %[addr],0f\n"
+                       "       stg     %[addr],%[psw_wait_addr]\n"
+                       "       stg     %[addr],%[psw_ext_addr]\n"
+                       "       lpswe   %[psw_wait]\n"
+                       "0:\n"
+                       : [addr] "=&d" (addr),
+                         [psw_wait_addr] "=Q" (psw_wait.addr),
+                         [psw_ext_addr] "=Q" (S390_lowcore.external_new_psw.addr)
+                       : [psw_wait] "Q" (psw_wait)
+                       : "cc", "memory");
+       } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG);
+
+       __ctl_load(cr0, 0, 0);
+       S390_lowcore.external_new_psw = psw_ext_save;
+}
+
+static int _sclp_servc(unsigned int cmd, char *sccb)
+{
+       unsigned int cc;
+
+       do {
+               asm volatile(
+                       "       .insn   rre,0xb2200000,%1,%2\n"
+                       "       ipm     %0\n"
+                       : "=d" (cc) : "d" (cmd), "a" (sccb)
+                       : "cc", "memory");
+               cc >>= 28;
+               if (cc == 3)
+                       return -EINVAL;
+               _sclp_wait_int();
+       } while (cc != 0);
+       return (*(unsigned short *)(sccb + 6) == 0x20) ? 0 : -EIO;
+}
+
+static int _sclp_setup(int disable)
+{
+       static unsigned char init_sccb[] = {
+               0x00, 0x1c,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x04,
+               0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       unsigned int *masks;
+       int rc;
+
+       memcpy(_sclp_work_area, init_sccb, 28);
+       masks = (unsigned int *)(_sclp_work_area + 12);
+       if (disable)
+               memset(masks, 0, 16);
+       /* SCLP write mask */
+       rc = _sclp_servc(0x00780005, _sclp_work_area);
+       if (rc)
+               return rc;
+       if ((masks[0] & masks[3]) != masks[0] ||
+           (masks[1] & masks[2]) != masks[1])
+               return -EIO;
+       return 0;
+}
+
+static int _sclp_print(const char *str)
+{
+       static unsigned char write_head[] = {
+               /* sccb header */
+               0x00, 0x52,                                     /* 0 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 2 */
+               /* evbuf */
+               0x00, 0x4a,                                     /* 8 */
+               0x02, 0x00, 0x00, 0x00,                         /* 10 */
+               /* mdb */
+               0x00, 0x44,                                     /* 14 */
+               0x00, 0x01,                                     /* 16 */
+               0xd4, 0xc4, 0xc2, 0x40,                         /* 18 */
+               0x00, 0x00, 0x00, 0x01,                         /* 22 */
+               /* go */
+               0x00, 0x38,                                     /* 26 */
+               0x00, 0x01,                                     /* 28 */
+               0x00, 0x00, 0x00, 0x00,                         /* 30 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 34 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 */
+               0x00, 0x00, 0x00, 0x00,                         /* 50 */
+               0x00, 0x00,                                     /* 54 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 56 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 64 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 72 */
+               0x00, 0x00,                                     /* 80 */
+       };
+       static unsigned char write_mto[] = {
+               /* mto  */
+               0x00, 0x0a,                                     /* 0 */
+               0x00, 0x04,                                     /* 2 */
+               0x10, 0x00,                                     /* 4 */
+               0x00, 0x00, 0x00, 0x00                          /* 6 */
+       };
+       unsigned char *ptr, ch;
+       unsigned int count;
+
+       memcpy(_sclp_work_area, write_head, sizeof(write_head));
+       ptr = _sclp_work_area + sizeof(write_head);
+       do {
+               memcpy(ptr, write_mto, sizeof(write_mto));
+               for (count = sizeof(write_mto); (ch = *str++) != 0; count++) {
+                       if (ch == 0x0a)
+                               break;
+                       ptr[count] = _ascebc[ch];
+               }
+               /* Update length fields in mto, mdb, evbuf and sccb */
+               *(unsigned short *) ptr = count;
+               *(unsigned short *)(_sclp_work_area + 14) += count;
+               *(unsigned short *)(_sclp_work_area + 8) += count;
+               *(unsigned short *)(_sclp_work_area + 0) += count;
+               ptr += count;
+       } while (ch != 0);
+
+       /* SCLP write data */
+       return _sclp_servc(0x00760005, _sclp_work_area);
+}
+
+int _sclp_print_early(const char *str)
+{
+       int rc;
+
+       rc = _sclp_setup(0);
+       if (rc)
+               return rc;
+       rc = _sclp_print(str);
+       if (rc)
+               return rc;
+       return _sclp_setup(1);
+}
index ca070d260af2e166b23b48553b2b6c02dc2a1046..ce0cbd6ba7ca9e5a8ca4b0cf05b37ea2a1e5dcc0 100644 (file)
@@ -62,6 +62,7 @@
 #include <asm/os_info.h>
 #include <asm/sclp.h>
 #include <asm/sysinfo.h>
+#include <asm/numa.h>
 #include "entry.h"
 
 /*
@@ -76,7 +77,7 @@ EXPORT_SYMBOL(console_devno);
 unsigned int console_irq = -1;
 EXPORT_SYMBOL(console_irq);
 
-unsigned long elf_hwcap = 0;
+unsigned long elf_hwcap __read_mostly = 0;
 char elf_platform[ELF_PLATFORM_SIZE];
 
 int __initdata memory_end_set;
@@ -688,7 +689,7 @@ static void __init setup_memory(void)
 /*
  * Setup hardware capabilities.
  */
-static void __init setup_hwcaps(void)
+static int __init setup_hwcaps(void)
 {
        static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
        struct cpuid cpu_id;
@@ -754,9 +755,11 @@ static void __init setup_hwcaps(void)
                elf_hwcap |= HWCAP_S390_TE;
 
        /*
-        * Vector extension HWCAP_S390_VXRS is bit 11.
+        * Vector extension HWCAP_S390_VXRS is bit 11. The Vector extension
+        * can be disabled with the "novx" parameter. Use MACHINE_HAS_VX
+        * instead of facility bit 129.
         */
-       if (test_facility(129))
+       if (MACHINE_HAS_VX)
                elf_hwcap |= HWCAP_S390_VXRS;
        get_cpu_id(&cpu_id);
        add_device_randomness(&cpu_id, sizeof(cpu_id));
@@ -793,7 +796,9 @@ static void __init setup_hwcaps(void)
                strcpy(elf_platform, "z13");
                break;
        }
+       return 0;
 }
+arch_initcall(setup_hwcaps);
 
 /*
  * Add system information as device randomness
@@ -879,11 +884,7 @@ void __init setup_arch(char **cmdline_p)
        setup_lowcore();
        smp_fill_possible_mask();
         cpu_init();
-
-       /*
-        * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
-        */
-       setup_hwcaps();
+       numa_setup();
 
        /*
         * Create kernel page tables and switch to virtual addressing.
index c551f22ce066466ebc6d6666b85a459716842683..9549af102d75aaa02e02b7bcbb02de06341bc5f8 100644 (file)
@@ -105,32 +105,13 @@ struct rt_sigframe
 static void store_sigregs(void)
 {
        save_access_regs(current->thread.acrs);
-       save_fp_ctl(&current->thread.fp_regs.fpc);
-       if (current->thread.vxrs) {
-               int i;
-
-               save_vx_regs(current->thread.vxrs);
-               for (i = 0; i < __NUM_FPRS; i++)
-                       current->thread.fp_regs.fprs[i] =
-                               *(freg_t *)(current->thread.vxrs + i);
-       } else
-               save_fp_regs(current->thread.fp_regs.fprs);
+       save_fpu_regs();
 }
 
 /* Load registers after signal return */
 static void load_sigregs(void)
 {
        restore_access_regs(current->thread.acrs);
-       /* restore_fp_ctl is done in restore_sigregs */
-       if (current->thread.vxrs) {
-               int i;
-
-               for (i = 0; i < __NUM_FPRS; i++)
-                       *(freg_t *)(current->thread.vxrs + i) =
-                               current->thread.fp_regs.fprs[i];
-               restore_vx_regs(current->thread.vxrs);
-       } else
-               restore_fp_regs(current->thread.fp_regs.fprs);
 }
 
 /* Returns non-zero on fault. */
@@ -146,8 +127,7 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
        memcpy(&user_sregs.regs.acrs, current->thread.acrs,
               sizeof(user_sregs.regs.acrs));
-       memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
-              sizeof(user_sregs.fpregs));
+       fpregs_store(&user_sregs.fpregs, &current->thread.fpu);
        if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
                return -EFAULT;
        return 0;
@@ -166,8 +146,8 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW_MASK_RI))
                return -EINVAL;
 
-       /* Loading the floating-point-control word can fail. Do that first. */
-       if (restore_fp_ctl(&user_sregs.fpregs.fpc))
+       /* Test the floating-point-control word. */
+       if (test_fp_ctl(user_sregs.fpregs.fpc))
                return -EINVAL;
 
        /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
@@ -185,8 +165,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
               sizeof(current->thread.acrs));
 
-       memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
-              sizeof(current->thread.fp_regs));
+       fpregs_load(&user_sregs.fpregs, &current->thread.fpu);
 
        clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
        return 0;
@@ -200,13 +179,13 @@ static int save_sigregs_ext(struct pt_regs *regs,
        int i;
 
        /* Save vector registers to signal stack */
-       if (current->thread.vxrs) {
+       if (is_vx_task(current)) {
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
+                       vxrs[i] = *((__u64 *)(current->thread.fpu.vxrs + i) + 1);
                if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
                                   sizeof(sregs_ext->vxrs_low)) ||
                    __copy_to_user(&sregs_ext->vxrs_high,
-                                  current->thread.vxrs + __NUM_VXRS_LOW,
+                                  current->thread.fpu.vxrs + __NUM_VXRS_LOW,
                                   sizeof(sregs_ext->vxrs_high)))
                        return -EFAULT;
        }
@@ -220,15 +199,15 @@ static int restore_sigregs_ext(struct pt_regs *regs,
        int i;
 
        /* Restore vector registers from signal stack */
-       if (current->thread.vxrs) {
+       if (is_vx_task(current)) {
                if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
                                     sizeof(sregs_ext->vxrs_low)) ||
-                   __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
+                   __copy_from_user(current->thread.fpu.vxrs + __NUM_VXRS_LOW,
                                     &sregs_ext->vxrs_high,
                                     sizeof(sregs_ext->vxrs_high)))
                        return -EFAULT;
                for (i = 0; i < __NUM_VXRS_LOW; i++)
-                       *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
+                       *((__u64 *)(current->thread.fpu.vxrs + i) + 1) = vxrs[i];
        }
        return 0;
 }
@@ -243,6 +222,7 @@ SYSCALL_DEFINE0(sigreturn)
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
                goto badframe;
        set_current_blocked(&set);
+       save_fpu_regs();
        if (restore_sigregs(regs, &frame->sregs))
                goto badframe;
        if (restore_sigregs_ext(regs, &frame->sregs_ext))
@@ -266,6 +246,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
        set_current_blocked(&set);
        if (restore_altstack(&frame->uc.uc_stack))
                goto badframe;
+       save_fpu_regs();
        if (restore_sigregs(regs, &frame->uc.uc_mcontext))
                goto badframe;
        if (restore_sigregs_ext(regs, &frame->uc.uc_mcontext_ext))
@@ -400,7 +381,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        uc_flags = 0;
        if (MACHINE_HAS_VX) {
                frame_size += sizeof(_sigregs_ext);
-               if (current->thread.vxrs)
+               if (is_vx_task(current))
                        uc_flags |= UC_VXRS;
        }
        frame = get_sigframe(&ksig->ka, regs, frame_size);
index 6f54c175f5c9012b5cc00f28d3d793c2bfc56ec5..c6355e6f3fcc990c98bdd4f80dfd1a8ac78a0e0b 100644 (file)
@@ -532,8 +532,8 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
 
 #ifdef CONFIG_CRASH_DUMP
 
-static void __smp_store_cpu_state(struct save_area_ext *sa_ext, u16 address,
-                                 int is_boot_cpu)
+static void __init __smp_store_cpu_state(struct save_area_ext *sa_ext,
+                                        u16 address, int is_boot_cpu)
 {
        void *lc = (void *)(unsigned long) store_prefix();
        unsigned long vx_sa;
index 1acad02681c49496a117559145877a2b362c959c..f3f4a137aef6e9bc1d4e23049cc6592aef86bf29 100644 (file)
@@ -276,9 +276,9 @@ SYSCALL(sys_ni_syscall,compat_sys_s390_fadvise64_64)
 SYSCALL(sys_statfs64,compat_sys_statfs64)
 SYSCALL(sys_fstatfs64,compat_sys_fstatfs64)
 SYSCALL(sys_remap_file_pages,compat_sys_remap_file_pages)
-NI_SYSCALL                                             /* 268 sys_mbind */
-NI_SYSCALL                                             /* 269 sys_get_mempolicy */
-NI_SYSCALL                                             /* 270 sys_set_mempolicy */
+SYSCALL(sys_mbind,compat_sys_mbind)
+SYSCALL(sys_get_mempolicy,compat_sys_get_mempolicy)
+SYSCALL(sys_set_mempolicy,compat_sys_set_mempolicy)
 SYSCALL(sys_mq_open,compat_sys_mq_open)
 SYSCALL(sys_mq_unlink,compat_sys_mq_unlink)
 SYSCALL(sys_mq_timedsend,compat_sys_mq_timedsend)
@@ -295,7 +295,7 @@ SYSCALL(sys_ioprio_get,compat_sys_ioprio_get)
 SYSCALL(sys_inotify_init,sys_inotify_init)
 SYSCALL(sys_inotify_add_watch,compat_sys_inotify_add_watch)    /* 285 */
 SYSCALL(sys_inotify_rm_watch,compat_sys_inotify_rm_watch)
-NI_SYSCALL                                             /* 287 sys_migrate_pages */
+SYSCALL(sys_migrate_pages,compat_sys_migrate_pages)
 SYSCALL(sys_openat,compat_sys_openat)
 SYSCALL(sys_mkdirat,compat_sys_mkdirat)
 SYSCALL(sys_mknodat,compat_sys_mknodat)                        /* 290 */
@@ -318,7 +318,7 @@ SYSCALL(sys_splice,compat_sys_splice)
 SYSCALL(sys_sync_file_range,compat_sys_s390_sync_file_range)
 SYSCALL(sys_tee,compat_sys_tee)
 SYSCALL(sys_vmsplice,compat_sys_vmsplice)
-NI_SYSCALL                                             /* 310 sys_move_pages */
+SYSCALL(sys_move_pages,compat_sys_move_pages)
 SYSCALL(sys_getcpu,compat_sys_getcpu)
 SYSCALL(sys_epoll_pwait,compat_sys_epoll_pwait)
 SYSCALL(sys_utimes,compat_sys_utimes)
index 9e733d965e08886611ef40535f09505c5b7b9878..627887b075a7c757bcaf4e9b20a6ce10e9152867 100644 (file)
@@ -58,6 +58,9 @@ EXPORT_SYMBOL_GPL(sched_clock_base_cc);
 
 static DEFINE_PER_CPU(struct clock_event_device, comparators);
 
+ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
+EXPORT_SYMBOL(s390_epoch_delta_notifier);
+
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
@@ -752,7 +755,7 @@ static void clock_sync_cpu(struct clock_sync_data *sync)
 static int etr_sync_clock(void *data)
 {
        static int first;
-       unsigned long long clock, old_clock, delay, delta;
+       unsigned long long clock, old_clock, clock_delta, delay, delta;
        struct clock_sync_data *etr_sync;
        struct etr_aib *sync_port, *aib;
        int port;
@@ -789,6 +792,9 @@ static int etr_sync_clock(void *data)
                delay = (unsigned long long)
                        (aib->edf2.etv - sync_port->edf2.etv) << 32;
                delta = adjust_time(old_clock, clock, delay);
+               clock_delta = clock - old_clock;
+               atomic_notifier_call_chain(&s390_epoch_delta_notifier, 0,
+                                          &clock_delta);
                etr_sync->fixup_cc = delta;
                fixup_clock_comparator(delta);
                /* Verify that the clock is properly set. */
@@ -1526,7 +1532,7 @@ void stp_island_check(void)
 static int stp_sync_clock(void *data)
 {
        static int first;
-       unsigned long long old_clock, delta;
+       unsigned long long old_clock, delta, new_clock, clock_delta;
        struct clock_sync_data *stp_sync;
        int rc;
 
@@ -1551,7 +1557,11 @@ static int stp_sync_clock(void *data)
                old_clock = get_tod_clock();
                rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0);
                if (rc == 0) {
-                       delta = adjust_time(old_clock, get_tod_clock(), 0);
+                       new_clock = get_tod_clock();
+                       delta = adjust_time(old_clock, new_clock, 0);
+                       clock_delta = new_clock - old_clock;
+                       atomic_notifier_call_chain(&s390_epoch_delta_notifier,
+                                                  0, &clock_delta);
                        fixup_clock_comparator(delta);
                        rc = chsc_sstpi(stp_page, &stp_info,
                                        sizeof(struct stp_sstpi));
index 5728c5bd44a8241b0d2fd3c79c770154194501ba..bf05e7fc3e70807c3f17eca0907c64e304f63328 100644 (file)
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
+#include <linux/nodemask.h>
+#include <linux/node.h>
 #include <asm/sysinfo.h>
+#include <asm/numa.h>
 
 #define PTF_HORIZONTAL (0UL)
 #define PTF_VERTICAL   (1UL)
@@ -37,8 +40,10 @@ static struct sysinfo_15_1_x *tl_info;
 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);
+/*
+ * Socket/Book linked lists and per_cpu(cpu_topology) updates are
+ * protected by "sched_domains_mutex".
+ */
 static struct mask_info socket_info;
 static struct mask_info book_info;
 
@@ -188,7 +193,6 @@ static void tl_to_masks(struct sysinfo_15_1_x *info)
 {
        struct cpuid cpu_id;
 
-       spin_lock_irq(&topology_lock);
        get_cpu_id(&cpu_id);
        clear_masks();
        switch (cpu_id.machine) {
@@ -199,7 +203,6 @@ static void tl_to_masks(struct sysinfo_15_1_x *info)
        default:
                __tl_to_masks_generic(info);
        }
-       spin_unlock_irq(&topology_lock);
 }
 
 static void topology_update_polarization_simple(void)
@@ -244,10 +247,8 @@ int topology_set_cpu_management(int fc)
 
 static void update_cpu_masks(void)
 {
-       unsigned long flags;
        int cpu;
 
-       spin_lock_irqsave(&topology_lock, flags);
        for_each_possible_cpu(cpu) {
                per_cpu(cpu_topology, cpu).thread_mask = cpu_thread_map(cpu);
                per_cpu(cpu_topology, cpu).core_mask = cpu_group_map(&socket_info, cpu);
@@ -259,7 +260,7 @@ static void update_cpu_masks(void)
                        per_cpu(cpu_topology, cpu).book_id = cpu;
                }
        }
-       spin_unlock_irqrestore(&topology_lock, flags);
+       numa_update_cpu_topology();
 }
 
 void store_topology(struct sysinfo_15_1_x *info)
@@ -274,21 +275,21 @@ int arch_update_cpu_topology(void)
 {
        struct sysinfo_15_1_x *info = tl_info;
        struct device *dev;
-       int cpu;
+       int cpu, rc = 0;
 
-       if (!MACHINE_HAS_TOPOLOGY) {
-               update_cpu_masks();
-               topology_update_polarization_simple();
-               return 0;
+       if (MACHINE_HAS_TOPOLOGY) {
+               rc = 1;
+               store_topology(info);
+               tl_to_masks(info);
        }
-       store_topology(info);
-       tl_to_masks(info);
        update_cpu_masks();
+       if (!MACHINE_HAS_TOPOLOGY)
+               topology_update_polarization_simple();
        for_each_online_cpu(cpu) {
                dev = get_cpu_device(cpu);
                kobject_uevent(&dev->kobj, KOBJ_CHANGE);
        }
-       return 1;
+       return rc;
 }
 
 static void topology_work_fn(struct work_struct *work)
index 7bea81d8a3635025b0f372c3f908ade71b188e1b..9861613fb35a7a0c1ef947451f37871937d9c5bd 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <asm/switch_to.h>
+#include <asm/fpu-internal.h>
 #include "entry.h"
 
 int show_unhandled_signals = 1;
@@ -151,7 +151,7 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
 DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN,
              "transaction constraint exception")
 
-static inline void do_fp_trap(struct pt_regs *regs, int fpc)
+static inline void do_fp_trap(struct pt_regs *regs, __u32 fpc)
 {
        int si_code = 0;
        /* FPC[2] is Data Exception Code */
@@ -227,7 +227,7 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
 int alloc_vector_registers(struct task_struct *tsk)
 {
        __vector128 *vxrs;
-       int i;
+       freg_t *fprs;
 
        /* Allocate vector register save area. */
        vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS,
@@ -236,15 +236,13 @@ int alloc_vector_registers(struct task_struct *tsk)
                return -ENOMEM;
        preempt_disable();
        if (tsk == current)
-               save_fp_regs(tsk->thread.fp_regs.fprs);
+               save_fpu_regs();
        /* Copy the 16 floating point registers */
-       for (i = 0; i < 16; i++)
-               *(freg_t *) &vxrs[i] = tsk->thread.fp_regs.fprs[i];
-       tsk->thread.vxrs = vxrs;
-       if (tsk == current) {
-               __ctl_set_bit(0, 17);
-               restore_vx_regs(vxrs);
-       }
+       convert_fp_to_vx(vxrs, tsk->thread.fpu.fprs);
+       fprs = tsk->thread.fpu.fprs;
+       tsk->thread.fpu.vxrs = vxrs;
+       tsk->thread.fpu.flags |= FPU_USE_VX;
+       kfree(fprs);
        preempt_enable();
        return 0;
 }
@@ -259,8 +257,8 @@ void vector_exception(struct pt_regs *regs)
        }
 
        /* get vector interrupt code from fpc */
-       asm volatile("stfpc %0" : "=Q" (current->thread.fp_regs.fpc));
-       vic = (current->thread.fp_regs.fpc & 0xf00) >> 8;
+       save_fpu_regs();
+       vic = (current->thread.fpu.fpc & 0xf00) >> 8;
        switch (vic) {
        case 1: /* invalid vector operation */
                si_code = FPE_FLTINV;
@@ -297,22 +295,22 @@ void data_exception(struct pt_regs *regs)
 
        location = get_trap_ip(regs);
 
-       asm volatile("stfpc %0" : "=Q" (current->thread.fp_regs.fpc));
+       save_fpu_regs();
        /* Check for vector register enablement */
-       if (MACHINE_HAS_VX && !current->thread.vxrs &&
-           (current->thread.fp_regs.fpc & FPC_DXC_MASK) == 0xfe00) {
+       if (MACHINE_HAS_VX && !is_vx_task(current) &&
+           (current->thread.fpu.fpc & FPC_DXC_MASK) == 0xfe00) {
                alloc_vector_registers(current);
                /* Vector data exception is suppressing, rewind psw. */
                regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
                clear_pt_regs_flag(regs, PIF_PER_TRAP);
                return;
        }
-       if (current->thread.fp_regs.fpc & FPC_DXC_MASK)
+       if (current->thread.fpu.fpc & FPC_DXC_MASK)
                signal = SIGFPE;
        else
                signal = SIGILL;
        if (signal == SIGFPE)
-               do_fp_trap(regs, current->thread.fp_regs.fpc);
+               do_fp_trap(regs, current->thread.fpu.fpc);
        else if (signal)
                do_trap(regs, signal, ILL_ILLOPN, "data exception");
 }
index 8ad2b34ad151324346a07fdefa5e3682c5a33e35..ee8a18e50a250d783f8e3ec70b11df49bc10b6b6 100644 (file)
@@ -13,7 +13,7 @@ KBUILD_AFLAGS_31 += -m31 -s
 KBUILD_CFLAGS_31 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_31 += -m31 -fPIC -shared -fno-common -fno-builtin
 KBUILD_CFLAGS_31 += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
-                       $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+                       $(call cc-ldoption, -Wl$(comma)--hash-style=both)
 
 $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_31)
 $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_31)
index 2a8ddfd12a5b97c6273b171f55da81b1fbdee940..c4b03f9ed22828731022fa479296ad4ebd281079 100644 (file)
@@ -13,7 +13,7 @@ KBUILD_AFLAGS_64 += -m64 -s
 KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin
 KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
-                       $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+                       $(call cc-ldoption, -Wl$(comma)--hash-style=both)
 
 $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
 $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64)
index e53d3595a7c8c1a54400d5fb3e984004cd864219..b9ce650e9e992065aa611f5bc654f59b5b8bf40f 100644 (file)
@@ -28,6 +28,7 @@ static atomic64_t virt_timer_elapsed;
 static DEFINE_PER_CPU(u64, mt_cycles[32]);
 static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 };
 static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 };
+static DEFINE_PER_CPU(u64, mt_scaling_jiffies);
 
 static inline u64 get_vtimer(void)
 {
@@ -85,7 +86,8 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
        S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
 
        /* Do MT utilization calculation */
-       if (smp_cpu_mtid) {
+       if (smp_cpu_mtid &&
+           time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies))) {
                u64 cycles_new[32], *cycles_old;
                u64 delta, mult, div;
 
@@ -105,6 +107,7 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
                                       sizeof(u64) * (smp_cpu_mtid + 1));
                        }
                }
+               __this_cpu_write(mt_scaling_jiffies, jiffies_64);
        }
 
        user = S390_lowcore.user_timer - ti->user_timer;
@@ -376,4 +379,11 @@ void vtime_init(void)
 {
        /* set initial cpu timer */
        set_vtimer(VTIMER_MAX_SLICE);
+       /* Setup initial MT scaling values */
+       if (smp_cpu_mtid) {
+               __this_cpu_write(mt_scaling_jiffies, jiffies);
+               __this_cpu_write(mt_scaling_mult, 1);
+               __this_cpu_write(mt_scaling_div, 1);
+               stcctm5(smp_cpu_mtid + 1, this_cpu_ptr(mt_cycles));
+       }
 }
index fc7ec95848c39c527c2a24ee723c9f45624e31a0..5fbfb88f847731db6ef4cb1ab87b32cf601703df 100644 (file)
@@ -27,13 +27,13 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)
 
        start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
        end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+       vcpu->stat.diagnose_10++;
 
        if (start & ~PAGE_MASK || end & ~PAGE_MASK || start >= end
            || start < 2 * PAGE_SIZE)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
        VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);
-       vcpu->stat.diagnose_10++;
 
        /*
         * We checked for start >= end above, so lets check for the
@@ -75,6 +75,9 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu)
        u16 rx = (vcpu->arch.sie_block->ipa & 0xf0) >> 4;
        u16 ry = (vcpu->arch.sie_block->ipa & 0x0f);
 
+       VCPU_EVENT(vcpu, 3, "diag page reference parameter block at 0x%llx",
+                  vcpu->run->s.regs.gprs[rx]);
+       vcpu->stat.diagnose_258++;
        if (vcpu->run->s.regs.gprs[rx] & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
        rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm));
@@ -85,6 +88,9 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu)
 
        switch (parm.subcode) {
        case 0: /* TOKEN */
+               VCPU_EVENT(vcpu, 3, "pageref token addr 0x%llx "
+                          "select mask 0x%llx compare mask 0x%llx",
+                          parm.token_addr, parm.select_mask, parm.compare_mask);
                if (vcpu->arch.pfault_token != KVM_S390_PFAULT_TOKEN_INVALID) {
                        /*
                         * If the pagefault handshake is already activated,
@@ -114,6 +120,7 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu)
                 * the cancel, therefore to reduce code complexity, we assume
                 * all outstanding tokens are already pending.
                 */
+               VCPU_EVENT(vcpu, 3, "pageref cancel addr 0x%llx", parm.token_addr);
                if (parm.token_addr || parm.select_mask ||
                    parm.compare_mask || parm.zarch)
                        return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -174,7 +181,8 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
        unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
        unsigned long subcode = vcpu->run->s.regs.gprs[reg] & 0xffff;
 
-       VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
+       VCPU_EVENT(vcpu, 3, "diag ipl functions, subcode %lx", subcode);
+       vcpu->stat.diagnose_308++;
        switch (subcode) {
        case 3:
                vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
@@ -202,6 +210,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
 {
        int ret;
 
+       vcpu->stat.diagnose_500++;
        /* No virtio-ccw notification? Get out quickly. */
        if (!vcpu->kvm->arch.css_support ||
            (vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY))
index e97b3455d7e6bfbb7b12c606a5224c5efeba37d4..47518a324d752286d4b0cb80784c43c316f31c45 100644 (file)
@@ -473,10 +473,45 @@ static void filter_guest_per_event(struct kvm_vcpu *vcpu)
                vcpu->arch.sie_block->iprcc &= ~PGM_PER;
 }
 
+#define pssec(vcpu) (vcpu->arch.sie_block->gcr[1] & _ASCE_SPACE_SWITCH)
+#define hssec(vcpu) (vcpu->arch.sie_block->gcr[13] & _ASCE_SPACE_SWITCH)
+#define old_ssec(vcpu) ((vcpu->arch.sie_block->tecmc >> 31) & 0x1)
+#define old_as_is_home(vcpu) !(vcpu->arch.sie_block->tecmc & 0xffff)
+
 void kvm_s390_handle_per_event(struct kvm_vcpu *vcpu)
 {
+       int new_as;
+
        if (debug_exit_required(vcpu))
                vcpu->guest_debug |= KVM_GUESTDBG_EXIT_PENDING;
 
        filter_guest_per_event(vcpu);
+
+       /*
+        * Only RP, SAC, SACF, PT, PTI, PR, PC instructions can trigger
+        * a space-switch event. PER events enforce space-switch events
+        * for these instructions. So if no PER event for the guest is left,
+        * we might have to filter the space-switch element out, too.
+        */
+       if (vcpu->arch.sie_block->iprcc == PGM_SPACE_SWITCH) {
+               vcpu->arch.sie_block->iprcc = 0;
+               new_as = psw_bits(vcpu->arch.sie_block->gpsw).as;
+
+               /*
+                * If the AS changed from / to home, we had RP, SAC or SACF
+                * instruction. Check primary and home space-switch-event
+                * controls. (theoretically home -> home produced no event)
+                */
+               if (((new_as == PSW_AS_HOME) ^ old_as_is_home(vcpu)) &&
+                    (pssec(vcpu) || hssec(vcpu)))
+                       vcpu->arch.sie_block->iprcc = PGM_SPACE_SWITCH;
+
+               /*
+                * PT, PTI, PR, PC instruction operate on primary AS only. Check
+                * if the primary-space-switch-event control was or got set.
+                */
+               if (new_as == PSW_AS_PRIMARY && !old_as_is_home(vcpu) &&
+                   (pssec(vcpu) || old_ssec(vcpu)))
+                       vcpu->arch.sie_block->iprcc = PGM_SPACE_SWITCH;
+       }
 }
index c98d89708e99fb19ee2217c826f75f2bd0e3a41a..b277d50dcf76a409072832059438e2f10ca3bc63 100644 (file)
@@ -30,7 +30,6 @@
 #define IOINT_SCHID_MASK 0x0000ffff
 #define IOINT_SSID_MASK 0x00030000
 #define IOINT_CSSID_MASK 0x03fc0000
-#define IOINT_AI_MASK 0x04000000
 #define PFAULT_INIT 0x0600
 #define PFAULT_DONE 0x0680
 #define VIRTIO_PARAM 0x0d00
@@ -72,9 +71,13 @@ static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu)
 
 static int ckc_irq_pending(struct kvm_vcpu *vcpu)
 {
+       preempt_disable();
        if (!(vcpu->arch.sie_block->ckc <
-             get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
+             get_tod_clock_fast() + vcpu->arch.sie_block->epoch)) {
+               preempt_enable();
                return 0;
+       }
+       preempt_enable();
        return ckc_interrupts_enabled(vcpu);
 }
 
@@ -311,8 +314,8 @@ static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu)
        li->irq.ext.ext_params2 = 0;
        spin_unlock(&li->lock);
 
-       VCPU_EVENT(vcpu, 4, "interrupt: pfault init parm:%x,parm64:%llx",
-                  0, ext.ext_params2);
+       VCPU_EVENT(vcpu, 4, "deliver: pfault init token 0x%llx",
+                  ext.ext_params2);
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
                                         KVM_S390_INT_PFAULT_INIT,
                                         0, ext.ext_params2);
@@ -368,7 +371,7 @@ static int __must_check __deliver_machine_check(struct kvm_vcpu *vcpu)
        spin_unlock(&fi->lock);
 
        if (deliver) {
-               VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
+               VCPU_EVENT(vcpu, 3, "deliver: machine check mcic 0x%llx",
                           mchk.mcic);
                trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
                                                 KVM_S390_MCHK,
@@ -403,7 +406,7 @@ static int __must_check __deliver_restart(struct kvm_vcpu *vcpu)
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        int rc;
 
-       VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
+       VCPU_EVENT(vcpu, 3, "%s", "deliver: cpu restart");
        vcpu->stat.deliver_restart_signal++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0);
 
@@ -427,7 +430,6 @@ static int __must_check __deliver_set_prefix(struct kvm_vcpu *vcpu)
        clear_bit(IRQ_PEND_SET_PREFIX, &li->pending_irqs);
        spin_unlock(&li->lock);
 
-       VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", prefix.address);
        vcpu->stat.deliver_prefix_signal++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
                                         KVM_S390_SIGP_SET_PREFIX,
@@ -450,7 +452,7 @@ static int __must_check __deliver_emergency_signal(struct kvm_vcpu *vcpu)
                clear_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
        spin_unlock(&li->lock);
 
-       VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
+       VCPU_EVENT(vcpu, 4, "%s", "deliver: sigp emerg");
        vcpu->stat.deliver_emergency_signal++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
                                         cpu_addr, 0);
@@ -477,7 +479,7 @@ static int __must_check __deliver_external_call(struct kvm_vcpu *vcpu)
        clear_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs);
        spin_unlock(&li->lock);
 
-       VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
+       VCPU_EVENT(vcpu, 4, "%s", "deliver: sigp ext call");
        vcpu->stat.deliver_external_call++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
                                         KVM_S390_INT_EXTERNAL_CALL,
@@ -506,7 +508,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        memset(&li->irq.pgm, 0, sizeof(pgm_info));
        spin_unlock(&li->lock);
 
-       VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
+       VCPU_EVENT(vcpu, 3, "deliver: program irq code 0x%x, ilc:%d",
                   pgm_info.code, ilc);
        vcpu->stat.deliver_program_int++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
@@ -622,7 +624,7 @@ static int __must_check __deliver_service(struct kvm_vcpu *vcpu)
        clear_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
        spin_unlock(&fi->lock);
 
-       VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
+       VCPU_EVENT(vcpu, 4, "deliver: sclp parameter 0x%x",
                   ext.ext_params);
        vcpu->stat.deliver_service_signal++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_SERVICE,
@@ -651,9 +653,6 @@ static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu)
                                        struct kvm_s390_interrupt_info,
                                        list);
        if (inti) {
-               trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
-                               KVM_S390_INT_PFAULT_DONE, 0,
-                               inti->ext.ext_params2);
                list_del(&inti->list);
                fi->counters[FIRQ_CNTR_PFAULT] -= 1;
        }
@@ -662,6 +661,12 @@ static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu)
        spin_unlock(&fi->lock);
 
        if (inti) {
+               trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
+                                                KVM_S390_INT_PFAULT_DONE, 0,
+                                                inti->ext.ext_params2);
+               VCPU_EVENT(vcpu, 4, "deliver: pfault done token 0x%llx",
+                          inti->ext.ext_params2);
+
                rc  = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE,
                                (u16 *)__LC_EXT_INT_CODE);
                rc |= put_guest_lc(vcpu, PFAULT_DONE,
@@ -691,7 +696,7 @@ static int __must_check __deliver_virtio(struct kvm_vcpu *vcpu)
                                        list);
        if (inti) {
                VCPU_EVENT(vcpu, 4,
-                          "interrupt: virtio parm:%x,parm64:%llx",
+                          "deliver: virtio parm: 0x%x,parm64: 0x%llx",
                           inti->ext.ext_params, inti->ext.ext_params2);
                vcpu->stat.deliver_virtio_interrupt++;
                trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
@@ -741,7 +746,7 @@ static int __must_check __deliver_io(struct kvm_vcpu *vcpu,
                                        struct kvm_s390_interrupt_info,
                                        list);
        if (inti) {
-               VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
+               VCPU_EVENT(vcpu, 4, "deliver: I/O 0x%llx", inti->type);
                vcpu->stat.deliver_io_int++;
                trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
                                inti->type,
@@ -855,7 +860,9 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
                goto no_timer;
        }
 
+       preempt_disable();
        now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
+       preempt_enable();
        sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
 
        /* underflow */
@@ -864,7 +871,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
 
        __set_cpu_idle(vcpu);
        hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
-       VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
+       VCPU_EVENT(vcpu, 4, "enabled wait via clock comparator: %llu ns", sltime);
 no_timer:
        srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
        kvm_vcpu_block(vcpu);
@@ -894,7 +901,9 @@ enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
        u64 now, sltime;
 
        vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
+       preempt_disable();
        now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
+       preempt_enable();
        sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
 
        /*
@@ -968,6 +977,10 @@ static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 
+       VCPU_EVENT(vcpu, 3, "inject: program irq code 0x%x", irq->u.pgm.code);
+       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
+                                  irq->u.pgm.code, 0);
+
        li->irq.pgm = irq->u.pgm;
        set_bit(IRQ_PEND_PROG, &li->pending_irqs);
        return 0;
@@ -978,9 +991,6 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        struct kvm_s390_irq irq;
 
-       VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
-       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, code,
-                                  0, 1);
        spin_lock(&li->lock);
        irq.u.pgm.code = code;
        __inject_prog(vcpu, &irq);
@@ -996,10 +1006,6 @@ int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu,
        struct kvm_s390_irq irq;
        int rc;
 
-       VCPU_EVENT(vcpu, 3, "inject: prog irq %d (from kernel)",
-                  pgm_info->code);
-       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
-                                  pgm_info->code, 0, 1);
        spin_lock(&li->lock);
        irq.u.pgm = *pgm_info;
        rc = __inject_prog(vcpu, &irq);
@@ -1012,11 +1018,11 @@ static int __inject_pfault_init(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 
-       VCPU_EVENT(vcpu, 3, "inject: external irq params:%x, params2:%llx",
-                  irq->u.ext.ext_params, irq->u.ext.ext_params2);
+       VCPU_EVENT(vcpu, 4, "inject: pfault init parameter block at 0x%llx",
+                  irq->u.ext.ext_params2);
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_PFAULT_INIT,
                                   irq->u.ext.ext_params,
-                                  irq->u.ext.ext_params2, 2);
+                                  irq->u.ext.ext_params2);
 
        li->irq.ext = irq->u.ext;
        set_bit(IRQ_PEND_PFAULT_INIT, &li->pending_irqs);
@@ -1045,10 +1051,10 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        struct kvm_s390_extcall_info *extcall = &li->irq.extcall;
        uint16_t src_id = irq->u.extcall.code;
 
-       VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
+       VCPU_EVENT(vcpu, 4, "inject: external call source-cpu:%u",
                   src_id);
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EXTERNAL_CALL,
-                                  src_id, 0, 2);
+                                  src_id, 0);
 
        /* sending vcpu invalid */
        if (src_id >= KVM_MAX_VCPUS ||
@@ -1070,10 +1076,10 @@ static int __inject_set_prefix(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        struct kvm_s390_prefix_info *prefix = &li->irq.prefix;
 
-       VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)",
+       VCPU_EVENT(vcpu, 3, "inject: set prefix to %x",
                   irq->u.prefix.address);
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_SET_PREFIX,
-                                  irq->u.prefix.address, 0, 2);
+                                  irq->u.prefix.address, 0);
 
        if (!is_vcpu_stopped(vcpu))
                return -EBUSY;
@@ -1090,7 +1096,7 @@ static int __inject_sigp_stop(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        struct kvm_s390_stop_info *stop = &li->irq.stop;
        int rc = 0;
 
-       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0, 2);
+       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0);
 
        if (irq->u.stop.flags & ~KVM_S390_STOP_SUPP_FLAGS)
                return -EINVAL;
@@ -1114,8 +1120,8 @@ static int __inject_sigp_restart(struct kvm_vcpu *vcpu,
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 
-       VCPU_EVENT(vcpu, 3, "inject: restart type %llx", irq->type);
-       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0, 2);
+       VCPU_EVENT(vcpu, 3, "%s", "inject: restart int");
+       trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0);
 
        set_bit(IRQ_PEND_RESTART, &li->pending_irqs);
        return 0;
@@ -1126,10 +1132,10 @@ static int __inject_sigp_emergency(struct kvm_vcpu *vcpu,
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 
-       VCPU_EVENT(vcpu, 3, "inject: emergency %u\n",
+       VCPU_EVENT(vcpu, 4, "inject: emergency from cpu %u",
                   irq->u.emerg.code);
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
-                                  irq->u.emerg.code, 0, 2);
+                                  irq->u.emerg.code, 0);
 
        set_bit(irq->u.emerg.code, li->sigp_emerg_pending);
        set_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
@@ -1142,10 +1148,10 @@ static int __inject_mchk(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        struct kvm_s390_mchk_info *mchk = &li->irq.mchk;
 
-       VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx",
+       VCPU_EVENT(vcpu, 3, "inject: machine check mcic 0x%llx",
                   irq->u.mchk.mcic);
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_MCHK, 0,
-                                  irq->u.mchk.mcic, 2);
+                                  irq->u.mchk.mcic);
 
        /*
         * Because repressible machine checks can be indicated along with
@@ -1172,9 +1178,9 @@ static int __inject_ckc(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 
-       VCPU_EVENT(vcpu, 3, "inject: type %x", KVM_S390_INT_CLOCK_COMP);
+       VCPU_EVENT(vcpu, 3, "%s", "inject: clock comparator external");
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP,
-                                  0, 0, 2);
+                                  0, 0);
 
        set_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs);
        atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
@@ -1185,9 +1191,9 @@ static int __inject_cpu_timer(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
 
-       VCPU_EVENT(vcpu, 3, "inject: type %x", KVM_S390_INT_CPU_TIMER);
+       VCPU_EVENT(vcpu, 3, "%s", "inject: cpu timer external");
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER,
-                                  0, 0, 2);
+                                  0, 0);
 
        set_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs);
        atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
@@ -1435,20 +1441,20 @@ int kvm_s390_inject_vm(struct kvm *kvm,
                inti->ext.ext_params2 = s390int->parm64;
                break;
        case KVM_S390_INT_SERVICE:
-               VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
+               VM_EVENT(kvm, 4, "inject: sclp parm:%x", s390int->parm);
                inti->ext.ext_params = s390int->parm;
                break;
        case KVM_S390_INT_PFAULT_DONE:
                inti->ext.ext_params2 = s390int->parm64;
                break;
        case KVM_S390_MCHK:
-               VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
+               VM_EVENT(kvm, 3, "inject: machine check mcic 0x%llx",
                         s390int->parm64);
                inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
                inti->mchk.mcic = s390int->parm64;
                break;
        case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
-               if (inti->type & IOINT_AI_MASK)
+               if (inti->type & KVM_S390_INT_IO_AI_MASK)
                        VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
                else
                        VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
@@ -1535,8 +1541,6 @@ static int do_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
 
        switch (irq->type) {
        case KVM_S390_PROGRAM_INT:
-               VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
-                          irq->u.pgm.code);
                rc = __inject_prog(vcpu, irq);
                break;
        case KVM_S390_SIGP_SET_PREFIX:
index f32f843a3631359e49b88169ab8a1eed2b76b946..98df53c013439836773e39f21396157eca28bdca 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/vmalloc.h>
 #include <asm/asm-offsets.h>
 #include <asm/lowcore.h>
+#include <asm/etr.h>
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
 #include <asm/switch_to.h>
@@ -108,6 +109,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "diagnose_10", VCPU_STAT(diagnose_10) },
        { "diagnose_44", VCPU_STAT(diagnose_44) },
        { "diagnose_9c", VCPU_STAT(diagnose_9c) },
+       { "diagnose_258", VCPU_STAT(diagnose_258) },
+       { "diagnose_308", VCPU_STAT(diagnose_308) },
+       { "diagnose_500", VCPU_STAT(diagnose_500) },
        { NULL }
 };
 
@@ -124,6 +128,7 @@ unsigned long kvm_s390_fac_list_mask_size(void)
 }
 
 static struct gmap_notifier gmap_notifier;
+debug_info_t *kvm_s390_dbf;
 
 /* Section: not file related */
 int kvm_arch_hardware_enable(void)
@@ -134,24 +139,69 @@ int kvm_arch_hardware_enable(void)
 
 static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address);
 
+/*
+ * This callback is executed during stop_machine(). All CPUs are therefore
+ * temporarily stopped. In order not to change guest behavior, we have to
+ * disable preemption whenever we touch the epoch of kvm and the VCPUs,
+ * so a CPU won't be stopped while calculating with the epoch.
+ */
+static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
+                         void *v)
+{
+       struct kvm *kvm;
+       struct kvm_vcpu *vcpu;
+       int i;
+       unsigned long long *delta = v;
+
+       list_for_each_entry(kvm, &vm_list, vm_list) {
+               kvm->arch.epoch -= *delta;
+               kvm_for_each_vcpu(i, vcpu, kvm) {
+                       vcpu->arch.sie_block->epoch -= *delta;
+               }
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_clock_notifier = {
+       .notifier_call = kvm_clock_sync,
+};
+
 int kvm_arch_hardware_setup(void)
 {
        gmap_notifier.notifier_call = kvm_gmap_notifier;
        gmap_register_ipte_notifier(&gmap_notifier);
+       atomic_notifier_chain_register(&s390_epoch_delta_notifier,
+                                      &kvm_clock_notifier);
        return 0;
 }
 
 void kvm_arch_hardware_unsetup(void)
 {
        gmap_unregister_ipte_notifier(&gmap_notifier);
+       atomic_notifier_chain_unregister(&s390_epoch_delta_notifier,
+                                        &kvm_clock_notifier);
 }
 
 int kvm_arch_init(void *opaque)
 {
+       kvm_s390_dbf = debug_register("kvm-trace", 32, 1, 7 * sizeof(long));
+       if (!kvm_s390_dbf)
+               return -ENOMEM;
+
+       if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view)) {
+               debug_unregister(kvm_s390_dbf);
+               return -ENOMEM;
+       }
+
        /* Register floating interrupt controller interface. */
        return kvm_register_device_ops(&kvm_flic_ops, KVM_DEV_TYPE_FLIC);
 }
 
+void kvm_arch_exit(void)
+{
+       debug_unregister(kvm_s390_dbf);
+}
+
 /* Section: device related */
 long kvm_arch_dev_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg)
@@ -281,10 +331,12 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
 
        switch (cap->cap) {
        case KVM_CAP_S390_IRQCHIP:
+               VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_IRQCHIP");
                kvm->arch.use_irqchip = 1;
                r = 0;
                break;
        case KVM_CAP_S390_USER_SIGP:
+               VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_SIGP");
                kvm->arch.user_sigp = 1;
                r = 0;
                break;
@@ -295,8 +347,11 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
                        r = 0;
                } else
                        r = -EINVAL;
+               VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s",
+                        r ? "(not available)" : "(success)");
                break;
        case KVM_CAP_S390_USER_STSI:
+               VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_STSI");
                kvm->arch.user_stsi = 1;
                r = 0;
                break;
@@ -314,6 +369,8 @@ static int kvm_s390_get_mem_control(struct kvm *kvm, struct kvm_device_attr *att
        switch (attr->attr) {
        case KVM_S390_VM_MEM_LIMIT_SIZE:
                ret = 0;
+               VM_EVENT(kvm, 3, "QUERY: max guest memory: %lu bytes",
+                        kvm->arch.gmap->asce_end);
                if (put_user(kvm->arch.gmap->asce_end, (u64 __user *)attr->addr))
                        ret = -EFAULT;
                break;
@@ -330,7 +387,13 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
        unsigned int idx;
        switch (attr->attr) {
        case KVM_S390_VM_MEM_ENABLE_CMMA:
+               /* enable CMMA only for z10 and later (EDAT_1) */
+               ret = -EINVAL;
+               if (!MACHINE_IS_LPAR || !MACHINE_HAS_EDAT1)
+                       break;
+
                ret = -EBUSY;
+               VM_EVENT(kvm, 3, "%s", "ENABLE: CMMA support");
                mutex_lock(&kvm->lock);
                if (atomic_read(&kvm->online_vcpus) == 0) {
                        kvm->arch.use_cmma = 1;
@@ -339,6 +402,11 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
                mutex_unlock(&kvm->lock);
                break;
        case KVM_S390_VM_MEM_CLR_CMMA:
+               ret = -EINVAL;
+               if (!kvm->arch.use_cmma)
+                       break;
+
+               VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
                mutex_lock(&kvm->lock);
                idx = srcu_read_lock(&kvm->srcu);
                s390_reset_cmma(kvm->arch.gmap->mm);
@@ -374,6 +442,7 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
                        }
                }
                mutex_unlock(&kvm->lock);
+               VM_EVENT(kvm, 3, "SET: max guest memory: %lu bytes", new_limit);
                break;
        }
        default:
@@ -400,22 +469,26 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
                        kvm->arch.crypto.crycb->aes_wrapping_key_mask,
                        sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
                kvm->arch.crypto.aes_kw = 1;
+               VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support");
                break;
        case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
                get_random_bytes(
                        kvm->arch.crypto.crycb->dea_wrapping_key_mask,
                        sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
                kvm->arch.crypto.dea_kw = 1;
+               VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support");
                break;
        case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
                kvm->arch.crypto.aes_kw = 0;
                memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0,
                        sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
+               VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support");
                break;
        case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
                kvm->arch.crypto.dea_kw = 0;
                memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0,
                        sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
+               VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support");
                break;
        default:
                mutex_unlock(&kvm->lock);
@@ -440,6 +513,7 @@ static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
 
        if (gtod_high != 0)
                return -EINVAL;
+       VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x\n", gtod_high);
 
        return 0;
 }
@@ -459,12 +533,15 @@ static int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
                return r;
 
        mutex_lock(&kvm->lock);
+       preempt_disable();
        kvm->arch.epoch = gtod - host_tod;
        kvm_s390_vcpu_block_all(kvm);
        kvm_for_each_vcpu(vcpu_idx, cur_vcpu, kvm)
                cur_vcpu->arch.sie_block->epoch = kvm->arch.epoch;
        kvm_s390_vcpu_unblock_all(kvm);
+       preempt_enable();
        mutex_unlock(&kvm->lock);
+       VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx\n", gtod);
        return 0;
 }
 
@@ -496,6 +573,7 @@ static int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
        if (copy_to_user((void __user *)attr->addr, &gtod_high,
                                         sizeof(gtod_high)))
                return -EFAULT;
+       VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x\n", gtod_high);
 
        return 0;
 }
@@ -509,9 +587,12 @@ static int kvm_s390_get_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
        if (r)
                return r;
 
+       preempt_disable();
        gtod = host_tod + kvm->arch.epoch;
+       preempt_enable();
        if (copy_to_user((void __user *)attr->addr, &gtod, sizeof(gtod)))
                return -EFAULT;
+       VM_EVENT(kvm, 3, "QUERY: TOD base: 0x%llx\n", gtod);
 
        return 0;
 }
@@ -821,7 +902,9 @@ static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
        }
 
        /* Enable storage key handling for the guest */
-       s390_enable_skey();
+       r = s390_enable_skey();
+       if (r)
+               goto out;
 
        for (i = 0; i < args->count; i++) {
                hva = gfn_to_hva(kvm, args->start_gfn + i);
@@ -879,8 +962,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
                if (kvm->arch.use_irqchip) {
                        /* Set up dummy routing. */
                        memset(&routing, 0, sizeof(routing));
-                       kvm_set_irq_routing(kvm, &routing, 0, 0);
-                       r = 0;
+                       r = kvm_set_irq_routing(kvm, &routing, 0, 0);
                }
                break;
        }
@@ -1043,7 +1125,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
        sprintf(debug_name, "kvm-%u", current->pid);
 
-       kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
+       kvm->arch.dbf = debug_register(debug_name, 32, 1, 7 * sizeof(long));
        if (!kvm->arch.dbf)
                goto out_err;
 
@@ -1086,7 +1168,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        mutex_init(&kvm->arch.ipte_mutex);
 
        debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
-       VM_EVENT(kvm, 3, "%s", "vm created");
+       VM_EVENT(kvm, 3, "vm created with type %lu", type);
 
        if (type & KVM_VM_S390_UCONTROL) {
                kvm->arch.gmap = NULL;
@@ -1103,6 +1185,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        kvm->arch.epoch = 0;
 
        spin_lock_init(&kvm->arch.start_stop_lock);
+       KVM_EVENT(3, "vm 0x%p created by pid %u", kvm, current->pid);
 
        return 0;
 out_err:
@@ -1110,6 +1193,7 @@ out_err:
        free_page((unsigned long)kvm->arch.model.fac);
        debug_unregister(kvm->arch.dbf);
        free_page((unsigned long)(kvm->arch.sca));
+       KVM_EVENT(3, "creation of vm failed: %d", rc);
        return rc;
 }
 
@@ -1131,7 +1215,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
        if (kvm_is_ucontrol(vcpu->kvm))
                gmap_free(vcpu->arch.gmap);
 
-       if (kvm_s390_cmma_enabled(vcpu->kvm))
+       if (vcpu->kvm->arch.use_cmma)
                kvm_s390_vcpu_unsetup_cmma(vcpu);
        free_page((unsigned long)(vcpu->arch.sie_block));
 
@@ -1166,6 +1250,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
                gmap_free(kvm->arch.gmap);
        kvm_s390_destroy_adapters(kvm);
        kvm_s390_clear_float_irqs(kvm);
+       KVM_EVENT(3, "vm 0x%p destroyed", kvm);
 }
 
 /* Section: vcpu related */
@@ -1198,21 +1283,54 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+/*
+ * Backs up the current FP/VX register save area on a particular
+ * destination.  Used to switch between different register save
+ * areas.
+ */
+static inline void save_fpu_to(struct fpu *dst)
+{
+       dst->fpc = current->thread.fpu.fpc;
+       dst->flags = current->thread.fpu.flags;
+       dst->regs = current->thread.fpu.regs;
+}
+
+/*
+ * Switches the FP/VX register save area from which to lazy
+ * restore register contents.
+ */
+static inline void load_fpu_from(struct fpu *from)
+{
+       current->thread.fpu.fpc = from->fpc;
+       current->thread.fpu.flags = from->flags;
+       current->thread.fpu.regs = from->regs;
+}
+
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
-       save_fp_ctl(&vcpu->arch.host_fpregs.fpc);
-       if (test_kvm_facility(vcpu->kvm, 129))
-               save_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs);
-       else
-               save_fp_regs(vcpu->arch.host_fpregs.fprs);
-       save_access_regs(vcpu->arch.host_acrs);
+       /* Save host register state */
+       save_fpu_regs();
+       save_fpu_to(&vcpu->arch.host_fpregs);
+
        if (test_kvm_facility(vcpu->kvm, 129)) {
-               restore_fp_ctl(&vcpu->run->s.regs.fpc);
-               restore_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
-       } else {
-               restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
-               restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
-       }
+               current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
+               current->thread.fpu.flags = FPU_USE_VX;
+               /*
+                * Use the register save area in the SIE-control block
+                * for register restore and save in kvm_arch_vcpu_put()
+                */
+               current->thread.fpu.vxrs =
+                       (__vector128 *)&vcpu->run->s.regs.vrs;
+               /* Always enable the vector extension for KVM */
+               __ctl_set_vx();
+       } else
+               load_fpu_from(&vcpu->arch.guest_fpregs);
+
+       if (test_fp_ctl(current->thread.fpu.fpc))
+               /* User space provided an invalid FPC, let's clear it */
+               current->thread.fpu.fpc = 0;
+
+       save_access_regs(vcpu->arch.host_acrs);
        restore_access_regs(vcpu->run->s.regs.acrs);
        gmap_enable(vcpu->arch.gmap);
        atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
@@ -1222,19 +1340,22 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
        atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
-       if (test_kvm_facility(vcpu->kvm, 129)) {
-               save_fp_ctl(&vcpu->run->s.regs.fpc);
-               save_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
-       } else {
-               save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
-               save_fp_regs(vcpu->arch.guest_fpregs.fprs);
-       }
-       save_access_regs(vcpu->run->s.regs.acrs);
-       restore_fp_ctl(&vcpu->arch.host_fpregs.fpc);
+
+       save_fpu_regs();
+
        if (test_kvm_facility(vcpu->kvm, 129))
-               restore_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs);
+               /*
+                * kvm_arch_vcpu_load() set up the register save area to
+                * the &vcpu->run->s.regs.vrs and, thus, the vector registers
+                * are already saved.  Only the floating-point control must be
+                * copied.
+                */
+               vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
        else
-               restore_fp_regs(vcpu->arch.host_fpregs.fprs);
+               save_fpu_to(&vcpu->arch.guest_fpregs);
+       load_fpu_from(&vcpu->arch.host_fpregs);
+
+       save_access_regs(vcpu->run->s.regs.acrs);
        restore_access_regs(vcpu->arch.host_acrs);
 }
 
@@ -1264,7 +1385,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 {
        mutex_lock(&vcpu->kvm->lock);
+       preempt_disable();
        vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
+       preempt_enable();
        mutex_unlock(&vcpu->kvm->lock);
        if (!kvm_is_ucontrol(vcpu->kvm))
                vcpu->arch.gmap = vcpu->kvm->arch.gmap;
@@ -1342,7 +1465,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        }
        vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
 
-       if (kvm_s390_cmma_enabled(vcpu->kvm)) {
+       if (vcpu->kvm->arch.use_cmma) {
                rc = kvm_s390_vcpu_setup_cmma(vcpu);
                if (rc)
                        return rc;
@@ -1377,7 +1500,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 
        vcpu->arch.sie_block = &sie_page->sie_block;
        vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
-       vcpu->arch.host_vregs = &sie_page->vregs;
 
        vcpu->arch.sie_block->icpua = id;
        if (!kvm_is_ucontrol(kvm)) {
@@ -1399,6 +1521,19 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
        vcpu->arch.local_int.wq = &vcpu->wq;
        vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
 
+       /*
+        * Allocate a save area for floating-point registers.  If the vector
+        * extension is available, register contents are saved in the SIE
+        * control block.  The allocated save area is still required in
+        * particular places, for example, in kvm_s390_vcpu_store_status().
+        */
+       vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
+                                              GFP_KERNEL);
+       if (!vcpu->arch.guest_fpregs.fprs) {
+               rc = -ENOMEM;
+               goto out_free_sie_block;
+       }
+
        rc = kvm_vcpu_init(vcpu, kvm, id);
        if (rc)
                goto out_free_sie_block;
@@ -1621,16 +1756,16 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
        if (test_fp_ctl(fpu->fpc))
                return -EINVAL;
-       memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
+       memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
        vcpu->arch.guest_fpregs.fpc = fpu->fpc;
-       restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
-       restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
+       save_fpu_regs();
+       load_fpu_from(&vcpu->arch.guest_fpregs);
        return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-       memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
+       memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
        fpu->fpc = vcpu->arch.guest_fpregs.fpc;
        return 0;
 }
@@ -1723,18 +1858,6 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
        return rc;
 }
 
-bool kvm_s390_cmma_enabled(struct kvm *kvm)
-{
-       if (!MACHINE_IS_LPAR)
-               return false;
-       /* only enable for z10 and later */
-       if (!MACHINE_HAS_EDAT1)
-               return false;
-       if (!kvm->arch.use_cmma)
-               return false;
-       return true;
-}
-
 static bool ibs_enabled(struct kvm_vcpu *vcpu)
 {
        return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_IBS;
@@ -2193,8 +2316,21 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
         * copying in vcpu load/put. Lets update our copies before we save
         * it into the save area
         */
-       save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
-       save_fp_regs(vcpu->arch.guest_fpregs.fprs);
+       save_fpu_regs();
+       if (test_kvm_facility(vcpu->kvm, 129)) {
+               /*
+                * If the vector extension is available, the vector registers
+                * which overlaps with floating-point registers are saved in
+                * the SIE-control block.  Hence, extract the floating-point
+                * registers and the FPC value and store them in the
+                * guest_fpregs structure.
+                */
+               WARN_ON(!is_vx_task(current));    /* XXX remove later */
+               vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc;
+               convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs,
+                                current->thread.fpu.vxrs);
+       } else
+               save_fpu_to(&vcpu->arch.guest_fpregs);
        save_access_regs(vcpu->run->s.regs.acrs);
 
        return kvm_s390_store_status_unloaded(vcpu, addr);
@@ -2221,10 +2357,13 @@ int kvm_s390_vcpu_store_adtl_status(struct kvm_vcpu *vcpu, unsigned long addr)
 
        /*
         * The guest VXRS are in the host VXRs due to the lazy
-        * copying in vcpu load/put. Let's update our copies before we save
-        * it into the save area.
+        * copying in vcpu load/put. We can simply call save_fpu_regs()
+        * to save the current register state because we are in the
+        * middle of a load/put cycle.
+        *
+        * Let's update our copies before we save it into the save area.
         */
-       save_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs);
+       save_fpu_regs();
 
        return kvm_s390_store_adtl_status_unloaded(vcpu, addr);
 }
@@ -2340,6 +2479,7 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        case KVM_CAP_S390_CSS_SUPPORT:
                if (!vcpu->kvm->arch.css_support) {
                        vcpu->kvm->arch.css_support = 1;
+                       VM_EVENT(vcpu->kvm, 3, "%s", "ENABLE: CSS support");
                        trace_kvm_s390_enable_css(vcpu->kvm);
                }
                r = 0;
index c5704786e4731d8099f04df7aa9dd7afd75e886c..c446aabf60d38890b3bcfb46e1eac6ce2f13361a 100644 (file)
@@ -27,6 +27,13 @@ typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
 #define TDB_FORMAT1            1
 #define IS_ITDB_VALID(vcpu)    ((*(char *)vcpu->arch.sie_block->itdba == TDB_FORMAT1))
 
+extern debug_info_t *kvm_s390_dbf;
+#define KVM_EVENT(d_loglevel, d_string, d_args...)\
+do { \
+       debug_sprintf_event(kvm_s390_dbf, d_loglevel, d_string "\n", \
+         d_args); \
+} while (0)
+
 #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
 do { \
        debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \
@@ -65,6 +72,8 @@ static inline u32 kvm_s390_get_prefix(struct kvm_vcpu *vcpu)
 
 static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
 {
+       VCPU_EVENT(vcpu, 3, "set prefix of cpu %03u to 0x%x", vcpu->vcpu_id,
+                  prefix);
        vcpu->arch.sie_block->prefix = prefix >> GUEST_PREFIX_SHIFT;
        kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
        kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
@@ -217,8 +226,6 @@ void exit_sie(struct kvm_vcpu *vcpu);
 void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu);
 int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
-/* is cmma enabled */
-bool kvm_s390_cmma_enabled(struct kvm *kvm);
 unsigned long kvm_s390_fac_list_mask_size(void);
 extern unsigned long kvm_s390_fac_list_mask[];
 
index ad42422457713721427a5f0e20f9887b8ed5e86e..4d21dc4d1a845ba38c86290594c07116b651d17c 100644 (file)
@@ -53,11 +53,14 @@ static int handle_set_clock(struct kvm_vcpu *vcpu)
                kvm_s390_set_psw_cc(vcpu, 3);
                return 0;
        }
+       VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", val);
        val = (val - hostclk) & ~0x3fUL;
 
        mutex_lock(&vcpu->kvm->lock);
+       preempt_disable();
        kvm_for_each_vcpu(i, cpup, vcpu->kvm)
                cpup->arch.sie_block->epoch = val;
+       preempt_enable();
        mutex_unlock(&vcpu->kvm->lock);
 
        kvm_s390_set_psw_cc(vcpu, 0);
@@ -98,8 +101,6 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
                return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 
        kvm_s390_set_prefix(vcpu, address);
-
-       VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
        trace_kvm_s390_handle_prefix(vcpu, 1, address);
        return 0;
 }
@@ -129,7 +130,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
-       VCPU_EVENT(vcpu, 5, "storing prefix to %x", address);
+       VCPU_EVENT(vcpu, 3, "STPX: storing prefix 0x%x into 0x%llx", address, operand2);
        trace_kvm_s390_handle_prefix(vcpu, 0, address);
        return 0;
 }
@@ -155,7 +156,7 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
-       VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", ga);
+       VCPU_EVENT(vcpu, 3, "STAP: storing cpu address (%u) to 0x%llx", vcpu_id, ga);
        trace_kvm_s390_handle_stap(vcpu, ga);
        return 0;
 }
@@ -167,6 +168,7 @@ static int __skey_check_enable(struct kvm_vcpu *vcpu)
                return rc;
 
        rc = s390_enable_skey();
+       VCPU_EVENT(vcpu, 3, "%s", "enabling storage keys for guest");
        trace_kvm_s390_skey_related_inst(vcpu);
        vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE);
        return rc;
@@ -370,7 +372,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
                            &fac, sizeof(fac));
        if (rc)
                return rc;
-       VCPU_EVENT(vcpu, 5, "store facility list value %x", fac);
+       VCPU_EVENT(vcpu, 3, "STFL: store facility list 0x%x", fac);
        trace_kvm_s390_handle_stfl(vcpu, fac);
        return 0;
 }
@@ -468,7 +470,7 @@ static int handle_stidp(struct kvm_vcpu *vcpu)
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
 
-       VCPU_EVENT(vcpu, 5, "%s", "store cpu id");
+       VCPU_EVENT(vcpu, 3, "STIDP: store cpu id 0x%llx", stidp_data);
        return 0;
 }
 
@@ -521,7 +523,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
        ar_t ar;
 
        vcpu->stat.instruction_stsi++;
-       VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);
+       VCPU_EVENT(vcpu, 3, "STSI: fc: %u sel1: %u sel2: %u", fc, sel1, sel2);
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
@@ -758,10 +760,10 @@ static int handle_essa(struct kvm_vcpu *vcpu)
        struct gmap *gmap;
        int i;
 
-       VCPU_EVENT(vcpu, 5, "cmma release %d pages", entries);
+       VCPU_EVENT(vcpu, 4, "ESSA: release %d pages", entries);
        gmap = vcpu->arch.gmap;
        vcpu->stat.instruction_essa++;
-       if (!kvm_s390_cmma_enabled(vcpu->kvm))
+       if (!vcpu->kvm->arch.use_cmma)
                return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
@@ -829,7 +831,7 @@ int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
        if (ga & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+       VCPU_EVENT(vcpu, 4, "LCTL: r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
        trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, ga);
 
        nr_regs = ((reg3 - reg1) & 0xf) + 1;
@@ -868,7 +870,7 @@ int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
        if (ga & 3)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       VCPU_EVENT(vcpu, 5, "stctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+       VCPU_EVENT(vcpu, 4, "STCTL r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
        trace_kvm_s390_handle_stctl(vcpu, 0, reg1, reg3, ga);
 
        reg = reg1;
@@ -902,7 +904,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
        if (ga & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+       VCPU_EVENT(vcpu, 4, "LCTLG: r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
        trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, ga);
 
        nr_regs = ((reg3 - reg1) & 0xf) + 1;
@@ -940,7 +942,7 @@ static int handle_stctg(struct kvm_vcpu *vcpu)
        if (ga & 7)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       VCPU_EVENT(vcpu, 5, "stctg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+       VCPU_EVENT(vcpu, 4, "STCTG r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
        trace_kvm_s390_handle_stctl(vcpu, 1, reg1, reg3, ga);
 
        reg = reg1;
index 72e58bd2bee78162e963dc2bd531e40e03e29d97..da690b69f9fe17a89c3f1dc3cd1b1119b832bd25 100644 (file)
@@ -205,9 +205,6 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu,
                *reg &= 0xffffffff00000000UL;
                *reg |= SIGP_STATUS_INCORRECT_STATE;
                return SIGP_CC_STATUS_STORED;
-       } else if (rc == 0) {
-               VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x",
-                          dst_vcpu->vcpu_id, irq.u.prefix.address);
        }
 
        return rc;
@@ -371,7 +368,8 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
        return rc;
 }
 
-static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code)
+static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code,
+                                          u16 cpu_addr)
 {
        if (!vcpu->kvm->arch.user_sigp)
                return 0;
@@ -414,9 +412,8 @@ static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code)
        default:
                vcpu->stat.instruction_sigp_unknown++;
        }
-
-       VCPU_EVENT(vcpu, 4, "sigp order %u: completely handled in user space",
-                  order_code);
+       VCPU_EVENT(vcpu, 3, "SIGP: order %u for CPU %d handled in userspace",
+                  order_code, cpu_addr);
 
        return 1;
 }
@@ -435,7 +432,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
        order_code = kvm_s390_get_base_disp_rs(vcpu, NULL);
-       if (handle_sigp_order_in_user_space(vcpu, order_code))
+       if (handle_sigp_order_in_user_space(vcpu, order_code, cpu_addr))
                return -EOPNOTSUPP;
 
        if (r1 % 2)
index 3208d33a48cb62a7a0704ba9a6216193f192c645..cc1d6c68356fc3ede1cb2dd22cc6781f83c8288b 100644 (file)
@@ -105,11 +105,22 @@ TRACE_EVENT(kvm_s390_vcpu_start_stop,
        {KVM_S390_PROGRAM_INT, "program interrupt"},                    \
        {KVM_S390_SIGP_SET_PREFIX, "sigp set prefix"},                  \
        {KVM_S390_RESTART, "sigp restart"},                             \
+       {KVM_S390_INT_PFAULT_INIT, "pfault init"},                      \
+       {KVM_S390_INT_PFAULT_DONE, "pfault done"},                      \
+       {KVM_S390_MCHK, "machine check"},                               \
+       {KVM_S390_INT_CLOCK_COMP, "clock comparator"},                  \
+       {KVM_S390_INT_CPU_TIMER, "cpu timer"},                          \
        {KVM_S390_INT_VIRTIO, "virtio interrupt"},                      \
        {KVM_S390_INT_SERVICE, "sclp interrupt"},                       \
        {KVM_S390_INT_EMERGENCY, "sigp emergency"},                     \
        {KVM_S390_INT_EXTERNAL_CALL, "sigp ext call"}
 
+#define get_irq_name(__type) \
+       (__type > KVM_S390_INT_IO_MAX ? \
+       __print_symbolic(__type, kvm_s390_int_type) : \
+               (__type & KVM_S390_INT_IO_AI_MASK ? \
+                "adapter I/O interrupt" : "subchannel I/O interrupt"))
+
 TRACE_EVENT(kvm_s390_inject_vm,
            TP_PROTO(__u64 type, __u32 parm, __u64 parm64, int who),
            TP_ARGS(type, parm, parm64, who),
@@ -131,22 +142,19 @@ TRACE_EVENT(kvm_s390_inject_vm,
            TP_printk("inject%s: type:%x (%s) parm:%x parm64:%llx",
                      (__entry->who == 1) ? " (from kernel)" :
                      (__entry->who == 2) ? " (from user)" : "",
-                     __entry->inttype,
-                     __print_symbolic(__entry->inttype, kvm_s390_int_type),
+                     __entry->inttype, get_irq_name(__entry->inttype),
                      __entry->parm, __entry->parm64)
        );
 
 TRACE_EVENT(kvm_s390_inject_vcpu,
-           TP_PROTO(unsigned int id, __u64 type, __u32 parm, __u64 parm64, \
-                    int who),
-           TP_ARGS(id, type, parm, parm64, who),
+           TP_PROTO(unsigned int id, __u64 type, __u32 parm, __u64 parm64),
+           TP_ARGS(id, type, parm, parm64),
 
            TP_STRUCT__entry(
                    __field(int, id)
                    __field(__u32, inttype)
                    __field(__u32, parm)
                    __field(__u64, parm64)
-                   __field(int, who)
                    ),
 
            TP_fast_assign(
@@ -154,15 +162,12 @@ TRACE_EVENT(kvm_s390_inject_vcpu,
                    __entry->inttype = type & 0x00000000ffffffff;
                    __entry->parm = parm;
                    __entry->parm64 = parm64;
-                   __entry->who = who;
                    ),
 
-           TP_printk("inject%s (vcpu %d): type:%x (%s) parm:%x parm64:%llx",
-                     (__entry->who == 1) ? " (from kernel)" :
-                     (__entry->who == 2) ? " (from user)" : "",
+           TP_printk("inject (vcpu %d): type:%x (%s) parm:%x parm64:%llx",
                      __entry->id, __entry->inttype,
-                     __print_symbolic(__entry->inttype, kvm_s390_int_type),
-                     __entry->parm, __entry->parm64)
+                     get_irq_name(__entry->inttype), __entry->parm,
+                     __entry->parm64)
        );
 
 /*
@@ -189,8 +194,8 @@ TRACE_EVENT(kvm_s390_deliver_interrupt,
            TP_printk("deliver interrupt (vcpu %d): type:%x (%s) "      \
                      "data:%08llx %016llx",
                      __entry->id, __entry->inttype,
-                     __print_symbolic(__entry->inttype, kvm_s390_int_type),
-                     __entry->data0, __entry->data1)
+                     get_irq_name(__entry->inttype), __entry->data0,
+                     __entry->data1)
        );
 
 /*
index 16dc42d83f9316c8524436457b2a92df59b2fbf0..246a7eb4b680208dd680207aafc09d8f0deefdda 100644 (file)
@@ -26,6 +26,7 @@ void __delay(unsigned long loops)
          */
        asm volatile("0: brct %0,0b" : : "d" ((loops/2) + 1));
 }
+EXPORT_SYMBOL(__delay);
 
 static void __udelay_disabled(unsigned long long usecs)
 {
index 4614d415bb58c96fdbbbdccd062074442ee5d681..0d002a746bec157b9bd38a5006564bba26bb8b04 100644 (file)
@@ -370,22 +370,9 @@ long __strncpy_from_user(char *dst, const char __user *src, long size)
 }
 EXPORT_SYMBOL(__strncpy_from_user);
 
-/*
- * The "old" uaccess variant without mvcos can be enforced with the
- * uaccess_primary kernel parameter. This is mainly for debugging purposes.
- */
-static int uaccess_primary __initdata;
-
-static int __init parse_uaccess_pt(char *__unused)
-{
-       uaccess_primary = 1;
-       return 0;
-}
-early_param("uaccess_primary", parse_uaccess_pt);
-
 static int __init uaccess_init(void)
 {
-       if (!uaccess_primary && test_facility(27))
+       if (test_facility(27))
                static_key_slow_inc(&have_mvcos);
        return 0;
 }
index 4c8f5d7f9c23d74c960cd1172f266391ba8ec1a3..f985856a538b75e8c62cdfec3950357cff8fff0d 100644 (file)
@@ -646,7 +646,7 @@ static void pfault_interrupt(struct ext_code ext_code,
                return;
        inc_irq_stat(IRQEXT_PFL);
        /* Get the token (= pid of the affected task). */
-       pid = sizeof(void *) == 4 ? param32 : param64;
+       pid = param64;
        rcu_read_lock();
        tsk = find_task_by_pid_ns(pid, &init_pid_ns);
        if (tsk)
index 1eb41bb3010cf2909bb44ddc83855bfed517891f..12bbf0e8478f84d0fe464029648cf2333c0cfde3 100644 (file)
@@ -30,6 +30,9 @@ static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
        do {
                pte = *ptep;
                barrier();
+               /* Similar to the PMD case, NUMA hinting must take slow path */
+               if (pte_protnone(pte))
+                       return 0;
                if ((pte_val(pte) & mask) != 0)
                        return 0;
                VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
@@ -125,6 +128,13 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
                if (unlikely(pmd_large(pmd))) {
+                       /*
+                        * NUMA hinting faults need to be handled in the GUP
+                        * slowpath for accounting purposes and so that they
+                        * can be serialised against THP migration.
+                        */
+                       if (pmd_protnone(pmd))
+                               return 0;
                        if (!gup_huge_pmd(pmdp, pmd, addr, next,
                                          write, pages, nr))
                                return 0;
index 76e873748b56e91579ad06fd2fece4e2c346a51f..2963b563621c29e345ca61541aaa472b453d9072 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/initrd.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
+#include <linux/memblock.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -138,7 +139,7 @@ void __init mem_init(void)
        cpumask_set_cpu(0, mm_cpumask(&init_mm));
        atomic_set(&init_mm.context.attach_count, 1);
 
-        max_mapnr = max_low_pfn;
+       set_max_mapnr(max_low_pfn);
         high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
        /* Setup guest page hinting */
@@ -170,37 +171,36 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
 #ifdef CONFIG_MEMORY_HOTPLUG
 int arch_add_memory(int nid, u64 start, u64 size)
 {
-       unsigned long zone_start_pfn, zone_end_pfn, nr_pages;
+       unsigned long normal_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
+       unsigned long dma_end_pfn = PFN_DOWN(MAX_DMA_ADDRESS);
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long size_pages = PFN_DOWN(size);
-       struct zone *zone;
-       int rc;
+       unsigned long nr_pages;
+       int rc, zone_enum;
 
        rc = vmem_add_mapping(start, size);
        if (rc)
                return rc;
-       for_each_zone(zone) {
-               if (zone_idx(zone) != ZONE_MOVABLE) {
-                       /* Add range within existing zone limits */
-                       zone_start_pfn = zone->zone_start_pfn;
-                       zone_end_pfn = zone->zone_start_pfn +
-                                      zone->spanned_pages;
+
+       while (size_pages > 0) {
+               if (start_pfn < dma_end_pfn) {
+                       nr_pages = (start_pfn + size_pages > dma_end_pfn) ?
+                                  dma_end_pfn - start_pfn : size_pages;
+                       zone_enum = ZONE_DMA;
+               } else if (start_pfn < normal_end_pfn) {
+                       nr_pages = (start_pfn + size_pages > normal_end_pfn) ?
+                                  normal_end_pfn - start_pfn : size_pages;
+                       zone_enum = ZONE_NORMAL;
                } else {
-                       /* Add remaining range to ZONE_MOVABLE */
-                       zone_start_pfn = start_pfn;
-                       zone_end_pfn = start_pfn + size_pages;
+                       nr_pages = size_pages;
+                       zone_enum = ZONE_MOVABLE;
                }
-               if (start_pfn < zone_start_pfn || start_pfn >= zone_end_pfn)
-                       continue;
-               nr_pages = (start_pfn + size_pages > zone_end_pfn) ?
-                          zone_end_pfn - start_pfn : size_pages;
-               rc = __add_pages(nid, zone, start_pfn, nr_pages);
+               rc = __add_pages(nid, NODE_DATA(nid)->node_zones + zone_enum,
+                                start_pfn, size_pages);
                if (rc)
                        break;
                start_pfn += nr_pages;
                size_pages -= nr_pages;
-               if (!size_pages)
-                       break;
        }
        if (rc)
                vmem_remove_mapping(start, size);
index b33f66110ca9401418f7d657b951d8bfb84d99c3..54ef3bc01b43c361a47d6a9112b9bb7bfcdc4501 100644 (file)
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/smp.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/quicklist.h>
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
 #include <linux/swapops.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 
-#define ALLOC_ORDER    2
-#define FRAG_MASK      0x03
-
 unsigned long *crst_table_alloc(struct mm_struct *mm)
 {
-       struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+       struct page *page = alloc_pages(GFP_KERNEL, 2);
 
        if (!page)
                return NULL;
@@ -42,7 +35,7 @@ unsigned long *crst_table_alloc(struct mm_struct *mm)
 
 void crst_table_free(struct mm_struct *mm, unsigned long *table)
 {
-       free_pages((unsigned long) table, ALLOC_ORDER);
+       free_pages((unsigned long) table, 2);
 }
 
 static void __crst_table_upgrade(void *arg)
@@ -176,7 +169,7 @@ struct gmap *gmap_alloc(struct mm_struct *mm, unsigned long limit)
        INIT_RADIX_TREE(&gmap->host_to_guest, GFP_ATOMIC);
        spin_lock_init(&gmap->guest_table_lock);
        gmap->mm = mm;
-       page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+       page = alloc_pages(GFP_KERNEL, 2);
        if (!page)
                goto out_free;
        page->index = 0;
@@ -247,7 +240,7 @@ void gmap_free(struct gmap *gmap)
 
        /* Free all segment & region tables. */
        list_for_each_entry_safe(page, next, &gmap->crst_list, lru)
-               __free_pages(page, ALLOC_ORDER);
+               __free_pages(page, 2);
        gmap_radix_tree_free(&gmap->guest_to_host);
        gmap_radix_tree_free(&gmap->host_to_guest);
        down_write(&gmap->mm->mmap_sem);
@@ -287,7 +280,7 @@ static int gmap_alloc_table(struct gmap *gmap, unsigned long *table,
        unsigned long *new;
 
        /* since we dont free the gmap table until gmap_free we can unlock */
-       page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+       page = alloc_pages(GFP_KERNEL, 2);
        if (!page)
                return -ENOMEM;
        new = (unsigned long *) page_to_phys(page);
@@ -302,7 +295,7 @@ static int gmap_alloc_table(struct gmap *gmap, unsigned long *table,
        }
        spin_unlock(&gmap->mm->page_table_lock);
        if (page)
-               __free_pages(page, ALLOC_ORDER);
+               __free_pages(page, 2);
        return 0;
 }
 
@@ -795,40 +788,6 @@ void gmap_do_ipte_notify(struct mm_struct *mm, unsigned long vmaddr, pte_t *pte)
 }
 EXPORT_SYMBOL_GPL(gmap_do_ipte_notify);
 
-static inline int page_table_with_pgste(struct page *page)
-{
-       return atomic_read(&page->_mapcount) == 0;
-}
-
-static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
-{
-       struct page *page;
-       unsigned long *table;
-
-       page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
-       if (!page)
-               return NULL;
-       if (!pgtable_page_ctor(page)) {
-               __free_page(page);
-               return NULL;
-       }
-       atomic_set(&page->_mapcount, 0);
-       table = (unsigned long *) page_to_phys(page);
-       clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
-       clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
-       return table;
-}
-
-static inline void page_table_free_pgste(unsigned long *table)
-{
-       struct page *page;
-
-       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       pgtable_page_dtor(page);
-       atomic_set(&page->_mapcount, -1);
-       __free_page(page);
-}
-
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
                          unsigned long key, bool nq)
 {
@@ -957,20 +916,6 @@ __initcall(page_table_register_sysctl);
 
 #else /* CONFIG_PGSTE */
 
-static inline int page_table_with_pgste(struct page *page)
-{
-       return 0;
-}
-
-static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
-{
-       return NULL;
-}
-
-static inline void page_table_free_pgste(unsigned long *table)
-{
-}
-
 static inline void gmap_unlink(struct mm_struct *mm, unsigned long *table,
                        unsigned long vmaddr)
 {
@@ -994,44 +939,55 @@ static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
  */
 unsigned long *page_table_alloc(struct mm_struct *mm)
 {
-       unsigned long *uninitialized_var(table);
-       struct page *uninitialized_var(page);
+       unsigned long *table;
+       struct page *page;
        unsigned int mask, bit;
 
-       if (mm_alloc_pgste(mm))
-               return page_table_alloc_pgste(mm);
-       /* Allocate fragments of a 4K page as 1K/2K page table */
-       spin_lock_bh(&mm->context.list_lock);
-       mask = FRAG_MASK;
-       if (!list_empty(&mm->context.pgtable_list)) {
-               page = list_first_entry(&mm->context.pgtable_list,
-                                       struct page, lru);
-               table = (unsigned long *) page_to_phys(page);
-               mask = atomic_read(&page->_mapcount);
-               mask = mask | (mask >> 4);
-       }
-       if ((mask & FRAG_MASK) == FRAG_MASK) {
-               spin_unlock_bh(&mm->context.list_lock);
-               page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
-               if (!page)
-                       return NULL;
-               if (!pgtable_page_ctor(page)) {
-                       __free_page(page);
-                       return NULL;
+       /* Try to get a fragment of a 4K page as a 2K page table */
+       if (!mm_alloc_pgste(mm)) {
+               table = NULL;
+               spin_lock_bh(&mm->context.list_lock);
+               if (!list_empty(&mm->context.pgtable_list)) {
+                       page = list_first_entry(&mm->context.pgtable_list,
+                                               struct page, lru);
+                       mask = atomic_read(&page->_mapcount);
+                       mask = (mask | (mask >> 4)) & 3;
+                       if (mask != 3) {
+                               table = (unsigned long *) page_to_phys(page);
+                               bit = mask & 1;         /* =1 -> second 2K */
+                               if (bit)
+                                       table += PTRS_PER_PTE;
+                               atomic_xor_bits(&page->_mapcount, 1U << bit);
+                               list_del(&page->lru);
+                       }
                }
+               spin_unlock_bh(&mm->context.list_lock);
+               if (table)
+                       return table;
+       }
+       /* Allocate a fresh page */
+       page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+       if (!page)
+               return NULL;
+       if (!pgtable_page_ctor(page)) {
+               __free_page(page);
+               return NULL;
+       }
+       /* Initialize page table */
+       table = (unsigned long *) page_to_phys(page);
+       if (mm_alloc_pgste(mm)) {
+               /* Return 4K page table with PGSTEs */
+               atomic_set(&page->_mapcount, 3);
+               clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
+               clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
+       } else {
+               /* Return the first 2K fragment of the page */
                atomic_set(&page->_mapcount, 1);
-               table = (unsigned long *) page_to_phys(page);
                clear_table(table, _PAGE_INVALID, PAGE_SIZE);
                spin_lock_bh(&mm->context.list_lock);
                list_add(&page->lru, &mm->context.pgtable_list);
-       } else {
-               for (bit = 1; mask & bit; bit <<= 1)
-                       table += PTRS_PER_PTE;
-               mask = atomic_xor_bits(&page->_mapcount, bit);
-               if ((mask & FRAG_MASK) == FRAG_MASK)
-                       list_del(&page->lru);
+               spin_unlock_bh(&mm->context.list_lock);
        }
-       spin_unlock_bh(&mm->context.list_lock);
        return table;
 }
 
@@ -1041,37 +997,23 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        unsigned int bit, mask;
 
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       if (page_table_with_pgste(page))
-               return page_table_free_pgste(table);
-       /* Free 1K/2K page table fragment of a 4K page */
-       bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
-       spin_lock_bh(&mm->context.list_lock);
-       if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
-               list_del(&page->lru);
-       mask = atomic_xor_bits(&page->_mapcount, bit);
-       if (mask & FRAG_MASK)
-               list_add(&page->lru, &mm->context.pgtable_list);
-       spin_unlock_bh(&mm->context.list_lock);
-       if (mask == 0) {
-               pgtable_page_dtor(page);
-               atomic_set(&page->_mapcount, -1);
-               __free_page(page);
+       if (!mm_alloc_pgste(mm)) {
+               /* Free 2K page table fragment of a 4K page */
+               bit = (__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
+               spin_lock_bh(&mm->context.list_lock);
+               mask = atomic_xor_bits(&page->_mapcount, 1U << bit);
+               if (mask & 3)
+                       list_add(&page->lru, &mm->context.pgtable_list);
+               else
+                       list_del(&page->lru);
+               spin_unlock_bh(&mm->context.list_lock);
+               if (mask != 0)
+                       return;
        }
-}
-
-static void __page_table_free_rcu(void *table, unsigned bit)
-{
-       struct page *page;
 
-       if (bit == FRAG_MASK)
-               return page_table_free_pgste(table);
-       /* Free 1K/2K page table fragment of a 4K page */
-       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       if (atomic_xor_bits(&page->_mapcount, bit) == 0) {
-               pgtable_page_dtor(page);
-               atomic_set(&page->_mapcount, -1);
-               __free_page(page);
-       }
+       pgtable_page_dtor(page);
+       atomic_set(&page->_mapcount, -1);
+       __free_page(page);
 }
 
 void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
@@ -1083,34 +1025,45 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
 
        mm = tlb->mm;
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       if (page_table_with_pgste(page)) {
+       if (mm_alloc_pgste(mm)) {
                gmap_unlink(mm, table, vmaddr);
-               table = (unsigned long *) (__pa(table) | FRAG_MASK);
+               table = (unsigned long *) (__pa(table) | 3);
                tlb_remove_table(tlb, table);
                return;
        }
-       bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
+       bit = (__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
        spin_lock_bh(&mm->context.list_lock);
-       if ((atomic_read(&page->_mapcount) & FRAG_MASK) != FRAG_MASK)
-               list_del(&page->lru);
-       mask = atomic_xor_bits(&page->_mapcount, bit | (bit << 4));
-       if (mask & FRAG_MASK)
+       mask = atomic_xor_bits(&page->_mapcount, 0x11U << bit);
+       if (mask & 3)
                list_add_tail(&page->lru, &mm->context.pgtable_list);
+       else
+               list_del(&page->lru);
        spin_unlock_bh(&mm->context.list_lock);
-       table = (unsigned long *) (__pa(table) | (bit << 4));
+       table = (unsigned long *) (__pa(table) | (1U << bit));
        tlb_remove_table(tlb, table);
 }
 
 static void __tlb_remove_table(void *_table)
 {
-       const unsigned long mask = (FRAG_MASK << 4) | FRAG_MASK;
-       void *table = (void *)((unsigned long) _table & ~mask);
-       unsigned type = (unsigned long) _table & mask;
-
-       if (type)
-               __page_table_free_rcu(table, type);
-       else
-               free_pages((unsigned long) table, ALLOC_ORDER);
+       unsigned int mask = (unsigned long) _table & 3;
+       void *table = (void *)((unsigned long) _table ^ mask);
+       struct page *page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+
+       switch (mask) {
+       case 0:         /* pmd or pud */
+               free_pages((unsigned long) table, 2);
+               break;
+       case 1:         /* lower 2K of a 4K page table */
+       case 2:         /* higher 2K of a 4K page table */
+               if (atomic_xor_bits(&page->_mapcount, mask << 4) != 0)
+                       break;
+               /* fallthrough */
+       case 3:         /* 4K page table with pgstes */
+               pgtable_page_dtor(page);
+               atomic_set(&page->_mapcount, -1);
+               __free_page(page);
+               break;
+       }
 }
 
 static void tlb_remove_table_smp_sync(void *arg)
diff --git a/arch/s390/numa/Makefile b/arch/s390/numa/Makefile
new file mode 100644 (file)
index 0000000..f94ecaf
--- /dev/null
@@ -0,0 +1,3 @@
+obj-y                  += numa.o
+obj-y                  += toptree.o
+obj-$(CONFIG_NUMA_EMU) += mode_emu.o
diff --git a/arch/s390/numa/mode_emu.c b/arch/s390/numa/mode_emu.c
new file mode 100644 (file)
index 0000000..7de4e2f
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * NUMA support for s390
+ *
+ * NUMA emulation (aka fake NUMA) distributes the available memory to nodes
+ * without using real topology information about the physical memory of the
+ * machine.
+ *
+ * It distributes the available CPUs to nodes while respecting the original
+ * machine topology information. This is done by trying to avoid to separate
+ * CPUs which reside on the same book or even on the same MC.
+ *
+ * Because the current Linux scheduler code requires a stable cpu to node
+ * mapping, cores are pinned to nodes when the first CPU thread is set online.
+ *
+ * Copyright IBM Corp. 2015
+ */
+
+#define KMSG_COMPONENT "numa_emu"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/memblock.h>
+#include <linux/node.h>
+#include <linux/memory.h>
+#include <linux/slab.h>
+#include <asm/smp.h>
+#include <asm/topology.h>
+#include "numa_mode.h"
+#include "toptree.h"
+
+/* Distances between the different system components */
+#define DIST_EMPTY     0
+#define DIST_CORE      1
+#define DIST_MC                2
+#define DIST_BOOK      3
+#define DIST_MAX       4
+
+/* Node distance reported to common code */
+#define EMU_NODE_DIST  10
+
+/* Node ID for free (not yet pinned) cores */
+#define NODE_ID_FREE   -1
+
+/* Different levels of toptree */
+enum toptree_level {CORE, MC, BOOK, NODE, TOPOLOGY};
+
+/* The two toptree IDs */
+enum {TOPTREE_ID_PHYS, TOPTREE_ID_NUMA};
+
+/* Number of NUMA nodes */
+static int emu_nodes = 1;
+/* NUMA stripe size */
+static unsigned long emu_size;
+
+/*
+ * Node to core pinning information updates are protected by
+ * "sched_domains_mutex".
+ */
+static struct {
+       s32 to_node_id[CONFIG_NR_CPUS]; /* Pinned core to node mapping */
+       int total;                      /* Total number of pinned cores */
+       int per_node_target;            /* Cores per node without extra cores */
+       int per_node[MAX_NUMNODES];     /* Number of cores pinned to node */
+} *emu_cores;
+
+/*
+ * Pin a core to a node
+ */
+static void pin_core_to_node(int core_id, int node_id)
+{
+       if (emu_cores->to_node_id[core_id] == NODE_ID_FREE) {
+               emu_cores->per_node[node_id]++;
+               emu_cores->to_node_id[core_id] = node_id;
+               emu_cores->total++;
+       } else {
+               WARN_ON(emu_cores->to_node_id[core_id] != node_id);
+       }
+}
+
+/*
+ * Number of pinned cores of a node
+ */
+static int cores_pinned(struct toptree *node)
+{
+       return emu_cores->per_node[node->id];
+}
+
+/*
+ * ID of the node where the core is pinned (or NODE_ID_FREE)
+ */
+static int core_pinned_to_node_id(struct toptree *core)
+{
+       return emu_cores->to_node_id[core->id];
+}
+
+/*
+ * Number of cores in the tree that are not yet pinned
+ */
+static int cores_free(struct toptree *tree)
+{
+       struct toptree *core;
+       int count = 0;
+
+       toptree_for_each(core, tree, CORE) {
+               if (core_pinned_to_node_id(core) == NODE_ID_FREE)
+                       count++;
+       }
+       return count;
+}
+
+/*
+ * Return node of core
+ */
+static struct toptree *core_node(struct toptree *core)
+{
+       return core->parent->parent->parent;
+}
+
+/*
+ * Return book of core
+ */
+static struct toptree *core_book(struct toptree *core)
+{
+       return core->parent->parent;
+}
+
+/*
+ * Return mc of core
+ */
+static struct toptree *core_mc(struct toptree *core)
+{
+       return core->parent;
+}
+
+/*
+ * Distance between two cores
+ */
+static int dist_core_to_core(struct toptree *core1, struct toptree *core2)
+{
+       if (core_book(core1)->id != core_book(core2)->id)
+               return DIST_BOOK;
+       if (core_mc(core1)->id != core_mc(core2)->id)
+               return DIST_MC;
+       /* Same core or sibling on same MC */
+       return DIST_CORE;
+}
+
+/*
+ * Distance of a node to a core
+ */
+static int dist_node_to_core(struct toptree *node, struct toptree *core)
+{
+       struct toptree *core_node;
+       int dist_min = DIST_MAX;
+
+       toptree_for_each(core_node, node, CORE)
+               dist_min = min(dist_min, dist_core_to_core(core_node, core));
+       return dist_min == DIST_MAX ? DIST_EMPTY : dist_min;
+}
+
+/*
+ * Unify will delete empty nodes, therefore recreate nodes.
+ */
+static void toptree_unify_tree(struct toptree *tree)
+{
+       int nid;
+
+       toptree_unify(tree);
+       for (nid = 0; nid < emu_nodes; nid++)
+               toptree_get_child(tree, nid);
+}
+
+/*
+ * Find the best/nearest node for a given core and ensure that no node
+ * gets more than "emu_cores->per_node_target + extra" cores.
+ */
+static struct toptree *node_for_core(struct toptree *numa, struct toptree *core,
+                                    int extra)
+{
+       struct toptree *node, *node_best = NULL;
+       int dist_cur, dist_best, cores_target;
+
+       cores_target = emu_cores->per_node_target + extra;
+       dist_best = DIST_MAX;
+       node_best = NULL;
+       toptree_for_each(node, numa, NODE) {
+               /* Already pinned cores must use their nodes */
+               if (core_pinned_to_node_id(core) == node->id) {
+                       node_best = node;
+                       break;
+               }
+               /* Skip nodes that already have enough cores */
+               if (cores_pinned(node) >= cores_target)
+                       continue;
+               dist_cur = dist_node_to_core(node, core);
+               if (dist_cur < dist_best) {
+                       dist_best = dist_cur;
+                       node_best = node;
+               }
+       }
+       return node_best;
+}
+
+/*
+ * Find the best node for each core with respect to "extra" core count
+ */
+static void toptree_to_numa_single(struct toptree *numa, struct toptree *phys,
+                                  int extra)
+{
+       struct toptree *node, *core, *tmp;
+
+       toptree_for_each_safe(core, tmp, phys, CORE) {
+               node = node_for_core(numa, core, extra);
+               if (!node)
+                       return;
+               toptree_move(core, node);
+               pin_core_to_node(core->id, node->id);
+       }
+}
+
+/*
+ * Move structures of given level to specified NUMA node
+ */
+static void move_level_to_numa_node(struct toptree *node, struct toptree *phys,
+                                   enum toptree_level level, bool perfect)
+{
+       int cores_free, cores_target = emu_cores->per_node_target;
+       struct toptree *cur, *tmp;
+
+       toptree_for_each_safe(cur, tmp, phys, level) {
+               cores_free = cores_target - toptree_count(node, CORE);
+               if (perfect) {
+                       if (cores_free == toptree_count(cur, CORE))
+                               toptree_move(cur, node);
+               } else {
+                       if (cores_free >= toptree_count(cur, CORE))
+                               toptree_move(cur, node);
+               }
+       }
+}
+
+/*
+ * Move structures of a given level to NUMA nodes. If "perfect" is specified
+ * move only perfectly fitting structures. Otherwise move also smaller
+ * than needed structures.
+ */
+static void move_level_to_numa(struct toptree *numa, struct toptree *phys,
+                              enum toptree_level level, bool perfect)
+{
+       struct toptree *node;
+
+       toptree_for_each(node, numa, NODE)
+               move_level_to_numa_node(node, phys, level, perfect);
+}
+
+/*
+ * For the first run try to move the big structures
+ */
+static void toptree_to_numa_first(struct toptree *numa, struct toptree *phys)
+{
+       struct toptree *core;
+
+       /* Always try to move perfectly fitting structures first */
+       move_level_to_numa(numa, phys, BOOK, true);
+       move_level_to_numa(numa, phys, BOOK, false);
+       move_level_to_numa(numa, phys, MC, true);
+       move_level_to_numa(numa, phys, MC, false);
+       /* Now pin all the moved cores */
+       toptree_for_each(core, numa, CORE)
+               pin_core_to_node(core->id, core_node(core)->id);
+}
+
+/*
+ * Allocate new topology and create required nodes
+ */
+static struct toptree *toptree_new(int id, int nodes)
+{
+       struct toptree *tree;
+       int nid;
+
+       tree = toptree_alloc(TOPOLOGY, id);
+       if (!tree)
+               goto fail;
+       for (nid = 0; nid < nodes; nid++) {
+               if (!toptree_get_child(tree, nid))
+                       goto fail;
+       }
+       return tree;
+fail:
+       panic("NUMA emulation could not allocate topology");
+}
+
+/*
+ * Allocate and initialize core to node mapping
+ */
+static void create_core_to_node_map(void)
+{
+       int i;
+
+       emu_cores = kzalloc(sizeof(*emu_cores), GFP_KERNEL);
+       if (emu_cores == NULL)
+               panic("Could not allocate cores to node memory");
+       for (i = 0; i < ARRAY_SIZE(emu_cores->to_node_id); i++)
+               emu_cores->to_node_id[i] = NODE_ID_FREE;
+}
+
+/*
+ * Move cores from physical topology into NUMA target topology
+ * and try to keep as much of the physical topology as possible.
+ */
+static struct toptree *toptree_to_numa(struct toptree *phys)
+{
+       static int first = 1;
+       struct toptree *numa;
+       int cores_total;
+
+       cores_total = emu_cores->total + cores_free(phys);
+       emu_cores->per_node_target = cores_total / emu_nodes;
+       numa = toptree_new(TOPTREE_ID_NUMA, emu_nodes);
+       if (first) {
+               toptree_to_numa_first(numa, phys);
+               first = 0;
+       }
+       toptree_to_numa_single(numa, phys, 0);
+       toptree_to_numa_single(numa, phys, 1);
+       toptree_unify_tree(numa);
+
+       WARN_ON(cpumask_weight(&phys->mask));
+       return numa;
+}
+
+/*
+ * Create a toptree out of the physical topology that we got from the hypervisor
+ */
+static struct toptree *toptree_from_topology(void)
+{
+       struct toptree *phys, *node, *book, *mc, *core;
+       struct cpu_topology_s390 *top;
+       int cpu;
+
+       phys = toptree_new(TOPTREE_ID_PHYS, 1);
+
+       for_each_online_cpu(cpu) {
+               top = &per_cpu(cpu_topology, cpu);
+               node = toptree_get_child(phys, 0);
+               book = toptree_get_child(node, top->book_id);
+               mc = toptree_get_child(book, top->socket_id);
+               core = toptree_get_child(mc, top->core_id);
+               if (!book || !mc || !core)
+                       panic("NUMA emulation could not allocate memory");
+               cpumask_set_cpu(cpu, &core->mask);
+               toptree_update_mask(mc);
+       }
+       return phys;
+}
+
+/*
+ * Add toptree core to topology and create correct CPU masks
+ */
+static void topology_add_core(struct toptree *core)
+{
+       struct cpu_topology_s390 *top;
+       int cpu;
+
+       for_each_cpu(cpu, &core->mask) {
+               top = &per_cpu(cpu_topology, cpu);
+               cpumask_copy(&top->thread_mask, &core->mask);
+               cpumask_copy(&top->core_mask, &core_mc(core)->mask);
+               cpumask_copy(&top->book_mask, &core_book(core)->mask);
+               cpumask_set_cpu(cpu, node_to_cpumask_map[core_node(core)->id]);
+               top->node_id = core_node(core)->id;
+       }
+}
+
+/*
+ * Apply toptree to topology and create CPU masks
+ */
+static void toptree_to_topology(struct toptree *numa)
+{
+       struct toptree *core;
+       int i;
+
+       /* Clear all node masks */
+       for (i = 0; i < MAX_NUMNODES; i++)
+               cpumask_clear(node_to_cpumask_map[i]);
+
+       /* Rebuild all masks */
+       toptree_for_each(core, numa, CORE)
+               topology_add_core(core);
+}
+
+/*
+ * Show the node to core mapping
+ */
+static void print_node_to_core_map(void)
+{
+       int nid, cid;
+
+       if (!numa_debug_enabled)
+               return;
+       printk(KERN_DEBUG "NUMA node to core mapping\n");
+       for (nid = 0; nid < emu_nodes; nid++) {
+               printk(KERN_DEBUG "  node %3d: ", nid);
+               for (cid = 0; cid < ARRAY_SIZE(emu_cores->to_node_id); cid++) {
+                       if (emu_cores->to_node_id[cid] == nid)
+                               printk(KERN_CONT "%d ", cid);
+               }
+               printk(KERN_CONT "\n");
+       }
+}
+
+/*
+ * Transfer physical topology into a NUMA topology and modify CPU masks
+ * according to the NUMA topology.
+ *
+ * Must be called with "sched_domains_mutex" lock held.
+ */
+static void emu_update_cpu_topology(void)
+{
+       struct toptree *phys, *numa;
+
+       if (emu_cores == NULL)
+               create_core_to_node_map();
+       phys = toptree_from_topology();
+       numa = toptree_to_numa(phys);
+       toptree_free(phys);
+       toptree_to_topology(numa);
+       toptree_free(numa);
+       print_node_to_core_map();
+}
+
+/*
+ * If emu_size is not set, use CONFIG_EMU_SIZE. Then round to minimum
+ * alignment (needed for memory hotplug).
+ */
+static unsigned long emu_setup_size_adjust(unsigned long size)
+{
+       size = size ? : CONFIG_EMU_SIZE;
+       size = roundup(size, memory_block_size_bytes());
+       return size;
+}
+
+/*
+ * If we have not enough memory for the specified nodes, reduce the node count.
+ */
+static int emu_setup_nodes_adjust(int nodes)
+{
+       int nodes_max;
+
+       nodes_max = memblock.memory.total_size / emu_size;
+       nodes_max = max(nodes_max, 1);
+       if (nodes_max >= nodes)
+               return nodes;
+       pr_warn("Not enough memory for %d nodes, reducing node count\n", nodes);
+       return nodes_max;
+}
+
+/*
+ * Early emu setup
+ */
+static void emu_setup(void)
+{
+       emu_size = emu_setup_size_adjust(emu_size);
+       emu_nodes = emu_setup_nodes_adjust(emu_nodes);
+       pr_info("Creating %d nodes with memory stripe size %ld MB\n",
+               emu_nodes, emu_size >> 20);
+}
+
+/*
+ * Return node id for given page number
+ */
+static int emu_pfn_to_nid(unsigned long pfn)
+{
+       return (pfn / (emu_size >> PAGE_SHIFT)) % emu_nodes;
+}
+
+/*
+ * Return stripe size
+ */
+static unsigned long emu_align(void)
+{
+       return emu_size;
+}
+
+/*
+ * Return distance between two nodes
+ */
+static int emu_distance(int node1, int node2)
+{
+       return (node1 != node2) * EMU_NODE_DIST;
+}
+
+/*
+ * Define callbacks for generic s390 NUMA infrastructure
+ */
+const struct numa_mode numa_mode_emu = {
+       .name = "emu",
+       .setup = emu_setup,
+       .update_cpu_topology = emu_update_cpu_topology,
+       .__pfn_to_nid = emu_pfn_to_nid,
+       .align = emu_align,
+       .distance = emu_distance,
+};
+
+/*
+ * Kernel parameter: emu_nodes=<n>
+ */
+static int __init early_parse_emu_nodes(char *p)
+{
+       int count;
+
+       if (kstrtoint(p, 0, &count) != 0 || count <= 0)
+               return 0;
+       if (count <= 0)
+               return 0;
+       emu_nodes = min(count, MAX_NUMNODES);
+       return 0;
+}
+early_param("emu_nodes", early_parse_emu_nodes);
+
+/*
+ * Kernel parameter: emu_size=[<n>[k|M|G|T]]
+ */
+static int __init early_parse_emu_size(char *p)
+{
+       emu_size = memparse(p, NULL);
+       return 0;
+}
+early_param("emu_size", early_parse_emu_size);
diff --git a/arch/s390/numa/numa.c b/arch/s390/numa/numa.c
new file mode 100644 (file)
index 0000000..09b1d23
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * NUMA support for s390
+ *
+ * Implement NUMA core code.
+ *
+ * Copyright IBM Corp. 2015
+ */
+
+#define KMSG_COMPONENT "numa"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/cpumask.h>
+#include <linux/bootmem.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+#include <linux/node.h>
+
+#include <asm/numa.h>
+#include "numa_mode.h"
+
+pg_data_t *node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(node_data);
+
+cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
+EXPORT_SYMBOL(node_to_cpumask_map);
+
+const struct numa_mode numa_mode_plain = {
+       .name = "plain",
+};
+
+static const struct numa_mode *mode = &numa_mode_plain;
+
+int numa_pfn_to_nid(unsigned long pfn)
+{
+       return mode->__pfn_to_nid ? mode->__pfn_to_nid(pfn) : 0;
+}
+
+void numa_update_cpu_topology(void)
+{
+       if (mode->update_cpu_topology)
+               mode->update_cpu_topology();
+}
+
+int __node_distance(int a, int b)
+{
+       return mode->distance ? mode->distance(a, b) : 0;
+}
+
+int numa_debug_enabled;
+
+/*
+ * alloc_node_data() - Allocate node data
+ */
+static __init pg_data_t *alloc_node_data(void)
+{
+       pg_data_t *res;
+
+       res = (pg_data_t *) memblock_alloc(sizeof(pg_data_t), 1);
+       if (!res)
+               panic("Could not allocate memory for node data!\n");
+       memset(res, 0, sizeof(pg_data_t));
+       return res;
+}
+
+/*
+ * numa_setup_memory() - Assign bootmem to nodes
+ *
+ * The memory is first added to memblock without any respect to nodes.
+ * This is fixed before remaining memblock memory is handed over to the
+ * buddy allocator.
+ * An important side effect is that large bootmem allocations might easily
+ * cross node boundaries, which can be needed for large allocations with
+ * smaller memory stripes in each node (i.e. when using NUMA emulation).
+ *
+ * Memory defines nodes:
+ * Therefore this routine also sets the nodes online with memory.
+ */
+static void __init numa_setup_memory(void)
+{
+       unsigned long cur_base, align, end_of_dram;
+       int nid = 0;
+
+       end_of_dram = memblock_end_of_DRAM();
+       align = mode->align ? mode->align() : ULONG_MAX;
+
+       /*
+        * Step through all available memory and assign it to the nodes
+        * indicated by the mode implementation.
+        * All nodes which are seen here will be set online.
+        */
+       cur_base = 0;
+       do {
+               nid = numa_pfn_to_nid(PFN_DOWN(cur_base));
+               node_set_online(nid);
+               memblock_set_node(cur_base, align, &memblock.memory, nid);
+               cur_base += align;
+       } while (cur_base < end_of_dram);
+
+       /* Allocate and fill out node_data */
+       for (nid = 0; nid < MAX_NUMNODES; nid++)
+               NODE_DATA(nid) = alloc_node_data();
+
+       for_each_online_node(nid) {
+               unsigned long start_pfn, end_pfn;
+               unsigned long t_start, t_end;
+               int i;
+
+               start_pfn = ULONG_MAX;
+               end_pfn = 0;
+               for_each_mem_pfn_range(i, nid, &t_start, &t_end, NULL) {
+                       if (t_start < start_pfn)
+                               start_pfn = t_start;
+                       if (t_end > end_pfn)
+                               end_pfn = t_end;
+               }
+               NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
+               NODE_DATA(nid)->node_id = nid;
+       }
+}
+
+/*
+ * numa_setup() - Earliest initialization
+ *
+ * Assign the mode and call the mode's setup routine.
+ */
+void __init numa_setup(void)
+{
+       pr_info("NUMA mode: %s\n", mode->name);
+       if (mode->setup)
+               mode->setup();
+       numa_setup_memory();
+       memblock_dump_all();
+}
+
+
+/*
+ * numa_init_early() - Initialization initcall
+ *
+ * This runs when only one CPU is online and before the first
+ * topology update is called for by the scheduler.
+ */
+static int __init numa_init_early(void)
+{
+       /* Attach all possible CPUs to node 0 for now. */
+       cpumask_copy(node_to_cpumask_map[0], cpu_possible_mask);
+       return 0;
+}
+early_initcall(numa_init_early);
+
+/*
+ * numa_init_late() - Initialization initcall
+ *
+ * Register NUMA nodes.
+ */
+static int __init numa_init_late(void)
+{
+       int nid;
+
+       for_each_online_node(nid)
+               register_one_node(nid);
+       return 0;
+}
+device_initcall(numa_init_late);
+
+static int __init parse_debug(char *parm)
+{
+       numa_debug_enabled = 1;
+       return 0;
+}
+early_param("numa_debug", parse_debug);
+
+static int __init parse_numa(char *parm)
+{
+       if (strcmp(parm, numa_mode_plain.name) == 0)
+               mode = &numa_mode_plain;
+#ifdef CONFIG_NUMA_EMU
+       if (strcmp(parm, numa_mode_emu.name) == 0)
+               mode = &numa_mode_emu;
+#endif
+       return 0;
+}
+early_param("numa", parse_numa);
diff --git a/arch/s390/numa/numa_mode.h b/arch/s390/numa/numa_mode.h
new file mode 100644 (file)
index 0000000..08953b0
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * NUMA support for s390
+ *
+ * Define declarations used for communication between NUMA mode
+ * implementations and NUMA core functionality.
+ *
+ * Copyright IBM Corp. 2015
+ */
+#ifndef __S390_NUMA_MODE_H
+#define __S390_NUMA_MODE_H
+
+struct numa_mode {
+       char *name;                             /* Name of mode */
+       void (*setup)(void);                    /* Initizalize mode */
+       void (*update_cpu_topology)(void);      /* Called by topology code */
+       int (*__pfn_to_nid)(unsigned long pfn); /* PFN to node ID */
+       unsigned long (*align)(void);           /* Minimum node alignment */
+       int (*distance)(int a, int b);          /* Distance between two nodes */
+};
+
+extern const struct numa_mode numa_mode_plain;
+extern const struct numa_mode numa_mode_emu;
+
+#endif /* __S390_NUMA_MODE_H */
diff --git a/arch/s390/numa/toptree.c b/arch/s390/numa/toptree.c
new file mode 100644 (file)
index 0000000..902d350
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * NUMA support for s390
+ *
+ * A tree structure used for machine topology mangling
+ *
+ * Copyright IBM Corp. 2015
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
+#include <linux/slab.h>
+#include <asm/numa.h>
+
+#include "toptree.h"
+
+/**
+ * toptree_alloc - Allocate and initialize a new tree node.
+ * @level: The node's vertical level; level 0 contains the leaves.
+ * @id: ID number, explicitly not unique beyond scope of node's siblings
+ *
+ * Allocate a new tree node and initialize it.
+ *
+ * RETURNS:
+ * Pointer to the new tree node or NULL on error
+ */
+struct toptree *toptree_alloc(int level, int id)
+{
+       struct toptree *res = kzalloc(sizeof(struct toptree), GFP_KERNEL);
+
+       if (!res)
+               return res;
+
+       INIT_LIST_HEAD(&res->children);
+       INIT_LIST_HEAD(&res->sibling);
+       cpumask_clear(&res->mask);
+       res->level = level;
+       res->id = id;
+       return res;
+}
+
+/**
+ * toptree_remove - Remove a tree node from a tree
+ * @cand: Pointer to the node to remove
+ *
+ * The node is detached from its parent node. The parent node's
+ * masks will be updated to reflect the loss of the child.
+ */
+static void toptree_remove(struct toptree *cand)
+{
+       struct toptree *oldparent;
+
+       list_del_init(&cand->sibling);
+       oldparent = cand->parent;
+       cand->parent = NULL;
+       toptree_update_mask(oldparent);
+}
+
+/**
+ * toptree_free - discard a tree node
+ * @cand: Pointer to the tree node to discard
+ *
+ * Checks if @cand is attached to a parent node. Detaches it
+ * cleanly using toptree_remove. Possible children are freed
+ * recursively. In the end @cand itself is freed.
+ */
+void toptree_free(struct toptree *cand)
+{
+       struct toptree *child, *tmp;
+
+       if (cand->parent)
+               toptree_remove(cand);
+       toptree_for_each_child_safe(child, tmp, cand)
+               toptree_free(child);
+       kfree(cand);
+}
+
+/**
+ * toptree_update_mask - Update node bitmasks
+ * @cand: Pointer to a tree node
+ *
+ * The node's cpumask will be updated by combining all children's
+ * masks. Then toptree_update_mask is called recursively for the
+ * parent if applicable.
+ *
+ * NOTE:
+ * This must not be called on leaves. If called on a leaf, its
+ * CPU mask is cleared and lost.
+ */
+void toptree_update_mask(struct toptree *cand)
+{
+       struct toptree *child;
+
+       cpumask_clear(&cand->mask);
+       list_for_each_entry(child, &cand->children, sibling)
+               cpumask_or(&cand->mask, &cand->mask, &child->mask);
+       if (cand->parent)
+               toptree_update_mask(cand->parent);
+}
+
+/**
+ * toptree_insert - Insert a tree node into tree
+ * @cand: Pointer to the node to insert
+ * @target: Pointer to the node to which @cand will added as a child
+ *
+ * Insert a tree node into a tree. Masks will be updated automatically.
+ *
+ * RETURNS:
+ * 0 on success, -1 if NULL is passed as argument or the node levels
+ * don't fit.
+ */
+static int toptree_insert(struct toptree *cand, struct toptree *target)
+{
+       if (!cand || !target)
+               return -1;
+       if (target->level != (cand->level + 1))
+               return -1;
+       list_add_tail(&cand->sibling, &target->children);
+       cand->parent = target;
+       toptree_update_mask(target);
+       return 0;
+}
+
+/**
+ * toptree_move_children - Move all child nodes of a node to a new place
+ * @cand: Pointer to the node whose children are to be moved
+ * @target: Pointer to the node to which @cand's children will be attached
+ *
+ * Take all child nodes of @cand and move them using toptree_move.
+ */
+static void toptree_move_children(struct toptree *cand, struct toptree *target)
+{
+       struct toptree *child, *tmp;
+
+       toptree_for_each_child_safe(child, tmp, cand)
+               toptree_move(child, target);
+}
+
+/**
+ * toptree_unify - Merge children with same ID
+ * @cand: Pointer to node whose direct children should be made unique
+ *
+ * When mangling the tree it is possible that a node has two or more children
+ * which have the same ID. This routine merges these children into one and
+ * moves all children of the merged nodes into the unified node.
+ */
+void toptree_unify(struct toptree *cand)
+{
+       struct toptree *child, *tmp, *cand_copy;
+
+       /* Threads cannot be split, cores are not split */
+       if (cand->level < 2)
+               return;
+
+       cand_copy = toptree_alloc(cand->level, 0);
+       toptree_for_each_child_safe(child, tmp, cand) {
+               struct toptree *tmpchild;
+
+               if (!cpumask_empty(&child->mask)) {
+                       tmpchild = toptree_get_child(cand_copy, child->id);
+                       toptree_move_children(child, tmpchild);
+               }
+               toptree_free(child);
+       }
+       toptree_move_children(cand_copy, cand);
+       toptree_free(cand_copy);
+
+       toptree_for_each_child(child, cand)
+               toptree_unify(child);
+}
+
+/**
+ * toptree_move - Move a node to another context
+ * @cand: Pointer to the node to move
+ * @target: Pointer to the node where @cand should go
+ *
+ * In the easiest case @cand is exactly on the level below @target
+ * and will be immediately moved to the target.
+ *
+ * If @target's level is not the direct parent level of @cand,
+ * nodes for the missing levels are created and put between
+ * @cand and @target. The "stacking" nodes' IDs are taken from
+ * @cand's parents.
+ *
+ * After this it is likely to have redundant nodes in the tree
+ * which are addressed by means of toptree_unify.
+ */
+void toptree_move(struct toptree *cand, struct toptree *target)
+{
+       struct toptree *stack_target, *real_insert_point, *ptr, *tmp;
+
+       if (cand->level + 1 == target->level) {
+               toptree_remove(cand);
+               toptree_insert(cand, target);
+               return;
+       }
+
+       real_insert_point = NULL;
+       ptr = cand;
+       stack_target = NULL;
+
+       do {
+               tmp = stack_target;
+               stack_target = toptree_alloc(ptr->level + 1,
+                                            ptr->parent->id);
+               toptree_insert(tmp, stack_target);
+               if (!real_insert_point)
+                       real_insert_point = stack_target;
+               ptr = ptr->parent;
+       } while (stack_target->level < (target->level - 1));
+
+       toptree_remove(cand);
+       toptree_insert(cand, real_insert_point);
+       toptree_insert(stack_target, target);
+}
+
+/**
+ * toptree_get_child - Access a tree node's child by its ID
+ * @cand: Pointer to tree node whose child is to access
+ * @id: The desired child's ID
+ *
+ * @cand's children are searched for a child with matching ID.
+ * If no match can be found, a new child with the desired ID
+ * is created and returned.
+ */
+struct toptree *toptree_get_child(struct toptree *cand, int id)
+{
+       struct toptree *child;
+
+       toptree_for_each_child(child, cand)
+               if (child->id == id)
+                       return child;
+       child = toptree_alloc(cand->level-1, id);
+       toptree_insert(child, cand);
+       return child;
+}
+
+/**
+ * toptree_first - Find the first descendant on specified level
+ * @context: Pointer to tree node whose descendants are to be used
+ * @level: The level of interest
+ *
+ * RETURNS:
+ * @context's first descendant on the specified level, or NULL
+ * if there is no matching descendant
+ */
+struct toptree *toptree_first(struct toptree *context, int level)
+{
+       struct toptree *child, *tmp;
+
+       if (context->level == level)
+               return context;
+
+       if (!list_empty(&context->children)) {
+               list_for_each_entry(child, &context->children, sibling) {
+                       tmp = toptree_first(child, level);
+                       if (tmp)
+                               return tmp;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * toptree_next_sibling - Return next sibling
+ * @cur: Pointer to a tree node
+ *
+ * RETURNS:
+ * If @cur has a parent and is not the last in the parent's children list,
+ * the next sibling is returned. Or NULL when there are no siblings left.
+ */
+static struct toptree *toptree_next_sibling(struct toptree *cur)
+{
+       if (cur->parent == NULL)
+               return NULL;
+
+       if (cur == list_last_entry(&cur->parent->children,
+                                  struct toptree, sibling))
+               return NULL;
+       return (struct toptree *) list_next_entry(cur, sibling);
+}
+
+/**
+ * toptree_next - Tree traversal function
+ * @cur: Pointer to current element
+ * @context: Pointer to the root node of the tree or subtree to
+ * be traversed.
+ * @level: The level of interest.
+ *
+ * RETURNS:
+ * Pointer to the next node on level @level
+ * or NULL when there is no next node.
+ */
+struct toptree *toptree_next(struct toptree *cur, struct toptree *context,
+                            int level)
+{
+       struct toptree *cur_context, *tmp;
+
+       if (!cur)
+               return NULL;
+
+       if (context->level == level)
+               return NULL;
+
+       tmp = toptree_next_sibling(cur);
+       if (tmp != NULL)
+               return tmp;
+
+       cur_context = cur;
+       while (cur_context->level < context->level - 1) {
+               /* Step up */
+               cur_context = cur_context->parent;
+               /* Step aside */
+               tmp = toptree_next_sibling(cur_context);
+               if (tmp != NULL) {
+                       /* Step down */
+                       tmp = toptree_first(tmp, level);
+                       if (tmp != NULL)
+                               return tmp;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * toptree_count - Count descendants on specified level
+ * @context: Pointer to node whose descendants are to be considered
+ * @level: Only descendants on the specified level will be counted
+ *
+ * RETURNS:
+ * Number of descendants on the specified level
+ */
+int toptree_count(struct toptree *context, int level)
+{
+       struct toptree *cur;
+       int cnt = 0;
+
+       toptree_for_each(cur, context, level)
+               cnt++;
+       return cnt;
+}
diff --git a/arch/s390/numa/toptree.h b/arch/s390/numa/toptree.h
new file mode 100644 (file)
index 0000000..bdf5020
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * NUMA support for s390
+ *
+ * A tree structure used for machine topology mangling
+ *
+ * Copyright IBM Corp. 2015
+ */
+#ifndef S390_TOPTREE_H
+#define S390_TOPTREE_H
+
+#include <linux/cpumask.h>
+#include <linux/list.h>
+
+struct toptree {
+       int level;
+       int id;
+       cpumask_t mask;
+       struct toptree *parent;
+       struct list_head sibling;
+       struct list_head children;
+};
+
+struct toptree *toptree_alloc(int level, int id);
+void toptree_free(struct toptree *cand);
+void toptree_update_mask(struct toptree *cand);
+void toptree_unify(struct toptree *cand);
+struct toptree *toptree_get_child(struct toptree *cand, int id);
+void toptree_move(struct toptree *cand, struct toptree *target);
+int toptree_count(struct toptree *context, int level);
+
+struct toptree *toptree_first(struct toptree *context, int level);
+struct toptree *toptree_next(struct toptree *cur, struct toptree *context,
+                            int level);
+
+#define toptree_for_each_child(child, ptree)                           \
+       list_for_each_entry(child,  &ptree->children, sibling)
+
+#define toptree_for_each_child_safe(child, ptmp, ptree)                        \
+       list_for_each_entry_safe(child, ptmp, &ptree->children, sibling)
+
+#define toptree_is_last(ptree)                                 \
+       ((ptree->parent == NULL) ||                             \
+        (ptree->parent->children.prev == &ptree->sibling))
+
+#define toptree_for_each(ptree, cont, ttype)           \
+       for (ptree = toptree_first(cont, ttype);        \
+            ptree != NULL;                             \
+            ptree = toptree_next(ptree, cont, ttype))
+
+#define toptree_for_each_safe(ptree, tmp, cont, ttype)         \
+       for (ptree = toptree_first(cont, ttype),                \
+                    tmp = toptree_next(ptree, cont, ttype);    \
+            ptree != NULL;                                     \
+            ptree = tmp,                                       \
+                    tmp = toptree_next(ptree, cont, ttype))
+
+#define toptree_for_each_sibling(ptree, start)                 \
+       toptree_for_each(ptree, start->parent, start->level)
+
+#endif /* S390_TOPTREE_H */
index 598f023cf8a6b9bf81634ea4db543f5b3bcb9884..17c04c7269e79d1d1c4c69ccc46769b07d62339e 100644 (file)
@@ -76,11 +76,6 @@ EXPORT_SYMBOL_GPL(zpci_iomap_start);
 
 static struct kmem_cache *zdev_fmb_cache;
 
-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;
@@ -269,7 +264,7 @@ void __iomem *pci_iomap_range(struct pci_dev *pdev,
                              unsigned long offset,
                              unsigned long max)
 {
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
        u64 addr;
        int idx;
 
@@ -385,7 +380,7 @@ static void zpci_irq_handler(struct airq_struct *airq)
 
 int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
        unsigned int hwirq, msi_vecs;
        unsigned long aisb;
        struct msi_desc *msi;
@@ -460,7 +455,7 @@ out:
 
 void arch_teardown_msi_irqs(struct pci_dev *pdev)
 {
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
        struct msi_desc *msi;
        int rc;
 
@@ -637,7 +632,7 @@ static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
        int i;
 
        for (i = 0; i < PCI_BAR_COUNT; i++) {
-               if (!zdev->bars[i].size)
+               if (!zdev->bars[i].size || !zdev->bars[i].res)
                        continue;
 
                zpci_free_iomap(zdev, zdev->bars[i].map_idx);
@@ -648,7 +643,7 @@ static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
 
 int pcibios_add_device(struct pci_dev *pdev)
 {
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
        struct resource *res;
        int i;
 
@@ -673,7 +668,7 @@ void pcibios_release_device(struct pci_dev *pdev)
 
 int pcibios_enable_device(struct pci_dev *pdev, int mask)
 {
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
 
        zdev->pdev = pdev;
        zpci_debug_init_device(zdev);
@@ -684,7 +679,7 @@ int pcibios_enable_device(struct pci_dev *pdev, int mask)
 
 void pcibios_disable_device(struct pci_dev *pdev)
 {
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
 
        zpci_fmb_disable_device(zdev);
        zpci_debug_exit_device(zdev);
@@ -695,7 +690,7 @@ void pcibios_disable_device(struct pci_dev *pdev)
 static int zpci_restore(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
        int ret = 0;
 
        if (zdev->state != ZPCI_FN_STATE_ONLINE)
@@ -717,7 +712,7 @@ out:
 static int zpci_freeze(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
 
        if (zdev->state != ZPCI_FN_STATE_ONLINE)
                return 0;
@@ -777,17 +772,22 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
 
        ret = zpci_setup_bus_resources(zdev, &resources);
        if (ret)
-               return ret;
+               goto error;
 
        zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
                                      zdev, &resources);
        if (!zdev->bus) {
-               zpci_cleanup_bus_resources(zdev);
-               return -EIO;
+               ret = -EIO;
+               goto error;
        }
        zdev->bus->max_bus_speed = zdev->max_bus_speed;
        pci_bus_add_devices(zdev->bus);
        return 0;
+
+error:
+       zpci_cleanup_bus_resources(zdev);
+       pci_free_resource_list(&resources);
+       return ret;
 }
 
 int zpci_enable_device(struct zpci_dev *zdev)
index 6fd8d583613807904eac33ab9ce5030709545f73..42b76580c8b8a6fa155da58f106d83096089389b 100644 (file)
@@ -277,7 +277,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
                                     enum dma_data_direction direction,
                                     struct dma_attrs *attrs)
 {
-       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        unsigned long nr_pages, iommu_page_index;
        unsigned long pa = page_to_phys(page) + offset;
        int flags = ZPCI_PTE_VALID;
@@ -316,7 +316,7 @@ 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(to_pci_dev(dev));
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        unsigned long iommu_page_index;
        int npages;
 
@@ -337,7 +337,7 @@ static void *s390_dma_alloc(struct device *dev, size_t size,
                            dma_addr_t *dma_handle, gfp_t flag,
                            struct dma_attrs *attrs)
 {
-       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        struct page *page;
        unsigned long pa;
        dma_addr_t map;
@@ -367,7 +367,7 @@ static void s390_dma_free(struct device *dev, size_t size,
                          void *pa, dma_addr_t dma_handle,
                          struct dma_attrs *attrs)
 {
-       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
 
        size = PAGE_ALIGN(size);
        atomic64_sub(size / PAGE_SIZE, &zdev->allocated_pages);
index ed2394dd14e92faf57ac34b63ef49731f08ade68..369a3e05d468dbf1973df24c77e4ae07e580c3b6 100644 (file)
@@ -46,15 +46,13 @@ struct zpci_ccdf_avail {
 static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
 {
        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
+       struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
 
        zpci_err("error CCDF:\n");
        zpci_err_hex(ccdf, sizeof(*ccdf));
 
-       if (!zdev)
-               return;
-
        pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
-              pci_name(zdev->pdev), ccdf->pec, ccdf->fid);
+              pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
 }
 
 void zpci_event_error(void *data)
@@ -89,7 +87,9 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                ret = zpci_enable_device(zdev);
                if (ret)
                        break;
+               pci_lock_rescan_remove();
                pci_rescan_bus(zdev->bus);
+               pci_unlock_rescan_remove();
                break;
        case 0x0302: /* Reserved -> Standby */
                if (!zdev)
@@ -97,7 +97,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                break;
        case 0x0303: /* Deconfiguration requested */
                if (pdev)
-                       pci_stop_and_remove_bus_device(pdev);
+                       pci_stop_and_remove_bus_device_locked(pdev);
 
                ret = zpci_disable_device(zdev);
                if (ret)
@@ -114,7 +114,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                        /* Give the driver a hint that the function is
                         * already unusable. */
                        pdev->error_state = pci_channel_io_perm_failure;
-                       pci_stop_and_remove_bus_device(pdev);
+                       pci_stop_and_remove_bus_device_locked(pdev);
                }
 
                zdev->fh = ccdf->fh;
index 85267c058af8067d1b6527f05ec483ab0a15c8b0..dcc2634ccbe295d9746a06909dae99fca5c91780 100644 (file)
@@ -8,10 +8,23 @@
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <asm/pci_insn.h>
+#include <asm/pci_debug.h>
 #include <asm/processor.h>
 
 #define ZPCI_INSN_BUSY_DELAY   1       /* 1 microsecond */
 
+static inline void zpci_err_insn(u8 cc, u8 status, u64 req, u64 offset)
+{
+       struct {
+               u8 cc;
+               u8 status;
+               u64 req;
+               u64 offset;
+       } data = {cc, status, req, offset};
+
+       zpci_err_hex(&data, sizeof(data));
+}
+
 /* Modify PCI Function Controls */
 static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
 {
@@ -38,8 +51,8 @@ int zpci_mod_fc(u64 req, struct zpci_fib *fib)
        } while (cc == 2);
 
        if (cc)
-               printk_once(KERN_ERR "%s: error cc: %d  status: %d\n",
-                            __func__, cc, status);
+               zpci_err_insn(cc, status, req, 0);
+
        return (cc) ? -EIO : 0;
 }
 
@@ -72,8 +85,8 @@ int zpci_refresh_trans(u64 fn, u64 addr, u64 range)
        } 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);
+               zpci_err_insn(cc, status, addr, range);
+
        return (cc) ? -EIO : 0;
 }
 
@@ -121,8 +134,8 @@ int zpci_load(u64 *data, u64 req, u64 offset)
        } 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);
+               zpci_err_insn(cc, status, req, offset);
+
        return (cc > 0) ? -EIO : cc;
 }
 EXPORT_SYMBOL_GPL(zpci_load);
@@ -159,8 +172,8 @@ int zpci_store(u64 data, u64 req, u64 offset)
        } 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);
+               zpci_err_insn(cc, status, req, offset);
+
        return (cc > 0) ? -EIO : cc;
 }
 EXPORT_SYMBOL_GPL(zpci_store);
@@ -195,8 +208,8 @@ int zpci_store_block(const u64 *data, u64 req, u64 offset)
        } 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);
+               zpci_err_insn(cc, status, req, offset);
+
        return (cc > 0) ? -EIO : cc;
 }
 EXPORT_SYMBOL_GPL(zpci_store_block);
index fa3ce891e5976196d1d4225fbf286226509266e1..f37a5808883dd8c782988f2ab995dda5b1f1340a 100644 (file)
@@ -16,7 +16,7 @@
 static ssize_t name##_show(struct device *dev,                         \
                           struct device_attribute *attr, char *buf)    \
 {                                                                      \
-       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));              \
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));               \
                                                                        \
        return sprintf(buf, fmt, zdev->member);                         \
 }                                                                      \
@@ -38,23 +38,30 @@ static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
        int ret;
 
        if (!device_remove_file_self(dev, attr))
                return count;
 
+       pci_lock_rescan_remove();
        pci_stop_and_remove_bus_device(pdev);
        ret = zpci_disable_device(zdev);
        if (ret)
-               return ret;
+               goto error;
 
        ret = zpci_enable_device(zdev);
        if (ret)
-               return ret;
+               goto error;
 
        pci_rescan_bus(zdev->bus);
+       pci_unlock_rescan_remove();
+
        return count;
+
+error:
+       pci_unlock_rescan_remove();
+       return ret;
 }
 static DEVICE_ATTR_WO(recover);
 
@@ -64,7 +71,7 @@ static ssize_t util_string_read(struct file *filp, struct kobject *kobj,
 {
        struct device *dev = kobj_to_dev(kobj);
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct zpci_dev *zdev = get_zdev(pdev);
+       struct zpci_dev *zdev = to_zpci(pdev);
 
        return memory_read_from_buffer(buf, count, &off, zdev->util_str,
                                       sizeof(zdev->util_str));
index cbf763b3015eb6ccb50608f5f53efc909ed60570..0288efc17ff3787c53bbfdf41e7f0f8492a4bd16 100644 (file)
 
 #include <asm/io.h>
 
-/* startup values */
-#define PCI_PROBE_BIOS         1
-#define PCI_PROBE_CONF1                2
-#define PCI_PROBE_CONF2                4
-#define PCI_NO_CHECKS          0x400
-#define PCI_ASSIGN_ROMS                0x1000
-#define PCI_BIOS_IRQ_SCAN      0x2000
-
 #define SH4_PCICR              0x100           /* PCI Control Register */
   #define SH4_PCICR_PREFIX       0xA5000000    /* CR prefix for write */
   #define SH4_PCICR_FTO                  0x00000400    /* TRDY/IRDY Enable */
index 0a47bd3e7bee1b20e94fa64a323319ae4dc26a54..4ca78ed71ad2c8ff33707fb8a472d55b553de36e 100644 (file)
@@ -355,13 +355,12 @@ static int sq_dev_add(struct device *dev, struct subsys_interface *sif)
        return error;
 }
 
-static int sq_dev_remove(struct device *dev, struct subsys_interface *sif)
+static void sq_dev_remove(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int cpu = dev->id;
        struct kobject *kobj = sq_kobject[cpu];
 
        kobject_put(kobj);
-       return 0;
 }
 
 static struct subsys_interface sq_interface = {
index c928bc64b4bac1b1c5eb88c71c348469796883c5..3a0e1a986bfe3cf89c9f3cb92ac04c056b0f86eb 100644 (file)
@@ -249,7 +249,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
                                         struct pci_bus *bus, int devfn)
 {
        struct dev_archdata *sd;
-       struct pci_slot *slot;
        struct platform_device *op;
        struct pci_dev *dev;
        const char *type;
@@ -290,10 +289,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
        dev->multifunction = 0;         /* maybe a lie? */
        set_pcie_port_type(dev);
 
-       list_for_each_entry(slot, &dev->bus->slots, list)
-               if (PCI_SLOT(dev->devfn) == slot->number)
-                       dev->slot = slot;
-
+       pci_dev_assign_slot(dev);
        dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff);
        dev->device = of_getintprop_default(node, "device-id", 0xffff);
        dev->subsystem_vendor =
index a3ed12f8f83bf2c894e3b6eedf8e250a9e7f8312..825867c5385304e3816a7b88f042330522c89443 100644 (file)
@@ -198,16 +198,13 @@ static int hv_stats_device_add(struct device *dev, struct subsys_interface *sif)
        return err;
 }
 
-static int hv_stats_device_remove(struct device *dev,
-                                 struct subsys_interface *sif)
+static void hv_stats_device_remove(struct device *dev,
+                                  struct subsys_interface *sif)
 {
        int cpu = dev->id;
 
-       if (!cpu_online(cpu))
-               return 0;
-
-       sysfs_remove_file(&dev->kobj, &dev_attr_hv_stats.attr);
-       return 0;
+       if (cpu_online(cpu))
+               sysfs_remove_file(&dev->kobj, &dev_attr_hv_stats.attr);
 }
 
 
index 5a4a089e8b1fd7166e396b52917424e1d9a421b5..9a2838cf05916a132ee573ad4c0061138fda716a 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
+obj-$(CONFIG_CRYPTO_CHACHA20_X86_64) += chacha20-x86_64.o
 obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o
 obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
 obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o
 obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o
 obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o
 obj-$(CONFIG_CRYPTO_CRCT10DIF_PCLMUL) += crct10dif-pclmul.o
+obj-$(CONFIG_CRYPTO_POLY1305_X86_64) += poly1305-x86_64.o
 
 # These modules require assembler to support AVX.
 ifeq ($(avx_supported),yes)
@@ -60,6 +62,7 @@ blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
 twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
+chacha20-x86_64-y := chacha20-ssse3-x86_64.o chacha20_glue.o
 serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o
 
 ifeq ($(avx_supported),yes)
@@ -75,6 +78,7 @@ endif
 
 ifeq ($(avx2_supported),yes)
        camellia-aesni-avx2-y := camellia-aesni-avx2-asm_64.o camellia_aesni_avx2_glue.o
+       chacha20-x86_64-y += chacha20-avx2-x86_64.o
        serpent-avx2-y := serpent-avx2-asm_64.o serpent_avx2_glue.o
 endif
 
@@ -82,8 +86,10 @@ aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
 aesni-intel-$(CONFIG_64BIT) += aesni-intel_avx-x86_64.o aes_ctrby8_avx-x86_64.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
+poly1305-x86_64-y := poly1305-sse2-x86_64.o poly1305_glue.o
 ifeq ($(avx2_supported),yes)
 sha1-ssse3-y += sha1_avx2_x86_64_asm.o
+poly1305-x86_64-y += poly1305-avx2-x86_64.o
 endif
 crc32c-intel-y := crc32c-intel_glue.o
 crc32c-intel-$(CONFIG_64BIT) += crc32c-pcl-intel-asm_64.o
index dccad38b59a8d741fe5f442b558b63de2b4d931d..3633ad6145c5229a57f40ccf30421916872d4f2a 100644 (file)
@@ -803,10 +803,7 @@ static int rfc4106_init(struct crypto_aead *aead)
                return PTR_ERR(cryptd_tfm);
 
        *ctx = cryptd_tfm;
-       crypto_aead_set_reqsize(
-               aead,
-               sizeof(struct aead_request) +
-               crypto_aead_reqsize(&cryptd_tfm->base));
+       crypto_aead_set_reqsize(aead, crypto_aead_reqsize(&cryptd_tfm->base));
        return 0;
 }
 
@@ -955,8 +952,8 @@ static int helper_rfc4106_encrypt(struct aead_request *req)
 
        /* Assuming we are supporting rfc4106 64-bit extended */
        /* sequence numbers We need to have the AAD length equal */
-       /* to 8 or 12 bytes */
-       if (unlikely(req->assoclen != 8 && req->assoclen != 12))
+       /* to 16 or 20 bytes */
+       if (unlikely(req->assoclen != 16 && req->assoclen != 20))
                return -EINVAL;
 
        /* IV below built */
@@ -992,9 +989,9 @@ static int helper_rfc4106_encrypt(struct aead_request *req)
        }
 
        kernel_fpu_begin();
-       aesni_gcm_enc_tfm(aes_ctx, dst, src, (unsigned long)req->cryptlen, iv,
-               ctx->hash_subkey, assoc, (unsigned long)req->assoclen, dst
-               + ((unsigned long)req->cryptlen), auth_tag_len);
+       aesni_gcm_enc_tfm(aes_ctx, dst, src, req->cryptlen, iv,
+                         ctx->hash_subkey, assoc, req->assoclen - 8,
+                         dst + req->cryptlen, auth_tag_len);
        kernel_fpu_end();
 
        /* The authTag (aka the Integrity Check Value) needs to be written
@@ -1033,12 +1030,12 @@ static int helper_rfc4106_decrypt(struct aead_request *req)
        struct scatter_walk dst_sg_walk;
        unsigned int i;
 
-       if (unlikely(req->assoclen != 8 && req->assoclen != 12))
+       if (unlikely(req->assoclen != 16 && req->assoclen != 20))
                return -EINVAL;
 
        /* Assuming we are supporting rfc4106 64-bit extended */
        /* sequence numbers We need to have the AAD length */
-       /* equal to 8 or 12 bytes */
+       /* equal to 16 or 20 bytes */
 
        tempCipherLen = (unsigned long)(req->cryptlen - auth_tag_len);
        /* IV below built */
@@ -1075,8 +1072,8 @@ static int helper_rfc4106_decrypt(struct aead_request *req)
 
        kernel_fpu_begin();
        aesni_gcm_dec_tfm(aes_ctx, dst, src, tempCipherLen, iv,
-               ctx->hash_subkey, assoc, (unsigned long)req->assoclen,
-               authTag, auth_tag_len);
+                         ctx->hash_subkey, assoc, req->assoclen - 8,
+                         authTag, auth_tag_len);
        kernel_fpu_end();
 
        /* Compare generated tag with passed in tag. */
@@ -1105,19 +1102,12 @@ static int rfc4106_encrypt(struct aead_request *req)
        struct crypto_aead *tfm = crypto_aead_reqtfm(req);
        struct cryptd_aead **ctx = crypto_aead_ctx(tfm);
        struct cryptd_aead *cryptd_tfm = *ctx;
-       struct aead_request *subreq = aead_request_ctx(req);
 
-       aead_request_set_tfm(subreq, irq_fpu_usable() ?
-                                    cryptd_aead_child(cryptd_tfm) :
-                                    &cryptd_tfm->base);
+       aead_request_set_tfm(req, irq_fpu_usable() ?
+                                 cryptd_aead_child(cryptd_tfm) :
+                                 &cryptd_tfm->base);
 
-       aead_request_set_callback(subreq, req->base.flags,
-                                 req->base.complete, req->base.data);
-       aead_request_set_crypt(subreq, req->src, req->dst,
-                              req->cryptlen, req->iv);
-       aead_request_set_ad(subreq, req->assoclen);
-
-       return crypto_aead_encrypt(subreq);
+       return crypto_aead_encrypt(req);
 }
 
 static int rfc4106_decrypt(struct aead_request *req)
@@ -1125,19 +1115,12 @@ static int rfc4106_decrypt(struct aead_request *req)
        struct crypto_aead *tfm = crypto_aead_reqtfm(req);
        struct cryptd_aead **ctx = crypto_aead_ctx(tfm);
        struct cryptd_aead *cryptd_tfm = *ctx;
-       struct aead_request *subreq = aead_request_ctx(req);
-
-       aead_request_set_tfm(subreq, irq_fpu_usable() ?
-                                    cryptd_aead_child(cryptd_tfm) :
-                                    &cryptd_tfm->base);
 
-       aead_request_set_callback(subreq, req->base.flags,
-                                 req->base.complete, req->base.data);
-       aead_request_set_crypt(subreq, req->src, req->dst,
-                              req->cryptlen, req->iv);
-       aead_request_set_ad(subreq, req->assoclen);
+       aead_request_set_tfm(req, irq_fpu_usable() ?
+                                 cryptd_aead_child(cryptd_tfm) :
+                                 &cryptd_tfm->base);
 
-       return crypto_aead_decrypt(subreq);
+       return crypto_aead_decrypt(req);
 }
 #endif
 
diff --git a/arch/x86/crypto/chacha20-avx2-x86_64.S b/arch/x86/crypto/chacha20-avx2-x86_64.S
new file mode 100644 (file)
index 0000000..16694e6
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, x64 AVX2 functions
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+.data
+.align 32
+
+ROT8:  .octa 0x0e0d0c0f0a09080b0605040702010003
+       .octa 0x0e0d0c0f0a09080b0605040702010003
+ROT16: .octa 0x0d0c0f0e09080b0a0504070601000302
+       .octa 0x0d0c0f0e09080b0a0504070601000302
+CTRINC:        .octa 0x00000003000000020000000100000000
+       .octa 0x00000007000000060000000500000004
+
+.text
+
+ENTRY(chacha20_8block_xor_avx2)
+       # %rdi: Input state matrix, s
+       # %rsi: 8 data blocks output, o
+       # %rdx: 8 data blocks input, i
+
+       # This function encrypts eight consecutive ChaCha20 blocks by loading
+       # the state matrix in AVX registers eight times. As we need some
+       # scratch registers, we save the first four registers on the stack. The
+       # algorithm performs each operation on the corresponding word of each
+       # state matrix, hence requires no word shuffling. For final XORing step
+       # we transpose the matrix by interleaving 32-, 64- and then 128-bit
+       # words, which allows us to do XOR in AVX registers. 8/16-bit word
+       # rotation is done with the slightly better performing byte shuffling,
+       # 7/12-bit word rotation uses traditional shift+OR.
+
+       vzeroupper
+       # 4 * 32 byte stack, 32-byte aligned
+       mov             %rsp, %r8
+       and             $~31, %rsp
+       sub             $0x80, %rsp
+
+       # x0..15[0-7] = s[0..15]
+       vpbroadcastd    0x00(%rdi),%ymm0
+       vpbroadcastd    0x04(%rdi),%ymm1
+       vpbroadcastd    0x08(%rdi),%ymm2
+       vpbroadcastd    0x0c(%rdi),%ymm3
+       vpbroadcastd    0x10(%rdi),%ymm4
+       vpbroadcastd    0x14(%rdi),%ymm5
+       vpbroadcastd    0x18(%rdi),%ymm6
+       vpbroadcastd    0x1c(%rdi),%ymm7
+       vpbroadcastd    0x20(%rdi),%ymm8
+       vpbroadcastd    0x24(%rdi),%ymm9
+       vpbroadcastd    0x28(%rdi),%ymm10
+       vpbroadcastd    0x2c(%rdi),%ymm11
+       vpbroadcastd    0x30(%rdi),%ymm12
+       vpbroadcastd    0x34(%rdi),%ymm13
+       vpbroadcastd    0x38(%rdi),%ymm14
+       vpbroadcastd    0x3c(%rdi),%ymm15
+       # x0..3 on stack
+       vmovdqa         %ymm0,0x00(%rsp)
+       vmovdqa         %ymm1,0x20(%rsp)
+       vmovdqa         %ymm2,0x40(%rsp)
+       vmovdqa         %ymm3,0x60(%rsp)
+
+       vmovdqa         CTRINC(%rip),%ymm1
+       vmovdqa         ROT8(%rip),%ymm2
+       vmovdqa         ROT16(%rip),%ymm3
+
+       # x12 += counter values 0-3
+       vpaddd          %ymm1,%ymm12,%ymm12
+
+       mov             $10,%ecx
+
+.Ldoubleround8:
+       # x0 += x4, x12 = rotl32(x12 ^ x0, 16)
+       vpaddd          0x00(%rsp),%ymm4,%ymm0
+       vmovdqa         %ymm0,0x00(%rsp)
+       vpxor           %ymm0,%ymm12,%ymm12
+       vpshufb         %ymm3,%ymm12,%ymm12
+       # x1 += x5, x13 = rotl32(x13 ^ x1, 16)
+       vpaddd          0x20(%rsp),%ymm5,%ymm0
+       vmovdqa         %ymm0,0x20(%rsp)
+       vpxor           %ymm0,%ymm13,%ymm13
+       vpshufb         %ymm3,%ymm13,%ymm13
+       # x2 += x6, x14 = rotl32(x14 ^ x2, 16)
+       vpaddd          0x40(%rsp),%ymm6,%ymm0
+       vmovdqa         %ymm0,0x40(%rsp)
+       vpxor           %ymm0,%ymm14,%ymm14
+       vpshufb         %ymm3,%ymm14,%ymm14
+       # x3 += x7, x15 = rotl32(x15 ^ x3, 16)
+       vpaddd          0x60(%rsp),%ymm7,%ymm0
+       vmovdqa         %ymm0,0x60(%rsp)
+       vpxor           %ymm0,%ymm15,%ymm15
+       vpshufb         %ymm3,%ymm15,%ymm15
+
+       # x8 += x12, x4 = rotl32(x4 ^ x8, 12)
+       vpaddd          %ymm12,%ymm8,%ymm8
+       vpxor           %ymm8,%ymm4,%ymm4
+       vpslld          $12,%ymm4,%ymm0
+       vpsrld          $20,%ymm4,%ymm4
+       vpor            %ymm0,%ymm4,%ymm4
+       # x9 += x13, x5 = rotl32(x5 ^ x9, 12)
+       vpaddd          %ymm13,%ymm9,%ymm9
+       vpxor           %ymm9,%ymm5,%ymm5
+       vpslld          $12,%ymm5,%ymm0
+       vpsrld          $20,%ymm5,%ymm5
+       vpor            %ymm0,%ymm5,%ymm5
+       # x10 += x14, x6 = rotl32(x6 ^ x10, 12)
+       vpaddd          %ymm14,%ymm10,%ymm10
+       vpxor           %ymm10,%ymm6,%ymm6
+       vpslld          $12,%ymm6,%ymm0
+       vpsrld          $20,%ymm6,%ymm6
+       vpor            %ymm0,%ymm6,%ymm6
+       # x11 += x15, x7 = rotl32(x7 ^ x11, 12)
+       vpaddd          %ymm15,%ymm11,%ymm11
+       vpxor           %ymm11,%ymm7,%ymm7
+       vpslld          $12,%ymm7,%ymm0
+       vpsrld          $20,%ymm7,%ymm7
+       vpor            %ymm0,%ymm7,%ymm7
+
+       # x0 += x4, x12 = rotl32(x12 ^ x0, 8)
+       vpaddd          0x00(%rsp),%ymm4,%ymm0
+       vmovdqa         %ymm0,0x00(%rsp)
+       vpxor           %ymm0,%ymm12,%ymm12
+       vpshufb         %ymm2,%ymm12,%ymm12
+       # x1 += x5, x13 = rotl32(x13 ^ x1, 8)
+       vpaddd          0x20(%rsp),%ymm5,%ymm0
+       vmovdqa         %ymm0,0x20(%rsp)
+       vpxor           %ymm0,%ymm13,%ymm13
+       vpshufb         %ymm2,%ymm13,%ymm13
+       # x2 += x6, x14 = rotl32(x14 ^ x2, 8)
+       vpaddd          0x40(%rsp),%ymm6,%ymm0
+       vmovdqa         %ymm0,0x40(%rsp)
+       vpxor           %ymm0,%ymm14,%ymm14
+       vpshufb         %ymm2,%ymm14,%ymm14
+       # x3 += x7, x15 = rotl32(x15 ^ x3, 8)
+       vpaddd          0x60(%rsp),%ymm7,%ymm0
+       vmovdqa         %ymm0,0x60(%rsp)
+       vpxor           %ymm0,%ymm15,%ymm15
+       vpshufb         %ymm2,%ymm15,%ymm15
+
+       # x8 += x12, x4 = rotl32(x4 ^ x8, 7)
+       vpaddd          %ymm12,%ymm8,%ymm8
+       vpxor           %ymm8,%ymm4,%ymm4
+       vpslld          $7,%ymm4,%ymm0
+       vpsrld          $25,%ymm4,%ymm4
+       vpor            %ymm0,%ymm4,%ymm4
+       # x9 += x13, x5 = rotl32(x5 ^ x9, 7)
+       vpaddd          %ymm13,%ymm9,%ymm9
+       vpxor           %ymm9,%ymm5,%ymm5
+       vpslld          $7,%ymm5,%ymm0
+       vpsrld          $25,%ymm5,%ymm5
+       vpor            %ymm0,%ymm5,%ymm5
+       # x10 += x14, x6 = rotl32(x6 ^ x10, 7)
+       vpaddd          %ymm14,%ymm10,%ymm10
+       vpxor           %ymm10,%ymm6,%ymm6
+       vpslld          $7,%ymm6,%ymm0
+       vpsrld          $25,%ymm6,%ymm6
+       vpor            %ymm0,%ymm6,%ymm6
+       # x11 += x15, x7 = rotl32(x7 ^ x11, 7)
+       vpaddd          %ymm15,%ymm11,%ymm11
+       vpxor           %ymm11,%ymm7,%ymm7
+       vpslld          $7,%ymm7,%ymm0
+       vpsrld          $25,%ymm7,%ymm7
+       vpor            %ymm0,%ymm7,%ymm7
+
+       # x0 += x5, x15 = rotl32(x15 ^ x0, 16)
+       vpaddd          0x00(%rsp),%ymm5,%ymm0
+       vmovdqa         %ymm0,0x00(%rsp)
+       vpxor           %ymm0,%ymm15,%ymm15
+       vpshufb         %ymm3,%ymm15,%ymm15
+       # x1 += x6, x12 = rotl32(x12 ^ x1, 16)%ymm0
+       vpaddd          0x20(%rsp),%ymm6,%ymm0
+       vmovdqa         %ymm0,0x20(%rsp)
+       vpxor           %ymm0,%ymm12,%ymm12
+       vpshufb         %ymm3,%ymm12,%ymm12
+       # x2 += x7, x13 = rotl32(x13 ^ x2, 16)
+       vpaddd          0x40(%rsp),%ymm7,%ymm0
+       vmovdqa         %ymm0,0x40(%rsp)
+       vpxor           %ymm0,%ymm13,%ymm13
+       vpshufb         %ymm3,%ymm13,%ymm13
+       # x3 += x4, x14 = rotl32(x14 ^ x3, 16)
+       vpaddd          0x60(%rsp),%ymm4,%ymm0
+       vmovdqa         %ymm0,0x60(%rsp)
+       vpxor           %ymm0,%ymm14,%ymm14
+       vpshufb         %ymm3,%ymm14,%ymm14
+
+       # x10 += x15, x5 = rotl32(x5 ^ x10, 12)
+       vpaddd          %ymm15,%ymm10,%ymm10
+       vpxor           %ymm10,%ymm5,%ymm5
+       vpslld          $12,%ymm5,%ymm0
+       vpsrld          $20,%ymm5,%ymm5
+       vpor            %ymm0,%ymm5,%ymm5
+       # x11 += x12, x6 = rotl32(x6 ^ x11, 12)
+       vpaddd          %ymm12,%ymm11,%ymm11
+       vpxor           %ymm11,%ymm6,%ymm6
+       vpslld          $12,%ymm6,%ymm0
+       vpsrld          $20,%ymm6,%ymm6
+       vpor            %ymm0,%ymm6,%ymm6
+       # x8 += x13, x7 = rotl32(x7 ^ x8, 12)
+       vpaddd          %ymm13,%ymm8,%ymm8
+       vpxor           %ymm8,%ymm7,%ymm7
+       vpslld          $12,%ymm7,%ymm0
+       vpsrld          $20,%ymm7,%ymm7
+       vpor            %ymm0,%ymm7,%ymm7
+       # x9 += x14, x4 = rotl32(x4 ^ x9, 12)
+       vpaddd          %ymm14,%ymm9,%ymm9
+       vpxor           %ymm9,%ymm4,%ymm4
+       vpslld          $12,%ymm4,%ymm0
+       vpsrld          $20,%ymm4,%ymm4
+       vpor            %ymm0,%ymm4,%ymm4
+
+       # x0 += x5, x15 = rotl32(x15 ^ x0, 8)
+       vpaddd          0x00(%rsp),%ymm5,%ymm0
+       vmovdqa         %ymm0,0x00(%rsp)
+       vpxor           %ymm0,%ymm15,%ymm15
+       vpshufb         %ymm2,%ymm15,%ymm15
+       # x1 += x6, x12 = rotl32(x12 ^ x1, 8)
+       vpaddd          0x20(%rsp),%ymm6,%ymm0
+       vmovdqa         %ymm0,0x20(%rsp)
+       vpxor           %ymm0,%ymm12,%ymm12
+       vpshufb         %ymm2,%ymm12,%ymm12
+       # x2 += x7, x13 = rotl32(x13 ^ x2, 8)
+       vpaddd          0x40(%rsp),%ymm7,%ymm0
+       vmovdqa         %ymm0,0x40(%rsp)
+       vpxor           %ymm0,%ymm13,%ymm13
+       vpshufb         %ymm2,%ymm13,%ymm13
+       # x3 += x4, x14 = rotl32(x14 ^ x3, 8)
+       vpaddd          0x60(%rsp),%ymm4,%ymm0
+       vmovdqa         %ymm0,0x60(%rsp)
+       vpxor           %ymm0,%ymm14,%ymm14
+       vpshufb         %ymm2,%ymm14,%ymm14
+
+       # x10 += x15, x5 = rotl32(x5 ^ x10, 7)
+       vpaddd          %ymm15,%ymm10,%ymm10
+       vpxor           %ymm10,%ymm5,%ymm5
+       vpslld          $7,%ymm5,%ymm0
+       vpsrld          $25,%ymm5,%ymm5
+       vpor            %ymm0,%ymm5,%ymm5
+       # x11 += x12, x6 = rotl32(x6 ^ x11, 7)
+       vpaddd          %ymm12,%ymm11,%ymm11
+       vpxor           %ymm11,%ymm6,%ymm6
+       vpslld          $7,%ymm6,%ymm0
+       vpsrld          $25,%ymm6,%ymm6
+       vpor            %ymm0,%ymm6,%ymm6
+       # x8 += x13, x7 = rotl32(x7 ^ x8, 7)
+       vpaddd          %ymm13,%ymm8,%ymm8
+       vpxor           %ymm8,%ymm7,%ymm7
+       vpslld          $7,%ymm7,%ymm0
+       vpsrld          $25,%ymm7,%ymm7
+       vpor            %ymm0,%ymm7,%ymm7
+       # x9 += x14, x4 = rotl32(x4 ^ x9, 7)
+       vpaddd          %ymm14,%ymm9,%ymm9
+       vpxor           %ymm9,%ymm4,%ymm4
+       vpslld          $7,%ymm4,%ymm0
+       vpsrld          $25,%ymm4,%ymm4
+       vpor            %ymm0,%ymm4,%ymm4
+
+       dec             %ecx
+       jnz             .Ldoubleround8
+
+       # x0..15[0-3] += s[0..15]
+       vpbroadcastd    0x00(%rdi),%ymm0
+       vpaddd          0x00(%rsp),%ymm0,%ymm0
+       vmovdqa         %ymm0,0x00(%rsp)
+       vpbroadcastd    0x04(%rdi),%ymm0
+       vpaddd          0x20(%rsp),%ymm0,%ymm0
+       vmovdqa         %ymm0,0x20(%rsp)
+       vpbroadcastd    0x08(%rdi),%ymm0
+       vpaddd          0x40(%rsp),%ymm0,%ymm0
+       vmovdqa         %ymm0,0x40(%rsp)
+       vpbroadcastd    0x0c(%rdi),%ymm0
+       vpaddd          0x60(%rsp),%ymm0,%ymm0
+       vmovdqa         %ymm0,0x60(%rsp)
+       vpbroadcastd    0x10(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm4,%ymm4
+       vpbroadcastd    0x14(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm5,%ymm5
+       vpbroadcastd    0x18(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm6,%ymm6
+       vpbroadcastd    0x1c(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm7,%ymm7
+       vpbroadcastd    0x20(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm8,%ymm8
+       vpbroadcastd    0x24(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm9,%ymm9
+       vpbroadcastd    0x28(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm10,%ymm10
+       vpbroadcastd    0x2c(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm11,%ymm11
+       vpbroadcastd    0x30(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm12,%ymm12
+       vpbroadcastd    0x34(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm13,%ymm13
+       vpbroadcastd    0x38(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm14,%ymm14
+       vpbroadcastd    0x3c(%rdi),%ymm0
+       vpaddd          %ymm0,%ymm15,%ymm15
+
+       # x12 += counter values 0-3
+       vpaddd          %ymm1,%ymm12,%ymm12
+
+       # interleave 32-bit words in state n, n+1
+       vmovdqa         0x00(%rsp),%ymm0
+       vmovdqa         0x20(%rsp),%ymm1
+       vpunpckldq      %ymm1,%ymm0,%ymm2
+       vpunpckhdq      %ymm1,%ymm0,%ymm1
+       vmovdqa         %ymm2,0x00(%rsp)
+       vmovdqa         %ymm1,0x20(%rsp)
+       vmovdqa         0x40(%rsp),%ymm0
+       vmovdqa         0x60(%rsp),%ymm1
+       vpunpckldq      %ymm1,%ymm0,%ymm2
+       vpunpckhdq      %ymm1,%ymm0,%ymm1
+       vmovdqa         %ymm2,0x40(%rsp)
+       vmovdqa         %ymm1,0x60(%rsp)
+       vmovdqa         %ymm4,%ymm0
+       vpunpckldq      %ymm5,%ymm0,%ymm4
+       vpunpckhdq      %ymm5,%ymm0,%ymm5
+       vmovdqa         %ymm6,%ymm0
+       vpunpckldq      %ymm7,%ymm0,%ymm6
+       vpunpckhdq      %ymm7,%ymm0,%ymm7
+       vmovdqa         %ymm8,%ymm0
+       vpunpckldq      %ymm9,%ymm0,%ymm8
+       vpunpckhdq      %ymm9,%ymm0,%ymm9
+       vmovdqa         %ymm10,%ymm0
+       vpunpckldq      %ymm11,%ymm0,%ymm10
+       vpunpckhdq      %ymm11,%ymm0,%ymm11
+       vmovdqa         %ymm12,%ymm0
+       vpunpckldq      %ymm13,%ymm0,%ymm12
+       vpunpckhdq      %ymm13,%ymm0,%ymm13
+       vmovdqa         %ymm14,%ymm0
+       vpunpckldq      %ymm15,%ymm0,%ymm14
+       vpunpckhdq      %ymm15,%ymm0,%ymm15
+
+       # interleave 64-bit words in state n, n+2
+       vmovdqa         0x00(%rsp),%ymm0
+       vmovdqa         0x40(%rsp),%ymm2
+       vpunpcklqdq     %ymm2,%ymm0,%ymm1
+       vpunpckhqdq     %ymm2,%ymm0,%ymm2
+       vmovdqa         %ymm1,0x00(%rsp)
+       vmovdqa         %ymm2,0x40(%rsp)
+       vmovdqa         0x20(%rsp),%ymm0
+       vmovdqa         0x60(%rsp),%ymm2
+       vpunpcklqdq     %ymm2,%ymm0,%ymm1
+       vpunpckhqdq     %ymm2,%ymm0,%ymm2
+       vmovdqa         %ymm1,0x20(%rsp)
+       vmovdqa         %ymm2,0x60(%rsp)
+       vmovdqa         %ymm4,%ymm0
+       vpunpcklqdq     %ymm6,%ymm0,%ymm4
+       vpunpckhqdq     %ymm6,%ymm0,%ymm6
+       vmovdqa         %ymm5,%ymm0
+       vpunpcklqdq     %ymm7,%ymm0,%ymm5
+       vpunpckhqdq     %ymm7,%ymm0,%ymm7
+       vmovdqa         %ymm8,%ymm0
+       vpunpcklqdq     %ymm10,%ymm0,%ymm8
+       vpunpckhqdq     %ymm10,%ymm0,%ymm10
+       vmovdqa         %ymm9,%ymm0
+       vpunpcklqdq     %ymm11,%ymm0,%ymm9
+       vpunpckhqdq     %ymm11,%ymm0,%ymm11
+       vmovdqa         %ymm12,%ymm0
+       vpunpcklqdq     %ymm14,%ymm0,%ymm12
+       vpunpckhqdq     %ymm14,%ymm0,%ymm14
+       vmovdqa         %ymm13,%ymm0
+       vpunpcklqdq     %ymm15,%ymm0,%ymm13
+       vpunpckhqdq     %ymm15,%ymm0,%ymm15
+
+       # interleave 128-bit words in state n, n+4
+       vmovdqa         0x00(%rsp),%ymm0
+       vperm2i128      $0x20,%ymm4,%ymm0,%ymm1
+       vperm2i128      $0x31,%ymm4,%ymm0,%ymm4
+       vmovdqa         %ymm1,0x00(%rsp)
+       vmovdqa         0x20(%rsp),%ymm0
+       vperm2i128      $0x20,%ymm5,%ymm0,%ymm1
+       vperm2i128      $0x31,%ymm5,%ymm0,%ymm5
+       vmovdqa         %ymm1,0x20(%rsp)
+       vmovdqa         0x40(%rsp),%ymm0
+       vperm2i128      $0x20,%ymm6,%ymm0,%ymm1
+       vperm2i128      $0x31,%ymm6,%ymm0,%ymm6
+       vmovdqa         %ymm1,0x40(%rsp)
+       vmovdqa         0x60(%rsp),%ymm0
+       vperm2i128      $0x20,%ymm7,%ymm0,%ymm1
+       vperm2i128      $0x31,%ymm7,%ymm0,%ymm7
+       vmovdqa         %ymm1,0x60(%rsp)
+       vperm2i128      $0x20,%ymm12,%ymm8,%ymm0
+       vperm2i128      $0x31,%ymm12,%ymm8,%ymm12
+       vmovdqa         %ymm0,%ymm8
+       vperm2i128      $0x20,%ymm13,%ymm9,%ymm0
+       vperm2i128      $0x31,%ymm13,%ymm9,%ymm13
+       vmovdqa         %ymm0,%ymm9
+       vperm2i128      $0x20,%ymm14,%ymm10,%ymm0
+       vperm2i128      $0x31,%ymm14,%ymm10,%ymm14
+       vmovdqa         %ymm0,%ymm10
+       vperm2i128      $0x20,%ymm15,%ymm11,%ymm0
+       vperm2i128      $0x31,%ymm15,%ymm11,%ymm15
+       vmovdqa         %ymm0,%ymm11
+
+       # xor with corresponding input, write to output
+       vmovdqa         0x00(%rsp),%ymm0
+       vpxor           0x0000(%rdx),%ymm0,%ymm0
+       vmovdqu         %ymm0,0x0000(%rsi)
+       vmovdqa         0x20(%rsp),%ymm0
+       vpxor           0x0080(%rdx),%ymm0,%ymm0
+       vmovdqu         %ymm0,0x0080(%rsi)
+       vmovdqa         0x40(%rsp),%ymm0
+       vpxor           0x0040(%rdx),%ymm0,%ymm0
+       vmovdqu         %ymm0,0x0040(%rsi)
+       vmovdqa         0x60(%rsp),%ymm0
+       vpxor           0x00c0(%rdx),%ymm0,%ymm0
+       vmovdqu         %ymm0,0x00c0(%rsi)
+       vpxor           0x0100(%rdx),%ymm4,%ymm4
+       vmovdqu         %ymm4,0x0100(%rsi)
+       vpxor           0x0180(%rdx),%ymm5,%ymm5
+       vmovdqu         %ymm5,0x00180(%rsi)
+       vpxor           0x0140(%rdx),%ymm6,%ymm6
+       vmovdqu         %ymm6,0x0140(%rsi)
+       vpxor           0x01c0(%rdx),%ymm7,%ymm7
+       vmovdqu         %ymm7,0x01c0(%rsi)
+       vpxor           0x0020(%rdx),%ymm8,%ymm8
+       vmovdqu         %ymm8,0x0020(%rsi)
+       vpxor           0x00a0(%rdx),%ymm9,%ymm9
+       vmovdqu         %ymm9,0x00a0(%rsi)
+       vpxor           0x0060(%rdx),%ymm10,%ymm10
+       vmovdqu         %ymm10,0x0060(%rsi)
+       vpxor           0x00e0(%rdx),%ymm11,%ymm11
+       vmovdqu         %ymm11,0x00e0(%rsi)
+       vpxor           0x0120(%rdx),%ymm12,%ymm12
+       vmovdqu         %ymm12,0x0120(%rsi)
+       vpxor           0x01a0(%rdx),%ymm13,%ymm13
+       vmovdqu         %ymm13,0x01a0(%rsi)
+       vpxor           0x0160(%rdx),%ymm14,%ymm14
+       vmovdqu         %ymm14,0x0160(%rsi)
+       vpxor           0x01e0(%rdx),%ymm15,%ymm15
+       vmovdqu         %ymm15,0x01e0(%rsi)
+
+       vzeroupper
+       mov             %r8,%rsp
+       ret
+ENDPROC(chacha20_8block_xor_avx2)
diff --git a/arch/x86/crypto/chacha20-ssse3-x86_64.S b/arch/x86/crypto/chacha20-ssse3-x86_64.S
new file mode 100644 (file)
index 0000000..712b130
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSSE3 functions
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+.data
+.align 16
+
+ROT8:  .octa 0x0e0d0c0f0a09080b0605040702010003
+ROT16: .octa 0x0d0c0f0e09080b0a0504070601000302
+CTRINC:        .octa 0x00000003000000020000000100000000
+
+.text
+
+ENTRY(chacha20_block_xor_ssse3)
+       # %rdi: Input state matrix, s
+       # %rsi: 1 data block output, o
+       # %rdx: 1 data block input, i
+
+       # This function encrypts one ChaCha20 block by loading the state matrix
+       # in four SSE registers. It performs matrix operation on four words in
+       # parallel, but requireds shuffling to rearrange the words after each
+       # round. 8/16-bit word rotation is done with the slightly better
+       # performing SSSE3 byte shuffling, 7/12-bit word rotation uses
+       # traditional shift+OR.
+
+       # x0..3 = s0..3
+       movdqa          0x00(%rdi),%xmm0
+       movdqa          0x10(%rdi),%xmm1
+       movdqa          0x20(%rdi),%xmm2
+       movdqa          0x30(%rdi),%xmm3
+       movdqa          %xmm0,%xmm8
+       movdqa          %xmm1,%xmm9
+       movdqa          %xmm2,%xmm10
+       movdqa          %xmm3,%xmm11
+
+       movdqa          ROT8(%rip),%xmm4
+       movdqa          ROT16(%rip),%xmm5
+
+       mov     $10,%ecx
+
+.Ldoubleround:
+
+       # x0 += x1, x3 = rotl32(x3 ^ x0, 16)
+       paddd           %xmm1,%xmm0
+       pxor            %xmm0,%xmm3
+       pshufb          %xmm5,%xmm3
+
+       # x2 += x3, x1 = rotl32(x1 ^ x2, 12)
+       paddd           %xmm3,%xmm2
+       pxor            %xmm2,%xmm1
+       movdqa          %xmm1,%xmm6
+       pslld           $12,%xmm6
+       psrld           $20,%xmm1
+       por             %xmm6,%xmm1
+
+       # x0 += x1, x3 = rotl32(x3 ^ x0, 8)
+       paddd           %xmm1,%xmm0
+       pxor            %xmm0,%xmm3
+       pshufb          %xmm4,%xmm3
+
+       # x2 += x3, x1 = rotl32(x1 ^ x2, 7)
+       paddd           %xmm3,%xmm2
+       pxor            %xmm2,%xmm1
+       movdqa          %xmm1,%xmm7
+       pslld           $7,%xmm7
+       psrld           $25,%xmm1
+       por             %xmm7,%xmm1
+
+       # x1 = shuffle32(x1, MASK(0, 3, 2, 1))
+       pshufd          $0x39,%xmm1,%xmm1
+       # x2 = shuffle32(x2, MASK(1, 0, 3, 2))
+       pshufd          $0x4e,%xmm2,%xmm2
+       # x3 = shuffle32(x3, MASK(2, 1, 0, 3))
+       pshufd          $0x93,%xmm3,%xmm3
+
+       # x0 += x1, x3 = rotl32(x3 ^ x0, 16)
+       paddd           %xmm1,%xmm0
+       pxor            %xmm0,%xmm3
+       pshufb          %xmm5,%xmm3
+
+       # x2 += x3, x1 = rotl32(x1 ^ x2, 12)
+       paddd           %xmm3,%xmm2
+       pxor            %xmm2,%xmm1
+       movdqa          %xmm1,%xmm6
+       pslld           $12,%xmm6
+       psrld           $20,%xmm1
+       por             %xmm6,%xmm1
+
+       # x0 += x1, x3 = rotl32(x3 ^ x0, 8)
+       paddd           %xmm1,%xmm0
+       pxor            %xmm0,%xmm3
+       pshufb          %xmm4,%xmm3
+
+       # x2 += x3, x1 = rotl32(x1 ^ x2, 7)
+       paddd           %xmm3,%xmm2
+       pxor            %xmm2,%xmm1
+       movdqa          %xmm1,%xmm7
+       pslld           $7,%xmm7
+       psrld           $25,%xmm1
+       por             %xmm7,%xmm1
+
+       # x1 = shuffle32(x1, MASK(2, 1, 0, 3))
+       pshufd          $0x93,%xmm1,%xmm1
+       # x2 = shuffle32(x2, MASK(1, 0, 3, 2))
+       pshufd          $0x4e,%xmm2,%xmm2
+       # x3 = shuffle32(x3, MASK(0, 3, 2, 1))
+       pshufd          $0x39,%xmm3,%xmm3
+
+       dec             %ecx
+       jnz             .Ldoubleround
+
+       # o0 = i0 ^ (x0 + s0)
+       movdqu          0x00(%rdx),%xmm4
+       paddd           %xmm8,%xmm0
+       pxor            %xmm4,%xmm0
+       movdqu          %xmm0,0x00(%rsi)
+       # o1 = i1 ^ (x1 + s1)
+       movdqu          0x10(%rdx),%xmm5
+       paddd           %xmm9,%xmm1
+       pxor            %xmm5,%xmm1
+       movdqu          %xmm1,0x10(%rsi)
+       # o2 = i2 ^ (x2 + s2)
+       movdqu          0x20(%rdx),%xmm6
+       paddd           %xmm10,%xmm2
+       pxor            %xmm6,%xmm2
+       movdqu          %xmm2,0x20(%rsi)
+       # o3 = i3 ^ (x3 + s3)
+       movdqu          0x30(%rdx),%xmm7
+       paddd           %xmm11,%xmm3
+       pxor            %xmm7,%xmm3
+       movdqu          %xmm3,0x30(%rsi)
+
+       ret
+ENDPROC(chacha20_block_xor_ssse3)
+
+ENTRY(chacha20_4block_xor_ssse3)
+       # %rdi: Input state matrix, s
+       # %rsi: 4 data blocks output, o
+       # %rdx: 4 data blocks input, i
+
+       # This function encrypts four consecutive ChaCha20 blocks by loading the
+       # the state matrix in SSE registers four times. As we need some scratch
+       # registers, we save the first four registers on the stack. The
+       # algorithm performs each operation on the corresponding word of each
+       # state matrix, hence requires no word shuffling. For final XORing step
+       # we transpose the matrix by interleaving 32- and then 64-bit words,
+       # which allows us to do XOR in SSE registers. 8/16-bit word rotation is
+       # done with the slightly better performing SSSE3 byte shuffling,
+       # 7/12-bit word rotation uses traditional shift+OR.
+
+       sub             $0x40,%rsp
+
+       # x0..15[0-3] = s0..3[0..3]
+       movq            0x00(%rdi),%xmm1
+       pshufd          $0x00,%xmm1,%xmm0
+       pshufd          $0x55,%xmm1,%xmm1
+       movq            0x08(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       movq            0x10(%rdi),%xmm5
+       pshufd          $0x00,%xmm5,%xmm4
+       pshufd          $0x55,%xmm5,%xmm5
+       movq            0x18(%rdi),%xmm7
+       pshufd          $0x00,%xmm7,%xmm6
+       pshufd          $0x55,%xmm7,%xmm7
+       movq            0x20(%rdi),%xmm9
+       pshufd          $0x00,%xmm9,%xmm8
+       pshufd          $0x55,%xmm9,%xmm9
+       movq            0x28(%rdi),%xmm11
+       pshufd          $0x00,%xmm11,%xmm10
+       pshufd          $0x55,%xmm11,%xmm11
+       movq            0x30(%rdi),%xmm13
+       pshufd          $0x00,%xmm13,%xmm12
+       pshufd          $0x55,%xmm13,%xmm13
+       movq            0x38(%rdi),%xmm15
+       pshufd          $0x00,%xmm15,%xmm14
+       pshufd          $0x55,%xmm15,%xmm15
+       # x0..3 on stack
+       movdqa          %xmm0,0x00(%rsp)
+       movdqa          %xmm1,0x10(%rsp)
+       movdqa          %xmm2,0x20(%rsp)
+       movdqa          %xmm3,0x30(%rsp)
+
+       movdqa          CTRINC(%rip),%xmm1
+       movdqa          ROT8(%rip),%xmm2
+       movdqa          ROT16(%rip),%xmm3
+
+       # x12 += counter values 0-3
+       paddd           %xmm1,%xmm12
+
+       mov             $10,%ecx
+
+.Ldoubleround4:
+       # x0 += x4, x12 = rotl32(x12 ^ x0, 16)
+       movdqa          0x00(%rsp),%xmm0
+       paddd           %xmm4,%xmm0
+       movdqa          %xmm0,0x00(%rsp)
+       pxor            %xmm0,%xmm12
+       pshufb          %xmm3,%xmm12
+       # x1 += x5, x13 = rotl32(x13 ^ x1, 16)
+       movdqa          0x10(%rsp),%xmm0
+       paddd           %xmm5,%xmm0
+       movdqa          %xmm0,0x10(%rsp)
+       pxor            %xmm0,%xmm13
+       pshufb          %xmm3,%xmm13
+       # x2 += x6, x14 = rotl32(x14 ^ x2, 16)
+       movdqa          0x20(%rsp),%xmm0
+       paddd           %xmm6,%xmm0
+       movdqa          %xmm0,0x20(%rsp)
+       pxor            %xmm0,%xmm14
+       pshufb          %xmm3,%xmm14
+       # x3 += x7, x15 = rotl32(x15 ^ x3, 16)
+       movdqa          0x30(%rsp),%xmm0
+       paddd           %xmm7,%xmm0
+       movdqa          %xmm0,0x30(%rsp)
+       pxor            %xmm0,%xmm15
+       pshufb          %xmm3,%xmm15
+
+       # x8 += x12, x4 = rotl32(x4 ^ x8, 12)
+       paddd           %xmm12,%xmm8
+       pxor            %xmm8,%xmm4
+       movdqa          %xmm4,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm4
+       por             %xmm0,%xmm4
+       # x9 += x13, x5 = rotl32(x5 ^ x9, 12)
+       paddd           %xmm13,%xmm9
+       pxor            %xmm9,%xmm5
+       movdqa          %xmm5,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm5
+       por             %xmm0,%xmm5
+       # x10 += x14, x6 = rotl32(x6 ^ x10, 12)
+       paddd           %xmm14,%xmm10
+       pxor            %xmm10,%xmm6
+       movdqa          %xmm6,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm6
+       por             %xmm0,%xmm6
+       # x11 += x15, x7 = rotl32(x7 ^ x11, 12)
+       paddd           %xmm15,%xmm11
+       pxor            %xmm11,%xmm7
+       movdqa          %xmm7,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm7
+       por             %xmm0,%xmm7
+
+       # x0 += x4, x12 = rotl32(x12 ^ x0, 8)
+       movdqa          0x00(%rsp),%xmm0
+       paddd           %xmm4,%xmm0
+       movdqa          %xmm0,0x00(%rsp)
+       pxor            %xmm0,%xmm12
+       pshufb          %xmm2,%xmm12
+       # x1 += x5, x13 = rotl32(x13 ^ x1, 8)
+       movdqa          0x10(%rsp),%xmm0
+       paddd           %xmm5,%xmm0
+       movdqa          %xmm0,0x10(%rsp)
+       pxor            %xmm0,%xmm13
+       pshufb          %xmm2,%xmm13
+       # x2 += x6, x14 = rotl32(x14 ^ x2, 8)
+       movdqa          0x20(%rsp),%xmm0
+       paddd           %xmm6,%xmm0
+       movdqa          %xmm0,0x20(%rsp)
+       pxor            %xmm0,%xmm14
+       pshufb          %xmm2,%xmm14
+       # x3 += x7, x15 = rotl32(x15 ^ x3, 8)
+       movdqa          0x30(%rsp),%xmm0
+       paddd           %xmm7,%xmm0
+       movdqa          %xmm0,0x30(%rsp)
+       pxor            %xmm0,%xmm15
+       pshufb          %xmm2,%xmm15
+
+       # x8 += x12, x4 = rotl32(x4 ^ x8, 7)
+       paddd           %xmm12,%xmm8
+       pxor            %xmm8,%xmm4
+       movdqa          %xmm4,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm4
+       por             %xmm0,%xmm4
+       # x9 += x13, x5 = rotl32(x5 ^ x9, 7)
+       paddd           %xmm13,%xmm9
+       pxor            %xmm9,%xmm5
+       movdqa          %xmm5,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm5
+       por             %xmm0,%xmm5
+       # x10 += x14, x6 = rotl32(x6 ^ x10, 7)
+       paddd           %xmm14,%xmm10
+       pxor            %xmm10,%xmm6
+       movdqa          %xmm6,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm6
+       por             %xmm0,%xmm6
+       # x11 += x15, x7 = rotl32(x7 ^ x11, 7)
+       paddd           %xmm15,%xmm11
+       pxor            %xmm11,%xmm7
+       movdqa          %xmm7,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm7
+       por             %xmm0,%xmm7
+
+       # x0 += x5, x15 = rotl32(x15 ^ x0, 16)
+       movdqa          0x00(%rsp),%xmm0
+       paddd           %xmm5,%xmm0
+       movdqa          %xmm0,0x00(%rsp)
+       pxor            %xmm0,%xmm15
+       pshufb          %xmm3,%xmm15
+       # x1 += x6, x12 = rotl32(x12 ^ x1, 16)
+       movdqa          0x10(%rsp),%xmm0
+       paddd           %xmm6,%xmm0
+       movdqa          %xmm0,0x10(%rsp)
+       pxor            %xmm0,%xmm12
+       pshufb          %xmm3,%xmm12
+       # x2 += x7, x13 = rotl32(x13 ^ x2, 16)
+       movdqa          0x20(%rsp),%xmm0
+       paddd           %xmm7,%xmm0
+       movdqa          %xmm0,0x20(%rsp)
+       pxor            %xmm0,%xmm13
+       pshufb          %xmm3,%xmm13
+       # x3 += x4, x14 = rotl32(x14 ^ x3, 16)
+       movdqa          0x30(%rsp),%xmm0
+       paddd           %xmm4,%xmm0
+       movdqa          %xmm0,0x30(%rsp)
+       pxor            %xmm0,%xmm14
+       pshufb          %xmm3,%xmm14
+
+       # x10 += x15, x5 = rotl32(x5 ^ x10, 12)
+       paddd           %xmm15,%xmm10
+       pxor            %xmm10,%xmm5
+       movdqa          %xmm5,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm5
+       por             %xmm0,%xmm5
+       # x11 += x12, x6 = rotl32(x6 ^ x11, 12)
+       paddd           %xmm12,%xmm11
+       pxor            %xmm11,%xmm6
+       movdqa          %xmm6,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm6
+       por             %xmm0,%xmm6
+       # x8 += x13, x7 = rotl32(x7 ^ x8, 12)
+       paddd           %xmm13,%xmm8
+       pxor            %xmm8,%xmm7
+       movdqa          %xmm7,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm7
+       por             %xmm0,%xmm7
+       # x9 += x14, x4 = rotl32(x4 ^ x9, 12)
+       paddd           %xmm14,%xmm9
+       pxor            %xmm9,%xmm4
+       movdqa          %xmm4,%xmm0
+       pslld           $12,%xmm0
+       psrld           $20,%xmm4
+       por             %xmm0,%xmm4
+
+       # x0 += x5, x15 = rotl32(x15 ^ x0, 8)
+       movdqa          0x00(%rsp),%xmm0
+       paddd           %xmm5,%xmm0
+       movdqa          %xmm0,0x00(%rsp)
+       pxor            %xmm0,%xmm15
+       pshufb          %xmm2,%xmm15
+       # x1 += x6, x12 = rotl32(x12 ^ x1, 8)
+       movdqa          0x10(%rsp),%xmm0
+       paddd           %xmm6,%xmm0
+       movdqa          %xmm0,0x10(%rsp)
+       pxor            %xmm0,%xmm12
+       pshufb          %xmm2,%xmm12
+       # x2 += x7, x13 = rotl32(x13 ^ x2, 8)
+       movdqa          0x20(%rsp),%xmm0
+       paddd           %xmm7,%xmm0
+       movdqa          %xmm0,0x20(%rsp)
+       pxor            %xmm0,%xmm13
+       pshufb          %xmm2,%xmm13
+       # x3 += x4, x14 = rotl32(x14 ^ x3, 8)
+       movdqa          0x30(%rsp),%xmm0
+       paddd           %xmm4,%xmm0
+       movdqa          %xmm0,0x30(%rsp)
+       pxor            %xmm0,%xmm14
+       pshufb          %xmm2,%xmm14
+
+       # x10 += x15, x5 = rotl32(x5 ^ x10, 7)
+       paddd           %xmm15,%xmm10
+       pxor            %xmm10,%xmm5
+       movdqa          %xmm5,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm5
+       por             %xmm0,%xmm5
+       # x11 += x12, x6 = rotl32(x6 ^ x11, 7)
+       paddd           %xmm12,%xmm11
+       pxor            %xmm11,%xmm6
+       movdqa          %xmm6,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm6
+       por             %xmm0,%xmm6
+       # x8 += x13, x7 = rotl32(x7 ^ x8, 7)
+       paddd           %xmm13,%xmm8
+       pxor            %xmm8,%xmm7
+       movdqa          %xmm7,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm7
+       por             %xmm0,%xmm7
+       # x9 += x14, x4 = rotl32(x4 ^ x9, 7)
+       paddd           %xmm14,%xmm9
+       pxor            %xmm9,%xmm4
+       movdqa          %xmm4,%xmm0
+       pslld           $7,%xmm0
+       psrld           $25,%xmm4
+       por             %xmm0,%xmm4
+
+       dec             %ecx
+       jnz             .Ldoubleround4
+
+       # x0[0-3] += s0[0]
+       # x1[0-3] += s0[1]
+       movq            0x00(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           0x00(%rsp),%xmm2
+       movdqa          %xmm2,0x00(%rsp)
+       paddd           0x10(%rsp),%xmm3
+       movdqa          %xmm3,0x10(%rsp)
+       # x2[0-3] += s0[2]
+       # x3[0-3] += s0[3]
+       movq            0x08(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           0x20(%rsp),%xmm2
+       movdqa          %xmm2,0x20(%rsp)
+       paddd           0x30(%rsp),%xmm3
+       movdqa          %xmm3,0x30(%rsp)
+
+       # x4[0-3] += s1[0]
+       # x5[0-3] += s1[1]
+       movq            0x10(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           %xmm2,%xmm4
+       paddd           %xmm3,%xmm5
+       # x6[0-3] += s1[2]
+       # x7[0-3] += s1[3]
+       movq            0x18(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           %xmm2,%xmm6
+       paddd           %xmm3,%xmm7
+
+       # x8[0-3] += s2[0]
+       # x9[0-3] += s2[1]
+       movq            0x20(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           %xmm2,%xmm8
+       paddd           %xmm3,%xmm9
+       # x10[0-3] += s2[2]
+       # x11[0-3] += s2[3]
+       movq            0x28(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           %xmm2,%xmm10
+       paddd           %xmm3,%xmm11
+
+       # x12[0-3] += s3[0]
+       # x13[0-3] += s3[1]
+       movq            0x30(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           %xmm2,%xmm12
+       paddd           %xmm3,%xmm13
+       # x14[0-3] += s3[2]
+       # x15[0-3] += s3[3]
+       movq            0x38(%rdi),%xmm3
+       pshufd          $0x00,%xmm3,%xmm2
+       pshufd          $0x55,%xmm3,%xmm3
+       paddd           %xmm2,%xmm14
+       paddd           %xmm3,%xmm15
+
+       # x12 += counter values 0-3
+       paddd           %xmm1,%xmm12
+
+       # interleave 32-bit words in state n, n+1
+       movdqa          0x00(%rsp),%xmm0
+       movdqa          0x10(%rsp),%xmm1
+       movdqa          %xmm0,%xmm2
+       punpckldq       %xmm1,%xmm2
+       punpckhdq       %xmm1,%xmm0
+       movdqa          %xmm2,0x00(%rsp)
+       movdqa          %xmm0,0x10(%rsp)
+       movdqa          0x20(%rsp),%xmm0
+       movdqa          0x30(%rsp),%xmm1
+       movdqa          %xmm0,%xmm2
+       punpckldq       %xmm1,%xmm2
+       punpckhdq       %xmm1,%xmm0
+       movdqa          %xmm2,0x20(%rsp)
+       movdqa          %xmm0,0x30(%rsp)
+       movdqa          %xmm4,%xmm0
+       punpckldq       %xmm5,%xmm4
+       punpckhdq       %xmm5,%xmm0
+       movdqa          %xmm0,%xmm5
+       movdqa          %xmm6,%xmm0
+       punpckldq       %xmm7,%xmm6
+       punpckhdq       %xmm7,%xmm0
+       movdqa          %xmm0,%xmm7
+       movdqa          %xmm8,%xmm0
+       punpckldq       %xmm9,%xmm8
+       punpckhdq       %xmm9,%xmm0
+       movdqa          %xmm0,%xmm9
+       movdqa          %xmm10,%xmm0
+       punpckldq       %xmm11,%xmm10
+       punpckhdq       %xmm11,%xmm0
+       movdqa          %xmm0,%xmm11
+       movdqa          %xmm12,%xmm0
+       punpckldq       %xmm13,%xmm12
+       punpckhdq       %xmm13,%xmm0
+       movdqa          %xmm0,%xmm13
+       movdqa          %xmm14,%xmm0
+       punpckldq       %xmm15,%xmm14
+       punpckhdq       %xmm15,%xmm0
+       movdqa          %xmm0,%xmm15
+
+       # interleave 64-bit words in state n, n+2
+       movdqa          0x00(%rsp),%xmm0
+       movdqa          0x20(%rsp),%xmm1
+       movdqa          %xmm0,%xmm2
+       punpcklqdq      %xmm1,%xmm2
+       punpckhqdq      %xmm1,%xmm0
+       movdqa          %xmm2,0x00(%rsp)
+       movdqa          %xmm0,0x20(%rsp)
+       movdqa          0x10(%rsp),%xmm0
+       movdqa          0x30(%rsp),%xmm1
+       movdqa          %xmm0,%xmm2
+       punpcklqdq      %xmm1,%xmm2
+       punpckhqdq      %xmm1,%xmm0
+       movdqa          %xmm2,0x10(%rsp)
+       movdqa          %xmm0,0x30(%rsp)
+       movdqa          %xmm4,%xmm0
+       punpcklqdq      %xmm6,%xmm4
+       punpckhqdq      %xmm6,%xmm0
+       movdqa          %xmm0,%xmm6
+       movdqa          %xmm5,%xmm0
+       punpcklqdq      %xmm7,%xmm5
+       punpckhqdq      %xmm7,%xmm0
+       movdqa          %xmm0,%xmm7
+       movdqa          %xmm8,%xmm0
+       punpcklqdq      %xmm10,%xmm8
+       punpckhqdq      %xmm10,%xmm0
+       movdqa          %xmm0,%xmm10
+       movdqa          %xmm9,%xmm0
+       punpcklqdq      %xmm11,%xmm9
+       punpckhqdq      %xmm11,%xmm0
+       movdqa          %xmm0,%xmm11
+       movdqa          %xmm12,%xmm0
+       punpcklqdq      %xmm14,%xmm12
+       punpckhqdq      %xmm14,%xmm0
+       movdqa          %xmm0,%xmm14
+       movdqa          %xmm13,%xmm0
+       punpcklqdq      %xmm15,%xmm13
+       punpckhqdq      %xmm15,%xmm0
+       movdqa          %xmm0,%xmm15
+
+       # xor with corresponding input, write to output
+       movdqa          0x00(%rsp),%xmm0
+       movdqu          0x00(%rdx),%xmm1
+       pxor            %xmm1,%xmm0
+       movdqu          %xmm0,0x00(%rsi)
+       movdqa          0x10(%rsp),%xmm0
+       movdqu          0x80(%rdx),%xmm1
+       pxor            %xmm1,%xmm0
+       movdqu          %xmm0,0x80(%rsi)
+       movdqa          0x20(%rsp),%xmm0
+       movdqu          0x40(%rdx),%xmm1
+       pxor            %xmm1,%xmm0
+       movdqu          %xmm0,0x40(%rsi)
+       movdqa          0x30(%rsp),%xmm0
+       movdqu          0xc0(%rdx),%xmm1
+       pxor            %xmm1,%xmm0
+       movdqu          %xmm0,0xc0(%rsi)
+       movdqu          0x10(%rdx),%xmm1
+       pxor            %xmm1,%xmm4
+       movdqu          %xmm4,0x10(%rsi)
+       movdqu          0x90(%rdx),%xmm1
+       pxor            %xmm1,%xmm5
+       movdqu          %xmm5,0x90(%rsi)
+       movdqu          0x50(%rdx),%xmm1
+       pxor            %xmm1,%xmm6
+       movdqu          %xmm6,0x50(%rsi)
+       movdqu          0xd0(%rdx),%xmm1
+       pxor            %xmm1,%xmm7
+       movdqu          %xmm7,0xd0(%rsi)
+       movdqu          0x20(%rdx),%xmm1
+       pxor            %xmm1,%xmm8
+       movdqu          %xmm8,0x20(%rsi)
+       movdqu          0xa0(%rdx),%xmm1
+       pxor            %xmm1,%xmm9
+       movdqu          %xmm9,0xa0(%rsi)
+       movdqu          0x60(%rdx),%xmm1
+       pxor            %xmm1,%xmm10
+       movdqu          %xmm10,0x60(%rsi)
+       movdqu          0xe0(%rdx),%xmm1
+       pxor            %xmm1,%xmm11
+       movdqu          %xmm11,0xe0(%rsi)
+       movdqu          0x30(%rdx),%xmm1
+       pxor            %xmm1,%xmm12
+       movdqu          %xmm12,0x30(%rsi)
+       movdqu          0xb0(%rdx),%xmm1
+       pxor            %xmm1,%xmm13
+       movdqu          %xmm13,0xb0(%rsi)
+       movdqu          0x70(%rdx),%xmm1
+       pxor            %xmm1,%xmm14
+       movdqu          %xmm14,0x70(%rsi)
+       movdqu          0xf0(%rdx),%xmm1
+       pxor            %xmm1,%xmm15
+       movdqu          %xmm15,0xf0(%rsi)
+
+       add             $0x40,%rsp
+       ret
+ENDPROC(chacha20_4block_xor_ssse3)
diff --git a/arch/x86/crypto/chacha20_glue.c b/arch/x86/crypto/chacha20_glue.c
new file mode 100644 (file)
index 0000000..effe216
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * 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 <crypto/algapi.h>
+#include <crypto/chacha20.h>
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/fpu/api.h>
+#include <asm/simd.h>
+
+#define CHACHA20_STATE_ALIGN 16
+
+asmlinkage void chacha20_block_xor_ssse3(u32 *state, u8 *dst, const u8 *src);
+asmlinkage void chacha20_4block_xor_ssse3(u32 *state, u8 *dst, const u8 *src);
+#ifdef CONFIG_AS_AVX2
+asmlinkage void chacha20_8block_xor_avx2(u32 *state, u8 *dst, const u8 *src);
+static bool chacha20_use_avx2;
+#endif
+
+static void chacha20_dosimd(u32 *state, u8 *dst, const u8 *src,
+                           unsigned int bytes)
+{
+       u8 buf[CHACHA20_BLOCK_SIZE];
+
+#ifdef CONFIG_AS_AVX2
+       if (chacha20_use_avx2) {
+               while (bytes >= CHACHA20_BLOCK_SIZE * 8) {
+                       chacha20_8block_xor_avx2(state, dst, src);
+                       bytes -= CHACHA20_BLOCK_SIZE * 8;
+                       src += CHACHA20_BLOCK_SIZE * 8;
+                       dst += CHACHA20_BLOCK_SIZE * 8;
+                       state[12] += 8;
+               }
+       }
+#endif
+       while (bytes >= CHACHA20_BLOCK_SIZE * 4) {
+               chacha20_4block_xor_ssse3(state, dst, src);
+               bytes -= CHACHA20_BLOCK_SIZE * 4;
+               src += CHACHA20_BLOCK_SIZE * 4;
+               dst += CHACHA20_BLOCK_SIZE * 4;
+               state[12] += 4;
+       }
+       while (bytes >= CHACHA20_BLOCK_SIZE) {
+               chacha20_block_xor_ssse3(state, dst, src);
+               bytes -= CHACHA20_BLOCK_SIZE;
+               src += CHACHA20_BLOCK_SIZE;
+               dst += CHACHA20_BLOCK_SIZE;
+               state[12]++;
+       }
+       if (bytes) {
+               memcpy(buf, src, bytes);
+               chacha20_block_xor_ssse3(state, buf, buf);
+               memcpy(dst, buf, bytes);
+       }
+}
+
+static int chacha20_simd(struct blkcipher_desc *desc, struct scatterlist *dst,
+                        struct scatterlist *src, unsigned int nbytes)
+{
+       u32 *state, state_buf[16 + (CHACHA20_STATE_ALIGN / sizeof(u32)) - 1];
+       struct blkcipher_walk walk;
+       int err;
+
+       if (!may_use_simd())
+               return crypto_chacha20_crypt(desc, dst, src, nbytes);
+
+       state = (u32 *)roundup((uintptr_t)state_buf, CHACHA20_STATE_ALIGN);
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt_block(desc, &walk, CHACHA20_BLOCK_SIZE);
+
+       crypto_chacha20_init(state, crypto_blkcipher_ctx(desc->tfm), walk.iv);
+
+       kernel_fpu_begin();
+
+       while (walk.nbytes >= CHACHA20_BLOCK_SIZE) {
+               chacha20_dosimd(state, walk.dst.virt.addr, walk.src.virt.addr,
+                               rounddown(walk.nbytes, CHACHA20_BLOCK_SIZE));
+               err = blkcipher_walk_done(desc, &walk,
+                                         walk.nbytes % CHACHA20_BLOCK_SIZE);
+       }
+
+       if (walk.nbytes) {
+               chacha20_dosimd(state, walk.dst.virt.addr, walk.src.virt.addr,
+                               walk.nbytes);
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+
+       kernel_fpu_end();
+
+       return err;
+}
+
+static struct crypto_alg alg = {
+       .cra_name               = "chacha20",
+       .cra_driver_name        = "chacha20-simd",
+       .cra_priority           = 300,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = 1,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_ctxsize            = sizeof(struct chacha20_ctx),
+       .cra_alignmask          = sizeof(u32) - 1,
+       .cra_module             = THIS_MODULE,
+       .cra_u                  = {
+               .blkcipher = {
+                       .min_keysize    = CHACHA20_KEY_SIZE,
+                       .max_keysize    = CHACHA20_KEY_SIZE,
+                       .ivsize         = CHACHA20_IV_SIZE,
+                       .geniv          = "seqiv",
+                       .setkey         = crypto_chacha20_setkey,
+                       .encrypt        = chacha20_simd,
+                       .decrypt        = chacha20_simd,
+               },
+       },
+};
+
+static int __init chacha20_simd_mod_init(void)
+{
+       if (!cpu_has_ssse3)
+               return -ENODEV;
+
+#ifdef CONFIG_AS_AVX2
+       chacha20_use_avx2 = cpu_has_avx && cpu_has_avx2 &&
+                           cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, NULL);
+#endif
+       return crypto_register_alg(&alg);
+}
+
+static void __exit chacha20_simd_mod_fini(void)
+{
+       crypto_unregister_alg(&alg);
+}
+
+module_init(chacha20_simd_mod_init);
+module_exit(chacha20_simd_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
+MODULE_DESCRIPTION("chacha20 cipher algorithm, SIMD accelerated");
+MODULE_ALIAS_CRYPTO("chacha20");
+MODULE_ALIAS_CRYPTO("chacha20-simd");
diff --git a/arch/x86/crypto/poly1305-avx2-x86_64.S b/arch/x86/crypto/poly1305-avx2-x86_64.S
new file mode 100644 (file)
index 0000000..eff2f41
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Poly1305 authenticator algorithm, RFC7539, x64 AVX2 functions
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+.data
+.align 32
+
+ANMASK:        .octa 0x0000000003ffffff0000000003ffffff
+       .octa 0x0000000003ffffff0000000003ffffff
+ORMASK:        .octa 0x00000000010000000000000001000000
+       .octa 0x00000000010000000000000001000000
+
+.text
+
+#define h0 0x00(%rdi)
+#define h1 0x04(%rdi)
+#define h2 0x08(%rdi)
+#define h3 0x0c(%rdi)
+#define h4 0x10(%rdi)
+#define r0 0x00(%rdx)
+#define r1 0x04(%rdx)
+#define r2 0x08(%rdx)
+#define r3 0x0c(%rdx)
+#define r4 0x10(%rdx)
+#define u0 0x00(%r8)
+#define u1 0x04(%r8)
+#define u2 0x08(%r8)
+#define u3 0x0c(%r8)
+#define u4 0x10(%r8)
+#define w0 0x14(%r8)
+#define w1 0x18(%r8)
+#define w2 0x1c(%r8)
+#define w3 0x20(%r8)
+#define w4 0x24(%r8)
+#define y0 0x28(%r8)
+#define y1 0x2c(%r8)
+#define y2 0x30(%r8)
+#define y3 0x34(%r8)
+#define y4 0x38(%r8)
+#define m %rsi
+#define hc0 %ymm0
+#define hc1 %ymm1
+#define hc2 %ymm2
+#define hc3 %ymm3
+#define hc4 %ymm4
+#define hc0x %xmm0
+#define hc1x %xmm1
+#define hc2x %xmm2
+#define hc3x %xmm3
+#define hc4x %xmm4
+#define t1 %ymm5
+#define t2 %ymm6
+#define t1x %xmm5
+#define t2x %xmm6
+#define ruwy0 %ymm7
+#define ruwy1 %ymm8
+#define ruwy2 %ymm9
+#define ruwy3 %ymm10
+#define ruwy4 %ymm11
+#define ruwy0x %xmm7
+#define ruwy1x %xmm8
+#define ruwy2x %xmm9
+#define ruwy3x %xmm10
+#define ruwy4x %xmm11
+#define svxz1 %ymm12
+#define svxz2 %ymm13
+#define svxz3 %ymm14
+#define svxz4 %ymm15
+#define d0 %r9
+#define d1 %r10
+#define d2 %r11
+#define d3 %r12
+#define d4 %r13
+
+ENTRY(poly1305_4block_avx2)
+       # %rdi: Accumulator h[5]
+       # %rsi: 64 byte input block m
+       # %rdx: Poly1305 key r[5]
+       # %rcx: Quadblock count
+       # %r8:  Poly1305 derived key r^2 u[5], r^3 w[5], r^4 y[5],
+
+       # This four-block variant uses loop unrolled block processing. It
+       # requires 4 Poly1305 keys: r, r^2, r^3 and r^4:
+       # h = (h + m) * r  =>  h = (h + m1) * r^4 + m2 * r^3 + m3 * r^2 + m4 * r
+
+       vzeroupper
+       push            %rbx
+       push            %r12
+       push            %r13
+
+       # combine r0,u0,w0,y0
+       vmovd           y0,ruwy0x
+       vmovd           w0,t1x
+       vpunpcklqdq     t1,ruwy0,ruwy0
+       vmovd           u0,t1x
+       vmovd           r0,t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,ruwy0,ruwy0
+
+       # combine r1,u1,w1,y1 and s1=r1*5,v1=u1*5,x1=w1*5,z1=y1*5
+       vmovd           y1,ruwy1x
+       vmovd           w1,t1x
+       vpunpcklqdq     t1,ruwy1,ruwy1
+       vmovd           u1,t1x
+       vmovd           r1,t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,ruwy1,ruwy1
+       vpslld          $2,ruwy1,svxz1
+       vpaddd          ruwy1,svxz1,svxz1
+
+       # combine r2,u2,w2,y2 and s2=r2*5,v2=u2*5,x2=w2*5,z2=y2*5
+       vmovd           y2,ruwy2x
+       vmovd           w2,t1x
+       vpunpcklqdq     t1,ruwy2,ruwy2
+       vmovd           u2,t1x
+       vmovd           r2,t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,ruwy2,ruwy2
+       vpslld          $2,ruwy2,svxz2
+       vpaddd          ruwy2,svxz2,svxz2
+
+       # combine r3,u3,w3,y3 and s3=r3*5,v3=u3*5,x3=w3*5,z3=y3*5
+       vmovd           y3,ruwy3x
+       vmovd           w3,t1x
+       vpunpcklqdq     t1,ruwy3,ruwy3
+       vmovd           u3,t1x
+       vmovd           r3,t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,ruwy3,ruwy3
+       vpslld          $2,ruwy3,svxz3
+       vpaddd          ruwy3,svxz3,svxz3
+
+       # combine r4,u4,w4,y4 and s4=r4*5,v4=u4*5,x4=w4*5,z4=y4*5
+       vmovd           y4,ruwy4x
+       vmovd           w4,t1x
+       vpunpcklqdq     t1,ruwy4,ruwy4
+       vmovd           u4,t1x
+       vmovd           r4,t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,ruwy4,ruwy4
+       vpslld          $2,ruwy4,svxz4
+       vpaddd          ruwy4,svxz4,svxz4
+
+.Ldoblock4:
+       # hc0 = [m[48-51] & 0x3ffffff, m[32-35] & 0x3ffffff,
+       #        m[16-19] & 0x3ffffff, m[ 0- 3] & 0x3ffffff + h0]
+       vmovd           0x00(m),hc0x
+       vmovd           0x10(m),t1x
+       vpunpcklqdq     t1,hc0,hc0
+       vmovd           0x20(m),t1x
+       vmovd           0x30(m),t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,hc0,hc0
+       vpand           ANMASK(%rip),hc0,hc0
+       vmovd           h0,t1x
+       vpaddd          t1,hc0,hc0
+       # hc1 = [(m[51-54] >> 2) & 0x3ffffff, (m[35-38] >> 2) & 0x3ffffff,
+       #        (m[19-22] >> 2) & 0x3ffffff, (m[ 3- 6] >> 2) & 0x3ffffff + h1]
+       vmovd           0x03(m),hc1x
+       vmovd           0x13(m),t1x
+       vpunpcklqdq     t1,hc1,hc1
+       vmovd           0x23(m),t1x
+       vmovd           0x33(m),t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,hc1,hc1
+       vpsrld          $2,hc1,hc1
+       vpand           ANMASK(%rip),hc1,hc1
+       vmovd           h1,t1x
+       vpaddd          t1,hc1,hc1
+       # hc2 = [(m[54-57] >> 4) & 0x3ffffff, (m[38-41] >> 4) & 0x3ffffff,
+       #        (m[22-25] >> 4) & 0x3ffffff, (m[ 6- 9] >> 4) & 0x3ffffff + h2]
+       vmovd           0x06(m),hc2x
+       vmovd           0x16(m),t1x
+       vpunpcklqdq     t1,hc2,hc2
+       vmovd           0x26(m),t1x
+       vmovd           0x36(m),t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,hc2,hc2
+       vpsrld          $4,hc2,hc2
+       vpand           ANMASK(%rip),hc2,hc2
+       vmovd           h2,t1x
+       vpaddd          t1,hc2,hc2
+       # hc3 = [(m[57-60] >> 6) & 0x3ffffff, (m[41-44] >> 6) & 0x3ffffff,
+       #        (m[25-28] >> 6) & 0x3ffffff, (m[ 9-12] >> 6) & 0x3ffffff + h3]
+       vmovd           0x09(m),hc3x
+       vmovd           0x19(m),t1x
+       vpunpcklqdq     t1,hc3,hc3
+       vmovd           0x29(m),t1x
+       vmovd           0x39(m),t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,hc3,hc3
+       vpsrld          $6,hc3,hc3
+       vpand           ANMASK(%rip),hc3,hc3
+       vmovd           h3,t1x
+       vpaddd          t1,hc3,hc3
+       # hc4 = [(m[60-63] >> 8) | (1<<24), (m[44-47] >> 8) | (1<<24),
+       #        (m[28-31] >> 8) | (1<<24), (m[12-15] >> 8) | (1<<24) + h4]
+       vmovd           0x0c(m),hc4x
+       vmovd           0x1c(m),t1x
+       vpunpcklqdq     t1,hc4,hc4
+       vmovd           0x2c(m),t1x
+       vmovd           0x3c(m),t2x
+       vpunpcklqdq     t2,t1,t1
+       vperm2i128      $0x20,t1,hc4,hc4
+       vpsrld          $8,hc4,hc4
+       vpor            ORMASK(%rip),hc4,hc4
+       vmovd           h4,t1x
+       vpaddd          t1,hc4,hc4
+
+       # t1 = [ hc0[3] * r0, hc0[2] * u0, hc0[1] * w0, hc0[0] * y0 ]
+       vpmuludq        hc0,ruwy0,t1
+       # t1 += [ hc1[3] * s4, hc1[2] * v4, hc1[1] * x4, hc1[0] * z4 ]
+       vpmuludq        hc1,svxz4,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc2[3] * s3, hc2[2] * v3, hc2[1] * x3, hc2[0] * z3 ]
+       vpmuludq        hc2,svxz3,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc3[3] * s2, hc3[2] * v2, hc3[1] * x2, hc3[0] * z2 ]
+       vpmuludq        hc3,svxz2,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc4[3] * s1, hc4[2] * v1, hc4[1] * x1, hc4[0] * z1 ]
+       vpmuludq        hc4,svxz1,t2
+       vpaddq          t2,t1,t1
+       # d0 = t1[0] + t1[1] + t[2] + t[3]
+       vpermq          $0xee,t1,t2
+       vpaddq          t2,t1,t1
+       vpsrldq         $8,t1,t2
+       vpaddq          t2,t1,t1
+       vmovq           t1x,d0
+
+       # t1 = [ hc0[3] * r1, hc0[2] * u1,hc0[1] * w1, hc0[0] * y1 ]
+       vpmuludq        hc0,ruwy1,t1
+       # t1 += [ hc1[3] * r0, hc1[2] * u0, hc1[1] * w0, hc1[0] * y0 ]
+       vpmuludq        hc1,ruwy0,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc2[3] * s4, hc2[2] * v4, hc2[1] * x4, hc2[0] * z4 ]
+       vpmuludq        hc2,svxz4,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc3[3] * s3, hc3[2] * v3, hc3[1] * x3, hc3[0] * z3 ]
+       vpmuludq        hc3,svxz3,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc4[3] * s2, hc4[2] * v2, hc4[1] * x2, hc4[0] * z2 ]
+       vpmuludq        hc4,svxz2,t2
+       vpaddq          t2,t1,t1
+       # d1 = t1[0] + t1[1] + t1[3] + t1[4]
+       vpermq          $0xee,t1,t2
+       vpaddq          t2,t1,t1
+       vpsrldq         $8,t1,t2
+       vpaddq          t2,t1,t1
+       vmovq           t1x,d1
+
+       # t1 = [ hc0[3] * r2, hc0[2] * u2, hc0[1] * w2, hc0[0] * y2 ]
+       vpmuludq        hc0,ruwy2,t1
+       # t1 += [ hc1[3] * r1, hc1[2] * u1, hc1[1] * w1, hc1[0] * y1 ]
+       vpmuludq        hc1,ruwy1,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc2[3] * r0, hc2[2] * u0, hc2[1] * w0, hc2[0] * y0 ]
+       vpmuludq        hc2,ruwy0,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc3[3] * s4, hc3[2] * v4, hc3[1] * x4, hc3[0] * z4 ]
+       vpmuludq        hc3,svxz4,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc4[3] * s3, hc4[2] * v3, hc4[1] * x3, hc4[0] * z3 ]
+       vpmuludq        hc4,svxz3,t2
+       vpaddq          t2,t1,t1
+       # d2 = t1[0] + t1[1] + t1[2] + t1[3]
+       vpermq          $0xee,t1,t2
+       vpaddq          t2,t1,t1
+       vpsrldq         $8,t1,t2
+       vpaddq          t2,t1,t1
+       vmovq           t1x,d2
+
+       # t1 = [ hc0[3] * r3, hc0[2] * u3, hc0[1] * w3, hc0[0] * y3 ]
+       vpmuludq        hc0,ruwy3,t1
+       # t1 += [ hc1[3] * r2, hc1[2] * u2, hc1[1] * w2, hc1[0] * y2 ]
+       vpmuludq        hc1,ruwy2,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc2[3] * r1, hc2[2] * u1, hc2[1] * w1, hc2[0] * y1 ]
+       vpmuludq        hc2,ruwy1,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc3[3] * r0, hc3[2] * u0, hc3[1] * w0, hc3[0] * y0 ]
+       vpmuludq        hc3,ruwy0,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc4[3] * s4, hc4[2] * v4, hc4[1] * x4, hc4[0] * z4 ]
+       vpmuludq        hc4,svxz4,t2
+       vpaddq          t2,t1,t1
+       # d3 = t1[0] + t1[1] + t1[2] + t1[3]
+       vpermq          $0xee,t1,t2
+       vpaddq          t2,t1,t1
+       vpsrldq         $8,t1,t2
+       vpaddq          t2,t1,t1
+       vmovq           t1x,d3
+
+       # t1 = [ hc0[3] * r4, hc0[2] * u4, hc0[1] * w4, hc0[0] * y4 ]
+       vpmuludq        hc0,ruwy4,t1
+       # t1 += [ hc1[3] * r3, hc1[2] * u3, hc1[1] * w3, hc1[0] * y3 ]
+       vpmuludq        hc1,ruwy3,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc2[3] * r2, hc2[2] * u2, hc2[1] * w2, hc2[0] * y2 ]
+       vpmuludq        hc2,ruwy2,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc3[3] * r1, hc3[2] * u1, hc3[1] * w1, hc3[0] * y1 ]
+       vpmuludq        hc3,ruwy1,t2
+       vpaddq          t2,t1,t1
+       # t1 += [ hc4[3] * r0, hc4[2] * u0, hc4[1] * w0, hc4[0] * y0 ]
+       vpmuludq        hc4,ruwy0,t2
+       vpaddq          t2,t1,t1
+       # d4 = t1[0] + t1[1] + t1[2] + t1[3]
+       vpermq          $0xee,t1,t2
+       vpaddq          t2,t1,t1
+       vpsrldq         $8,t1,t2
+       vpaddq          t2,t1,t1
+       vmovq           t1x,d4
+
+       # d1 += d0 >> 26
+       mov             d0,%rax
+       shr             $26,%rax
+       add             %rax,d1
+       # h0 = d0 & 0x3ffffff
+       mov             d0,%rbx
+       and             $0x3ffffff,%ebx
+
+       # d2 += d1 >> 26
+       mov             d1,%rax
+       shr             $26,%rax
+       add             %rax,d2
+       # h1 = d1 & 0x3ffffff
+       mov             d1,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h1
+
+       # d3 += d2 >> 26
+       mov             d2,%rax
+       shr             $26,%rax
+       add             %rax,d3
+       # h2 = d2 & 0x3ffffff
+       mov             d2,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h2
+
+       # d4 += d3 >> 26
+       mov             d3,%rax
+       shr             $26,%rax
+       add             %rax,d4
+       # h3 = d3 & 0x3ffffff
+       mov             d3,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h3
+
+       # h0 += (d4 >> 26) * 5
+       mov             d4,%rax
+       shr             $26,%rax
+       lea             (%eax,%eax,4),%eax
+       add             %eax,%ebx
+       # h4 = d4 & 0x3ffffff
+       mov             d4,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h4
+
+       # h1 += h0 >> 26
+       mov             %ebx,%eax
+       shr             $26,%eax
+       add             %eax,h1
+       # h0 = h0 & 0x3ffffff
+       andl            $0x3ffffff,%ebx
+       mov             %ebx,h0
+
+       add             $0x40,m
+       dec             %rcx
+       jnz             .Ldoblock4
+
+       vzeroupper
+       pop             %r13
+       pop             %r12
+       pop             %rbx
+       ret
+ENDPROC(poly1305_4block_avx2)
diff --git a/arch/x86/crypto/poly1305-sse2-x86_64.S b/arch/x86/crypto/poly1305-sse2-x86_64.S
new file mode 100644 (file)
index 0000000..338c748
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * Poly1305 authenticator algorithm, RFC7539, x64 SSE2 functions
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+
+.data
+.align 16
+
+ANMASK:        .octa 0x0000000003ffffff0000000003ffffff
+ORMASK:        .octa 0x00000000010000000000000001000000
+
+.text
+
+#define h0 0x00(%rdi)
+#define h1 0x04(%rdi)
+#define h2 0x08(%rdi)
+#define h3 0x0c(%rdi)
+#define h4 0x10(%rdi)
+#define r0 0x00(%rdx)
+#define r1 0x04(%rdx)
+#define r2 0x08(%rdx)
+#define r3 0x0c(%rdx)
+#define r4 0x10(%rdx)
+#define s1 0x00(%rsp)
+#define s2 0x04(%rsp)
+#define s3 0x08(%rsp)
+#define s4 0x0c(%rsp)
+#define m %rsi
+#define h01 %xmm0
+#define h23 %xmm1
+#define h44 %xmm2
+#define t1 %xmm3
+#define t2 %xmm4
+#define t3 %xmm5
+#define t4 %xmm6
+#define mask %xmm7
+#define d0 %r8
+#define d1 %r9
+#define d2 %r10
+#define d3 %r11
+#define d4 %r12
+
+ENTRY(poly1305_block_sse2)
+       # %rdi: Accumulator h[5]
+       # %rsi: 16 byte input block m
+       # %rdx: Poly1305 key r[5]
+       # %rcx: Block count
+
+       # This single block variant tries to improve performance by doing two
+       # multiplications in parallel using SSE instructions. There is quite
+       # some quardword packing involved, hence the speedup is marginal.
+
+       push            %rbx
+       push            %r12
+       sub             $0x10,%rsp
+
+       # s1..s4 = r1..r4 * 5
+       mov             r1,%eax
+       lea             (%eax,%eax,4),%eax
+       mov             %eax,s1
+       mov             r2,%eax
+       lea             (%eax,%eax,4),%eax
+       mov             %eax,s2
+       mov             r3,%eax
+       lea             (%eax,%eax,4),%eax
+       mov             %eax,s3
+       mov             r4,%eax
+       lea             (%eax,%eax,4),%eax
+       mov             %eax,s4
+
+       movdqa          ANMASK(%rip),mask
+
+.Ldoblock:
+       # h01 = [0, h1, 0, h0]
+       # h23 = [0, h3, 0, h2]
+       # h44 = [0, h4, 0, h4]
+       movd            h0,h01
+       movd            h1,t1
+       movd            h2,h23
+       movd            h3,t2
+       movd            h4,h44
+       punpcklqdq      t1,h01
+       punpcklqdq      t2,h23
+       punpcklqdq      h44,h44
+
+       # h01 += [ (m[3-6] >> 2) & 0x3ffffff, m[0-3] & 0x3ffffff ]
+       movd            0x00(m),t1
+       movd            0x03(m),t2
+       psrld           $2,t2
+       punpcklqdq      t2,t1
+       pand            mask,t1
+       paddd           t1,h01
+       # h23 += [ (m[9-12] >> 6) & 0x3ffffff, (m[6-9] >> 4) & 0x3ffffff ]
+       movd            0x06(m),t1
+       movd            0x09(m),t2
+       psrld           $4,t1
+       psrld           $6,t2
+       punpcklqdq      t2,t1
+       pand            mask,t1
+       paddd           t1,h23
+       # h44 += [ (m[12-15] >> 8) | (1 << 24), (m[12-15] >> 8) | (1 << 24) ]
+       mov             0x0c(m),%eax
+       shr             $8,%eax
+       or              $0x01000000,%eax
+       movd            %eax,t1
+       pshufd          $0xc4,t1,t1
+       paddd           t1,h44
+
+       # t1[0] = h0 * r0 + h2 * s3
+       # t1[1] = h1 * s4 + h3 * s2
+       movd            r0,t1
+       movd            s4,t2
+       punpcklqdq      t2,t1
+       pmuludq         h01,t1
+       movd            s3,t2
+       movd            s2,t3
+       punpcklqdq      t3,t2
+       pmuludq         h23,t2
+       paddq           t2,t1
+       # t2[0] = h0 * r1 + h2 * s4
+       # t2[1] = h1 * r0 + h3 * s3
+       movd            r1,t2
+       movd            r0,t3
+       punpcklqdq      t3,t2
+       pmuludq         h01,t2
+       movd            s4,t3
+       movd            s3,t4
+       punpcklqdq      t4,t3
+       pmuludq         h23,t3
+       paddq           t3,t2
+       # t3[0] = h4 * s1
+       # t3[1] = h4 * s2
+       movd            s1,t3
+       movd            s2,t4
+       punpcklqdq      t4,t3
+       pmuludq         h44,t3
+       # d0 = t1[0] + t1[1] + t3[0]
+       # d1 = t2[0] + t2[1] + t3[1]
+       movdqa          t1,t4
+       punpcklqdq      t2,t4
+       punpckhqdq      t2,t1
+       paddq           t4,t1
+       paddq           t3,t1
+       movq            t1,d0
+       psrldq          $8,t1
+       movq            t1,d1
+
+       # t1[0] = h0 * r2 + h2 * r0
+       # t1[1] = h1 * r1 + h3 * s4
+       movd            r2,t1
+       movd            r1,t2
+       punpcklqdq      t2,t1
+       pmuludq         h01,t1
+       movd            r0,t2
+       movd            s4,t3
+       punpcklqdq      t3,t2
+       pmuludq         h23,t2
+       paddq           t2,t1
+       # t2[0] = h0 * r3 + h2 * r1
+       # t2[1] = h1 * r2 + h3 * r0
+       movd            r3,t2
+       movd            r2,t3
+       punpcklqdq      t3,t2
+       pmuludq         h01,t2
+       movd            r1,t3
+       movd            r0,t4
+       punpcklqdq      t4,t3
+       pmuludq         h23,t3
+       paddq           t3,t2
+       # t3[0] = h4 * s3
+       # t3[1] = h4 * s4
+       movd            s3,t3
+       movd            s4,t4
+       punpcklqdq      t4,t3
+       pmuludq         h44,t3
+       # d2 = t1[0] + t1[1] + t3[0]
+       # d3 = t2[0] + t2[1] + t3[1]
+       movdqa          t1,t4
+       punpcklqdq      t2,t4
+       punpckhqdq      t2,t1
+       paddq           t4,t1
+       paddq           t3,t1
+       movq            t1,d2
+       psrldq          $8,t1
+       movq            t1,d3
+
+       # t1[0] = h0 * r4 + h2 * r2
+       # t1[1] = h1 * r3 + h3 * r1
+       movd            r4,t1
+       movd            r3,t2
+       punpcklqdq      t2,t1
+       pmuludq         h01,t1
+       movd            r2,t2
+       movd            r1,t3
+       punpcklqdq      t3,t2
+       pmuludq         h23,t2
+       paddq           t2,t1
+       # t3[0] = h4 * r0
+       movd            r0,t3
+       pmuludq         h44,t3
+       # d4 = t1[0] + t1[1] + t3[0]
+       movdqa          t1,t4
+       psrldq          $8,t4
+       paddq           t4,t1
+       paddq           t3,t1
+       movq            t1,d4
+
+       # d1 += d0 >> 26
+       mov             d0,%rax
+       shr             $26,%rax
+       add             %rax,d1
+       # h0 = d0 & 0x3ffffff
+       mov             d0,%rbx
+       and             $0x3ffffff,%ebx
+
+       # d2 += d1 >> 26
+       mov             d1,%rax
+       shr             $26,%rax
+       add             %rax,d2
+       # h1 = d1 & 0x3ffffff
+       mov             d1,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h1
+
+       # d3 += d2 >> 26
+       mov             d2,%rax
+       shr             $26,%rax
+       add             %rax,d3
+       # h2 = d2 & 0x3ffffff
+       mov             d2,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h2
+
+       # d4 += d3 >> 26
+       mov             d3,%rax
+       shr             $26,%rax
+       add             %rax,d4
+       # h3 = d3 & 0x3ffffff
+       mov             d3,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h3
+
+       # h0 += (d4 >> 26) * 5
+       mov             d4,%rax
+       shr             $26,%rax
+       lea             (%eax,%eax,4),%eax
+       add             %eax,%ebx
+       # h4 = d4 & 0x3ffffff
+       mov             d4,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h4
+
+       # h1 += h0 >> 26
+       mov             %ebx,%eax
+       shr             $26,%eax
+       add             %eax,h1
+       # h0 = h0 & 0x3ffffff
+       andl            $0x3ffffff,%ebx
+       mov             %ebx,h0
+
+       add             $0x10,m
+       dec             %rcx
+       jnz             .Ldoblock
+
+       add             $0x10,%rsp
+       pop             %r12
+       pop             %rbx
+       ret
+ENDPROC(poly1305_block_sse2)
+
+
+#define u0 0x00(%r8)
+#define u1 0x04(%r8)
+#define u2 0x08(%r8)
+#define u3 0x0c(%r8)
+#define u4 0x10(%r8)
+#define hc0 %xmm0
+#define hc1 %xmm1
+#define hc2 %xmm2
+#define hc3 %xmm5
+#define hc4 %xmm6
+#define ru0 %xmm7
+#define ru1 %xmm8
+#define ru2 %xmm9
+#define ru3 %xmm10
+#define ru4 %xmm11
+#define sv1 %xmm12
+#define sv2 %xmm13
+#define sv3 %xmm14
+#define sv4 %xmm15
+#undef d0
+#define d0 %r13
+
+ENTRY(poly1305_2block_sse2)
+       # %rdi: Accumulator h[5]
+       # %rsi: 16 byte input block m
+       # %rdx: Poly1305 key r[5]
+       # %rcx: Doubleblock count
+       # %r8:  Poly1305 derived key r^2 u[5]
+
+       # This two-block variant further improves performance by using loop
+       # unrolled block processing. This is more straight forward and does
+       # less byte shuffling, but requires a second Poly1305 key r^2:
+       # h = (h + m) * r    =>    h = (h + m1) * r^2 + m2 * r
+
+       push            %rbx
+       push            %r12
+       push            %r13
+
+       # combine r0,u0
+       movd            u0,ru0
+       movd            r0,t1
+       punpcklqdq      t1,ru0
+
+       # combine r1,u1 and s1=r1*5,v1=u1*5
+       movd            u1,ru1
+       movd            r1,t1
+       punpcklqdq      t1,ru1
+       movdqa          ru1,sv1
+       pslld           $2,sv1
+       paddd           ru1,sv1
+
+       # combine r2,u2 and s2=r2*5,v2=u2*5
+       movd            u2,ru2
+       movd            r2,t1
+       punpcklqdq      t1,ru2
+       movdqa          ru2,sv2
+       pslld           $2,sv2
+       paddd           ru2,sv2
+
+       # combine r3,u3 and s3=r3*5,v3=u3*5
+       movd            u3,ru3
+       movd            r3,t1
+       punpcklqdq      t1,ru3
+       movdqa          ru3,sv3
+       pslld           $2,sv3
+       paddd           ru3,sv3
+
+       # combine r4,u4 and s4=r4*5,v4=u4*5
+       movd            u4,ru4
+       movd            r4,t1
+       punpcklqdq      t1,ru4
+       movdqa          ru4,sv4
+       pslld           $2,sv4
+       paddd           ru4,sv4
+
+.Ldoblock2:
+       # hc0 = [ m[16-19] & 0x3ffffff, h0 + m[0-3] & 0x3ffffff ]
+       movd            0x00(m),hc0
+       movd            0x10(m),t1
+       punpcklqdq      t1,hc0
+       pand            ANMASK(%rip),hc0
+       movd            h0,t1
+       paddd           t1,hc0
+       # hc1 = [ (m[19-22] >> 2) & 0x3ffffff, h1 + (m[3-6] >> 2) & 0x3ffffff ]
+       movd            0x03(m),hc1
+       movd            0x13(m),t1
+       punpcklqdq      t1,hc1
+       psrld           $2,hc1
+       pand            ANMASK(%rip),hc1
+       movd            h1,t1
+       paddd           t1,hc1
+       # hc2 = [ (m[22-25] >> 4) & 0x3ffffff, h2 + (m[6-9] >> 4) & 0x3ffffff ]
+       movd            0x06(m),hc2
+       movd            0x16(m),t1
+       punpcklqdq      t1,hc2
+       psrld           $4,hc2
+       pand            ANMASK(%rip),hc2
+       movd            h2,t1
+       paddd           t1,hc2
+       # hc3 = [ (m[25-28] >> 6) & 0x3ffffff, h3 + (m[9-12] >> 6) & 0x3ffffff ]
+       movd            0x09(m),hc3
+       movd            0x19(m),t1
+       punpcklqdq      t1,hc3
+       psrld           $6,hc3
+       pand            ANMASK(%rip),hc3
+       movd            h3,t1
+       paddd           t1,hc3
+       # hc4 = [ (m[28-31] >> 8) | (1<<24), h4 + (m[12-15] >> 8) | (1<<24) ]
+       movd            0x0c(m),hc4
+       movd            0x1c(m),t1
+       punpcklqdq      t1,hc4
+       psrld           $8,hc4
+       por             ORMASK(%rip),hc4
+       movd            h4,t1
+       paddd           t1,hc4
+
+       # t1 = [ hc0[1] * r0, hc0[0] * u0 ]
+       movdqa          ru0,t1
+       pmuludq         hc0,t1
+       # t1 += [ hc1[1] * s4, hc1[0] * v4 ]
+       movdqa          sv4,t2
+       pmuludq         hc1,t2
+       paddq           t2,t1
+       # t1 += [ hc2[1] * s3, hc2[0] * v3 ]
+       movdqa          sv3,t2
+       pmuludq         hc2,t2
+       paddq           t2,t1
+       # t1 += [ hc3[1] * s2, hc3[0] * v2 ]
+       movdqa          sv2,t2
+       pmuludq         hc3,t2
+       paddq           t2,t1
+       # t1 += [ hc4[1] * s1, hc4[0] * v1 ]
+       movdqa          sv1,t2
+       pmuludq         hc4,t2
+       paddq           t2,t1
+       # d0 = t1[0] + t1[1]
+       movdqa          t1,t2
+       psrldq          $8,t2
+       paddq           t2,t1
+       movq            t1,d0
+
+       # t1 = [ hc0[1] * r1, hc0[0] * u1 ]
+       movdqa          ru1,t1
+       pmuludq         hc0,t1
+       # t1 += [ hc1[1] * r0, hc1[0] * u0 ]
+       movdqa          ru0,t2
+       pmuludq         hc1,t2
+       paddq           t2,t1
+       # t1 += [ hc2[1] * s4, hc2[0] * v4 ]
+       movdqa          sv4,t2
+       pmuludq         hc2,t2
+       paddq           t2,t1
+       # t1 += [ hc3[1] * s3, hc3[0] * v3 ]
+       movdqa          sv3,t2
+       pmuludq         hc3,t2
+       paddq           t2,t1
+       # t1 += [ hc4[1] * s2, hc4[0] * v2 ]
+       movdqa          sv2,t2
+       pmuludq         hc4,t2
+       paddq           t2,t1
+       # d1 = t1[0] + t1[1]
+       movdqa          t1,t2
+       psrldq          $8,t2
+       paddq           t2,t1
+       movq            t1,d1
+
+       # t1 = [ hc0[1] * r2, hc0[0] * u2 ]
+       movdqa          ru2,t1
+       pmuludq         hc0,t1
+       # t1 += [ hc1[1] * r1, hc1[0] * u1 ]
+       movdqa          ru1,t2
+       pmuludq         hc1,t2
+       paddq           t2,t1
+       # t1 += [ hc2[1] * r0, hc2[0] * u0 ]
+       movdqa          ru0,t2
+       pmuludq         hc2,t2
+       paddq           t2,t1
+       # t1 += [ hc3[1] * s4, hc3[0] * v4 ]
+       movdqa          sv4,t2
+       pmuludq         hc3,t2
+       paddq           t2,t1
+       # t1 += [ hc4[1] * s3, hc4[0] * v3 ]
+       movdqa          sv3,t2
+       pmuludq         hc4,t2
+       paddq           t2,t1
+       # d2 = t1[0] + t1[1]
+       movdqa          t1,t2
+       psrldq          $8,t2
+       paddq           t2,t1
+       movq            t1,d2
+
+       # t1 = [ hc0[1] * r3, hc0[0] * u3 ]
+       movdqa          ru3,t1
+       pmuludq         hc0,t1
+       # t1 += [ hc1[1] * r2, hc1[0] * u2 ]
+       movdqa          ru2,t2
+       pmuludq         hc1,t2
+       paddq           t2,t1
+       # t1 += [ hc2[1] * r1, hc2[0] * u1 ]
+       movdqa          ru1,t2
+       pmuludq         hc2,t2
+       paddq           t2,t1
+       # t1 += [ hc3[1] * r0, hc3[0] * u0 ]
+       movdqa          ru0,t2
+       pmuludq         hc3,t2
+       paddq           t2,t1
+       # t1 += [ hc4[1] * s4, hc4[0] * v4 ]
+       movdqa          sv4,t2
+       pmuludq         hc4,t2
+       paddq           t2,t1
+       # d3 = t1[0] + t1[1]
+       movdqa          t1,t2
+       psrldq          $8,t2
+       paddq           t2,t1
+       movq            t1,d3
+
+       # t1 = [ hc0[1] * r4, hc0[0] * u4 ]
+       movdqa          ru4,t1
+       pmuludq         hc0,t1
+       # t1 += [ hc1[1] * r3, hc1[0] * u3 ]
+       movdqa          ru3,t2
+       pmuludq         hc1,t2
+       paddq           t2,t1
+       # t1 += [ hc2[1] * r2, hc2[0] * u2 ]
+       movdqa          ru2,t2
+       pmuludq         hc2,t2
+       paddq           t2,t1
+       # t1 += [ hc3[1] * r1, hc3[0] * u1 ]
+       movdqa          ru1,t2
+       pmuludq         hc3,t2
+       paddq           t2,t1
+       # t1 += [ hc4[1] * r0, hc4[0] * u0 ]
+       movdqa          ru0,t2
+       pmuludq         hc4,t2
+       paddq           t2,t1
+       # d4 = t1[0] + t1[1]
+       movdqa          t1,t2
+       psrldq          $8,t2
+       paddq           t2,t1
+       movq            t1,d4
+
+       # d1 += d0 >> 26
+       mov             d0,%rax
+       shr             $26,%rax
+       add             %rax,d1
+       # h0 = d0 & 0x3ffffff
+       mov             d0,%rbx
+       and             $0x3ffffff,%ebx
+
+       # d2 += d1 >> 26
+       mov             d1,%rax
+       shr             $26,%rax
+       add             %rax,d2
+       # h1 = d1 & 0x3ffffff
+       mov             d1,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h1
+
+       # d3 += d2 >> 26
+       mov             d2,%rax
+       shr             $26,%rax
+       add             %rax,d3
+       # h2 = d2 & 0x3ffffff
+       mov             d2,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h2
+
+       # d4 += d3 >> 26
+       mov             d3,%rax
+       shr             $26,%rax
+       add             %rax,d4
+       # h3 = d3 & 0x3ffffff
+       mov             d3,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h3
+
+       # h0 += (d4 >> 26) * 5
+       mov             d4,%rax
+       shr             $26,%rax
+       lea             (%eax,%eax,4),%eax
+       add             %eax,%ebx
+       # h4 = d4 & 0x3ffffff
+       mov             d4,%rax
+       and             $0x3ffffff,%eax
+       mov             %eax,h4
+
+       # h1 += h0 >> 26
+       mov             %ebx,%eax
+       shr             $26,%eax
+       add             %eax,h1
+       # h0 = h0 & 0x3ffffff
+       andl            $0x3ffffff,%ebx
+       mov             %ebx,h0
+
+       add             $0x20,m
+       dec             %rcx
+       jnz             .Ldoblock2
+
+       pop             %r13
+       pop             %r12
+       pop             %rbx
+       ret
+ENDPROC(poly1305_2block_sse2)
diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c
new file mode 100644 (file)
index 0000000..f7170d7
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Poly1305 authenticator algorithm, RFC7539, SIMD glue code
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * 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 <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/poly1305.h>
+#include <linux/crypto.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/fpu/api.h>
+#include <asm/simd.h>
+
+struct poly1305_simd_desc_ctx {
+       struct poly1305_desc_ctx base;
+       /* derived key u set? */
+       bool uset;
+#ifdef CONFIG_AS_AVX2
+       /* derived keys r^3, r^4 set? */
+       bool wset;
+#endif
+       /* derived Poly1305 key r^2 */
+       u32 u[5];
+       /* ... silently appended r^3 and r^4 when using AVX2 */
+};
+
+asmlinkage void poly1305_block_sse2(u32 *h, const u8 *src,
+                                   const u32 *r, unsigned int blocks);
+asmlinkage void poly1305_2block_sse2(u32 *h, const u8 *src, const u32 *r,
+                                    unsigned int blocks, const u32 *u);
+#ifdef CONFIG_AS_AVX2
+asmlinkage void poly1305_4block_avx2(u32 *h, const u8 *src, const u32 *r,
+                                    unsigned int blocks, const u32 *u);
+static bool poly1305_use_avx2;
+#endif
+
+static int poly1305_simd_init(struct shash_desc *desc)
+{
+       struct poly1305_simd_desc_ctx *sctx = shash_desc_ctx(desc);
+
+       sctx->uset = false;
+#ifdef CONFIG_AS_AVX2
+       sctx->wset = false;
+#endif
+
+       return crypto_poly1305_init(desc);
+}
+
+static void poly1305_simd_mult(u32 *a, const u32 *b)
+{
+       u8 m[POLY1305_BLOCK_SIZE];
+
+       memset(m, 0, sizeof(m));
+       /* The poly1305 block function adds a hi-bit to the accumulator which
+        * we don't need for key multiplication; compensate for it. */
+       a[4] -= 1 << 24;
+       poly1305_block_sse2(a, m, b, 1);
+}
+
+static unsigned int poly1305_simd_blocks(struct poly1305_desc_ctx *dctx,
+                                        const u8 *src, unsigned int srclen)
+{
+       struct poly1305_simd_desc_ctx *sctx;
+       unsigned int blocks, datalen;
+
+       BUILD_BUG_ON(offsetof(struct poly1305_simd_desc_ctx, base));
+       sctx = container_of(dctx, struct poly1305_simd_desc_ctx, base);
+
+       if (unlikely(!dctx->sset)) {
+               datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
+               src += srclen - datalen;
+               srclen = datalen;
+       }
+
+#ifdef CONFIG_AS_AVX2
+       if (poly1305_use_avx2 && srclen >= POLY1305_BLOCK_SIZE * 4) {
+               if (unlikely(!sctx->wset)) {
+                       if (!sctx->uset) {
+                               memcpy(sctx->u, dctx->r, sizeof(sctx->u));
+                               poly1305_simd_mult(sctx->u, dctx->r);
+                               sctx->uset = true;
+                       }
+                       memcpy(sctx->u + 5, sctx->u, sizeof(sctx->u));
+                       poly1305_simd_mult(sctx->u + 5, dctx->r);
+                       memcpy(sctx->u + 10, sctx->u + 5, sizeof(sctx->u));
+                       poly1305_simd_mult(sctx->u + 10, dctx->r);
+                       sctx->wset = true;
+               }
+               blocks = srclen / (POLY1305_BLOCK_SIZE * 4);
+               poly1305_4block_avx2(dctx->h, src, dctx->r, blocks, sctx->u);
+               src += POLY1305_BLOCK_SIZE * 4 * blocks;
+               srclen -= POLY1305_BLOCK_SIZE * 4 * blocks;
+       }
+#endif
+       if (likely(srclen >= POLY1305_BLOCK_SIZE * 2)) {
+               if (unlikely(!sctx->uset)) {
+                       memcpy(sctx->u, dctx->r, sizeof(sctx->u));
+                       poly1305_simd_mult(sctx->u, dctx->r);
+                       sctx->uset = true;
+               }
+               blocks = srclen / (POLY1305_BLOCK_SIZE * 2);
+               poly1305_2block_sse2(dctx->h, src, dctx->r, blocks, sctx->u);
+               src += POLY1305_BLOCK_SIZE * 2 * blocks;
+               srclen -= POLY1305_BLOCK_SIZE * 2 * blocks;
+       }
+       if (srclen >= POLY1305_BLOCK_SIZE) {
+               poly1305_block_sse2(dctx->h, src, dctx->r, 1);
+               srclen -= POLY1305_BLOCK_SIZE;
+       }
+       return srclen;
+}
+
+static int poly1305_simd_update(struct shash_desc *desc,
+                               const u8 *src, unsigned int srclen)
+{
+       struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+       unsigned int bytes;
+
+       /* kernel_fpu_begin/end is costly, use fallback for small updates */
+       if (srclen <= 288 || !may_use_simd())
+               return crypto_poly1305_update(desc, src, srclen);
+
+       kernel_fpu_begin();
+
+       if (unlikely(dctx->buflen)) {
+               bytes = min(srclen, POLY1305_BLOCK_SIZE - dctx->buflen);
+               memcpy(dctx->buf + dctx->buflen, src, bytes);
+               src += bytes;
+               srclen -= bytes;
+               dctx->buflen += bytes;
+
+               if (dctx->buflen == POLY1305_BLOCK_SIZE) {
+                       poly1305_simd_blocks(dctx, dctx->buf,
+                                            POLY1305_BLOCK_SIZE);
+                       dctx->buflen = 0;
+               }
+       }
+
+       if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
+               bytes = poly1305_simd_blocks(dctx, src, srclen);
+               src += srclen - bytes;
+               srclen = bytes;
+       }
+
+       kernel_fpu_end();
+
+       if (unlikely(srclen)) {
+               dctx->buflen = srclen;
+               memcpy(dctx->buf, src, srclen);
+       }
+
+       return 0;
+}
+
+static struct shash_alg alg = {
+       .digestsize     = POLY1305_DIGEST_SIZE,
+       .init           = poly1305_simd_init,
+       .update         = poly1305_simd_update,
+       .final          = crypto_poly1305_final,
+       .setkey         = crypto_poly1305_setkey,
+       .descsize       = sizeof(struct poly1305_simd_desc_ctx),
+       .base           = {
+               .cra_name               = "poly1305",
+               .cra_driver_name        = "poly1305-simd",
+               .cra_priority           = 300,
+               .cra_flags              = CRYPTO_ALG_TYPE_SHASH,
+               .cra_alignmask          = sizeof(u32) - 1,
+               .cra_blocksize          = POLY1305_BLOCK_SIZE,
+               .cra_module             = THIS_MODULE,
+       },
+};
+
+static int __init poly1305_simd_mod_init(void)
+{
+       if (!cpu_has_xmm2)
+               return -ENODEV;
+
+#ifdef CONFIG_AS_AVX2
+       poly1305_use_avx2 = cpu_has_avx && cpu_has_avx2 &&
+                           cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, NULL);
+       alg.descsize = sizeof(struct poly1305_simd_desc_ctx);
+       if (poly1305_use_avx2)
+               alg.descsize += 10 * sizeof(u32);
+#endif
+       return crypto_register_shash(&alg);
+}
+
+static void __exit poly1305_simd_mod_exit(void)
+{
+       crypto_unregister_shash(&alg);
+}
+
+module_init(poly1305_simd_mod_init);
+module_exit(poly1305_simd_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
+MODULE_DESCRIPTION("Poly1305 authenticator");
+MODULE_ALIAS_CRYPTO("poly1305");
+MODULE_ALIAS_CRYPTO("poly1305-simd");
index 5a1844765a7aba6dab47b878daf6eb723c044c03..a7e257d9cb90b9f34ecb03180fec8c54f2afd82f 100644 (file)
@@ -140,6 +140,7 @@ sysexit_from_sys_call:
         */
        andl    $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
        movl    RIP(%rsp), %ecx         /* User %eip */
+       movq    RAX(%rsp), %rax
        RESTORE_RSI_RDI
        xorl    %edx, %edx              /* Do not leak kernel information */
        xorq    %r8, %r8
@@ -219,7 +220,6 @@ sysexit_from_sys_call:
 1:     setbe   %al                     /* 1 if error, 0 if not */
        movzbl  %al, %edi               /* zero-extend that into %edi */
        call    __audit_syscall_exit
-       movq    RAX(%rsp), %rax         /* reload syscall return value */
        movl    $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %edi
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
@@ -368,6 +368,7 @@ sysretl_from_sys_call:
        RESTORE_RSI_RDI_RDX
        movl    RIP(%rsp), %ecx
        movl    EFLAGS(%rsp), %r11d
+       movq    RAX(%rsp), %rax
        xorq    %r10, %r10
        xorq    %r9, %r9
        xorq    %r8, %r8
index 49ec9038ec14102a286c9b4bed126a6825613439..c12e845f59e6b40c5afb62d8ecf1e08f22dce4db 100644 (file)
@@ -252,6 +252,11 @@ struct kvm_pio_request {
        int size;
 };
 
+struct rsvd_bits_validate {
+       u64 rsvd_bits_mask[2][4];
+       u64 bad_mt_xwr;
+};
+
 /*
  * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
  * 32-bit).  The kvm_mmu structure abstracts the details of the current mmu
@@ -289,8 +294,15 @@ struct kvm_mmu {
 
        u64 *pae_root;
        u64 *lm_root;
-       u64 rsvd_bits_mask[2][4];
-       u64 bad_mt_xwr;
+
+       /*
+        * check zero bits on shadow page table entries, these
+        * bits include not only hardware reserved bits but also
+        * the bits spte never used.
+        */
+       struct rsvd_bits_validate shadow_zero_check;
+
+       struct rsvd_bits_validate guest_rsvd_check;
 
        /*
         * Bitmap: bit set = last pte in walk
@@ -358,6 +370,11 @@ struct kvm_mtrr {
        struct list_head head;
 };
 
+/* Hyper-V per vcpu emulation context */
+struct kvm_vcpu_hv {
+       u64 hv_vapic;
+};
+
 struct kvm_vcpu_arch {
        /*
         * rip and regs accesses must go through
@@ -514,8 +531,7 @@ struct kvm_vcpu_arch {
        /* used for guest single stepping over the given code position */
        unsigned long singlestep_rip;
 
-       /* fields used by HYPER-V emulation */
-       u64 hv_vapic;
+       struct kvm_vcpu_hv hyperv;
 
        cpumask_var_t wbinvd_dirty_mask;
 
@@ -586,6 +602,17 @@ struct kvm_apic_map {
        struct kvm_lapic *logical_map[16][16];
 };
 
+/* Hyper-V emulation context */
+struct kvm_hv {
+       u64 hv_guest_os_id;
+       u64 hv_hypercall;
+       u64 hv_tsc_page;
+
+       /* Hyper-v based guest crash (NT kernel bugcheck) parameters */
+       u64 hv_crash_param[HV_X64_MSR_CRASH_PARAMS];
+       u64 hv_crash_ctl;
+};
+
 struct kvm_arch {
        unsigned int n_used_mmu_pages;
        unsigned int n_requested_mmu_pages;
@@ -645,16 +672,14 @@ struct kvm_arch {
        /* reads protected by irq_srcu, writes by irq_lock */
        struct hlist_head mask_notifier_list;
 
-       /* fields used by HYPER-V emulation */
-       u64 hv_guest_os_id;
-       u64 hv_hypercall;
-       u64 hv_tsc_page;
+       struct kvm_hv hyperv;
 
        #ifdef CONFIG_KVM_MMU_AUDIT
        int audit_point;
        #endif
 
        bool boot_vcpu_runs_old_kvmclock;
+       u32 bsp_vcpu_id;
 
        u64 disabled_quirks;
 };
@@ -1203,5 +1228,7 @@ int __x86_set_memory_region(struct kvm *kvm,
                            const struct kvm_userspace_memory_region *mem);
 int x86_set_memory_region(struct kvm *kvm,
                          const struct kvm_userspace_memory_region *mem);
+bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
+bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
 
 #endif /* _ASM_X86_KVM_HOST_H */
index c163215abb9ad99ee1c9eac3210acfb0380614b6..aaf59b7da98a2c7898390512c77601cd38b79eb1 100644 (file)
@@ -7,6 +7,7 @@
 
 struct ms_hyperv_info {
        u32 features;
+       u32 misc_features;
        u32 hints;
 };
 
@@ -20,4 +21,8 @@ void hyperv_vector_handler(struct pt_regs *regs);
 void hv_setup_vmbus_irq(void (*handler)(void));
 void hv_remove_vmbus_irq(void);
 
+void hv_setup_kexec_handler(void (*handler)(void));
+void hv_remove_kexec_handler(void);
+void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
+void hv_remove_crash_handler(void);
 #endif
index 164e3f8d3c3dbb6eb4fc0ea60e01cae15fe5116e..fa1195dae42541aaa1d836782a3a65aa25640e74 100644 (file)
@@ -93,8 +93,6 @@ extern raw_spinlock_t pci_config_lock;
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
-extern bool mp_should_keep_irq(struct device *dev);
-
 struct pci_raw_ops {
        int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
                                                int reg, int len, u32 *val);
index 6fe6b182c9981dd891a9a5bc9a55b3e6591a6f9f..9dfce4e0417d92adc623d32ff93f67109316b451 100644 (file)
@@ -57,9 +57,9 @@ struct sigcontext {
        unsigned long ip;
        unsigned long flags;
        unsigned short cs;
-       unsigned short __pad2;  /* Was called gs, but was always zero. */
-       unsigned short __pad1;  /* Was called fs, but was always zero. */
-       unsigned short ss;
+       unsigned short gs;
+       unsigned short fs;
+       unsigned short __pad0;
        unsigned long err;
        unsigned long trapno;
        unsigned long oldmask;
index 751bf4b7bf114da12231a56f4217c2583ddeafb2..d7f3b3b78ac313ca8a871d3a53b3d118850a657d 100644 (file)
@@ -79,12 +79,12 @@ do {                                                                        \
 #else /* CONFIG_X86_32 */
 
 /* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT    "pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp\t"
+#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
 
 #define __EXTRA_CLOBBER  \
        , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
-         "r12", "r13", "r14", "r15", "flags"
+         "r12", "r13", "r14", "r15"
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #define __switch_canary                                                          \
@@ -100,11 +100,7 @@ do {                                                                       \
 #define __switch_canary_iparam
 #endif /* CC_STACKPROTECTOR */
 
-/*
- * There is no need to save or restore flags, because flags are always
- * clean in kernel mode, with the possible exception of IOPL.  Kernel IOPL
- * has no effect.
- */
+/* Save restore flags to clear handle leaking NT */
 #define switch_to(prev, next, last) \
        asm volatile(SAVE_CONTEXT                                         \
             "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
index da772edd19ab568e8cc969514b5ef500e1d2d6f5..448b7ca61aee313826176a31f080616f8670aa54 100644 (file)
@@ -47,6 +47,7 @@
 #define CPU_BASED_MOV_DR_EXITING                0x00800000
 #define CPU_BASED_UNCOND_IO_EXITING             0x01000000
 #define CPU_BASED_USE_IO_BITMAPS                0x02000000
+#define CPU_BASED_MONITOR_TRAP_FLAG             0x08000000
 #define CPU_BASED_USE_MSR_BITMAPS               0x10000000
 #define CPU_BASED_MONITOR_EXITING               0x20000000
 #define CPU_BASED_PAUSE_EXITING                 0x40000000
@@ -367,29 +368,29 @@ enum vmcs_field {
 #define TYPE_PHYSICAL_APIC_EVENT        (10 << 12)
 #define TYPE_PHYSICAL_APIC_INST         (15 << 12)
 
-/* segment AR */
-#define SEGMENT_AR_L_MASK (1 << 13)
-
-#define AR_TYPE_ACCESSES_MASK 1
-#define AR_TYPE_READABLE_MASK (1 << 1)
-#define AR_TYPE_WRITEABLE_MASK (1 << 2)
-#define AR_TYPE_CODE_MASK (1 << 3)
-#define AR_TYPE_MASK 0x0f
-#define AR_TYPE_BUSY_64_TSS 11
-#define AR_TYPE_BUSY_32_TSS 11
-#define AR_TYPE_BUSY_16_TSS 3
-#define AR_TYPE_LDT 2
-
-#define AR_UNUSABLE_MASK (1 << 16)
-#define AR_S_MASK (1 << 4)
-#define AR_P_MASK (1 << 7)
-#define AR_L_MASK (1 << 13)
-#define AR_DB_MASK (1 << 14)
-#define AR_G_MASK (1 << 15)
-#define AR_DPL_SHIFT 5
-#define AR_DPL(ar) (((ar) >> AR_DPL_SHIFT) & 3)
-
-#define AR_RESERVD_MASK 0xfffe0f00
+/* segment AR in VMCS -- these are different from what LAR reports */
+#define VMX_SEGMENT_AR_L_MASK (1 << 13)
+
+#define VMX_AR_TYPE_ACCESSES_MASK 1
+#define VMX_AR_TYPE_READABLE_MASK (1 << 1)
+#define VMX_AR_TYPE_WRITEABLE_MASK (1 << 2)
+#define VMX_AR_TYPE_CODE_MASK (1 << 3)
+#define VMX_AR_TYPE_MASK 0x0f
+#define VMX_AR_TYPE_BUSY_64_TSS 11
+#define VMX_AR_TYPE_BUSY_32_TSS 11
+#define VMX_AR_TYPE_BUSY_16_TSS 3
+#define VMX_AR_TYPE_LDT 2
+
+#define VMX_AR_UNUSABLE_MASK (1 << 16)
+#define VMX_AR_S_MASK (1 << 4)
+#define VMX_AR_P_MASK (1 << 7)
+#define VMX_AR_L_MASK (1 << 13)
+#define VMX_AR_DB_MASK (1 << 14)
+#define VMX_AR_G_MASK (1 << 15)
+#define VMX_AR_DPL_SHIFT 5
+#define VMX_AR_DPL(ar) (((ar) >> VMX_AR_DPL_SHIFT) & 3)
+
+#define VMX_AR_RESERVD_MASK 0xfffe0f00
 
 #define TSS_PRIVATE_MEMSLOT                    (KVM_USER_MEM_SLOTS + 0)
 #define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT       (KVM_USER_MEM_SLOTS + 1)
index f36d56bd76324543f6f0c208bea569ea96e6e802..f0412c50c47b22e3840b900eb2054fb4476f98c6 100644 (file)
@@ -27,6 +27,8 @@
 #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)
+/* Partition reference TSC MSR is available */
+#define HV_X64_MSR_REFERENCE_TSC_AVAILABLE              (1 << 9)
 
 /* A partition's reference time stamp counter (TSC) page */
 #define HV_X64_MSR_REFERENCE_TSC               0x40000021
index 0e8a973de9ee8aec0c555a5e9e8b23348e2cc10b..40836a9a7250c99a16dc5969057177f66aa57186 100644 (file)
@@ -177,24 +177,9 @@ struct sigcontext {
        __u64 rip;
        __u64 eflags;           /* RFLAGS */
        __u16 cs;
-
-       /*
-        * Prior to 2.5.64 ("[PATCH] x86-64 updates for 2.5.64-bk3"),
-        * Linux saved and restored fs and gs in these slots.  This
-        * was counterproductive, as fsbase and gsbase were never
-        * saved, so arch_prctl was presumably unreliable.
-        *
-        * If these slots are ever needed for any other purpose, there
-        * is some risk that very old 64-bit binaries could get
-        * confused.  I doubt that many such binaries still work,
-        * though, since the same patch in 2.5.64 also removed the
-        * 64-bit set_thread_area syscall, so it appears that there is
-        * no TLS API that works in both pre- and post-2.5.64 kernels.
-        */
-       __u16 __pad2;           /* Was gs. */
-       __u16 __pad1;           /* Was fs. */
-
-       __u16 ss;
+       __u16 gs;
+       __u16 fs;
+       __u16 __pad0;
        __u64 err;
        __u64 trapno;
        __u64 oldmask;
index 1fe92181ee9ef8b3cb061a6091a732b2b9fa7bf0..37fee272618f1de348a7d5961f1792debba72991 100644 (file)
@@ -58,6 +58,7 @@
 #define EXIT_REASON_INVALID_STATE       33
 #define EXIT_REASON_MSR_LOAD_FAIL       34
 #define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_MONITOR_TRAP_FLAG   37
 #define EXIT_REASON_MONITOR_INSTRUCTION 39
 #define EXIT_REASON_PAUSE_INSTRUCTION   40
 #define EXIT_REASON_MCE_DURING_VMENTRY  41
        { EXIT_REASON_MSR_READ,              "MSR_READ" }, \
        { EXIT_REASON_MSR_WRITE,             "MSR_WRITE" }, \
        { EXIT_REASON_MWAIT_INSTRUCTION,     "MWAIT_INSTRUCTION" }, \
+       { EXIT_REASON_MONITOR_TRAP_FLAG,     "MONITOR_TRAP_FLAG" }, \
        { EXIT_REASON_MONITOR_INSTRUCTION,   "MONITOR_INSTRUCTION" }, \
        { EXIT_REASON_PAUSE_INSTRUCTION,     "PAUSE_INSTRUCTION" }, \
        { EXIT_REASON_MCE_DURING_VMENTRY,    "MCE_DURING_VMENTRY" }, \
index dcb52850a28fcbe00a4a25ddf47d6f4ccedf3c9c..cde732c1b495997ab715fdba70699c9ca144949b 100644 (file)
@@ -1424,7 +1424,7 @@ static inline void __x2apic_disable(void)
 {
        u64 msr;
 
-       if (cpu_has_apic)
+       if (!cpu_has_apic)
                return;
 
        rdmsrl(MSR_IA32_APICBASE, msr);
@@ -1483,10 +1483,13 @@ void x2apic_setup(void)
 
 static __init void x2apic_disable(void)
 {
-       u32 x2apic_id;
+       u32 x2apic_id, state = x2apic_state;
 
-       if (x2apic_state != X2APIC_ON)
-               goto out;
+       x2apic_mode = 0;
+       x2apic_state = X2APIC_DISABLED;
+
+       if (state != X2APIC_ON)
+               return;
 
        x2apic_id = read_apic_id();
        if (x2apic_id >= 255)
@@ -1494,9 +1497,6 @@ static __init void x2apic_disable(void)
 
        __x2apic_disable();
        register_lapic_address(mp_lapic_addr);
-out:
-       x2apic_state = X2APIC_DISABLED;
-       x2apic_mode = 0;
 }
 
 static __init void x2apic_enable(void)
index f813261d97405710c99cd0982d047a227a4c4fd3..2683f36e4e0a5e67311a7bcdbceea61c17382ec6 100644 (file)
@@ -322,7 +322,7 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
                irq_data->chip = &lapic_controller;
                irq_data->chip_data = data;
                irq_data->hwirq = virq + i;
-               err = assign_irq_vector_policy(virq, irq_data->node, data,
+               err = assign_irq_vector_policy(virq + i, irq_data->node, data,
                                               info);
                if (err)
                        goto error;
index 6236a54a63f449ce2ea824be13a3bcca2f57e4b9..3c986390058a555472ddd5486fe353fd59a89ec7 100644 (file)
@@ -377,17 +377,16 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif)
        return err;
 }
 
-static int mc_device_remove(struct device *dev, struct subsys_interface *sif)
+static void mc_device_remove(struct device *dev, struct subsys_interface *sif)
 {
        int cpu = dev->id;
 
        if (!cpu_online(cpu))
-               return 0;
+               return;
 
        pr_debug("CPU%d removed\n", cpu);
        microcode_fini_cpu(cpu);
        sysfs_remove_group(&dev->kobj, &mc_attr_group);
-       return 0;
 }
 
 static struct subsys_interface mc_cpu_interface = {
index aad4bd84b475ec4c762e72f62bbd9fb07f7ac2c4..f794bfa3c1383c2d9ac1bb3c2ec384fb0d0db52c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/efi.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/kexec.h>
 #include <asm/processor.h>
 #include <asm/hypervisor.h>
 #include <asm/hyperv.h>
 #include <asm/i8259.h>
 #include <asm/apic.h>
 #include <asm/timer.h>
+#include <asm/reboot.h>
 
 struct ms_hyperv_info ms_hyperv;
 EXPORT_SYMBOL_GPL(ms_hyperv);
 
+static void (*hv_kexec_handler)(void);
+static void (*hv_crash_handler)(struct pt_regs *regs);
+
 #if IS_ENABLED(CONFIG_HYPERV)
 static void (*vmbus_handler)(void);
 
@@ -67,8 +72,47 @@ void hv_remove_vmbus_irq(void)
 }
 EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
 EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
+
+void hv_setup_kexec_handler(void (*handler)(void))
+{
+       hv_kexec_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
+
+void hv_remove_kexec_handler(void)
+{
+       hv_kexec_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
+
+void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
+{
+       hv_crash_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
+
+void hv_remove_crash_handler(void)
+{
+       hv_crash_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
 #endif
 
+static void hv_machine_shutdown(void)
+{
+       if (kexec_in_progress && hv_kexec_handler)
+               hv_kexec_handler();
+       native_machine_shutdown();
+}
+
+static void hv_machine_crash_shutdown(struct pt_regs *regs)
+{
+       if (hv_crash_handler)
+               hv_crash_handler(regs);
+       native_machine_crash_shutdown(regs);
+}
+
+
 static uint32_t  __init ms_hyperv_platform(void)
 {
        u32 eax;
@@ -114,6 +158,7 @@ static void __init ms_hyperv_init_platform(void)
         * Extract the features and hints
         */
        ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
+       ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
        ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
 
        printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
@@ -141,6 +186,8 @@ static void __init ms_hyperv_init_platform(void)
        no_timer_check = 1;
 #endif
 
+       machine_ops.shutdown = hv_machine_shutdown;
+       machine_ops.crash_shutdown = hv_machine_crash_shutdown;
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
index b9826a981fb20fa45a7c1255e277e9ad1cd5d150..6326ae24e4d5b4f3d228111c10f5c85df0e40d3f 100644 (file)
@@ -2534,7 +2534,7 @@ static int intel_pmu_cpu_prepare(int cpu)
        if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
                cpuc->shared_regs = allocate_shared_regs(cpu);
                if (!cpuc->shared_regs)
-                       return NOTIFY_BAD;
+                       goto err;
        }
 
        if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
@@ -2542,18 +2542,27 @@ static int intel_pmu_cpu_prepare(int cpu)
 
                cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
                if (!cpuc->constraint_list)
-                       return NOTIFY_BAD;
+                       goto err_shared_regs;
 
                cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
-               if (!cpuc->excl_cntrs) {
-                       kfree(cpuc->constraint_list);
-                       kfree(cpuc->shared_regs);
-                       return NOTIFY_BAD;
-               }
+               if (!cpuc->excl_cntrs)
+                       goto err_constraint_list;
+
                cpuc->excl_thread_id = 0;
        }
 
        return NOTIFY_OK;
+
+err_constraint_list:
+       kfree(cpuc->constraint_list);
+       cpuc->constraint_list = NULL;
+
+err_shared_regs:
+       kfree(cpuc->shared_regs);
+       cpuc->shared_regs = NULL;
+
+err:
+       return NOTIFY_BAD;
 }
 
 static void intel_pmu_cpu_starting(int cpu)
index 63eb68b73589bcbbc21f9c526193adca0de2e52d..377e8f8ed39186ad4ef57b33264592ed8459a037 100644 (file)
@@ -1255,7 +1255,7 @@ static inline void cqm_pick_event_reader(int cpu)
        cpumask_set_cpu(cpu, &cqm_cpumask);
 }
 
-static void intel_cqm_cpu_prepare(unsigned int cpu)
+static void intel_cqm_cpu_starting(unsigned int cpu)
 {
        struct intel_pqr_state *state = &per_cpu(pqr_state, cpu);
        struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -1296,13 +1296,11 @@ static int intel_cqm_cpu_notifier(struct notifier_block *nb,
        unsigned int cpu  = (unsigned long)hcpu;
 
        switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               intel_cqm_cpu_prepare(cpu);
-               break;
        case CPU_DOWN_PREPARE:
                intel_cqm_cpu_exit(cpu);
                break;
        case CPU_STARTING:
+               intel_cqm_cpu_starting(cpu);
                cqm_pick_event_reader(cpu);
                break;
        }
@@ -1373,7 +1371,7 @@ static int __init intel_cqm_init(void)
                goto out;
 
        for_each_online_cpu(i) {
-               intel_cqm_cpu_prepare(i);
+               intel_cqm_cpu_starting(i);
                cqm_pick_event_reader(i);
        }
 
index 79de954626fd971f1d24553078bed1f199d52267..d25097c3fc1d1af8af35c156f05121f9f4d46a94 100644 (file)
@@ -270,7 +270,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
        dst_fpu->fpregs_active = 0;
        dst_fpu->last_cpu = -1;
 
-       if (src_fpu->fpstate_active)
+       if (src_fpu->fpstate_active && cpu_has_fpu)
                fpu_copy(dst_fpu, src_fpu);
 
        return 0;
index 1e173f6285c73b76b2e6ab41daed7681406c5d15..d14e9ac3235a1ac73174ffb95b2990d5163d2933 100644 (file)
@@ -40,7 +40,12 @@ static void fpu__init_cpu_generic(void)
        write_cr0(cr0);
 
        /* Flush out any pending x87 state: */
-       asm volatile ("fninit");
+#ifdef CONFIG_MATH_EMULATION
+       if (!cpu_has_fpu)
+               fpstate_init_soft(&current->thread.fpu.state.soft);
+       else
+#endif
+               asm volatile ("fninit");
 }
 
 /*
index 397688beed4be5ce7d9445d7847d44613d2d84b5..c27cad7267655c3794972344adf0b7924e38c138 100644 (file)
@@ -408,6 +408,7 @@ static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
 static void mwait_idle(void)
 {
        if (!current_set_polling_and_test()) {
+               trace_cpu_idle_rcuidle(1, smp_processor_id());
                if (this_cpu_has(X86_BUG_CLFLUSH_MONITOR)) {
                        smp_mb(); /* quirk */
                        clflush((void *)&current_thread_info()->flags);
@@ -419,6 +420,7 @@ static void mwait_idle(void)
                        __sti_mwait(0, 0);
                else
                        local_irq_enable();
+               trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
        } else {
                local_irq_enable();
        }
index 206996c1669db344aba7ff072f734552723e7938..71820c42b6ce6bc1020bbc44277967d7e23f011e 100644 (file)
@@ -93,8 +93,15 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
                COPY(r15);
 #endif /* CONFIG_X86_64 */
 
+#ifdef CONFIG_X86_32
                COPY_SEG_CPL3(cs);
                COPY_SEG_CPL3(ss);
+#else /* !CONFIG_X86_32 */
+               /* Kernel saves and restores only the CS segment register on signals,
+                * which is the bare minimum needed to allow mixed 32/64-bit code.
+                * App's signal handler can save/restore other segments if needed. */
+               COPY_SEG_CPL3(cs);
+#endif /* CONFIG_X86_32 */
 
                get_user_ex(tmpflags, &sc->flags);
                regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
@@ -154,9 +161,8 @@ int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
 #else /* !CONFIG_X86_32 */
                put_user_ex(regs->flags, &sc->flags);
                put_user_ex(regs->cs, &sc->cs);
-               put_user_ex(0, &sc->__pad2);
-               put_user_ex(0, &sc->__pad1);
-               put_user_ex(regs->ss, &sc->ss);
+               put_user_ex(0, &sc->gs);
+               put_user_ex(0, &sc->fs);
 #endif /* CONFIG_X86_32 */
 
                put_user_ex(fpstate, &sc->fpstate);
@@ -451,19 +457,9 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
 
        regs->sp = (unsigned long)frame;
 
-       /*
-        * Set up the CS and SS registers to run signal handlers in
-        * 64-bit mode, even if the handler happens to be interrupting
-        * 32-bit or 16-bit code.
-        *
-        * SS is subtle.  In 64-bit mode, we don't need any particular
-        * SS descriptor, but we do need SS to be valid.  It's possible
-        * that the old SS is entirely bogus -- this can happen if the
-        * signal we're trying to deliver is #GP or #SS caused by a bad
-        * SS value.
-        */
+       /* Set up the CS register to run signal handlers in 64-bit mode,
+          even if the handler happens to be interrupting 32-bit code. */
        regs->cs = __USER_CS;
-       regs->ss = __USER_DS;
 
        return 0;
 }
index 6273324186ac5ca7adba69be5ded69f23d8882f7..0ccb53a9fcd9361b83c7acd26e1f64601816a3d1 100644 (file)
@@ -28,11 +28,11 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re
                struct desc_struct *desc;
                unsigned long base;
 
-               seg &= ~7UL;
+               seg >>= 3;
 
                mutex_lock(&child->mm->context.lock);
                if (unlikely(!child->mm->context.ldt ||
-                            (seg >> 3) >= child->mm->context.ldt->size))
+                            seg >= child->mm->context.ldt->size))
                        addr = -1L; /* bogus selector, access would fault */
                else {
                        desc = &child->mm->context.ldt->entries[seg];
index 67d215cb8953274c602923bfa2682d417cd6909d..a1ff508bb423b946bddc531dc456bd68a54024b0 100644 (file)
@@ -12,7 +12,9 @@ kvm-y                 += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
 kvm-$(CONFIG_KVM_ASYNC_PF)     += $(KVM)/async_pf.o
 
 kvm-y                  += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
-                          i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o
+                          i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
+                          hyperv.o
+
 kvm-$(CONFIG_KVM_DEVICE_ASSIGNMENT)    += assigned-dev.o iommu.o
 kvm-intel-y            += vmx.o pmu_intel.o
 kvm-amd-y              += svm.o pmu_amd.o
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
new file mode 100644 (file)
index 0000000..a8160d2
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ * KVM Microsoft Hyper-V emulation
+ *
+ * derived from arch/x86/kvm/x86.c
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ * Copyright (C) 2008 Qumranet, Inc.
+ * Copyright IBM Corporation, 2008
+ * Copyright 2010 Red Hat, Inc. and/or its affiliates.
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ *   Avi Kivity   <avi@qumranet.com>
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *   Amit Shah    <amit.shah@qumranet.com>
+ *   Ben-Ami Yassour <benami@il.ibm.com>
+ *   Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "x86.h"
+#include "lapic.h"
+#include "hyperv.h"
+
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+#include "trace.h"
+
+static bool kvm_hv_msr_partition_wide(u32 msr)
+{
+       bool r = false;
+
+       switch (msr) {
+       case HV_X64_MSR_GUEST_OS_ID:
+       case HV_X64_MSR_HYPERCALL:
+       case HV_X64_MSR_REFERENCE_TSC:
+       case HV_X64_MSR_TIME_REF_COUNT:
+       case HV_X64_MSR_CRASH_CTL:
+       case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+               r = true;
+               break;
+       }
+
+       return r;
+}
+
+static int kvm_hv_msr_get_crash_data(struct kvm_vcpu *vcpu,
+                                    u32 index, u64 *pdata)
+{
+       struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+       if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param)))
+               return -EINVAL;
+
+       *pdata = hv->hv_crash_param[index];
+       return 0;
+}
+
+static int kvm_hv_msr_get_crash_ctl(struct kvm_vcpu *vcpu, u64 *pdata)
+{
+       struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+       *pdata = hv->hv_crash_ctl;
+       return 0;
+}
+
+static int kvm_hv_msr_set_crash_ctl(struct kvm_vcpu *vcpu, u64 data, bool host)
+{
+       struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+       if (host)
+               hv->hv_crash_ctl = data & HV_X64_MSR_CRASH_CTL_NOTIFY;
+
+       if (!host && (data & HV_X64_MSR_CRASH_CTL_NOTIFY)) {
+
+               vcpu_debug(vcpu, "hv crash (0x%llx 0x%llx 0x%llx 0x%llx 0x%llx)\n",
+                         hv->hv_crash_param[0],
+                         hv->hv_crash_param[1],
+                         hv->hv_crash_param[2],
+                         hv->hv_crash_param[3],
+                         hv->hv_crash_param[4]);
+
+               /* Send notification about crash to user space */
+               kvm_make_request(KVM_REQ_HV_CRASH, vcpu);
+       }
+
+       return 0;
+}
+
+static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu,
+                                    u32 index, u64 data)
+{
+       struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+       if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param)))
+               return -EINVAL;
+
+       hv->hv_crash_param[index] = data;
+       return 0;
+}
+
+static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
+                            bool host)
+{
+       struct kvm *kvm = vcpu->kvm;
+       struct kvm_hv *hv = &kvm->arch.hyperv;
+
+       switch (msr) {
+       case HV_X64_MSR_GUEST_OS_ID:
+               hv->hv_guest_os_id = data;
+               /* setting guest os id to zero disables hypercall page */
+               if (!hv->hv_guest_os_id)
+                       hv->hv_hypercall &= ~HV_X64_MSR_HYPERCALL_ENABLE;
+               break;
+       case HV_X64_MSR_HYPERCALL: {
+               u64 gfn;
+               unsigned long addr;
+               u8 instructions[4];
+
+               /* if guest os id is not set hypercall should remain disabled */
+               if (!hv->hv_guest_os_id)
+                       break;
+               if (!(data & HV_X64_MSR_HYPERCALL_ENABLE)) {
+                       hv->hv_hypercall = data;
+                       break;
+               }
+               gfn = data >> HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT;
+               addr = gfn_to_hva(kvm, gfn);
+               if (kvm_is_error_hva(addr))
+                       return 1;
+               kvm_x86_ops->patch_hypercall(vcpu, instructions);
+               ((unsigned char *)instructions)[3] = 0xc3; /* ret */
+               if (__copy_to_user((void __user *)addr, instructions, 4))
+                       return 1;
+               hv->hv_hypercall = data;
+               mark_page_dirty(kvm, gfn);
+               break;
+       }
+       case HV_X64_MSR_REFERENCE_TSC: {
+               u64 gfn;
+               HV_REFERENCE_TSC_PAGE tsc_ref;
+
+               memset(&tsc_ref, 0, sizeof(tsc_ref));
+               hv->hv_tsc_page = data;
+               if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
+                       break;
+               gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
+               if (kvm_write_guest(
+                               kvm,
+                               gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
+                               &tsc_ref, sizeof(tsc_ref)))
+                       return 1;
+               mark_page_dirty(kvm, gfn);
+               break;
+       }
+       case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+               return kvm_hv_msr_set_crash_data(vcpu,
+                                                msr - HV_X64_MSR_CRASH_P0,
+                                                data);
+       case HV_X64_MSR_CRASH_CTL:
+               return kvm_hv_msr_set_crash_ctl(vcpu, data, host);
+       default:
+               vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n",
+                           msr, data);
+               return 1;
+       }
+       return 0;
+}
+
+static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+       struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
+
+       switch (msr) {
+       case HV_X64_MSR_APIC_ASSIST_PAGE: {
+               u64 gfn;
+               unsigned long addr;
+
+               if (!(data & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE)) {
+                       hv->hv_vapic = data;
+                       if (kvm_lapic_enable_pv_eoi(vcpu, 0))
+                               return 1;
+                       break;
+               }
+               gfn = data >> HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT;
+               addr = kvm_vcpu_gfn_to_hva(vcpu, gfn);
+               if (kvm_is_error_hva(addr))
+                       return 1;
+               if (__clear_user((void __user *)addr, PAGE_SIZE))
+                       return 1;
+               hv->hv_vapic = data;
+               kvm_vcpu_mark_page_dirty(vcpu, gfn);
+               if (kvm_lapic_enable_pv_eoi(vcpu,
+                                           gfn_to_gpa(gfn) | KVM_MSR_ENABLED))
+                       return 1;
+               break;
+       }
+       case HV_X64_MSR_EOI:
+               return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
+       case HV_X64_MSR_ICR:
+               return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
+       case HV_X64_MSR_TPR:
+               return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
+       default:
+               vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n",
+                           msr, data);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+       u64 data = 0;
+       struct kvm *kvm = vcpu->kvm;
+       struct kvm_hv *hv = &kvm->arch.hyperv;
+
+       switch (msr) {
+       case HV_X64_MSR_GUEST_OS_ID:
+               data = hv->hv_guest_os_id;
+               break;
+       case HV_X64_MSR_HYPERCALL:
+               data = hv->hv_hypercall;
+               break;
+       case HV_X64_MSR_TIME_REF_COUNT: {
+               data =
+                    div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100);
+               break;
+       }
+       case HV_X64_MSR_REFERENCE_TSC:
+               data = hv->hv_tsc_page;
+               break;
+       case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+               return kvm_hv_msr_get_crash_data(vcpu,
+                                                msr - HV_X64_MSR_CRASH_P0,
+                                                pdata);
+       case HV_X64_MSR_CRASH_CTL:
+               return kvm_hv_msr_get_crash_ctl(vcpu, pdata);
+       default:
+               vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
+               return 1;
+       }
+
+       *pdata = data;
+       return 0;
+}
+
+static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+       u64 data = 0;
+       struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
+
+       switch (msr) {
+       case HV_X64_MSR_VP_INDEX: {
+               int r;
+               struct kvm_vcpu *v;
+
+               kvm_for_each_vcpu(r, v, vcpu->kvm) {
+                       if (v == vcpu) {
+                               data = r;
+                               break;
+                       }
+               }
+               break;
+       }
+       case HV_X64_MSR_EOI:
+               return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
+       case HV_X64_MSR_ICR:
+               return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
+       case HV_X64_MSR_TPR:
+               return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
+       case HV_X64_MSR_APIC_ASSIST_PAGE:
+               data = hv->hv_vapic;
+               break;
+       default:
+               vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
+               return 1;
+       }
+       *pdata = data;
+       return 0;
+}
+
+int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
+{
+       if (kvm_hv_msr_partition_wide(msr)) {
+               int r;
+
+               mutex_lock(&vcpu->kvm->lock);
+               r = kvm_hv_set_msr_pw(vcpu, msr, data, host);
+               mutex_unlock(&vcpu->kvm->lock);
+               return r;
+       } else
+               return kvm_hv_set_msr(vcpu, msr, data);
+}
+
+int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+       if (kvm_hv_msr_partition_wide(msr)) {
+               int r;
+
+               mutex_lock(&vcpu->kvm->lock);
+               r = kvm_hv_get_msr_pw(vcpu, msr, pdata);
+               mutex_unlock(&vcpu->kvm->lock);
+               return r;
+       } else
+               return kvm_hv_get_msr(vcpu, msr, pdata);
+}
+
+bool kvm_hv_hypercall_enabled(struct kvm *kvm)
+{
+       return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
+}
+
+int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
+{
+       u64 param, ingpa, outgpa, ret;
+       uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
+       bool fast, longmode;
+
+       /*
+        * hypercall generates UD from non zero cpl and real mode
+        * per HYPER-V spec
+        */
+       if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) {
+               kvm_queue_exception(vcpu, UD_VECTOR);
+               return 0;
+       }
+
+       longmode = is_64_bit_mode(vcpu);
+
+       if (!longmode) {
+               param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
+                       (kvm_register_read(vcpu, VCPU_REGS_RAX) & 0xffffffff);
+               ingpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RBX) << 32) |
+                       (kvm_register_read(vcpu, VCPU_REGS_RCX) & 0xffffffff);
+               outgpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDI) << 32) |
+                       (kvm_register_read(vcpu, VCPU_REGS_RSI) & 0xffffffff);
+       }
+#ifdef CONFIG_X86_64
+       else {
+               param = kvm_register_read(vcpu, VCPU_REGS_RCX);
+               ingpa = kvm_register_read(vcpu, VCPU_REGS_RDX);
+               outgpa = kvm_register_read(vcpu, VCPU_REGS_R8);
+       }
+#endif
+
+       code = param & 0xffff;
+       fast = (param >> 16) & 0x1;
+       rep_cnt = (param >> 32) & 0xfff;
+       rep_idx = (param >> 48) & 0xfff;
+
+       trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
+
+       switch (code) {
+       case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT:
+               kvm_vcpu_on_spin(vcpu);
+               break;
+       default:
+               res = HV_STATUS_INVALID_HYPERCALL_CODE;
+               break;
+       }
+
+       ret = res | (((u64)rep_done & 0xfff) << 32);
+       if (longmode) {
+               kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
+       } else {
+               kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
+               kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
+       }
+
+       return 1;
+}
diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
new file mode 100644 (file)
index 0000000..c7bce55
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * KVM Microsoft Hyper-V emulation
+ *
+ * derived from arch/x86/kvm/x86.c
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ * Copyright (C) 2008 Qumranet, Inc.
+ * Copyright IBM Corporation, 2008
+ * Copyright 2010 Red Hat, Inc. and/or its affiliates.
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ *   Avi Kivity   <avi@qumranet.com>
+ *   Yaniv Kamay  <yaniv@qumranet.com>
+ *   Amit Shah    <amit.shah@qumranet.com>
+ *   Ben-Ami Yassour <benami@il.ibm.com>
+ *   Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef __ARCH_X86_KVM_HYPERV_H__
+#define __ARCH_X86_KVM_HYPERV_H__
+
+int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host);
+int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
+bool kvm_hv_hypercall_enabled(struct kvm *kvm);
+int kvm_hv_hypercall(struct kvm_vcpu *vcpu);
+
+#endif
index fef922ff263589de97348e76ee4faeaeb5aaeef2..7cc2360f1848e1893a3a554c0a773731a1f3f146 100644 (file)
@@ -651,15 +651,10 @@ fail_unlock:
        return NULL;
 }
 
-void kvm_destroy_pic(struct kvm *kvm)
+void kvm_destroy_pic(struct kvm_pic *vpic)
 {
-       struct kvm_pic *vpic = kvm->arch.vpic;
-
-       if (vpic) {
-               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_master);
-               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_slave);
-               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_eclr);
-               kvm->arch.vpic = NULL;
-               kfree(vpic);
-       }
+       kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_master);
+       kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_slave);
+       kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_eclr);
+       kfree(vpic);
 }
index ad68c73008c57f0c1926f0cec9e83f79fe070252..3d782a2c336aceb4b4fac3092b68f1c3143e1a12 100644 (file)
@@ -74,7 +74,7 @@ struct kvm_pic {
 };
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
-void kvm_destroy_pic(struct kvm *kvm);
+void kvm_destroy_pic(struct kvm_pic *vpic);
 int kvm_pic_read_irq(struct kvm *kvm);
 void kvm_pic_update_irq(struct kvm_pic *s);
 
@@ -85,11 +85,11 @@ static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
 
 static inline int irqchip_in_kernel(struct kvm *kvm)
 {
-       int ret;
+       struct kvm_pic *vpic = pic_irqchip(kvm);
 
-       ret = (pic_irqchip(kvm) != NULL);
+       /* Read vpic before kvm->irq_routing.  */
        smp_rmb();
-       return ret;
+       return vpic != NULL;
 }
 
 void kvm_pic_reset(struct kvm_kpic_state *s);
index 2a5ca97c263bb48092ea80f88c7d30120ea63b6e..9a3e342e3cda7ecfc42c86d981d791601d9615f5 100644 (file)
@@ -1900,8 +1900,9 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
        if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
                return;
 
-       kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
-                               sizeof(u32));
+       if (kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+                                 sizeof(u32)))
+               return;
 
        apic_set_tpr(vcpu->arch.apic, data & 0xff);
 }
index 71952748222a4a08597711acc21a599c9c499990..764037991d2609e5b78a89b3cc677ccb6cef0237 100644 (file)
@@ -91,7 +91,7 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
 
 static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
 {
-       return vcpu->arch.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE;
+       return vcpu->arch.hyperv.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE;
 }
 
 int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
index 44171462bd2a31561645aff21c83584b82eed6ff..fb16a8ea3dee026d24a6e47332326226cf3a70e0 100644 (file)
@@ -357,12 +357,6 @@ static u64 __get_spte_lockless(u64 *sptep)
 {
        return ACCESS_ONCE(*sptep);
 }
-
-static bool __check_direct_spte_mmio_pf(u64 spte)
-{
-       /* It is valid if the spte is zapped. */
-       return spte == 0ull;
-}
 #else
 union split_spte {
        struct {
@@ -478,23 +472,6 @@ retry:
 
        return spte.spte;
 }
-
-static bool __check_direct_spte_mmio_pf(u64 spte)
-{
-       union split_spte sspte = (union split_spte)spte;
-       u32 high_mmio_mask = shadow_mmio_mask >> 32;
-
-       /* It is valid if the spte is zapped. */
-       if (spte == 0ull)
-               return true;
-
-       /* It is valid if the spte is being zapped. */
-       if (sspte.spte_low == 0ull &&
-           (sspte.spte_high & high_mmio_mask) == high_mmio_mask)
-               return true;
-
-       return false;
-}
 #endif
 
 static bool spte_is_locklessly_modifiable(u64 spte)
@@ -3291,54 +3268,89 @@ static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu *vcpu, gva_t vaddr,
        return vcpu->arch.nested_mmu.translate_gpa(vcpu, vaddr, access, exception);
 }
 
-static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+static bool
+__is_rsvd_bits_set(struct rsvd_bits_validate *rsvd_check, u64 pte, int level)
 {
-       if (direct)
-               return vcpu_match_mmio_gpa(vcpu, addr);
+       int bit7 = (pte >> 7) & 1, low6 = pte & 0x3f;
 
-       return vcpu_match_mmio_gva(vcpu, addr);
+       return (pte & rsvd_check->rsvd_bits_mask[bit7][level-1]) |
+               ((rsvd_check->bad_mt_xwr & (1ull << low6)) != 0);
 }
 
+static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
+{
+       return __is_rsvd_bits_set(&mmu->guest_rsvd_check, gpte, level);
+}
 
-/*
- * On direct hosts, the last spte is only allows two states
- * for mmio page fault:
- *   - It is the mmio spte
- *   - It is zapped or it is being zapped.
- *
- * This function completely checks the spte when the last spte
- * is not the mmio spte.
- */
-static bool check_direct_spte_mmio_pf(u64 spte)
+static bool is_shadow_zero_bits_set(struct kvm_mmu *mmu, u64 spte, int level)
 {
-       return __check_direct_spte_mmio_pf(spte);
+       return __is_rsvd_bits_set(&mmu->shadow_zero_check, spte, level);
 }
 
-static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr)
+static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+{
+       if (direct)
+               return vcpu_match_mmio_gpa(vcpu, addr);
+
+       return vcpu_match_mmio_gva(vcpu, addr);
+}
+
+/* return true if reserved bit is detected on spte. */
+static bool
+walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
 {
        struct kvm_shadow_walk_iterator iterator;
-       u64 spte = 0ull;
+       u64 sptes[PT64_ROOT_LEVEL], spte = 0ull;
+       int root, leaf;
+       bool reserved = false;
 
        if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
-               return spte;
+               goto exit;
 
        walk_shadow_page_lockless_begin(vcpu);
-       for_each_shadow_entry_lockless(vcpu, addr, iterator, spte)
+
+       for (shadow_walk_init(&iterator, vcpu, addr), root = iterator.level;
+            shadow_walk_okay(&iterator);
+            __shadow_walk_next(&iterator, spte)) {
+               leaf = iterator.level;
+               spte = mmu_spte_get_lockless(iterator.sptep);
+
+               sptes[leaf - 1] = spte;
+
                if (!is_shadow_present_pte(spte))
                        break;
+
+               reserved |= is_shadow_zero_bits_set(&vcpu->arch.mmu, spte,
+                                                   leaf);
+       }
+
        walk_shadow_page_lockless_end(vcpu);
 
-       return spte;
+       if (reserved) {
+               pr_err("%s: detect reserved bits on spte, addr 0x%llx, dump hierarchy:\n",
+                      __func__, addr);
+               while (root >= leaf) {
+                       pr_err("------ spte 0x%llx level %d.\n",
+                              sptes[root - 1], root);
+                       root--;
+               }
+       }
+exit:
+       *sptep = spte;
+       return reserved;
 }
 
 int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 {
        u64 spte;
+       bool reserved;
 
        if (quickly_check_mmio_pf(vcpu, addr, direct))
                return RET_MMIO_PF_EMULATE;
 
-       spte = walk_shadow_page_get_mmio_spte(vcpu, addr);
+       reserved = walk_shadow_page_get_mmio_spte(vcpu, addr, &spte);
+       if (unlikely(reserved))
+               return RET_MMIO_PF_BUG;
 
        if (is_mmio_spte(spte)) {
                gfn_t gfn = get_mmio_spte_gfn(spte);
@@ -3355,13 +3367,6 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
                return RET_MMIO_PF_EMULATE;
        }
 
-       /*
-        * It's ok if the gva is remapped by other cpus on shadow guest,
-        * it's a BUG if the gfn is not a mmio page.
-        */
-       if (direct && !check_direct_spte_mmio_pf(spte))
-               return RET_MMIO_PF_BUG;
-
        /*
         * If the page table is zapped by other cpus, let CPU fault again on
         * the address.
@@ -3604,19 +3609,21 @@ static inline bool is_last_gpte(struct kvm_mmu *mmu, unsigned level, unsigned gp
 #include "paging_tmpl.h"
 #undef PTTYPE
 
-static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
-                                 struct kvm_mmu *context)
+static void
+__reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
+                       struct rsvd_bits_validate *rsvd_check,
+                       int maxphyaddr, int level, bool nx, bool gbpages,
+                       bool pse)
 {
-       int maxphyaddr = cpuid_maxphyaddr(vcpu);
        u64 exb_bit_rsvd = 0;
        u64 gbpages_bit_rsvd = 0;
        u64 nonleaf_bit8_rsvd = 0;
 
-       context->bad_mt_xwr = 0;
+       rsvd_check->bad_mt_xwr = 0;
 
-       if (!context->nx)
+       if (!nx)
                exb_bit_rsvd = rsvd_bits(63, 63);
-       if (!guest_cpuid_has_gbpages(vcpu))
+       if (!gbpages)
                gbpages_bit_rsvd = rsvd_bits(7, 7);
 
        /*
@@ -3626,80 +3633,95 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
        if (guest_cpuid_is_amd(vcpu))
                nonleaf_bit8_rsvd = rsvd_bits(8, 8);
 
-       switch (context->root_level) {
+       switch (level) {
        case PT32_ROOT_LEVEL:
                /* no rsvd bits for 2 level 4K page table entries */
-               context->rsvd_bits_mask[0][1] = 0;
-               context->rsvd_bits_mask[0][0] = 0;
-               context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+               rsvd_check->rsvd_bits_mask[0][1] = 0;
+               rsvd_check->rsvd_bits_mask[0][0] = 0;
+               rsvd_check->rsvd_bits_mask[1][0] =
+                       rsvd_check->rsvd_bits_mask[0][0];
 
-               if (!is_pse(vcpu)) {
-                       context->rsvd_bits_mask[1][1] = 0;
+               if (!pse) {
+                       rsvd_check->rsvd_bits_mask[1][1] = 0;
                        break;
                }
 
                if (is_cpuid_PSE36())
                        /* 36bits PSE 4MB page */
-                       context->rsvd_bits_mask[1][1] = rsvd_bits(17, 21);
+                       rsvd_check->rsvd_bits_mask[1][1] = rsvd_bits(17, 21);
                else
                        /* 32 bits PSE 4MB page */
-                       context->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
+                       rsvd_check->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
                break;
        case PT32E_ROOT_LEVEL:
-               context->rsvd_bits_mask[0][2] =
+               rsvd_check->rsvd_bits_mask[0][2] =
                        rsvd_bits(maxphyaddr, 63) |
                        rsvd_bits(5, 8) | rsvd_bits(1, 2);      /* PDPTE */
-               context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[0][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 62);      /* PDE */
-               context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[0][0] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 62);      /* PTE */
-               context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[1][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 62) |
                        rsvd_bits(13, 20);              /* large page */
-               context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+               rsvd_check->rsvd_bits_mask[1][0] =
+                       rsvd_check->rsvd_bits_mask[0][0];
                break;
        case PT64_ROOT_LEVEL:
-               context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
-                       nonleaf_bit8_rsvd | rsvd_bits(7, 7) | rsvd_bits(maxphyaddr, 51);
-               context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
-                       nonleaf_bit8_rsvd | gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
-               context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[0][3] = exb_bit_rsvd |
+                       nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
+                       rsvd_bits(maxphyaddr, 51);
+               rsvd_check->rsvd_bits_mask[0][2] = exb_bit_rsvd |
+                       nonleaf_bit8_rsvd | gbpages_bit_rsvd |
                        rsvd_bits(maxphyaddr, 51);
-               context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[0][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 51);
-               context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
-               context->rsvd_bits_mask[1][2] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+                       rsvd_bits(maxphyaddr, 51);
+               rsvd_check->rsvd_bits_mask[1][3] =
+                       rsvd_check->rsvd_bits_mask[0][3];
+               rsvd_check->rsvd_bits_mask[1][2] = exb_bit_rsvd |
                        gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51) |
                        rsvd_bits(13, 29);
-               context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+               rsvd_check->rsvd_bits_mask[1][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 51) |
                        rsvd_bits(13, 20);              /* large page */
-               context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+               rsvd_check->rsvd_bits_mask[1][0] =
+                       rsvd_check->rsvd_bits_mask[0][0];
                break;
        }
 }
 
-static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
-               struct kvm_mmu *context, bool execonly)
+static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
+                                 struct kvm_mmu *context)
+{
+       __reset_rsvds_bits_mask(vcpu, &context->guest_rsvd_check,
+                               cpuid_maxphyaddr(vcpu), context->root_level,
+                               context->nx, guest_cpuid_has_gbpages(vcpu),
+                               is_pse(vcpu));
+}
+
+static void
+__reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check,
+                           int maxphyaddr, bool execonly)
 {
-       int maxphyaddr = cpuid_maxphyaddr(vcpu);
        int pte;
 
-       context->rsvd_bits_mask[0][3] =
+       rsvd_check->rsvd_bits_mask[0][3] =
                rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 7);
-       context->rsvd_bits_mask[0][2] =
+       rsvd_check->rsvd_bits_mask[0][2] =
                rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 6);
-       context->rsvd_bits_mask[0][1] =
+       rsvd_check->rsvd_bits_mask[0][1] =
                rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 6);
-       context->rsvd_bits_mask[0][0] = rsvd_bits(maxphyaddr, 51);
+       rsvd_check->rsvd_bits_mask[0][0] = rsvd_bits(maxphyaddr, 51);
 
        /* large page */
-       context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
-       context->rsvd_bits_mask[1][2] =
+       rsvd_check->rsvd_bits_mask[1][3] = rsvd_check->rsvd_bits_mask[0][3];
+       rsvd_check->rsvd_bits_mask[1][2] =
                rsvd_bits(maxphyaddr, 51) | rsvd_bits(12, 29);
-       context->rsvd_bits_mask[1][1] =
+       rsvd_check->rsvd_bits_mask[1][1] =
                rsvd_bits(maxphyaddr, 51) | rsvd_bits(12, 20);
-       context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+       rsvd_check->rsvd_bits_mask[1][0] = rsvd_check->rsvd_bits_mask[0][0];
 
        for (pte = 0; pte < 64; pte++) {
                int rwx_bits = pte & 7;
@@ -3707,10 +3729,64 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
                if (mt == 0x2 || mt == 0x3 || mt == 0x7 ||
                                rwx_bits == 0x2 || rwx_bits == 0x6 ||
                                (rwx_bits == 0x4 && !execonly))
-                       context->bad_mt_xwr |= (1ull << pte);
+                       rsvd_check->bad_mt_xwr |= (1ull << pte);
        }
 }
 
+static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
+               struct kvm_mmu *context, bool execonly)
+{
+       __reset_rsvds_bits_mask_ept(&context->guest_rsvd_check,
+                                   cpuid_maxphyaddr(vcpu), execonly);
+}
+
+/*
+ * the page table on host is the shadow page table for the page
+ * table in guest or amd nested guest, its mmu features completely
+ * follow the features in guest.
+ */
+void
+reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
+{
+       __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
+                               boot_cpu_data.x86_phys_bits,
+                               context->shadow_root_level, context->nx,
+                               guest_cpuid_has_gbpages(vcpu), is_pse(vcpu));
+}
+EXPORT_SYMBOL_GPL(reset_shadow_zero_bits_mask);
+
+/*
+ * the direct page table on host, use as much mmu features as
+ * possible, however, kvm currently does not do execution-protection.
+ */
+static void
+reset_tdp_shadow_zero_bits_mask(struct kvm_vcpu *vcpu,
+                               struct kvm_mmu *context)
+{
+       if (guest_cpuid_is_amd(vcpu))
+               __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
+                                       boot_cpu_data.x86_phys_bits,
+                                       context->shadow_root_level, false,
+                                       cpu_has_gbpages, true);
+       else
+               __reset_rsvds_bits_mask_ept(&context->shadow_zero_check,
+                                           boot_cpu_data.x86_phys_bits,
+                                           false);
+
+}
+
+/*
+ * as the comments in reset_shadow_zero_bits_mask() except it
+ * is the shadow page table for intel nested guest.
+ */
+static void
+reset_ept_shadow_zero_bits_mask(struct kvm_vcpu *vcpu,
+                               struct kvm_mmu *context, bool execonly)
+{
+       __reset_rsvds_bits_mask_ept(&context->shadow_zero_check,
+                                   boot_cpu_data.x86_phys_bits, execonly);
+}
+
 static void update_permission_bitmask(struct kvm_vcpu *vcpu,
                                      struct kvm_mmu *mmu, bool ept)
 {
@@ -3889,6 +3965,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
 
        update_permission_bitmask(vcpu, context, false);
        update_last_pte_bitmap(vcpu, context);
+       reset_tdp_shadow_zero_bits_mask(vcpu, context);
 }
 
 void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
@@ -3916,6 +3993,7 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
        context->base_role.smap_andnot_wp
                = smap && !is_write_protection(vcpu);
        context->base_role.smm = is_smm(vcpu);
+       reset_shadow_zero_bits_mask(vcpu, context);
 }
 EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu);
 
@@ -3939,6 +4017,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly)
 
        update_permission_bitmask(vcpu, context, true);
        reset_rsvds_bits_mask_ept(vcpu, context, execonly);
+       reset_ept_shadow_zero_bits_mask(vcpu, context, execonly);
 }
 EXPORT_SYMBOL_GPL(kvm_init_shadow_ept_mmu);
 
@@ -4860,28 +4939,6 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm)
        return nr_mmu_pages;
 }
 
-int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])
-{
-       struct kvm_shadow_walk_iterator iterator;
-       u64 spte;
-       int nr_sptes = 0;
-
-       if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
-               return nr_sptes;
-
-       walk_shadow_page_lockless_begin(vcpu);
-       for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
-               sptes[iterator.level-1] = spte;
-               nr_sptes++;
-               if (!is_shadow_present_pte(spte))
-                       break;
-       }
-       walk_shadow_page_lockless_end(vcpu);
-
-       return nr_sptes;
-}
-EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy);
-
 void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
 {
        kvm_mmu_unload(vcpu);
index 398d21c0f6dd05273fea48598bef016e1c26b51c..e4202e41d53541f06a468e0b72beac483e2e7b8f 100644 (file)
@@ -50,9 +50,11 @@ static inline u64 rsvd_bits(int s, int e)
        return ((1ULL << (e - s + 1)) - 1) << s;
 }
 
-int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask);
 
+void
+reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
+
 /*
  * Return values of handle_mmio_page_fault_common:
  * RET_MMIO_PF_EMULATE: it is a real mmio page fault, emulate the instruction
index 0f67d7e2480074f9d313e0f6af43bd9b64c5a555..736e6ab8784d339d7af10bda1324f9a8fbe3c618 100644 (file)
@@ -128,14 +128,6 @@ static inline void FNAME(protect_clean_gpte)(unsigned *access, unsigned gpte)
        *access &= mask;
 }
 
-static bool FNAME(is_rsvd_bits_set)(struct kvm_mmu *mmu, u64 gpte, int level)
-{
-       int bit7 = (gpte >> 7) & 1, low6 = gpte & 0x3f;
-
-       return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) |
-               ((mmu->bad_mt_xwr & (1ull << low6)) != 0);
-}
-
 static inline int FNAME(is_present_gpte)(unsigned long pte)
 {
 #if PTTYPE != PTTYPE_EPT
@@ -172,7 +164,7 @@ static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
                                  struct kvm_mmu_page *sp, u64 *spte,
                                  u64 gpte)
 {
-       if (FNAME(is_rsvd_bits_set)(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
+       if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
                goto no_present;
 
        if (!FNAME(is_present_gpte)(gpte))
@@ -353,8 +345,7 @@ retry_walk:
                if (unlikely(!FNAME(is_present_gpte)(pte)))
                        goto error;
 
-               if (unlikely(FNAME(is_rsvd_bits_set)(mmu, pte,
-                                                    walker->level))) {
+               if (unlikely(is_rsvd_bits_set(mmu, pte, walker->level))) {
                        errcode |= PFERR_RSVD_MASK | PFERR_PRESENT_MASK;
                        goto error;
                }
index 886aa25a7131479b5acd64d4aa9f1600984335d2..39b91127ef07a48a3cf4313d2d0340088bf8b7c6 100644 (file)
@@ -133,8 +133,6 @@ static int amd_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        /* MSR_K7_PERFCTRn */
        pmc = get_gp_pmc(pmu, msr, MSR_K7_PERFCTR0);
        if (pmc) {
-               if (!msr_info->host_initiated)
-                       data = (s64)data;
                pmc->counter += data - pmc_read_counter(pmc);
                return 0;
        }
index 8e0c0844c6b9681e31e64bdeba0f1822108bec3e..74d825716f4fc158af4d52cd860bf63bbb8ccdf3 100644 (file)
@@ -1173,6 +1173,10 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
        if (!is_mmio && !kvm_arch_has_assigned_device(vcpu->kvm))
                return 0;
 
+       if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED) &&
+           kvm_read_cr0(vcpu) & X86_CR0_CD)
+               return _PAGE_NOCACHE;
+
        mtrr = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
        return mtrr2protval[mtrr];
 }
@@ -1667,13 +1671,10 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 
        if (!vcpu->fpu_active)
                cr0 |= X86_CR0_TS;
-       /*
-        * re-enable caching here because the QEMU bios
-        * does not do it - this results in some delay at
-        * reboot
-        */
-       if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
-               cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
+
+       /* These are emulated via page tables.  */
+       cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
+
        svm->vmcb->save.cr0 = cr0;
        mark_dirty(svm->vmcb, VMCB_CR);
        update_cr0_intercept(svm);
@@ -2106,6 +2107,7 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
        vcpu->arch.mmu.get_pdptr         = nested_svm_get_tdp_pdptr;
        vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
        vcpu->arch.mmu.shadow_root_level = get_npt_level();
+       reset_shadow_zero_bits_mask(vcpu, &vcpu->arch.mmu);
        vcpu->arch.walk_mmu              = &vcpu->arch.nested_mmu;
 }
 
index 83b7b5cd75d52dd67976274da3c11807f1c35490..da1590ea43fc607592722fa2ee1a095911b43163 100644 (file)
@@ -2443,10 +2443,10 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
                CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING |
 #endif
                CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
-               CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
-               CPU_BASED_RDPMC_EXITING | CPU_BASED_RDTSC_EXITING |
-               CPU_BASED_PAUSE_EXITING | CPU_BASED_TPR_SHADOW |
-               CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+               CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_TRAP_FLAG |
+               CPU_BASED_MONITOR_EXITING | CPU_BASED_RDPMC_EXITING |
+               CPU_BASED_RDTSC_EXITING | CPU_BASED_PAUSE_EXITING |
+               CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
        /*
         * We can allow some features even when not supported by the
         * hardware. For example, L1 can specify an MSR bitmap - and we
@@ -3423,12 +3423,12 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
        vmx_segment_cache_clear(to_vmx(vcpu));
 
        guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
-       if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
+       if ((guest_tr_ar & VMX_AR_TYPE_MASK) != VMX_AR_TYPE_BUSY_64_TSS) {
                pr_debug_ratelimited("%s: tss fixup for long mode. \n",
                                     __func__);
                vmcs_write32(GUEST_TR_AR_BYTES,
-                            (guest_tr_ar & ~AR_TYPE_MASK)
-                            | AR_TYPE_BUSY_64_TSS);
+                            (guest_tr_ar & ~VMX_AR_TYPE_MASK)
+                            | VMX_AR_TYPE_BUSY_64_TSS);
        }
        vmx_set_efer(vcpu, vcpu->arch.efer | EFER_LMA);
 }
@@ -3719,7 +3719,7 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu)
                return 0;
        else {
                int ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
-               return AR_DPL(ar);
+               return VMX_AR_DPL(ar);
        }
 }
 
@@ -3847,11 +3847,11 @@ static bool code_segment_valid(struct kvm_vcpu *vcpu)
 
        if (cs.unusable)
                return false;
-       if (~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_ACCESSES_MASK))
+       if (~cs.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_ACCESSES_MASK))
                return false;
        if (!cs.s)
                return false;
-       if (cs.type & AR_TYPE_WRITEABLE_MASK) {
+       if (cs.type & VMX_AR_TYPE_WRITEABLE_MASK) {
                if (cs.dpl > cs_rpl)
                        return false;
        } else {
@@ -3901,7 +3901,7 @@ static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
                return false;
        if (!var.present)
                return false;
-       if (~var.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK)) {
+       if (~var.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_WRITEABLE_MASK)) {
                if (var.dpl < rpl) /* DPL < RPL */
                        return false;
        }
@@ -5759,73 +5759,9 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
        return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
 }
 
-static u64 ept_rsvd_mask(u64 spte, int level)
-{
-       int i;
-       u64 mask = 0;
-
-       for (i = 51; i > boot_cpu_data.x86_phys_bits; i--)
-               mask |= (1ULL << i);
-
-       if (level == 4)
-               /* bits 7:3 reserved */
-               mask |= 0xf8;
-       else if (spte & (1ULL << 7))
-               /*
-                * 1GB/2MB page, bits 29:12 or 20:12 reserved respectively,
-                * level == 1 if the hypervisor is using the ignored bit 7.
-                */
-               mask |= (PAGE_SIZE << ((level - 1) * 9)) - PAGE_SIZE;
-       else if (level > 1)
-               /* bits 6:3 reserved */
-               mask |= 0x78;
-
-       return mask;
-}
-
-static void ept_misconfig_inspect_spte(struct kvm_vcpu *vcpu, u64 spte,
-                                      int level)
-{
-       printk(KERN_ERR "%s: spte 0x%llx level %d\n", __func__, spte, level);
-
-       /* 010b (write-only) */
-       WARN_ON((spte & 0x7) == 0x2);
-
-       /* 110b (write/execute) */
-       WARN_ON((spte & 0x7) == 0x6);
-
-       /* 100b (execute-only) and value not supported by logical processor */
-       if (!cpu_has_vmx_ept_execute_only())
-               WARN_ON((spte & 0x7) == 0x4);
-
-       /* not 000b */
-       if ((spte & 0x7)) {
-               u64 rsvd_bits = spte & ept_rsvd_mask(spte, level);
-
-               if (rsvd_bits != 0) {
-                       printk(KERN_ERR "%s: rsvd_bits = 0x%llx\n",
-                                        __func__, rsvd_bits);
-                       WARN_ON(1);
-               }
-
-               /* bits 5:3 are _not_ reserved for large page or leaf page */
-               if ((rsvd_bits & 0x38) == 0) {
-                       u64 ept_mem_type = (spte & 0x38) >> 3;
-
-                       if (ept_mem_type == 2 || ept_mem_type == 3 ||
-                           ept_mem_type == 7) {
-                               printk(KERN_ERR "%s: ept_mem_type=0x%llx\n",
-                                               __func__, ept_mem_type);
-                               WARN_ON(1);
-                       }
-               }
-       }
-}
-
 static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
 {
-       u64 sptes[4];
-       int nr_sptes, i, ret;
+       int ret;
        gpa_t gpa;
 
        gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
@@ -5846,13 +5782,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
                return 1;
 
        /* It is the real ept misconfig */
-       printk(KERN_ERR "EPT: Misconfiguration.\n");
-       printk(KERN_ERR "EPT: GPA: 0x%llx\n", gpa);
-
-       nr_sptes = kvm_mmu_get_spte_hierarchy(vcpu, gpa, sptes);
-
-       for (i = PT64_ROOT_LEVEL; i > PT64_ROOT_LEVEL - nr_sptes; --i)
-               ept_misconfig_inspect_spte(vcpu, sptes[i-1], i);
+       WARN_ON(1);
 
        vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
        vcpu->run->hw.hardware_exit_reason = EXIT_REASON_EPT_MISCONFIG;
@@ -6246,6 +6176,11 @@ static int handle_mwait(struct kvm_vcpu *vcpu)
        return handle_nop(vcpu);
 }
 
+static int handle_monitor_trap(struct kvm_vcpu *vcpu)
+{
+       return 1;
+}
+
 static int handle_monitor(struct kvm_vcpu *vcpu)
 {
        printk_once(KERN_WARNING "kvm: MONITOR instruction emulated as NOP!\n");
@@ -6408,8 +6343,12 @@ static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer)
  */
 static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
                                 unsigned long exit_qualification,
-                                u32 vmx_instruction_info, gva_t *ret)
+                                u32 vmx_instruction_info, bool wr, gva_t *ret)
 {
+       gva_t off;
+       bool exn;
+       struct kvm_segment s;
+
        /*
         * According to Vol. 3B, "Information for VM Exits Due to Instruction
         * Execution", on an exit, vmx_instruction_info holds most of the
@@ -6434,22 +6373,63 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
 
        /* Addr = segment_base + offset */
        /* offset = base + [index * scale] + displacement */
-       *ret = vmx_get_segment_base(vcpu, seg_reg);
+       off = exit_qualification; /* holds the displacement */
        if (base_is_valid)
-               *ret += kvm_register_read(vcpu, base_reg);
+               off += kvm_register_read(vcpu, base_reg);
        if (index_is_valid)
-               *ret += kvm_register_read(vcpu, index_reg)<<scaling;
-       *ret += exit_qualification; /* holds the displacement */
+               off += kvm_register_read(vcpu, index_reg)<<scaling;
+       vmx_get_segment(vcpu, &s, seg_reg);
+       *ret = s.base + off;
 
        if (addr_size == 1) /* 32 bit */
                *ret &= 0xffffffff;
 
-       /*
-        * TODO: throw #GP (and return 1) in various cases that the VM*
-        * instructions require it - e.g., offset beyond segment limit,
-        * unusable or unreadable/unwritable segment, non-canonical 64-bit
-        * address, and so on. Currently these are not checked.
-        */
+       /* Checks for #GP/#SS exceptions. */
+       exn = false;
+       if (is_protmode(vcpu)) {
+               /* Protected mode: apply checks for segment validity in the
+                * following order:
+                * - segment type check (#GP(0) may be thrown)
+                * - usability check (#GP(0)/#SS(0))
+                * - limit check (#GP(0)/#SS(0))
+                */
+               if (wr)
+                       /* #GP(0) if the destination operand is located in a
+                        * read-only data segment or any code segment.
+                        */
+                       exn = ((s.type & 0xa) == 0 || (s.type & 8));
+               else
+                       /* #GP(0) if the source operand is located in an
+                        * execute-only code segment
+                        */
+                       exn = ((s.type & 0xa) == 8);
+       }
+       if (exn) {
+               kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+               return 1;
+       }
+       if (is_long_mode(vcpu)) {
+               /* Long mode: #GP(0)/#SS(0) if the memory address is in a
+                * non-canonical form. This is an only check for long mode.
+                */
+               exn = is_noncanonical_address(*ret);
+       } else if (is_protmode(vcpu)) {
+               /* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
+                */
+               exn = (s.unusable != 0);
+               /* Protected mode: #GP(0)/#SS(0) if the memory
+                * operand is outside the segment limit.
+                */
+               exn = exn || (off + sizeof(u64) > s.limit);
+       }
+       if (exn) {
+               kvm_queue_exception_e(vcpu,
+                                     seg_reg == VCPU_SREG_SS ?
+                                               SS_VECTOR : GP_VECTOR,
+                                     0);
+               return 1;
+       }
+
        return 0;
 }
 
@@ -6471,7 +6451,7 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
        int maxphyaddr = cpuid_maxphyaddr(vcpu);
 
        if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
-                       vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
+                       vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
                return 1;
 
        if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
@@ -6999,7 +6979,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
                        field_value);
        } else {
                if (get_vmx_mem_address(vcpu, exit_qualification,
-                               vmx_instruction_info, &gva))
+                               vmx_instruction_info, true, &gva))
                        return 1;
                /* _system ok, as nested_vmx_check_permission verified cpl=0 */
                kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
@@ -7036,7 +7016,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
                        (((vmx_instruction_info) >> 3) & 0xf));
        else {
                if (get_vmx_mem_address(vcpu, exit_qualification,
-                               vmx_instruction_info, &gva))
+                               vmx_instruction_info, false, &gva))
                        return 1;
                if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
                           &field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
@@ -7128,7 +7108,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
                return 1;
 
        if (get_vmx_mem_address(vcpu, exit_qualification,
-                       vmx_instruction_info, &vmcs_gva))
+                       vmx_instruction_info, true, &vmcs_gva))
                return 1;
        /* ok to use *_system, as nested_vmx_check_permission verified cpl=0 */
        if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
@@ -7184,7 +7164,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
         * operand is read even if it isn't needed (e.g., for type==global)
         */
        if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
-                       vmx_instruction_info, &gva))
+                       vmx_instruction_info, false, &gva))
                return 1;
        if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
                                sizeof(operand), &e)) {
@@ -7282,6 +7262,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
        [EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
        [EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
        [EXIT_REASON_MWAIT_INSTRUCTION]       = handle_mwait,
+       [EXIT_REASON_MONITOR_TRAP_FLAG]       = handle_monitor_trap,
        [EXIT_REASON_MONITOR_INSTRUCTION]     = handle_monitor,
        [EXIT_REASON_INVEPT]                  = handle_invept,
        [EXIT_REASON_INVVPID]                 = handle_invvpid,
@@ -7542,6 +7523,8 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                return true;
        case EXIT_REASON_MWAIT_INSTRUCTION:
                return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
+       case EXIT_REASON_MONITOR_TRAP_FLAG:
+               return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
        case EXIT_REASON_MONITOR_INSTRUCTION:
                return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
        case EXIT_REASON_PAUSE_INSTRUCTION:
index 5ef2560075bfb80e6fdabcdf51f71258091e4339..4bbc2a1676c9831d57c27646101521a92e855969 100644 (file)
@@ -29,6 +29,7 @@
 #include "cpuid.h"
 #include "assigned-dev.h"
 #include "pmu.h"
+#include "hyperv.h"
 
 #include <linux/clocksource.h>
 #include <linux/interrupt.h>
@@ -221,11 +222,9 @@ static void shared_msr_update(unsigned slot, u32 msr)
 void kvm_define_shared_msr(unsigned slot, u32 msr)
 {
        BUG_ON(slot >= KVM_NR_SHARED_MSRS);
+       shared_msrs_global.msrs[slot] = msr;
        if (slot >= shared_msrs_global.nr)
                shared_msrs_global.nr = slot + 1;
-       shared_msrs_global.msrs[slot] = msr;
-       /* we need ensured the shared_msr_global have been updated */
-       smp_wmb();
 }
 EXPORT_SYMBOL_GPL(kvm_define_shared_msr);
 
@@ -526,7 +525,8 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3)
        }
        for (i = 0; i < ARRAY_SIZE(pdpte); ++i) {
                if (is_present_gpte(pdpte[i]) &&
-                   (pdpte[i] & vcpu->arch.mmu.rsvd_bits_mask[0][2])) {
+                   (pdpte[i] &
+                    vcpu->arch.mmu.guest_rsvd_check.rsvd_bits_mask[0][2])) {
                        ret = 0;
                        goto out;
                }
@@ -949,6 +949,8 @@ static u32 emulated_msrs[] = {
        MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
        HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
        HV_X64_MSR_TIME_REF_COUNT, HV_X64_MSR_REFERENCE_TSC,
+       HV_X64_MSR_CRASH_P0, HV_X64_MSR_CRASH_P1, HV_X64_MSR_CRASH_P2,
+       HV_X64_MSR_CRASH_P3, HV_X64_MSR_CRASH_P4, HV_X64_MSR_CRASH_CTL,
        HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
        MSR_KVM_PV_EOI_EN,
 
@@ -1217,11 +1219,6 @@ static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,
                 __func__, base_khz, scaled_khz, shift, *pmultiplier);
 }
 
-static inline u64 get_kernel_ns(void)
-{
-       return ktime_get_boot_ns();
-}
-
 #ifdef CONFIG_X86_64
 static atomic_t kvm_guest_has_master_clock = ATOMIC_INIT(0);
 #endif
@@ -1869,123 +1866,6 @@ out:
        return r;
 }
 
-static bool kvm_hv_hypercall_enabled(struct kvm *kvm)
-{
-       return kvm->arch.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
-}
-
-static bool kvm_hv_msr_partition_wide(u32 msr)
-{
-       bool r = false;
-       switch (msr) {
-       case HV_X64_MSR_GUEST_OS_ID:
-       case HV_X64_MSR_HYPERCALL:
-       case HV_X64_MSR_REFERENCE_TSC:
-       case HV_X64_MSR_TIME_REF_COUNT:
-               r = true;
-               break;
-       }
-
-       return r;
-}
-
-static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
-{
-       struct kvm *kvm = vcpu->kvm;
-
-       switch (msr) {
-       case HV_X64_MSR_GUEST_OS_ID:
-               kvm->arch.hv_guest_os_id = data;
-               /* setting guest os id to zero disables hypercall page */
-               if (!kvm->arch.hv_guest_os_id)
-                       kvm->arch.hv_hypercall &= ~HV_X64_MSR_HYPERCALL_ENABLE;
-               break;
-       case HV_X64_MSR_HYPERCALL: {
-               u64 gfn;
-               unsigned long addr;
-               u8 instructions[4];
-
-               /* if guest os id is not set hypercall should remain disabled */
-               if (!kvm->arch.hv_guest_os_id)
-                       break;
-               if (!(data & HV_X64_MSR_HYPERCALL_ENABLE)) {
-                       kvm->arch.hv_hypercall = data;
-                       break;
-               }
-               gfn = data >> HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT;
-               addr = gfn_to_hva(kvm, gfn);
-               if (kvm_is_error_hva(addr))
-                       return 1;
-               kvm_x86_ops->patch_hypercall(vcpu, instructions);
-               ((unsigned char *)instructions)[3] = 0xc3; /* ret */
-               if (__copy_to_user((void __user *)addr, instructions, 4))
-                       return 1;
-               kvm->arch.hv_hypercall = data;
-               mark_page_dirty(kvm, gfn);
-               break;
-       }
-       case HV_X64_MSR_REFERENCE_TSC: {
-               u64 gfn;
-               HV_REFERENCE_TSC_PAGE tsc_ref;
-               memset(&tsc_ref, 0, sizeof(tsc_ref));
-               kvm->arch.hv_tsc_page = data;
-               if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
-                       break;
-               gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
-               if (kvm_write_guest(kvm, gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
-                       &tsc_ref, sizeof(tsc_ref)))
-                       return 1;
-               mark_page_dirty(kvm, gfn);
-               break;
-       }
-       default:
-               vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
-                           "data 0x%llx\n", msr, data);
-               return 1;
-       }
-       return 0;
-}
-
-static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data)
-{
-       switch (msr) {
-       case HV_X64_MSR_APIC_ASSIST_PAGE: {
-               u64 gfn;
-               unsigned long addr;
-
-               if (!(data & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE)) {
-                       vcpu->arch.hv_vapic = data;
-                       if (kvm_lapic_enable_pv_eoi(vcpu, 0))
-                               return 1;
-                       break;
-               }
-               gfn = data >> HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT;
-               addr = kvm_vcpu_gfn_to_hva(vcpu, gfn);
-               if (kvm_is_error_hva(addr))
-                       return 1;
-               if (__clear_user((void __user *)addr, PAGE_SIZE))
-                       return 1;
-               vcpu->arch.hv_vapic = data;
-               kvm_vcpu_mark_page_dirty(vcpu, gfn);
-               if (kvm_lapic_enable_pv_eoi(vcpu, gfn_to_gpa(gfn) | KVM_MSR_ENABLED))
-                       return 1;
-               break;
-       }
-       case HV_X64_MSR_EOI:
-               return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
-       case HV_X64_MSR_ICR:
-               return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
-       case HV_X64_MSR_TPR:
-               return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
-       default:
-               vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
-                           "data 0x%llx\n", msr, data);
-               return 1;
-       }
-
-       return 0;
-}
-
 static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
 {
        gpa_t gpa = data & ~0x3f;
@@ -2105,7 +1985,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                if (guest_cpuid_has_tsc_adjust(vcpu)) {
                        if (!msr_info->host_initiated) {
                                s64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
-                               kvm_x86_ops->adjust_tsc_offset(vcpu, adj, true);
+                               adjust_tsc_offset_guest(vcpu, adj);
                        }
                        vcpu->arch.ia32_tsc_adjust_msr = data;
                }
@@ -2224,15 +2104,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                 */
                break;
        case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
-               if (kvm_hv_msr_partition_wide(msr)) {
-                       int r;
-                       mutex_lock(&vcpu->kvm->lock);
-                       r = set_msr_hyperv_pw(vcpu, msr, data);
-                       mutex_unlock(&vcpu->kvm->lock);
-                       return r;
-               } else
-                       return set_msr_hyperv(vcpu, msr, data);
-               break;
+       case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+       case HV_X64_MSR_CRASH_CTL:
+               return kvm_hv_set_msr_common(vcpu, msr, data,
+                                            msr_info->host_initiated);
        case MSR_IA32_BBL_CR_CTL3:
                /* Drop writes to this legacy MSR -- see rdmsr
                 * counterpart for further detail.
@@ -2315,68 +2190,6 @@ static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        return 0;
 }
 
-static int get_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
-{
-       u64 data = 0;
-       struct kvm *kvm = vcpu->kvm;
-
-       switch (msr) {
-       case HV_X64_MSR_GUEST_OS_ID:
-               data = kvm->arch.hv_guest_os_id;
-               break;
-       case HV_X64_MSR_HYPERCALL:
-               data = kvm->arch.hv_hypercall;
-               break;
-       case HV_X64_MSR_TIME_REF_COUNT: {
-               data =
-                    div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100);
-               break;
-       }
-       case HV_X64_MSR_REFERENCE_TSC:
-               data = kvm->arch.hv_tsc_page;
-               break;
-       default:
-               vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
-               return 1;
-       }
-
-       *pdata = data;
-       return 0;
-}
-
-static int get_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
-{
-       u64 data = 0;
-
-       switch (msr) {
-       case HV_X64_MSR_VP_INDEX: {
-               int r;
-               struct kvm_vcpu *v;
-               kvm_for_each_vcpu(r, v, vcpu->kvm) {
-                       if (v == vcpu) {
-                               data = r;
-                               break;
-                       }
-               }
-               break;
-       }
-       case HV_X64_MSR_EOI:
-               return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
-       case HV_X64_MSR_ICR:
-               return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
-       case HV_X64_MSR_TPR:
-               return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
-       case HV_X64_MSR_APIC_ASSIST_PAGE:
-               data = vcpu->arch.hv_vapic;
-               break;
-       default:
-               vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
-               return 1;
-       }
-       *pdata = data;
-       return 0;
-}
-
 int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
        switch (msr_info->index) {
@@ -2493,14 +2306,10 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = 0x20000000;
                break;
        case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
-               if (kvm_hv_msr_partition_wide(msr_info->index)) {
-                       int r;
-                       mutex_lock(&vcpu->kvm->lock);
-                       r = get_msr_hyperv_pw(vcpu, msr_info->index, &msr_info->data);
-                       mutex_unlock(&vcpu->kvm->lock);
-                       return r;
-               } else
-                       return get_msr_hyperv(vcpu, msr_info->index, &msr_info->data);
+       case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+       case HV_X64_MSR_CRASH_CTL:
+               return kvm_hv_get_msr_common(vcpu,
+                                            msr_info->index, &msr_info->data);
                break;
        case MSR_IA32_BBL_CR_CTL3:
                /* This legacy MSR exists but isn't fully documented in current
@@ -2651,6 +2460,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_TSC_DEADLINE_TIMER:
        case KVM_CAP_ENABLE_CAP_VM:
        case KVM_CAP_DISABLE_QUIRKS:
+       case KVM_CAP_SET_BOOT_CPU_ID:
 #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
        case KVM_CAP_ASSIGN_DEV_IRQ:
        case KVM_CAP_PCI_2_3:
@@ -3817,30 +3627,25 @@ long kvm_arch_vm_ioctl(struct file *filp,
                        r = kvm_ioapic_init(kvm);
                        if (r) {
                                mutex_lock(&kvm->slots_lock);
-                               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
-                                                         &vpic->dev_master);
-                               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
-                                                         &vpic->dev_slave);
-                               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
-                                                         &vpic->dev_eclr);
+                               kvm_destroy_pic(vpic);
                                mutex_unlock(&kvm->slots_lock);
-                               kfree(vpic);
                                goto create_irqchip_unlock;
                        }
                } else
                        goto create_irqchip_unlock;
-               smp_wmb();
-               kvm->arch.vpic = vpic;
-               smp_wmb();
                r = kvm_setup_default_irq_routing(kvm);
                if (r) {
                        mutex_lock(&kvm->slots_lock);
                        mutex_lock(&kvm->irq_lock);
                        kvm_ioapic_destroy(kvm);
-                       kvm_destroy_pic(kvm);
+                       kvm_destroy_pic(vpic);
                        mutex_unlock(&kvm->irq_lock);
                        mutex_unlock(&kvm->slots_lock);
+                       goto create_irqchip_unlock;
                }
+               /* Write kvm->irq_routing before kvm->arch.vpic.  */
+               smp_wmb();
+               kvm->arch.vpic = vpic;
        create_irqchip_unlock:
                mutex_unlock(&kvm->lock);
                break;
@@ -3967,6 +3772,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = kvm_vm_ioctl_reinject(kvm, &control);
                break;
        }
+       case KVM_SET_BOOT_CPU_ID:
+               r = 0;
+               mutex_lock(&kvm->lock);
+               if (atomic_read(&kvm->online_vcpus) != 0)
+                       r = -EBUSY;
+               else
+                       kvm->arch.bsp_vcpu_id = arg;
+               mutex_unlock(&kvm->lock);
+               break;
        case KVM_XEN_HVM_CONFIG: {
                r = -EFAULT;
                if (copy_from_user(&kvm->arch.xen_hvm_config, argp,
@@ -5882,66 +5696,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
-int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
-{
-       u64 param, ingpa, outgpa, ret;
-       uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
-       bool fast, longmode;
-
-       /*
-        * hypercall generates UD from non zero cpl and real mode
-        * per HYPER-V spec
-        */
-       if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) {
-               kvm_queue_exception(vcpu, UD_VECTOR);
-               return 0;
-       }
-
-       longmode = is_64_bit_mode(vcpu);
-
-       if (!longmode) {
-               param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
-                       (kvm_register_read(vcpu, VCPU_REGS_RAX) & 0xffffffff);
-               ingpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RBX) << 32) |
-                       (kvm_register_read(vcpu, VCPU_REGS_RCX) & 0xffffffff);
-               outgpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDI) << 32) |
-                       (kvm_register_read(vcpu, VCPU_REGS_RSI) & 0xffffffff);
-       }
-#ifdef CONFIG_X86_64
-       else {
-               param = kvm_register_read(vcpu, VCPU_REGS_RCX);
-               ingpa = kvm_register_read(vcpu, VCPU_REGS_RDX);
-               outgpa = kvm_register_read(vcpu, VCPU_REGS_R8);
-       }
-#endif
-
-       code = param & 0xffff;
-       fast = (param >> 16) & 0x1;
-       rep_cnt = (param >> 32) & 0xfff;
-       rep_idx = (param >> 48) & 0xfff;
-
-       trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
-
-       switch (code) {
-       case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT:
-               kvm_vcpu_on_spin(vcpu);
-               break;
-       default:
-               res = HV_STATUS_INVALID_HYPERCALL_CODE;
-               break;
-       }
-
-       ret = res | (((u64)rep_done & 0xfff) << 32);
-       if (longmode) {
-               kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
-       } else {
-               kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
-               kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
-       }
-
-       return 1;
-}
-
 /*
  * kvm_pv_kick_cpu_op:  Kick a vcpu.
  *
@@ -6327,6 +6081,7 @@ static void process_smi_save_state_64(struct kvm_vcpu *vcpu, char *buf)
 static void process_smi(struct kvm_vcpu *vcpu)
 {
        struct kvm_segment cs, ds;
+       struct desc_ptr dt;
        char buf[512];
        u32 cr0;
 
@@ -6359,6 +6114,10 @@ static void process_smi(struct kvm_vcpu *vcpu)
 
        kvm_x86_ops->set_cr4(vcpu, 0);
 
+       /* Undocumented: IDT limit is set to zero on entry to SMM.  */
+       dt.address = dt.size = 0;
+       kvm_x86_ops->set_idt(vcpu, &dt);
+
        __kvm_set_dr(vcpu, 7, DR7_FIXED_1);
 
        cs.selector = (vcpu->arch.smbase >> 4) & 0xffff;
@@ -6513,6 +6272,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                        vcpu_scan_ioapic(vcpu);
                if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
                        kvm_vcpu_reload_apic_access_page(vcpu);
+               if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
+                       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+                       vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
+                       r = 0;
+                       goto out;
+               }
        }
 
        if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
@@ -7535,6 +7300,17 @@ void kvm_arch_check_processor_compat(void *rtn)
        kvm_x86_ops->check_processor_compatibility(rtn);
 }
 
+bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu)
+{
+       return vcpu->kvm->arch.bsp_vcpu_id == vcpu->vcpu_id;
+}
+EXPORT_SYMBOL_GPL(kvm_vcpu_is_reset_bsp);
+
+bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
+{
+       return (vcpu->arch.apic_base & MSR_IA32_APICBASE_BSP) != 0;
+}
+
 bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
 {
        return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
index 0ca2f3e4803c2a5846be297a51eb5c1cf67aff4a..2f822cd886c26cb631d50c38fb933d5898bcc0c0 100644 (file)
@@ -147,6 +147,11 @@ static inline void kvm_register_writel(struct kvm_vcpu *vcpu,
        return kvm_register_write(vcpu, reg, val);
 }
 
+static inline u64 get_kernel_ns(void)
+{
+       return ktime_get_boot_ns();
+}
+
 static inline bool kvm_check_has_quirk(struct kvm *kvm, u64 quirk)
 {
        return !(kvm->arch.disabled_quirks & quirk);
index f37e84ab49f38e335bde57880a6cbe8640fb2c4b..3d8f2e421466a8af255eba9602748fee8753a377 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/traps.h>
-#include <asm/desc.h>
 #include <asm/user.h>
 #include <asm/fpu/internal.h>
 
@@ -181,7 +180,7 @@ void math_emulate(struct math_emu_info *info)
                        math_abort(FPU_info, SIGILL);
                }
 
-               code_descriptor = LDT_DESCRIPTOR(FPU_CS);
+               code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
                if (SEG_D_SIZE(code_descriptor)) {
                        /* The above test may be wrong, the book is not clear */
                        /* Segmented 32 bit protected mode */
index 9ccecb61a4fa129a82028b27edc18b91a2f99042..5e044d506b7aae8b17b2142966b11477cfe8e372 100644 (file)
 #include <linux/kernel.h>
 #include <linux/mm.h>
 
-/* s is always from a cpu register, and the cpu does bounds checking
- * during register load --> no further bounds checks needed */
-#define LDT_DESCRIPTOR(s)      (((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
+#include <asm/desc.h>
+#include <asm/mmu_context.h>
+
+static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg)
+{
+       static struct desc_struct zero_desc;
+       struct desc_struct ret = zero_desc;
+
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
+       seg >>= 3;
+       mutex_lock(&current->mm->context.lock);
+       if (current->mm->context.ldt && seg < current->mm->context.ldt->size)
+               ret = current->mm->context.ldt->entries[seg];
+       mutex_unlock(&current->mm->context.lock);
+#endif
+       return ret;
+}
+
 #define SEG_D_SIZE(x)          ((x).b & (3 << 21))
 #define SEG_G_BIT(x)           ((x).b & (1 << 23))
 #define SEG_GRANULARITY(x)     (((x).b & (1 << 23)) ? 4096 : 1)
index 6ef5e99380f92134ba86a6a693b5ac6d3434e6d4..8300db71c2a62681006e137350961742190ec9dc 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/stddef.h>
 
 #include <asm/uaccess.h>
-#include <asm/desc.h>
 
 #include "fpu_system.h"
 #include "exception.h"
@@ -158,7 +157,7 @@ static long pm_address(u_char FPU_modrm, u_char segment,
                addr->selector = PM_REG_(segment);
        }
 
-       descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
+       descriptor = FPU_get_ldt_descriptor(addr->selector);
        base_address = SEG_BASE_ADDR(descriptor);
        address = base_address + offset;
        limit = base_address
index 8fd6f44aee8370958076fb4a8af3e13a2781fe33..09d3afc0a181c1ac44ca654f9fde35796dbe3843 100644 (file)
@@ -166,7 +166,6 @@ void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
-       pci_read_bridge_bases(b);
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
 }
@@ -673,24 +672,22 @@ int pcibios_add_device(struct pci_dev *dev)
        return 0;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+int pcibios_alloc_irq(struct pci_dev *dev)
 {
-       int err;
-
-       if ((err = pci_enable_resources(dev, mask)) < 0)
-               return err;
-
-       if (!pci_dev_msi_enabled(dev))
-               return pcibios_enable_irq(dev);
-       return 0;
+       return pcibios_enable_irq(dev);
 }
 
-void pcibios_disable_device (struct pci_dev *dev)
+void pcibios_free_irq(struct pci_dev *dev)
 {
-       if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+       if (pcibios_disable_irq)
                pcibios_disable_irq(dev);
 }
 
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       return pci_enable_resources(dev, mask);
+}
+
 int pci_ext_cfg_avail(void)
 {
        if (raw_pci_ext_ops)
index 9a2b7101ae8af6d402f15c66831bcd15b7790325..e58565556703bfc781e29f4e387cbd0e2ea1ced8 100644 (file)
@@ -62,19 +62,6 @@ static void pci_fixup_umc_ide(struct pci_dev *d)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
 
-static void pci_fixup_ncr53c810(struct pci_dev *d)
-{
-       /*
-        * NCR 53C810 returns class code 0 (at least on some systems).
-        * Fix class to be PCI_CLASS_STORAGE_SCSI
-        */
-       if (!d->class) {
-               dev_warn(&d->dev, "Fixing NCR 53C810 class code\n");
-               d->class = PCI_CLASS_STORAGE_SCSI << 8;
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
-
 static void pci_fixup_latency(struct pci_dev *d)
 {
        /*
index 27062303c88135b5d614455ed372861516903e53..22aaefb4f1cadf5bc136b4a72af08939fc4aae30 100644 (file)
@@ -211,7 +211,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
        struct irq_alloc_info info;
        int polarity;
 
-       if (dev->irq_managed && dev->irq > 0)
+       if (pci_has_managed_irq(dev))
                return 0;
 
        if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
@@ -234,10 +234,13 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-       if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
-           dev->irq > 0) {
+       if (pci_has_managed_irq(dev)) {
                mp_unmap_irq(dev->irq);
                dev->irq_managed = 0;
+               /*
+                * Don't reset dev->irq here, otherwise
+                * intel_mid_pci_irq_enable() will fail on next call.
+                */
        }
 }
 
index 9bd115484745703791c6515b289938546d2478ab..32e70343e6fdd0e58ab80644284dd01000dccd82 100644 (file)
@@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        struct pci_dev *temp_dev;
                        int irq;
 
-                       if (dev->irq_managed && dev->irq > 0)
+                       if (pci_has_managed_irq(dev))
                                return 0;
 
                        irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
@@ -1230,8 +1230,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        }
                        dev = temp_dev;
                        if (irq >= 0) {
-                               dev->irq_managed = 1;
-                               dev->irq = irq;
+                               pci_set_managed_irq(dev, irq);
                                dev_info(&dev->dev, "PCI->APIC IRQ transform: "
                                         "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
                                return 0;
@@ -1257,24 +1256,10 @@ static int pirq_enable_irq(struct pci_dev *dev)
        return 0;
 }
 
-bool mp_should_keep_irq(struct device *dev)
-{
-       if (dev->power.is_prepared)
-               return true;
-#ifdef CONFIG_PM
-       if (dev->power.runtime_status == RPM_SUSPENDING)
-               return true;
-#endif
-
-       return false;
-}
-
 static void pirq_disable_irq(struct pci_dev *dev)
 {
-       if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
-           dev->irq_managed && dev->irq) {
+       if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
                mp_unmap_irq(dev->irq);
-               dev->irq = 0;
-               dev->irq_managed = 0;
+               pci_reset_managed_irq(dev);
        }
 }
index e88fda867a33b198bc356aded57d59f48fcfb4ee..484145368a241207d8aa80a5f758a7d0f3ef54cb 100644 (file)
@@ -8,7 +8,7 @@ config XEN
        select PARAVIRT_CLOCK
        select XEN_HAVE_PVMMU
        depends on X86_64 || (X86_32 && X86_PAE)
-       depends on X86_TSC
+       depends on X86_LOCAL_APIC && X86_TSC
        help
          This is the Linux Xen port.  Enabling this will allow the
          kernel to boot in a paravirtualized environment under the
@@ -17,7 +17,7 @@ config XEN
 config XEN_DOM0
        def_bool y
        depends on XEN && PCI_XEN && SWIOTLB_XEN
-       depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI
+       depends on X86_IO_APIC && ACPI && PCI
 
 config XEN_PVHVM
        def_bool y
index 7322755f337af760db6086450591c584c4dcda77..4b6e29ac0968c1a76451d3ff773652bc4afed138 100644 (file)
@@ -13,13 +13,13 @@ CFLAGS_mmu.o                        := $(nostackp)
 obj-y          := enlighten.o setup.o multicalls.o mmu.o irq.o \
                        time.o xen-asm.o xen-asm_$(BITS).o \
                        grant-table.o suspend.o platform-pci-unplug.o \
-                       p2m.o
+                       p2m.o apic.o
 
 obj-$(CONFIG_EVENT_TRACING) += trace.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
 obj-$(CONFIG_XEN_DEBUG_FS)     += debugfs.o
-obj-$(CONFIG_XEN_DOM0)         += apic.o vga.o
+obj-$(CONFIG_XEN_DOM0)         += vga.o
 obj-$(CONFIG_SWIOTLB_XEN)      += pci-swiotlb-xen.o
 obj-$(CONFIG_XEN_EFI)          += efi.o
index c20fe29e65f48b4706789e0ad59bb33b1a3acc18..2292721b1d103844ade9f8a7f436a649c811f77d 100644 (file)
@@ -101,17 +101,15 @@ struct dom0_vga_console_info;
 
 #ifdef CONFIG_XEN_DOM0
 void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
-void __init xen_init_apic(void);
 #else
 static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
                                       size_t size)
 {
 }
-static inline void __init xen_init_apic(void)
-{
-}
 #endif
 
+void __init xen_init_apic(void);
+
 #ifdef CONFIG_XEN_EFI
 extern void xen_efi_init(void);
 #else
index e5b872ba24843ee84ee65346dd87ab79abb6141b..3bd3504a6cc768a3a259c22fbf9cc1c739e54e44 100644 (file)
@@ -14,12 +14,15 @@ config XTENSA
        select GENERIC_IRQ_SHOW
        select GENERIC_PCI_IOMAP
        select GENERIC_SCHED_CLOCK
+       select HAVE_DMA_API_DEBUG
+       select HAVE_DMA_ATTRS
        select HAVE_FUNCTION_TRACER
        select HAVE_IRQ_TIME_ACCOUNTING
        select HAVE_OPROFILE
        select HAVE_PERF_EVENTS
        select IRQ_DOMAIN
        select MODULES_USE_ELF_RELA
+       select PERF_USE_VMALLOC
        select VIRT_TO_BUS
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
@@ -61,9 +64,7 @@ config TRACE_IRQFLAGS_SUPPORT
        def_bool y
 
 config MMU
-       bool
-       default n if !XTENSA_VARIANT_CUSTOM
-       default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM
+       def_bool n
 
 config VARIANT_IRQ_SWITCH
        def_bool n
@@ -71,9 +72,6 @@ config VARIANT_IRQ_SWITCH
 config HAVE_XTENSA_GPIO32
        def_bool n
 
-config MAY_HAVE_SMP
-       def_bool n
-
 menu "Processor type and features"
 
 choice
@@ -100,7 +98,6 @@ config XTENSA_VARIANT_DC233C
 
 config XTENSA_VARIANT_CUSTOM
        bool "Custom Xtensa processor configuration"
-       select MAY_HAVE_SMP
        select HAVE_XTENSA_GPIO32
        help
          Select this variant to use a custom Xtensa processor configuration.
@@ -126,10 +123,21 @@ config XTENSA_VARIANT_MMU
        bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)"
        depends on XTENSA_VARIANT_CUSTOM
        default y
+       select MMU
        help
          Build a Conventional Kernel with full MMU support,
          ie: it supports a TLB with auto-loading, page protection.
 
+config XTENSA_VARIANT_HAVE_PERF_EVENTS
+       bool "Core variant has Performance Monitor Module"
+       depends on XTENSA_VARIANT_CUSTOM
+       default n
+       help
+         Enable if core variant has Performance Monitor Module with
+         External Registers Interface.
+
+         If unsure, say N.
+
 config XTENSA_UNALIGNED_USER
        bool "Unaligned memory access in use space"
        help
@@ -143,7 +151,7 @@ source "kernel/Kconfig.preempt"
 
 config HAVE_SMP
        bool "System Supports SMP (MX)"
-       depends on MAY_HAVE_SMP
+       depends on XTENSA_VARIANT_CUSTOM
        select XTENSA_MX
        help
          This option is use to indicate that the system-on-a-chip (SOC)
index 5b478accd5fcae8237ca010330a1c99d299fa6b4..63c223dff5f1eebed92297d2cd641535a3aeceb9 100644 (file)
@@ -2,7 +2,6 @@ generic-y += bitsperlong.h
 generic-y += bug.h
 generic-y += clkdev.h
 generic-y += cputime.h
-generic-y += device.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
index 00b7d46b35b848226cacd90034bc241181d3389c..ebcd1f6fc8cb9f64c64f2fa332fb573fd32ef8d7 100644 (file)
@@ -29,7 +29,7 @@
  *
  * Locking interrupts looks like this:
  *
- *    rsil a15, LOCKLEVEL
+ *    rsil a15, TOPLEVEL
  *    <code>
  *    wsr  a15, PS
  *    rsync
@@ -106,7 +106,7 @@ static inline void atomic_##op(int i, atomic_t * v)                 \
        unsigned int vval;                                              \
                                                                        \
        __asm__ __volatile__(                                           \
-                       "       rsil    a15, "__stringify(LOCKLEVEL)"\n"\
+                       "       rsil    a15, "__stringify(TOPLEVEL)"\n"\
                        "       l32i    %0, %2, 0\n"                    \
                        "       " #op " %0, %0, %1\n"                   \
                        "       s32i    %0, %2, 0\n"                    \
@@ -124,7 +124,7 @@ static inline int atomic_##op##_return(int i, atomic_t * v)         \
        unsigned int vval;                                              \
                                                                        \
        __asm__ __volatile__(                                           \
-                       "       rsil    a15,"__stringify(LOCKLEVEL)"\n" \
+                       "       rsil    a15,"__stringify(TOPLEVEL)"\n"  \
                        "       l32i    %0, %2, 0\n"                    \
                        "       " #op " %0, %0, %1\n"                   \
                        "       s32i    %0, %2, 0\n"                    \
@@ -272,7 +272,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
        unsigned int vval;
 
        __asm__ __volatile__(
-                       "       rsil    a15,"__stringify(LOCKLEVEL)"\n"
+                       "       rsil    a15,"__stringify(TOPLEVEL)"\n"
                        "       l32i    %0, %2, 0\n"
                        "       xor     %1, %4, %3\n"
                        "       and     %0, %0, %4\n"
@@ -306,7 +306,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
        unsigned int vval;
 
        __asm__ __volatile__(
-                       "       rsil    a15,"__stringify(LOCKLEVEL)"\n"
+                       "       rsil    a15,"__stringify(TOPLEVEL)"\n"
                        "       l32i    %0, %2, 0\n"
                        "       or      %0, %0, %1\n"
                        "       s32i    %0, %2, 0\n"
index 370b26f38414d9e33af67244a96bc7c9a8a96622..201e9009efd81c6cd0bd97c3490931d800a39c95 100644 (file)
@@ -34,7 +34,7 @@ __cmpxchg_u32(volatile int *p, int old, int new)
        return new;
 #else
        __asm__ __volatile__(
-                       "       rsil    a15, "__stringify(LOCKLEVEL)"\n"
+                       "       rsil    a15, "__stringify(TOPLEVEL)"\n"
                        "       l32i    %0, %1, 0\n"
                        "       bne     %0, %2, 1f\n"
                        "       s32i    %3, %1, 0\n"
@@ -123,7 +123,7 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
 #else
        unsigned long tmp;
        __asm__ __volatile__(
-                       "       rsil    a15, "__stringify(LOCKLEVEL)"\n"
+                       "       rsil    a15, "__stringify(TOPLEVEL)"\n"
                        "       l32i    %0, %1, 0\n"
                        "       s32i    %2, %1, 0\n"
                        "       wsr     a15, ps\n"
diff --git a/arch/xtensa/include/asm/device.h b/arch/xtensa/include/asm/device.h
new file mode 100644 (file)
index 0000000..fe1f5c8
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_XTENSA_DEVICE_H
+#define _ASM_XTENSA_DEVICE_H
+
+struct dma_map_ops;
+
+struct dev_archdata {
+       /* DMA operations on that device */
+       struct dma_map_ops *dma_ops;
+};
+
+struct pdev_archdata {
+};
+
+#endif /* _ASM_XTENSA_DEVICE_H */
index 1f5f6dc097365ab4f4be0a00a481859dc29e4256..f01cb3044e50d310112a94abb597b8ac7aed1b35 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * include/asm-xtensa/dma-mapping.h
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Copyright (C) 2003 - 2005 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  */
 
 #ifndef _XTENSA_DMA_MAPPING_H
 
 #include <asm/cache.h>
 #include <asm/io.h>
+
+#include <asm-generic/dma-coherent.h>
+
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 
 #define DMA_ERROR_CODE         (~(dma_addr_t)0x0)
 
-/*
- * DMA-consistent mapping functions.
- */
-
-extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long);
-extern void consistent_free(void*, size_t, dma_addr_t);
-extern void consistent_sync(void*, size_t, int);
-
-#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)
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, gfp_t flag);
+extern struct dma_map_ops xtensa_dma_map_ops;
 
-void dma_free_coherent(struct device *dev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle);
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-       consistent_sync(ptr, size, direction);
-       return virt_to_phys(ptr);
-}
-
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-                enum dma_data_direction direction)
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 {
-       BUG_ON(direction == DMA_NONE);
+       if (dev && dev->archdata.dma_ops)
+               return dev->archdata.dma_ops;
+       else
+               return &xtensa_dma_map_ops;
 }
 
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
-          enum dma_data_direction direction)
-{
-       int i;
-       struct scatterlist *sg;
-
-       BUG_ON(direction == DMA_NONE);
-
-       for_each_sg(sglist, sg, nents, i) {
-               BUG_ON(!sg_page(sg));
+#include <asm-generic/dma-mapping-common.h>
 
-               sg->dma_address = sg_phys(sg);
-               consistent_sync(sg_virt(sg), sg->length, direction);
-       }
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_free_noncoherent(d, s, v, h) dma_free_attrs(d, s, v, h, NULL)
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_free_coherent(d, s, c, h) dma_free_attrs(d, s, c, h, NULL)
 
-       return nents;
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page, unsigned long offset,
-            size_t size, enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-       return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset;
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-              enum dma_data_direction direction)
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t gfp,
+                                   struct dma_attrs *attrs)
 {
-       BUG_ON(direction == DMA_NONE);
-}
+       void *ret;
+       struct dma_map_ops *ops = get_dma_ops(dev);
 
+       if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+               return ret;
 
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-            enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-               enum dma_data_direction direction)
-{
-       consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
-}
+       ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
+       debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
 
-static inline void
-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-                          size_t size, enum dma_data_direction direction)
-{
-       consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
+       return ret;
 }
 
-static inline void
-dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-                     unsigned long offset, size_t size,
-                     enum dma_data_direction direction)
-{
-
-       consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
-}
-
-static inline void
-dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-                     unsigned long offset, size_t size,
-                     enum dma_data_direction direction)
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *vaddr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
+       struct dma_map_ops *ops = get_dma_ops(dev);
 
-       consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
-}
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nelems,
-                enum dma_data_direction dir)
-{
-       int i;
-       struct scatterlist *sg;
+       if (dma_release_from_coherent(dev, get_order(size), vaddr))
+               return;
 
-       for_each_sg(sglist, sg, nelems, i)
-               consistent_sync(sg_virt(sg), sg->length, dir);
+       ops->free(dev, size, vaddr, dma_handle, attrs);
+       debug_dma_free_coherent(dev, size, vaddr, dma_handle);
 }
 
-static inline void
-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
-                      int nelems, enum dma_data_direction dir)
-{
-       int i;
-       struct scatterlist *sg;
-
-       for_each_sg(sglist, sg, nelems, i)
-               consistent_sync(sg_virt(sg), sg->length, dir);
-}
 static inline int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-       return 0;
+       struct dma_map_ops *ops = get_dma_ops(dev);
+
+       debug_dma_mapping_error(dev, dma_addr);
+       return ops->mapping_error(dev, dma_addr);
 }
 
 static inline int
@@ -168,39 +92,7 @@ dma_set_mask(struct device *dev, u64 mask)
        return 0;
 }
 
-static inline void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-              enum dma_data_direction direction)
-{
-       consistent_sync(vaddr, size, direction);
-}
-
-/* Not supported for now */
-static inline int dma_mmap_coherent(struct device *dev,
-                                   struct vm_area_struct *vma, void *cpu_addr,
-                                   dma_addr_t dma_addr, size_t size)
-{
-       return -EINVAL;
-}
-
-static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
-                                 void *cpu_addr, dma_addr_t dma_addr,
-                                 size_t size)
-{
-       return -EINVAL;
-}
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
-                                   dma_addr_t *dma_handle, gfp_t flag,
-                                   struct dma_attrs *attrs)
-{
-       return NULL;
-}
-
-static inline void dma_free_attrs(struct device *dev, size_t size,
-                                 void *vaddr, dma_addr_t dma_handle,
-                                 struct dma_attrs *attrs)
-{
-}
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                   enum dma_data_direction direction);
 
 #endif /* _XTENSA_DMA_MAPPING_H */
index ea36674c6ec5d9828e757112e9caa13b785bf72e..8e090c709046f9663d4c80d16e5011846d8cf3a6 100644 (file)
@@ -6,6 +6,7 @@
  * for more details.
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  */
 
 #ifndef _XTENSA_IRQFLAGS_H
@@ -23,8 +24,27 @@ static inline unsigned long arch_local_save_flags(void)
 static inline unsigned long arch_local_irq_save(void)
 {
        unsigned long flags;
-       asm volatile("rsil %0, "__stringify(LOCKLEVEL)
+#if XTENSA_FAKE_NMI
+#if defined(CONFIG_DEBUG_KERNEL) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
+       unsigned long tmp;
+
+       asm volatile("rsr       %0, ps\t\n"
+                    "extui     %1, %0, 0, 4\t\n"
+                    "bgei      %1, "__stringify(LOCKLEVEL)", 1f\t\n"
+                    "rsil      %0, "__stringify(LOCKLEVEL)"\n"
+                    "1:"
+                    : "=a" (flags), "=a" (tmp) :: "memory");
+#else
+       asm volatile("rsr       %0, ps\t\n"
+                    "or        %0, %0, %1\t\n"
+                    "xsr       %0, ps\t\n"
+                    "rsync"
+                    : "=&a" (flags) : "a" (LOCKLEVEL) : "memory");
+#endif
+#else
+       asm volatile("rsil      %0, "__stringify(LOCKLEVEL)
                     : "=a" (flags) :: "memory");
+#endif
        return flags;
 }
 
index b61bdf0eea254457c12013696106aa260efaba76..83e2e4bc01ba24f54965df8b4ee3de7855e028e0 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * include/asm-xtensa/processor.h
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Copyright (C) 2001 - 2008 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  */
 
 #ifndef _XTENSA_PROCESSOR_H
 #define STACK_TOP      TASK_SIZE
 #define STACK_TOP_MAX  STACK_TOP
 
+/*
+ * General exception cause assigned to fake NMI. Fake NMI needs to be handled
+ * differently from other interrupts, but it uses common kernel entry/exit
+ * code.
+ */
+
+#define EXCCAUSE_MAPPED_NMI    62
+
 /*
  * General exception cause assigned to debug exceptions. Debug exceptions go
  * to their own vector, rather than the general exception vectors (user,
 
 #define VALID_DOUBLE_EXCEPTION_ADDRESS 64
 
+#define XTENSA_INT_LEVEL(intno) _XTENSA_INT_LEVEL(intno)
+#define _XTENSA_INT_LEVEL(intno) XCHAL_INT##intno##_LEVEL
+
+#define XTENSA_INTLEVEL_MASK(level) _XTENSA_INTLEVEL_MASK(level)
+#define _XTENSA_INTLEVEL_MASK(level) (XCHAL_INTLEVEL##level##_MASK)
+
+#define IS_POW2(v) (((v) & ((v) - 1)) == 0)
+
+#define PROFILING_INTLEVEL XTENSA_INT_LEVEL(XCHAL_PROFILING_INTERRUPT)
+
 /* LOCKLEVEL defines the interrupt level that masks all
  * general-purpose interrupts.
  */
+#if defined(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) && \
+       defined(XCHAL_PROFILING_INTERRUPT) && \
+       PROFILING_INTLEVEL == XCHAL_EXCM_LEVEL && \
+       XCHAL_EXCM_LEVEL > 1 && \
+       IS_POW2(XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL))
+#define LOCKLEVEL (XCHAL_EXCM_LEVEL - 1)
+#else
 #define LOCKLEVEL XCHAL_EXCM_LEVEL
+#endif
+#define TOPLEVEL XCHAL_EXCM_LEVEL
+#define XTENSA_FAKE_NMI (LOCKLEVEL < TOPLEVEL)
 
 /* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
  * registers
index 6a05fcb0a20de444d05d0706ff49795e0028ea94..fe06e8ed162b754ce2c6cceec4ddb9682030f088 100644 (file)
@@ -33,4 +33,12 @@ void walk_stackframe(unsigned long *sp,
                int (*fn)(struct stackframe *frame, void *data),
                void *data);
 
+void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
+                            int (*kfn)(struct stackframe *frame, void *data),
+                            int (*ufn)(struct stackframe *frame, void *data),
+                            void *data);
+void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
+                          int (*ufn)(struct stackframe *frame, void *data),
+                          void *data);
+
 #endif /* _XTENSA_STACKTRACE_H */
index 677bfcf4ee5ddab2207ed0e5f2885b4accd29f16..28f33a8b7f5f5b5b70d7d2f6cb6c0533bdc80a05 100644 (file)
@@ -25,30 +25,39 @@ static inline void spill_registers(void)
 {
 #if XCHAL_NUM_AREGS > 16
        __asm__ __volatile__ (
-               "       call12  1f\n"
+               "       call  1f\n"
                "       _j      2f\n"
                "       retw\n"
                "       .align  4\n"
                "1:\n"
+#if XCHAL_NUM_AREGS == 32
+               "       _entry  a1, 32\n"
+               "       addi    a8, a0, 3\n"
+               "       _entry  a1, 16\n"
+               "       mov     a12, a12\n"
+               "       retw\n"
+#else
                "       _entry  a1, 48\n"
-               "       addi    a12, a0, 3\n"
-#if XCHAL_NUM_AREGS > 32
-               "       .rept   (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
+               "       call12  1f\n"
+               "       retw\n"
+               "       .align  4\n"
+               "1:\n"
+               "       .rept   (" __stringify(XCHAL_NUM_AREGS) " - 16) / 12\n"
                "       _entry  a1, 48\n"
                "       mov     a12, a0\n"
                "       .endr\n"
-#endif
-               "       _entry  a1, 48\n"
+               "       _entry  a1, 16\n"
 #if XCHAL_NUM_AREGS % 12 == 0
-               "       mov     a8, a8\n"
-#elif XCHAL_NUM_AREGS % 12 == 4
                "       mov     a12, a12\n"
-#elif XCHAL_NUM_AREGS % 12 == 8
+#elif XCHAL_NUM_AREGS % 12 == 4
                "       mov     a4, a4\n"
+#elif XCHAL_NUM_AREGS % 12 == 8
+               "       mov     a8, a8\n"
 #endif
                "       retw\n"
+#endif
                "2:\n"
-               : : : "a12", "a13", "memory");
+               : : : "a8", "a9", "memory");
 #else
        __asm__ __volatile__ (
                "       mov     a12, a12\n"
index d3a0f0fd56ddce023cb27594e6fff8e2e455e761..50137bc9e15036a79828e09f3cbad70b970e0855 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
 obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
 obj-$(CONFIG_SMP) += smp.o mxhead.o
+obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o
 
 AFLAGS_head.o += -mtext-section-literals
 
@@ -27,10 +28,11 @@ AFLAGS_head.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \
-       -e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g'       \
-       -e 's/\*(\(\.text .*\))/*(.literal \1)/g'                        \
-       -e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g'
+sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+       -e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+       -e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+       -e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+       -e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
 cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $<    \
index 82bbfa5a05b34389c0947b2846bc68d49282c2a7..504130357597f937cf9d4381c5f9201d9f3197a6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/xtensa/kernel/entry.S
- *
  * Low-level exception handling
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -8,6 +6,7 @@
  * for more details.
  *
  * Copyright (C) 2004 - 2008 by Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  *
  * Chris Zankel <chris@zankel.net>
  *
 #endif
        .endm
 
+
+       .macro  irq_save flags tmp
+#if XTENSA_FAKE_NMI
+#if defined(CONFIG_DEBUG_KERNEL) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
+       rsr     \flags, ps
+       extui   \tmp, \flags, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
+       bgei    \tmp, LOCKLEVEL, 99f
+       rsil    \tmp, LOCKLEVEL
+99:
+#else
+       movi    \tmp, LOCKLEVEL
+       rsr     \flags, ps
+       or      \flags, \flags, \tmp
+       xsr     \flags, ps
+       rsync
+#endif
+#else
+       rsil    \flags, LOCKLEVEL
+#endif
+       .endm
+
 /* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
 
 /*
@@ -122,6 +142,7 @@ _user_exception:
        /* Save SAR and turn off single stepping */
 
        movi    a2, 0
+       wsr     a2, depc                # terminate user stack trace with 0
        rsr     a3, sar
        xsr     a2, icountlevel
        s32i    a3, a1, PT_SAR
@@ -301,7 +322,18 @@ _kernel_exception:
        s32i    a14, a1, PT_AREG14
        s32i    a15, a1, PT_AREG15
 
+       _bnei   a2, 1, 1f
+
+       /* Copy spill slots of a0 and a1 to imitate movsp
+        * in order to keep exception stack continuous
+        */
+       l32i    a3, a1, PT_SIZE
+       l32i    a0, a1, PT_SIZE + 4
+       s32e    a3, a1, -16
+       s32e    a0, a1, -12
 1:
+       l32i    a0, a1, PT_AREG0        # restore saved a0
+       wsr     a0, depc
 
 #ifdef KERNEL_STACK_OVERFLOW_CHECK
 
@@ -340,75 +372,88 @@ common_exception:
 
        /* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
-       rsr     a0, exccause
+       rsr     a2, exccause
        movi    a3, 0
-       rsr     a2, excsave1
-       s32i    a0, a1, PT_EXCCAUSE
-       s32i    a3, a2, EXC_TABLE_FIXUP
-
-       /* All unrecoverable states are saved on stack, now, and a1 is valid,
-        * so we can allow exceptions and interrupts (*) again.
-        * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
+       rsr     a0, excsave1
+       s32i    a2, a1, PT_EXCCAUSE
+       s32i    a3, a0, EXC_TABLE_FIXUP
+
+       /* All unrecoverable states are saved on stack, now, and a1 is valid.
+        * Now we can allow exceptions again. In case we've got an interrupt
+        * PS.INTLEVEL is set to LOCKLEVEL disabling furhter interrupts,
+        * otherwise it's left unchanged.
         *
-        * (*) We only allow interrupts if they were previously enabled and
-        *     we're not handling an IRQ
+        * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
         */
 
        rsr     a3, ps
-       addi    a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT
-       movi    a2, LOCKLEVEL
+       s32i    a3, a1, PT_PS           # save ps
+
+#if XTENSA_FAKE_NMI
+       /* Correct PS needs to be saved in the PT_PS:
+        * - in case of exception or level-1 interrupt it's in the PS,
+        *   and is already saved.
+        * - in case of medium level interrupt it's in the excsave2.
+        */
+       movi    a0, EXCCAUSE_MAPPED_NMI
+       extui   a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
+       beq     a2, a0, .Lmedium_level_irq
+       bnei    a2, EXCCAUSE_LEVEL1_INTERRUPT, .Lexception
+       beqz    a3, .Llevel1_irq        # level-1 IRQ sets ps.intlevel to 0
+
+.Lmedium_level_irq:
+       rsr     a0, excsave2
+       s32i    a0, a1, PT_PS           # save medium-level interrupt ps
+       bgei    a3, LOCKLEVEL, .Lexception
+
+.Llevel1_irq:
+       movi    a3, LOCKLEVEL
+
+.Lexception:
+       movi    a0, 1 << PS_WOE_BIT
+       or      a3, a3, a0
+#else
+       addi    a2, a2, -EXCCAUSE_LEVEL1_INTERRUPT
+       movi    a0, LOCKLEVEL
        extui   a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
                                        # a3 = PS.INTLEVEL
-       moveqz  a3, a2, a0              # a3 = LOCKLEVEL iff interrupt
+       moveqz  a3, a0, a2              # a3 = LOCKLEVEL iff interrupt
        movi    a2, 1 << PS_WOE_BIT
        or      a3, a3, a2
-       rsr     a0, exccause
-       xsr     a3, ps
+       rsr     a2, exccause
+#endif
 
-       s32i    a3, a1, PT_PS           # save ps
+       /* restore return address (or 0 if return to userspace) */
+       rsr     a0, depc
+       wsr     a3, ps
+       rsync                           # PS.WOE => rsync => overflow
 
        /* Save lbeg, lend */
 
-       rsr     a2, lbeg
+       rsr     a4, lbeg
        rsr     a3, lend
-       s32i    a2, a1, PT_LBEG
+       s32i    a4, a1, PT_LBEG
        s32i    a3, a1, PT_LEND
 
        /* Save SCOMPARE1 */
 
 #if XCHAL_HAVE_S32C1I
-       rsr     a2, scompare1
-       s32i    a2, a1, PT_SCOMPARE1
+       rsr     a3, scompare1
+       s32i    a3, a1, PT_SCOMPARE1
 #endif
 
        /* Save optional registers. */
 
-       save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
+       save_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT
        
-#ifdef CONFIG_TRACE_IRQFLAGS
-       l32i    a4, a1, PT_DEPC
-       /* Double exception means we came here with an exception
-        * while PS.EXCM was set, i.e. interrupts disabled.
-        */
-       bgeui   a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
-       l32i    a4, a1, PT_EXCCAUSE
-       bnei    a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
-       /* We came here with an interrupt means interrupts were enabled
-        * and we've just disabled them.
-        */
-       movi    a4, trace_hardirqs_off
-       callx4  a4
-1:
-#endif
-
        /* Go to second-level dispatcher. Set up parameters to pass to the
         * exception handler and call the exception handler.
         */
 
        rsr     a4, excsave1
        mov     a6, a1                  # pass stack frame
-       mov     a7, a0                  # pass EXCCAUSE
-       addx4   a4, a0, a4
+       mov     a7, a2                  # pass EXCCAUSE
+       addx4   a4, a2, a4
        l32i    a4, a4, EXC_TABLE_DEFAULT               # load handler
 
        /* Call the second-level handler */
@@ -419,8 +464,17 @@ common_exception:
        .global common_exception_return
 common_exception_return:
 
+#if XTENSA_FAKE_NMI
+       l32i    a2, a1, PT_EXCCAUSE
+       movi    a3, EXCCAUSE_MAPPED_NMI
+       beq     a2, a3, .LNMIexit
+#endif
 1:
-       rsil    a2, LOCKLEVEL
+       irq_save a2, a3
+#ifdef CONFIG_TRACE_IRQFLAGS
+       movi    a4, trace_hardirqs_off
+       callx4  a4
+#endif
 
        /* Jump if we are returning from kernel exceptions. */
 
@@ -445,6 +499,10 @@ common_exception_return:
 
        /* Call do_signal() */
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+       movi    a4, trace_hardirqs_on
+       callx4  a4
+#endif
        rsil    a2, 0
        movi    a4, do_notify_resume    # int do_notify_resume(struct pt_regs*)
        mov     a6, a1
@@ -453,6 +511,10 @@ common_exception_return:
 
 3:     /* Reschedule */
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+       movi    a4, trace_hardirqs_on
+       callx4  a4
+#endif
        rsil    a2, 0
        movi    a4, schedule    # void schedule (void)
        callx4  a4
@@ -471,6 +533,12 @@ common_exception_return:
        j       1b
 #endif
 
+#if XTENSA_FAKE_NMI
+.LNMIexit:
+       l32i    a3, a1, PT_PS
+       _bbci.l a3, PS_UM_BIT, 4f
+#endif
+
 5:
 #ifdef CONFIG_DEBUG_TLB_SANITY
        l32i    a4, a1, PT_DEPC
@@ -481,16 +549,8 @@ common_exception_return:
 6:
 4:
 #ifdef CONFIG_TRACE_IRQFLAGS
-       l32i    a4, a1, PT_DEPC
-       /* Double exception means we came here with an exception
-        * while PS.EXCM was set, i.e. interrupts disabled.
-        */
-       bgeui   a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
-       l32i    a4, a1, PT_EXCCAUSE
-       bnei    a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
-       /* We came here with an interrupt means interrupts were enabled
-        * and we'll reenable them on return.
-        */
+       extui   a4, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
+       bgei    a4, LOCKLEVEL, 1f
        movi    a4, trace_hardirqs_on
        callx4  a4
 1:
@@ -568,12 +628,13 @@ user_exception_exit:
         *       (if we have restored WSBITS-1 frames).
         */
 
+2:
 #if XCHAL_HAVE_THREADPTR
        l32i    a3, a1, PT_THREADPTR
        wur     a3, threadptr
 #endif
 
-2:     j       common_exception_exit
+       j       common_exception_exit
 
        /* This is the kernel exception exit.
         * We avoided to do a MOVSP when we entered the exception, but we
@@ -1561,6 +1622,13 @@ ENTRY(fast_second_level_miss)
        rfde
 
 9:     l32i    a0, a1, TASK_ACTIVE_MM  # unlikely case mm == 0
+       bnez    a0, 8b
+
+       /* Even more unlikely case active_mm == 0.
+        * We can get here with NMI in the middle of context_switch that
+        * touches vmalloc area.
+        */
+       movi    a0, init_mm
        j       8b
 
 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
@@ -1820,7 +1888,7 @@ ENDPROC(system_call)
        mov     a12, a0
        .endr
 #endif
-       _entry  a1, 48
+       _entry  a1, 16
 #if XCHAL_NUM_AREGS % 12 == 0
        mov     a8, a8
 #elif XCHAL_NUM_AREGS % 12 == 4
@@ -1844,7 +1912,7 @@ ENDPROC(system_call)
 
 ENTRY(_switch_to)
 
-       entry   a1, 16
+       entry   a1, 48
 
        mov     a11, a3                 # and 'next' (a3)
 
@@ -1864,10 +1932,8 @@ ENTRY(_switch_to)
 
        /* Disable ints while we manipulate the stack pointer. */
 
-       rsil    a14, LOCKLEVEL
-       rsr     a3, excsave1
+       irq_save a14, a3
        rsync
-       s32i    a3, a3, EXC_TABLE_FIXUP /* enter critical section */
 
        /* Switch CPENABLE */
 
@@ -1888,9 +1954,7 @@ ENTRY(_switch_to)
         */
 
        rsr     a3, excsave1            # exc_table
-       movi    a6, 0
        addi    a7, a5, PT_REGS_OFFSET
-       s32i    a6, a3, EXC_TABLE_FIXUP
        s32i    a7, a3, EXC_TABLE_KSTK
 
        /* restore context of the task 'next' */
index 3eee94f621ebd723195d326965cb6afc6998c85f..6df31cacc4b884c85c509a552edddcca55c0418a 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/uaccess.h>
 #include <asm/platform.h>
 
-atomic_t irq_err_count;
+DECLARE_PER_CPU(unsigned long, nmi_count);
 
 asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
 {
@@ -57,11 +57,16 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
 
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
+       unsigned cpu __maybe_unused;
 #ifdef CONFIG_SMP
        show_ipi_list(p, prec);
 #endif
-       seq_printf(p, "%*s: ", prec, "ERR");
-       seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
+#if XTENSA_FAKE_NMI
+       seq_printf(p, "%*s:", prec, "NMI");
+       for_each_online_cpu(cpu)
+               seq_printf(p, " %10lu", per_cpu(nmi_count, cpu));
+       seq_puts(p, "   Non-maskable interrupts\n");
+#endif
        return 0;
 }
 
@@ -106,6 +111,12 @@ int xtensa_irq_map(struct irq_domain *d, unsigned int irq,
                irq_set_chip_and_handler_name(irq, irq_chip,
                                handle_percpu_irq, "timer");
                irq_clear_status_flags(irq, IRQ_LEVEL);
+#ifdef XCHAL_INTTYPE_MASK_PROFILING
+       } else if (mask & XCHAL_INTTYPE_MASK_PROFILING) {
+               irq_set_chip_and_handler_name(irq, irq_chip,
+                               handle_percpu_irq, "profiling");
+               irq_set_status_flags(irq, IRQ_LEVEL);
+#endif
        } else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
                /* XCHAL_INTTYPE_MASK_NMI */
                irq_set_chip_and_handler_name(irq, irq_chip,
index e8b76b8e4b2910a17435fd971da65138b97cbfde..fb75ebf1463a1d14a46a784fae38fa6010815761 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/xtensa/kernel/pci-dma.c
- *
  * DMA coherent memory allocation.
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -9,6 +7,7 @@
  * option) any later version.
  *
  * Copyright (C) 2002 - 2005 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  *
  * Based on version for i386.
  *
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                   enum dma_data_direction dir)
+{
+       switch (dir) {
+       case DMA_BIDIRECTIONAL:
+               __flush_invalidate_dcache_range((unsigned long)vaddr, size);
+               break;
+
+       case DMA_FROM_DEVICE:
+               __invalidate_dcache_range((unsigned long)vaddr, size);
+               break;
+
+       case DMA_TO_DEVICE:
+               __flush_dcache_range((unsigned long)vaddr, size);
+               break;
+
+       case DMA_NONE:
+               BUG();
+               break;
+       }
+}
+EXPORT_SYMBOL(dma_cache_sync);
+
+static void xtensa_sync_single_for_cpu(struct device *dev,
+                                      dma_addr_t dma_handle, size_t size,
+                                      enum dma_data_direction dir)
+{
+       void *vaddr;
+
+       switch (dir) {
+       case DMA_BIDIRECTIONAL:
+       case DMA_FROM_DEVICE:
+               vaddr = bus_to_virt(dma_handle);
+               __invalidate_dcache_range((unsigned long)vaddr, size);
+               break;
+
+       case DMA_NONE:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void xtensa_sync_single_for_device(struct device *dev,
+                                         dma_addr_t dma_handle, size_t size,
+                                         enum dma_data_direction dir)
+{
+       void *vaddr;
+
+       switch (dir) {
+       case DMA_BIDIRECTIONAL:
+       case DMA_TO_DEVICE:
+               vaddr = bus_to_virt(dma_handle);
+               __flush_dcache_range((unsigned long)vaddr, size);
+               break;
+
+       case DMA_NONE:
+               BUG();
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void xtensa_sync_sg_for_cpu(struct device *dev,
+                                  struct scatterlist *sg, int nents,
+                                  enum dma_data_direction dir)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nents, i) {
+               xtensa_sync_single_for_cpu(dev, sg_dma_address(s),
+                                          sg_dma_len(s), dir);
+       }
+}
+
+static void xtensa_sync_sg_for_device(struct device *dev,
+                                     struct scatterlist *sg, int nents,
+                                     enum dma_data_direction dir)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nents, i) {
+               xtensa_sync_single_for_device(dev, sg_dma_address(s),
+                                             sg_dma_len(s), dir);
+       }
+}
+
 /*
  * Note: We assume that the full memory space is always mapped to 'kseg'
  *      Otherwise we have to use page attributes (not implemented).
  */
 
-void *
-dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
+static void *xtensa_dma_alloc(struct device *dev, size_t size,
+                             dma_addr_t *handle, gfp_t flag,
+                             struct dma_attrs *attrs)
 {
        unsigned long ret;
        unsigned long uncached = 0;
@@ -52,20 +145,15 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
        BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
               ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
 
+       uncached = ret + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
+       *handle = virt_to_bus((void *)ret);
+       __invalidate_dcache_range(ret, size);
 
-       if (ret != 0) {
-               memset((void*) ret, 0, size);
-               uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;
-               *handle = virt_to_bus((void*)ret);
-               __flush_invalidate_dcache_range(ret, size);
-       }
-
-       return (void*)uncached;
+       return (void *)uncached;
 }
-EXPORT_SYMBOL(dma_alloc_coherent);
 
-void dma_free_coherent(struct device *hwdev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle)
+static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr,
+                           dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        unsigned long addr = (unsigned long)vaddr +
                XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
@@ -75,24 +163,79 @@ void dma_free_coherent(struct device *hwdev, size_t size,
 
        free_pages(addr, get_order(size));
 }
-EXPORT_SYMBOL(dma_free_coherent);
 
+static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
+                                 unsigned long offset, size_t size,
+                                 enum dma_data_direction dir,
+                                 struct dma_attrs *attrs)
+{
+       dma_addr_t dma_handle = page_to_phys(page) + offset;
+
+       BUG_ON(PageHighMem(page));
+       xtensa_sync_single_for_device(dev, dma_handle, size, dir);
+       return dma_handle;
+}
 
-void consistent_sync(void *vaddr, size_t size, int direction)
+static void xtensa_unmap_page(struct device *dev, dma_addr_t dma_handle,
+                             size_t size, enum dma_data_direction dir,
+                             struct dma_attrs *attrs)
 {
-       switch (direction) {
-       case PCI_DMA_NONE:
-               BUG();
-       case PCI_DMA_FROMDEVICE:        /* invalidate only */
-               __invalidate_dcache_range((unsigned long)vaddr,
-                                         (unsigned long)size);
-               break;
+       xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
+}
 
-       case PCI_DMA_TODEVICE:          /* writeback only */
-       case PCI_DMA_BIDIRECTIONAL:     /* writeback and invalidate */
-               __flush_invalidate_dcache_range((unsigned long)vaddr,
-                                               (unsigned long)size);
-               break;
+static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
+                        int nents, enum dma_data_direction dir,
+                        struct dma_attrs *attrs)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nents, i) {
+               s->dma_address = xtensa_map_page(dev, sg_page(s), s->offset,
+                                                s->length, dir, attrs);
+       }
+       return nents;
+}
+
+static void xtensa_unmap_sg(struct device *dev,
+                           struct scatterlist *sg, int nents,
+                           enum dma_data_direction dir,
+                           struct dma_attrs *attrs)
+{
+       struct scatterlist *s;
+       int i;
+
+       for_each_sg(sg, s, nents, i) {
+               xtensa_unmap_page(dev, sg_dma_address(s),
+                                 sg_dma_len(s), dir, attrs);
        }
 }
-EXPORT_SYMBOL(consistent_sync);
+
+int xtensa_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       return 0;
+}
+
+struct dma_map_ops xtensa_dma_map_ops = {
+       .alloc = xtensa_dma_alloc,
+       .free = xtensa_dma_free,
+       .map_page = xtensa_map_page,
+       .unmap_page = xtensa_unmap_page,
+       .map_sg = xtensa_map_sg,
+       .unmap_sg = xtensa_unmap_sg,
+       .sync_single_for_cpu = xtensa_sync_single_for_cpu,
+       .sync_single_for_device = xtensa_sync_single_for_device,
+       .sync_sg_for_cpu = xtensa_sync_sg_for_cpu,
+       .sync_sg_for_device = xtensa_sync_sg_for_device,
+       .mapping_error = xtensa_dma_mapping_error,
+};
+EXPORT_SYMBOL(xtensa_dma_map_ops);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init xtensa_dma_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+       return 0;
+}
+fs_initcall(xtensa_dma_init);
index b848cc3dc913d8de7dc5181fc140a9f83215e6cf..d27b4dcf221f8904e34198474d396c77b1034bb6 100644 (file)
@@ -210,10 +210,6 @@ subsys_initcall(pcibios_init);
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       if (bus->parent) {
-               /* This is a subordinate bridge */
-               pci_read_bridge_bases(bus);
-       }
 }
 
 void pcibios_set_master(struct pci_dev *dev)
diff --git a/arch/xtensa/kernel/perf_event.c b/arch/xtensa/kernel/perf_event.c
new file mode 100644 (file)
index 0000000..54f0118
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Xtensa Performance Monitor Module driver
+ * See Tensilica Debug User's Guide for PMU registers documentation.
+ *
+ * Copyright (C) 2015 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+
+#include <asm/processor.h>
+#include <asm/stacktrace.h>
+
+/* Global control/status for all perf counters */
+#define XTENSA_PMU_PMG                 0x1000
+/* Perf counter values */
+#define XTENSA_PMU_PM(i)               (0x1080 + (i) * 4)
+/* Perf counter control registers */
+#define XTENSA_PMU_PMCTRL(i)           (0x1100 + (i) * 4)
+/* Perf counter status registers */
+#define XTENSA_PMU_PMSTAT(i)           (0x1180 + (i) * 4)
+
+#define XTENSA_PMU_PMG_PMEN            0x1
+
+#define XTENSA_PMU_COUNTER_MASK                0xffffffffULL
+#define XTENSA_PMU_COUNTER_MAX         0x7fffffff
+
+#define XTENSA_PMU_PMCTRL_INTEN                0x00000001
+#define XTENSA_PMU_PMCTRL_KRNLCNT      0x00000008
+#define XTENSA_PMU_PMCTRL_TRACELEVEL   0x000000f0
+#define XTENSA_PMU_PMCTRL_SELECT_SHIFT 8
+#define XTENSA_PMU_PMCTRL_SELECT       0x00001f00
+#define XTENSA_PMU_PMCTRL_MASK_SHIFT   16
+#define XTENSA_PMU_PMCTRL_MASK         0xffff0000
+
+#define XTENSA_PMU_MASK(select, mask) \
+       (((select) << XTENSA_PMU_PMCTRL_SELECT_SHIFT) | \
+        ((mask) << XTENSA_PMU_PMCTRL_MASK_SHIFT) | \
+        XTENSA_PMU_PMCTRL_TRACELEVEL | \
+        XTENSA_PMU_PMCTRL_INTEN)
+
+#define XTENSA_PMU_PMSTAT_OVFL         0x00000001
+#define XTENSA_PMU_PMSTAT_INTASRT      0x00000010
+
+struct xtensa_pmu_events {
+       /* Array of events currently on this core */
+       struct perf_event *event[XCHAL_NUM_PERF_COUNTERS];
+       /* Bitmap of used hardware counters */
+       unsigned long used_mask[BITS_TO_LONGS(XCHAL_NUM_PERF_COUNTERS)];
+};
+static DEFINE_PER_CPU(struct xtensa_pmu_events, xtensa_pmu_events);
+
+static const u32 xtensa_hw_ctl[] = {
+       [PERF_COUNT_HW_CPU_CYCLES]              = XTENSA_PMU_MASK(0, 0x1),
+       [PERF_COUNT_HW_INSTRUCTIONS]            = XTENSA_PMU_MASK(2, 0xffff),
+       [PERF_COUNT_HW_CACHE_REFERENCES]        = XTENSA_PMU_MASK(10, 0x1),
+       [PERF_COUNT_HW_CACHE_MISSES]            = XTENSA_PMU_MASK(12, 0x1),
+       /* Taken and non-taken branches + taken loop ends */
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = XTENSA_PMU_MASK(2, 0x490),
+       /* Instruction-related + other global stall cycles */
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XTENSA_PMU_MASK(4, 0x1ff),
+       /* Data-related global stall cycles */
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = XTENSA_PMU_MASK(3, 0x1ff),
+};
+
+#define C(_x) PERF_COUNT_HW_CACHE_##_x
+
+static const u32 xtensa_cache_ctl[][C(OP_MAX)][C(RESULT_MAX)] = {
+       [C(L1D)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = XTENSA_PMU_MASK(10, 0x1),
+                       [C(RESULT_MISS)]        = XTENSA_PMU_MASK(10, 0x2),
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = XTENSA_PMU_MASK(11, 0x1),
+                       [C(RESULT_MISS)]        = XTENSA_PMU_MASK(11, 0x2),
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = XTENSA_PMU_MASK(8, 0x1),
+                       [C(RESULT_MISS)]        = XTENSA_PMU_MASK(8, 0x2),
+               },
+       },
+       [C(DTLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = XTENSA_PMU_MASK(9, 0x1),
+                       [C(RESULT_MISS)]        = XTENSA_PMU_MASK(9, 0x8),
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = XTENSA_PMU_MASK(7, 0x1),
+                       [C(RESULT_MISS)]        = XTENSA_PMU_MASK(7, 0x8),
+               },
+       },
+};
+
+static int xtensa_pmu_cache_event(u64 config)
+{
+       unsigned int cache_type, cache_op, cache_result;
+       int ret;
+
+       cache_type = (config >>  0) & 0xff;
+       cache_op = (config >>  8) & 0xff;
+       cache_result = (config >> 16) & 0xff;
+
+       if (cache_type >= ARRAY_SIZE(xtensa_cache_ctl) ||
+           cache_op >= C(OP_MAX) ||
+           cache_result >= C(RESULT_MAX))
+               return -EINVAL;
+
+       ret = xtensa_cache_ctl[cache_type][cache_op][cache_result];
+
+       if (ret == 0)
+               return -EINVAL;
+
+       return ret;
+}
+
+static inline uint32_t xtensa_pmu_read_counter(int idx)
+{
+       return get_er(XTENSA_PMU_PM(idx));
+}
+
+static inline void xtensa_pmu_write_counter(int idx, uint32_t v)
+{
+       set_er(v, XTENSA_PMU_PM(idx));
+}
+
+static void xtensa_perf_event_update(struct perf_event *event,
+                                    struct hw_perf_event *hwc, int idx)
+{
+       uint64_t prev_raw_count, new_raw_count;
+       int64_t delta;
+
+       do {
+               prev_raw_count = local64_read(&hwc->prev_count);
+               new_raw_count = xtensa_pmu_read_counter(event->hw.idx);
+       } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                                new_raw_count) != prev_raw_count);
+
+       delta = (new_raw_count - prev_raw_count) & XTENSA_PMU_COUNTER_MASK;
+
+       local64_add(delta, &event->count);
+       local64_sub(delta, &hwc->period_left);
+}
+
+static bool xtensa_perf_event_set_period(struct perf_event *event,
+                                        struct hw_perf_event *hwc, int idx)
+{
+       bool rc = false;
+       s64 left;
+
+       if (!is_sampling_event(event)) {
+               left = XTENSA_PMU_COUNTER_MAX;
+       } else {
+               s64 period = hwc->sample_period;
+
+               left = local64_read(&hwc->period_left);
+               if (left <= -period) {
+                       left = period;
+                       local64_set(&hwc->period_left, left);
+                       hwc->last_period = period;
+                       rc = true;
+               } else if (left <= 0) {
+                       left += period;
+                       local64_set(&hwc->period_left, left);
+                       hwc->last_period = period;
+                       rc = true;
+               }
+               if (left > XTENSA_PMU_COUNTER_MAX)
+                       left = XTENSA_PMU_COUNTER_MAX;
+       }
+
+       local64_set(&hwc->prev_count, -left);
+       xtensa_pmu_write_counter(idx, -left);
+       perf_event_update_userpage(event);
+
+       return rc;
+}
+
+static void xtensa_pmu_enable(struct pmu *pmu)
+{
+       set_er(get_er(XTENSA_PMU_PMG) | XTENSA_PMU_PMG_PMEN, XTENSA_PMU_PMG);
+}
+
+static void xtensa_pmu_disable(struct pmu *pmu)
+{
+       set_er(get_er(XTENSA_PMU_PMG) & ~XTENSA_PMU_PMG_PMEN, XTENSA_PMU_PMG);
+}
+
+static int xtensa_pmu_event_init(struct perf_event *event)
+{
+       int ret;
+
+       switch (event->attr.type) {
+       case PERF_TYPE_HARDWARE:
+               if (event->attr.config >= ARRAY_SIZE(xtensa_hw_ctl) ||
+                   xtensa_hw_ctl[event->attr.config] == 0)
+                       return -EINVAL;
+               event->hw.config = xtensa_hw_ctl[event->attr.config];
+               return 0;
+
+       case PERF_TYPE_HW_CACHE:
+               ret = xtensa_pmu_cache_event(event->attr.config);
+               if (ret < 0)
+                       return ret;
+               event->hw.config = ret;
+               return 0;
+
+       case PERF_TYPE_RAW:
+               /* Not 'previous counter' select */
+               if ((event->attr.config & XTENSA_PMU_PMCTRL_SELECT) ==
+                   (1 << XTENSA_PMU_PMCTRL_SELECT_SHIFT))
+                       return -EINVAL;
+               event->hw.config = (event->attr.config &
+                                   (XTENSA_PMU_PMCTRL_KRNLCNT |
+                                    XTENSA_PMU_PMCTRL_TRACELEVEL |
+                                    XTENSA_PMU_PMCTRL_SELECT |
+                                    XTENSA_PMU_PMCTRL_MASK)) |
+                       XTENSA_PMU_PMCTRL_INTEN;
+               return 0;
+
+       default:
+               return -ENOENT;
+       }
+}
+
+/*
+ * Starts/Stops a counter present on the PMU. The PMI handler
+ * should stop the counter when perf_event_overflow() returns
+ * !0. ->start() will be used to continue.
+ */
+static void xtensa_pmu_start(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       if (WARN_ON_ONCE(idx == -1))
+               return;
+
+       if (flags & PERF_EF_RELOAD) {
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+               xtensa_perf_event_set_period(event, hwc, idx);
+       }
+
+       hwc->state = 0;
+
+       set_er(hwc->config, XTENSA_PMU_PMCTRL(idx));
+}
+
+static void xtensa_pmu_stop(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               set_er(0, XTENSA_PMU_PMCTRL(idx));
+               set_er(get_er(XTENSA_PMU_PMSTAT(idx)),
+                      XTENSA_PMU_PMSTAT(idx));
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       if ((flags & PERF_EF_UPDATE) &&
+           !(event->hw.state & PERF_HES_UPTODATE)) {
+               xtensa_perf_event_update(event, &event->hw, idx);
+               event->hw.state |= PERF_HES_UPTODATE;
+       }
+}
+
+/*
+ * Adds/Removes a counter to/from the PMU, can be done inside
+ * a transaction, see the ->*_txn() methods.
+ */
+static int xtensa_pmu_add(struct perf_event *event, int flags)
+{
+       struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       if (__test_and_set_bit(idx, ev->used_mask)) {
+               idx = find_first_zero_bit(ev->used_mask,
+                                         XCHAL_NUM_PERF_COUNTERS);
+               if (idx == XCHAL_NUM_PERF_COUNTERS)
+                       return -EAGAIN;
+
+               __set_bit(idx, ev->used_mask);
+               hwc->idx = idx;
+       }
+       ev->event[idx] = event;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       if (flags & PERF_EF_START)
+               xtensa_pmu_start(event, PERF_EF_RELOAD);
+
+       perf_event_update_userpage(event);
+       return 0;
+}
+
+static void xtensa_pmu_del(struct perf_event *event, int flags)
+{
+       struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
+
+       xtensa_pmu_stop(event, PERF_EF_UPDATE);
+       __clear_bit(event->hw.idx, ev->used_mask);
+       perf_event_update_userpage(event);
+}
+
+static void xtensa_pmu_read(struct perf_event *event)
+{
+       xtensa_perf_event_update(event, &event->hw, event->hw.idx);
+}
+
+static int callchain_trace(struct stackframe *frame, void *data)
+{
+       struct perf_callchain_entry *entry = data;
+
+       perf_callchain_store(entry, frame->pc);
+       return 0;
+}
+
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+                          struct pt_regs *regs)
+{
+       xtensa_backtrace_kernel(regs, PERF_MAX_STACK_DEPTH,
+                               callchain_trace, NULL, entry);
+}
+
+void perf_callchain_user(struct perf_callchain_entry *entry,
+                        struct pt_regs *regs)
+{
+       xtensa_backtrace_user(regs, PERF_MAX_STACK_DEPTH,
+                             callchain_trace, entry);
+}
+
+void perf_event_print_debug(void)
+{
+       unsigned long flags;
+       unsigned i;
+
+       local_irq_save(flags);
+       pr_info("CPU#%d: PMG: 0x%08lx\n", smp_processor_id(),
+               get_er(XTENSA_PMU_PMG));
+       for (i = 0; i < XCHAL_NUM_PERF_COUNTERS; ++i)
+               pr_info("PM%d: 0x%08lx, PMCTRL%d: 0x%08lx, PMSTAT%d: 0x%08lx\n",
+                       i, get_er(XTENSA_PMU_PM(i)),
+                       i, get_er(XTENSA_PMU_PMCTRL(i)),
+                       i, get_er(XTENSA_PMU_PMSTAT(i)));
+       local_irq_restore(flags);
+}
+
+irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id)
+{
+       irqreturn_t rc = IRQ_NONE;
+       struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
+       unsigned i;
+
+       for (i = find_first_bit(ev->used_mask, XCHAL_NUM_PERF_COUNTERS);
+            i < XCHAL_NUM_PERF_COUNTERS;
+            i = find_next_bit(ev->used_mask, XCHAL_NUM_PERF_COUNTERS, i + 1)) {
+               uint32_t v = get_er(XTENSA_PMU_PMSTAT(i));
+               struct perf_event *event = ev->event[i];
+               struct hw_perf_event *hwc = &event->hw;
+               u64 last_period;
+
+               if (!(v & XTENSA_PMU_PMSTAT_OVFL))
+                       continue;
+
+               set_er(v, XTENSA_PMU_PMSTAT(i));
+               xtensa_perf_event_update(event, hwc, i);
+               last_period = hwc->last_period;
+               if (xtensa_perf_event_set_period(event, hwc, i)) {
+                       struct perf_sample_data data;
+                       struct pt_regs *regs = get_irq_regs();
+
+                       perf_sample_data_init(&data, 0, last_period);
+                       if (perf_event_overflow(event, &data, regs))
+                               xtensa_pmu_stop(event, 0);
+               }
+
+               rc = IRQ_HANDLED;
+       }
+       return rc;
+}
+
+static struct pmu xtensa_pmu = {
+       .pmu_enable = xtensa_pmu_enable,
+       .pmu_disable = xtensa_pmu_disable,
+       .event_init = xtensa_pmu_event_init,
+       .add = xtensa_pmu_add,
+       .del = xtensa_pmu_del,
+       .start = xtensa_pmu_start,
+       .stop = xtensa_pmu_stop,
+       .read = xtensa_pmu_read,
+};
+
+static void xtensa_pmu_setup(void)
+{
+       unsigned i;
+
+       set_er(0, XTENSA_PMU_PMG);
+       for (i = 0; i < XCHAL_NUM_PERF_COUNTERS; ++i) {
+               set_er(0, XTENSA_PMU_PMCTRL(i));
+               set_er(get_er(XTENSA_PMU_PMSTAT(i)), XTENSA_PMU_PMSTAT(i));
+       }
+}
+
+static int xtensa_pmu_notifier(struct notifier_block *self,
+                              unsigned long action, void *data)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               xtensa_pmu_setup();
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static int __init xtensa_pmu_init(void)
+{
+       int ret;
+       int irq = irq_create_mapping(NULL, XCHAL_PROFILING_INTERRUPT);
+
+       perf_cpu_notifier(xtensa_pmu_notifier);
+#if XTENSA_FAKE_NMI
+       enable_irq(irq);
+#else
+       ret = request_irq(irq, xtensa_pmu_irq_handler, IRQF_PERCPU,
+                         "pmu", NULL);
+       if (ret < 0)
+               return ret;
+#endif
+
+       ret = perf_pmu_register(&xtensa_pmu, "cpu", PERF_TYPE_RAW);
+       if (ret)
+               free_irq(irq, NULL);
+
+       return ret;
+}
+early_initcall(xtensa_pmu_init);
index 7d2c317bd98b30eb2a82e2770d0ff236de66fe03..7538d802b65abbc88f2e3769ff77e117282470c7 100644 (file)
@@ -1,11 +1,12 @@
 /*
- * arch/xtensa/kernel/stacktrace.c
+ * Kernel and userspace stack tracing.
  *
  * 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 - 2013 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  */
 #include <linux/export.h>
 #include <linux/sched.h>
 
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
+#include <asm/uaccess.h>
+
+#if IS_ENABLED(CONFIG_OPROFILE) || IS_ENABLED(CONFIG_PERF_EVENTS)
+
+/* Address of common_exception_return, used to check the
+ * transition from kernel to user space.
+ */
+extern int common_exception_return;
+
+/* A struct that maps to the part of the frame containing the a0 and
+ * a1 registers.
+ */
+struct frame_start {
+       unsigned long a0;
+       unsigned long a1;
+};
+
+void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
+                          int (*ufn)(struct stackframe *frame, void *data),
+                          void *data)
+{
+       unsigned long windowstart = regs->windowstart;
+       unsigned long windowbase = regs->windowbase;
+       unsigned long a0 = regs->areg[0];
+       unsigned long a1 = regs->areg[1];
+       unsigned long pc = regs->pc;
+       struct stackframe frame;
+       int index;
+
+       if (!depth--)
+               return;
+
+       frame.pc = pc;
+       frame.sp = a1;
+
+       if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
+               return;
+
+       /* Two steps:
+        *
+        * 1. Look through the register window for the
+        * previous PCs in the call trace.
+        *
+        * 2. Look on the stack.
+        */
+
+       /* Step 1.  */
+       /* Rotate WINDOWSTART to move the bit corresponding to
+        * the current window to the bit #0.
+        */
+       windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
+
+       /* Look for bits that are set, they correspond to
+        * valid windows.
+        */
+       for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
+               if (windowstart & (1 << index)) {
+                       /* Get the PC from a0 and a1. */
+                       pc = MAKE_PC_FROM_RA(a0, pc);
+                       /* Read a0 and a1 from the
+                        * corresponding position in AREGs.
+                        */
+                       a0 = regs->areg[index * 4];
+                       a1 = regs->areg[index * 4 + 1];
+
+                       frame.pc = pc;
+                       frame.sp = a1;
+
+                       if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
+                               return;
+               }
+
+       /* Step 2. */
+       /* We are done with the register window, we need to
+        * look through the stack.
+        */
+       if (!depth)
+               return;
+
+       /* Start from the a1 register. */
+       /* a1 = regs->areg[1]; */
+       while (a0 != 0 && depth--) {
+               struct frame_start frame_start;
+               /* Get the location for a1, a0 for the
+                * previous frame from the current a1.
+                */
+               unsigned long *psp = (unsigned long *)a1;
+
+               psp -= 4;
+
+               /* Check if the region is OK to access. */
+               if (!access_ok(VERIFY_READ, psp, sizeof(frame_start)))
+                       return;
+               /* Copy a1, a0 from user space stack frame. */
+               if (__copy_from_user_inatomic(&frame_start, psp,
+                                             sizeof(frame_start)))
+                       return;
+
+               pc = MAKE_PC_FROM_RA(a0, pc);
+               a0 = frame_start.a0;
+               a1 = frame_start.a1;
+
+               frame.pc = pc;
+               frame.sp = a1;
+
+               if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
+                       return;
+       }
+}
+EXPORT_SYMBOL(xtensa_backtrace_user);
+
+void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
+                            int (*kfn)(struct stackframe *frame, void *data),
+                            int (*ufn)(struct stackframe *frame, void *data),
+                            void *data)
+{
+       unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
+               regs->depc : regs->pc;
+       unsigned long sp_start, sp_end;
+       unsigned long a0 = regs->areg[0];
+       unsigned long a1 = regs->areg[1];
+
+       sp_start = a1 & ~(THREAD_SIZE - 1);
+       sp_end = sp_start + THREAD_SIZE;
+
+       /* Spill the register window to the stack first. */
+       spill_registers();
+
+       /* Read the stack frames one by one and create the PC
+        * from the a0 and a1 registers saved there.
+        */
+       while (a1 > sp_start && a1 < sp_end && depth--) {
+               struct stackframe frame;
+               unsigned long *psp = (unsigned long *)a1;
+
+               frame.pc = pc;
+               frame.sp = a1;
+
+               if (kernel_text_address(pc) && kfn(&frame, data))
+                       return;
+
+               if (pc == (unsigned long)&common_exception_return) {
+                       regs = (struct pt_regs *)a1;
+                       if (user_mode(regs)) {
+                               if (ufn == NULL)
+                                       return;
+                               xtensa_backtrace_user(regs, depth, ufn, data);
+                               return;
+                       }
+                       a0 = regs->areg[0];
+                       a1 = regs->areg[1];
+                       continue;
+               }
+
+               sp_start = a1;
+
+               pc = MAKE_PC_FROM_RA(a0, pc);
+               a0 = *(psp - 4);
+               a1 = *(psp - 3);
+       }
+}
+EXPORT_SYMBOL(xtensa_backtrace_kernel);
+
+#endif
 
 void walk_stackframe(unsigned long *sp,
                int (*fn)(struct stackframe *frame, void *data),
index 9d2f45f010ef7e9448e3837e873b617f0a493b23..42d441f7898b94db35e3a2cd55af500f23f6435a 100644 (file)
@@ -62,6 +62,7 @@ extern void fast_coprocessor(void);
 
 extern void do_illegal_instruction (struct pt_regs*);
 extern void do_interrupt (struct pt_regs*);
+extern void do_nmi(struct pt_regs *);
 extern void do_unaligned_user (struct pt_regs*);
 extern void do_multihit (struct pt_regs*, unsigned long);
 extern void do_page_fault (struct pt_regs*, unsigned long);
@@ -146,6 +147,9 @@ COPROCESSOR(6),
 #if XTENSA_HAVE_COPROCESSOR(7)
 COPROCESSOR(7),
 #endif
+#if XTENSA_FAKE_NMI
+{ EXCCAUSE_MAPPED_NMI,                 0,              do_nmi },
+#endif
 { EXCCAUSE_MAPPED_DEBUG,               0,              do_debug },
 { -1, -1, 0 }
 
@@ -199,6 +203,28 @@ void do_multihit(struct pt_regs *regs, unsigned long exccause)
 
 extern void do_IRQ(int, struct pt_regs *);
 
+#if XTENSA_FAKE_NMI
+
+irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id);
+
+DEFINE_PER_CPU(unsigned long, nmi_count);
+
+void do_nmi(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs;
+
+       if ((regs->ps & PS_INTLEVEL_MASK) < LOCKLEVEL)
+               trace_hardirqs_off();
+
+       old_regs = set_irq_regs(regs);
+       nmi_enter();
+       ++*this_cpu_ptr(&nmi_count);
+       xtensa_pmu_irq_handler(0, NULL);
+       nmi_exit();
+       set_irq_regs(old_regs);
+}
+#endif
+
 void do_interrupt(struct pt_regs *regs)
 {
        static const unsigned int_level_mask[] = {
@@ -211,8 +237,11 @@ void do_interrupt(struct pt_regs *regs)
                XCHAL_INTLEVEL6_MASK,
                XCHAL_INTLEVEL7_MASK,
        };
-       struct pt_regs *old_regs = set_irq_regs(regs);
+       struct pt_regs *old_regs;
+
+       trace_hardirqs_off();
 
+       old_regs = set_irq_regs(regs);
        irq_enter();
 
        for (;;) {
index 1b397a902292f8224f27856f6ff14471fad1e6ff..abcdb527f18aa654115a4c4d5d5ce1cddd67e8cc 100644 (file)
@@ -627,7 +627,11 @@ ENTRY(_Level\level\()InterruptVector)
        wsr     a0, excsave2
        rsr     a0, epc\level
        wsr     a0, epc1
+       .if     \level <= LOCKLEVEL
        movi    a0, EXCCAUSE_LEVEL1_INTERRUPT
+       .else
+       movi    a0, EXCCAUSE_MAPPED_NMI
+       .endif
        wsr     a0, exccause
        rsr     a0, eps\level
                                        # branch to user or kernel vector
@@ -682,11 +686,13 @@ ENDPROC(_WindowOverflow4)
        .align 4
 _SimulateUserKernelVectorException:
        addi    a0, a0, (1 << PS_EXCM_BIT)
+#if !XTENSA_FAKE_NMI
        wsr     a0, ps
+#endif
        bbsi.l  a0, PS_UM_BIT, 1f       # branch if user mode
-       rsr     a0, excsave2            # restore a0
+       xsr     a0, excsave2            # restore a0
        j       _KernelExceptionVector  # simulate kernel vector exception
-1:     rsr     a0, excsave2            # restore a0
+1:     xsr     a0, excsave2            # restore a0
        j       _UserExceptionVector    # simulate user vector exception
 #endif
 
index 83a44a33cfa11221f99ba5f8d836e02a0c4c9f92..c9784c1b18d8c6223afe359e4e4405b430b91780 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/hardirq.h>
+#include <linux/perf_event.h>
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
@@ -142,6 +143,12 @@ good_area:
        }
 
        up_read(&mm->mmap_sem);
+       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
+       if (flags & VM_FAULT_MAJOR)
+               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
+       else if (flags & VM_FAULT_MINOR)
+               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
+
        return;
 
        /* Something tried to access memory that isn't in our memory map..
index 5f03a593d84f9000d6db447f599f40af7048af42..8f952034e161b03ab806555ac36b06f8f4c74f76 100644 (file)
  * @file backtrace.c
  *
  * @remark Copyright 2008 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  * @remark Read the file COPYING
  *
  */
 
 #include <linux/oprofile.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
+#include <asm/stacktrace.h>
 
-/* Address of common_exception_return, used to check the
- * transition from kernel to user space.
- */
-extern int common_exception_return;
-
-/* A struct that maps to the part of the frame containing the a0 and
- * a1 registers.
- */
-struct frame_start {
-       unsigned long a0;
-       unsigned long a1;
-};
-
-static void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth)
-{
-       unsigned long windowstart = regs->windowstart;
-       unsigned long windowbase = regs->windowbase;
-       unsigned long a0 = regs->areg[0];
-       unsigned long a1 = regs->areg[1];
-       unsigned long pc = MAKE_PC_FROM_RA(a0, regs->pc);
-       int index;
-
-       /* First add the current PC to the trace. */
-       if (pc != 0 && pc <= TASK_SIZE)
-               oprofile_add_trace(pc);
-       else
-               return;
-
-       /* Two steps:
-        *
-        * 1. Look through the register window for the
-        * previous PCs in the call trace.
-        *
-        * 2. Look on the stack.
-        */
-
-       /* Step 1.  */
-       /* Rotate WINDOWSTART to move the bit corresponding to
-        * the current window to the bit #0.
-        */
-       windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
-
-       /* Look for bits that are set, they correspond to
-        * valid windows.
-        */
-       for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
-               if (windowstart & (1 << index)) {
-                       /* Read a0 and a1 from the
-                        * corresponding position in AREGs.
-                        */
-                       a0 = regs->areg[index * 4];
-                       a1 = regs->areg[index * 4 + 1];
-                       /* Get the PC from a0 and a1. */
-                       pc = MAKE_PC_FROM_RA(a0, pc);
-
-                       /* Add the PC to the trace. */
-                       if (pc != 0 && pc <= TASK_SIZE)
-                               oprofile_add_trace(pc);
-                       else
-                               return;
-               }
-
-       /* Step 2. */
-       /* We are done with the register window, we need to
-        * look through the stack.
-        */
-       if (depth > 0) {
-               /* Start from the a1 register. */
-               /* a1 = regs->areg[1]; */
-               while (a0 != 0 && depth--) {
-
-                       struct frame_start frame_start;
-                       /* Get the location for a1, a0 for the
-                        * previous frame from the current a1.
-                        */
-                       unsigned long *psp = (unsigned long *)a1;
-                       psp -= 4;
-
-                       /* Check if the region is OK to access. */
-                       if (!access_ok(VERIFY_READ, psp, sizeof(frame_start)))
-                               return;
-                       /* Copy a1, a0 from user space stack frame. */
-                       if (__copy_from_user_inatomic(&frame_start, psp,
-                                               sizeof(frame_start)))
-                               return;
-
-                       a0 = frame_start.a0;
-                       a1 = frame_start.a1;
-                       pc = MAKE_PC_FROM_RA(a0, pc);
-
-                       if (pc != 0 && pc <= TASK_SIZE)
-                               oprofile_add_trace(pc);
-                       else
-                               return;
-               }
-       }
-}
-
-static void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth)
+static int xtensa_backtrace_cb(struct stackframe *frame, void *data)
 {
-       unsigned long pc = regs->pc;
-       unsigned long *psp;
-       unsigned long sp_start, sp_end;
-       unsigned long a0 = regs->areg[0];
-       unsigned long a1 = regs->areg[1];
-
-       sp_start = a1 & ~(THREAD_SIZE-1);
-       sp_end = sp_start + THREAD_SIZE;
-
-       /* Spill the register window to the stack first. */
-       spill_registers();
-
-       /* Read the stack frames one by one and create the PC
-        * from the a0 and a1 registers saved there.
-        */
-       while (a1 > sp_start && a1 < sp_end && depth--) {
-               pc = MAKE_PC_FROM_RA(a0, pc);
-
-               /* Add the PC to the trace. */
-               oprofile_add_trace(pc);
-               if (pc == (unsigned long) &common_exception_return) {
-                       regs = (struct pt_regs *)a1;
-                       if (user_mode(regs)) {
-                               pc = regs->pc;
-                               if (pc != 0 && pc <= TASK_SIZE)
-                                       oprofile_add_trace(pc);
-                               else
-                                       return;
-                               return xtensa_backtrace_user(regs, depth);
-                       }
-                       a0 = regs->areg[0];
-                       a1 = regs->areg[1];
-                       continue;
-               }
-
-               psp = (unsigned long *)a1;
-
-               a0 = *(psp - 4);
-               a1 = *(psp - 3);
-
-               if (a1 <= (unsigned long)psp)
-                       return;
-
-       }
-       return;
+       oprofile_add_trace(frame->pc);
+       return 0;
 }
 
 void xtensa_backtrace(struct pt_regs * const regs, unsigned int depth)
 {
        if (user_mode(regs))
-               xtensa_backtrace_user(regs, depth);
+               xtensa_backtrace_user(regs, depth, xtensa_backtrace_cb, NULL);
        else
-               xtensa_backtrace_kernel(regs, depth);
+               xtensa_backtrace_kernel(regs, depth, xtensa_backtrace_cb,
+                                       xtensa_backtrace_cb, NULL);
 }
index 8ab021b1f14128d49948de51f685a78fd7180fa2..976a3859453707b5d2acaa1e7f80b0e81a16a74e 100644 (file)
@@ -105,13 +105,17 @@ static char *split_if_spec(char *str, ...)
 
        va_start(ap, str);
        while ((arg = va_arg(ap, char**)) != NULL) {
-               if (*str == '\0')
+               if (*str == '\0') {
+                       va_end(ap);
                        return NULL;
+               }
                end = strchr(str, ',');
                if (end != str)
                        *arg = str;
-               if (end == NULL)
+               if (end == NULL) {
+                       va_end(ap);
                        return NULL;
+               }
                *end++ = '\0';
                str = end;
        }
index 12600bfffca93f4547e2325eeda9669ff443a7a7..e0057d035200c4dd5e42d191f0395a7769489905 100644 (file)
@@ -241,8 +241,8 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  * Description:
  *    Enables a low level driver to set a hard upper limit,
  *    max_hw_sectors, on the size of requests.  max_hw_sectors is set by
- *    the device driver based upon the combined capabilities of I/O
- *    controller and storage device.
+ *    the device driver based upon the capabilities of the I/O
+ *    controller.
  *
  *    max_sectors is a soft limit imposed by the block layer for
  *    filesystem type requests.  This value can be overridden on a
index b4cfc5754033b9ddfa17d8ad395baf0e751891bd..b582ea7f78d3f4dd71d8effef93d5db0d3f8cf92 100644 (file)
@@ -48,6 +48,8 @@ config CRYPTO_AEAD
 config CRYPTO_AEAD2
        tristate
        select CRYPTO_ALGAPI2
+       select CRYPTO_NULL2
+       select CRYPTO_RNG2
 
 config CRYPTO_BLKCIPHER
        tristate
@@ -150,12 +152,16 @@ config CRYPTO_GF128MUL
 
 config CRYPTO_NULL
        tristate "Null algorithms"
-       select CRYPTO_ALGAPI
-       select CRYPTO_BLKCIPHER
-       select CRYPTO_HASH
+       select CRYPTO_NULL2
        help
          These are 'Null' algorithms, used by IPsec, which do nothing.
 
+config CRYPTO_NULL2
+       tristate
+       select CRYPTO_ALGAPI2
+       select CRYPTO_BLKCIPHER2
+       select CRYPTO_HASH2
+
 config CRYPTO_PCRYPT
        tristate "Parallel crypto engine"
        depends on SMP
@@ -200,6 +206,7 @@ config CRYPTO_AUTHENC
        select CRYPTO_BLKCIPHER
        select CRYPTO_MANAGER
        select CRYPTO_HASH
+       select CRYPTO_NULL
        help
          Authenc: Combined mode wrapper for IPsec.
          This is required for IPSec.
@@ -470,6 +477,18 @@ config CRYPTO_POLY1305
          It is used for the ChaCha20-Poly1305 AEAD, specified in RFC7539 for use
          in IETF protocols. This is the portable C implementation of Poly1305.
 
+config CRYPTO_POLY1305_X86_64
+       tristate "Poly1305 authenticator algorithm (x86_64/SSE2/AVX2)"
+       depends on X86 && 64BIT
+       select CRYPTO_POLY1305
+       help
+         Poly1305 authenticator algorithm, RFC7539.
+
+         Poly1305 is an authenticator algorithm designed by Daniel J. Bernstein.
+         It is used for the ChaCha20-Poly1305 AEAD, specified in RFC7539 for use
+         in IETF protocols. This is the x86_64 assembler implementation using SIMD
+         instructions.
+
 config CRYPTO_MD4
        tristate "MD4 digest algorithm"
        select CRYPTO_HASH
@@ -1213,6 +1232,21 @@ config CRYPTO_CHACHA20
          See also:
          <http://cr.yp.to/chacha/chacha-20080128.pdf>
 
+config CRYPTO_CHACHA20_X86_64
+       tristate "ChaCha20 cipher algorithm (x86_64/SSSE3/AVX2)"
+       depends on X86 && 64BIT
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_CHACHA20
+       help
+         ChaCha20 cipher algorithm, RFC7539.
+
+         ChaCha20 is a 256-bit high-speed stream cipher designed by Daniel J.
+         Bernstein and further specified in RFC7539 for use in IETF protocols.
+         This is the x86_64 assembler implementation using SIMD instructions.
+
+         See also:
+         <http://cr.yp.to/chacha/chacha-20080128.pdf>
+
 config CRYPTO_SEED
        tristate "SEED cipher algorithm"
        select CRYPTO_ALGAPI
index a16a7e7f2d607cf4a89af86b60c22905c268fd6f..e2c59819b236f61303f87989193e26517d5ad3a9 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_CRYPTO_AEAD2) += aead.o
 
 crypto_blkcipher-y := ablkcipher.o
 crypto_blkcipher-y += blkcipher.o
+crypto_blkcipher-y += skcipher.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER2) += crypto_blkcipher.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER2) += chainiv.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER2) += eseqiv.o
@@ -46,7 +47,7 @@ obj-$(CONFIG_CRYPTO_CMAC) += cmac.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
 obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
 obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
-obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
+obj-$(CONFIG_CRYPTO_NULL2) += crypto_null.o
 obj-$(CONFIG_CRYPTO_MD4) += md4.o
 obj-$(CONFIG_CRYPTO_MD5) += md5.o
 obj-$(CONFIG_CRYPTO_RMD128) += rmd128.o
index 07bf99773548bf9f088b6ff8380edb4caf7cda4a..9b18a1e40d6af896be358c72113cbddb78c7acaa 100644 (file)
@@ -3,7 +3,7 @@
  *
  * This file provides API support for AEAD algorithms.
  *
- * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
  *
  * 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
  */
 
 #include <crypto/internal/geniv.h>
+#include <crypto/internal/rng.h>
+#include <crypto/null.h>
 #include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/rtnetlink.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/cryptouser.h>
 
 #include "internal.h"
 
-struct compat_request_ctx {
-       struct scatterlist src[2];
-       struct scatterlist dst[2];
-       struct scatterlist ivbuf[2];
-       struct scatterlist *ivsg;
-       struct aead_givcrypt_request subreq;
-};
-
-static int aead_null_givencrypt(struct aead_givcrypt_request *req);
-static int aead_null_givdecrypt(struct aead_givcrypt_request *req);
-
 static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
                            unsigned int keylen)
 {
@@ -53,7 +43,7 @@ static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
 
        alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
        memcpy(alignbuffer, key, keylen);
-       ret = tfm->setkey(tfm, alignbuffer, keylen);
+       ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen);
        memset(alignbuffer, 0, keylen);
        kfree(buffer);
        return ret;
@@ -64,12 +54,10 @@ int crypto_aead_setkey(struct crypto_aead *tfm,
 {
        unsigned long alignmask = crypto_aead_alignmask(tfm);
 
-       tfm = tfm->child;
-
        if ((unsigned long)key & alignmask)
                return setkey_unaligned(tfm, key, keylen);
 
-       return tfm->setkey(tfm, key, keylen);
+       return crypto_aead_alg(tfm)->setkey(tfm, key, keylen);
 }
 EXPORT_SYMBOL_GPL(crypto_aead_setkey);
 
@@ -80,100 +68,17 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
        if (authsize > crypto_aead_maxauthsize(tfm))
                return -EINVAL;
 
-       if (tfm->setauthsize) {
-               err = tfm->setauthsize(tfm->child, authsize);
+       if (crypto_aead_alg(tfm)->setauthsize) {
+               err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize);
                if (err)
                        return err;
        }
 
-       tfm->child->authsize = authsize;
        tfm->authsize = authsize;
        return 0;
 }
 EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
 
-struct aead_old_request {
-       struct scatterlist srcbuf[2];
-       struct scatterlist dstbuf[2];
-       struct aead_request subreq;
-};
-
-unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
-{
-       return tfm->reqsize + sizeof(struct aead_old_request);
-}
-EXPORT_SYMBOL_GPL(crypto_aead_reqsize);
-
-static int old_crypt(struct aead_request *req,
-                    int (*crypt)(struct aead_request *req))
-{
-       struct aead_old_request *nreq = aead_request_ctx(req);
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct scatterlist *src, *dst;
-
-       if (req->old)
-               return crypt(req);
-
-       src = scatterwalk_ffwd(nreq->srcbuf, req->src, req->assoclen);
-       dst = req->src == req->dst ?
-             src : scatterwalk_ffwd(nreq->dstbuf, req->dst, req->assoclen);
-
-       aead_request_set_tfm(&nreq->subreq, aead);
-       aead_request_set_callback(&nreq->subreq, aead_request_flags(req),
-                                 req->base.complete, req->base.data);
-       aead_request_set_crypt(&nreq->subreq, src, dst, req->cryptlen,
-                              req->iv);
-       aead_request_set_assoc(&nreq->subreq, req->src, req->assoclen);
-
-       return crypt(&nreq->subreq);
-}
-
-static int old_encrypt(struct aead_request *req)
-{
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct old_aead_alg *alg = crypto_old_aead_alg(aead);
-
-       return old_crypt(req, alg->encrypt);
-}
-
-static int old_decrypt(struct aead_request *req)
-{
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct old_aead_alg *alg = crypto_old_aead_alg(aead);
-
-       return old_crypt(req, alg->decrypt);
-}
-
-static int no_givcrypt(struct aead_givcrypt_request *req)
-{
-       return -ENOSYS;
-}
-
-static int crypto_old_aead_init_tfm(struct crypto_tfm *tfm)
-{
-       struct old_aead_alg *alg = &tfm->__crt_alg->cra_aead;
-       struct crypto_aead *crt = __crypto_aead_cast(tfm);
-
-       if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
-               return -EINVAL;
-
-       crt->setkey = alg->setkey;
-       crt->setauthsize = alg->setauthsize;
-       crt->encrypt = old_encrypt;
-       crt->decrypt = old_decrypt;
-       if (alg->ivsize) {
-               crt->givencrypt = alg->givencrypt ?: no_givcrypt;
-               crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
-       } else {
-               crt->givencrypt = aead_null_givencrypt;
-               crt->givdecrypt = aead_null_givdecrypt;
-       }
-       crt->child = __crypto_aead_cast(tfm);
-       crt->authsize = alg->maxauthsize;
-
-       return 0;
-}
-
 static void crypto_aead_exit_tfm(struct crypto_tfm *tfm)
 {
        struct crypto_aead *aead = __crypto_aead_cast(tfm);
@@ -187,14 +92,6 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
        struct crypto_aead *aead = __crypto_aead_cast(tfm);
        struct aead_alg *alg = crypto_aead_alg(aead);
 
-       if (crypto_old_aead_alg(aead)->encrypt)
-               return crypto_old_aead_init_tfm(tfm);
-
-       aead->setkey = alg->setkey;
-       aead->setauthsize = alg->setauthsize;
-       aead->encrypt = alg->encrypt;
-       aead->decrypt = alg->decrypt;
-       aead->child = __crypto_aead_cast(tfm);
        aead->authsize = alg->maxauthsize;
 
        if (alg->exit)
@@ -206,64 +103,6 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
        return 0;
 }
 
-#ifdef CONFIG_NET
-static int crypto_old_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
-{
-       struct crypto_report_aead raead;
-       struct old_aead_alg *aead = &alg->cra_aead;
-
-       strncpy(raead.type, "aead", sizeof(raead.type));
-       strncpy(raead.geniv, aead->geniv ?: "<built-in>", sizeof(raead.geniv));
-
-       raead.blocksize = alg->cra_blocksize;
-       raead.maxauthsize = aead->maxauthsize;
-       raead.ivsize = aead->ivsize;
-
-       if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
-                   sizeof(struct crypto_report_aead), &raead))
-               goto nla_put_failure;
-       return 0;
-
-nla_put_failure:
-       return -EMSGSIZE;
-}
-#else
-static int crypto_old_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
-{
-       return -ENOSYS;
-}
-#endif
-
-static void crypto_old_aead_show(struct seq_file *m, struct crypto_alg *alg)
-       __attribute__ ((unused));
-static void crypto_old_aead_show(struct seq_file *m, struct crypto_alg *alg)
-{
-       struct old_aead_alg *aead = &alg->cra_aead;
-
-       seq_printf(m, "type         : aead\n");
-       seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
-                                            "yes" : "no");
-       seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-       seq_printf(m, "ivsize       : %u\n", aead->ivsize);
-       seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
-       seq_printf(m, "geniv        : %s\n", aead->geniv ?: "<built-in>");
-}
-
-const struct crypto_type crypto_aead_type = {
-       .extsize = crypto_alg_extsize,
-       .init_tfm = crypto_aead_init_tfm,
-#ifdef CONFIG_PROC_FS
-       .show = crypto_old_aead_show,
-#endif
-       .report = crypto_old_aead_report,
-       .lookup = crypto_lookup_aead,
-       .maskclear = ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV),
-       .maskset = CRYPTO_ALG_TYPE_MASK,
-       .type = CRYPTO_ALG_TYPE_AEAD,
-       .tfmsize = offsetof(struct crypto_aead, base),
-};
-EXPORT_SYMBOL_GPL(crypto_aead_type);
-
 #ifdef CONFIG_NET
 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
@@ -307,93 +146,31 @@ static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
        seq_printf(m, "geniv        : <none>\n");
 }
 
-static const struct crypto_type crypto_new_aead_type = {
-       .extsize = crypto_alg_extsize,
-       .init_tfm = crypto_aead_init_tfm,
-#ifdef CONFIG_PROC_FS
-       .show = crypto_aead_show,
-#endif
-       .report = crypto_aead_report,
-       .maskclear = ~CRYPTO_ALG_TYPE_MASK,
-       .maskset = CRYPTO_ALG_TYPE_MASK,
-       .type = CRYPTO_ALG_TYPE_AEAD,
-       .tfmsize = offsetof(struct crypto_aead, base),
-};
-
-static int aead_null_givencrypt(struct aead_givcrypt_request *req)
-{
-       return crypto_aead_encrypt(&req->areq);
-}
-
-static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
-{
-       return crypto_aead_decrypt(&req->areq);
-}
-
-#ifdef CONFIG_NET
-static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
-{
-       struct crypto_report_aead raead;
-       struct old_aead_alg *aead = &alg->cra_aead;
-
-       strncpy(raead.type, "nivaead", sizeof(raead.type));
-       strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv));
-
-       raead.blocksize = alg->cra_blocksize;
-       raead.maxauthsize = aead->maxauthsize;
-       raead.ivsize = aead->ivsize;
-
-       if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
-                   sizeof(struct crypto_report_aead), &raead))
-               goto nla_put_failure;
-       return 0;
-
-nla_put_failure:
-       return -EMSGSIZE;
-}
-#else
-static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+static void crypto_aead_free_instance(struct crypto_instance *inst)
 {
-       return -ENOSYS;
-}
-#endif
-
+       struct aead_instance *aead = aead_instance(inst);
 
-static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
-       __attribute__ ((unused));
-static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
-{
-       struct old_aead_alg *aead = &alg->cra_aead;
+       if (!aead->free) {
+               inst->tmpl->free(inst);
+               return;
+       }
 
-       seq_printf(m, "type         : nivaead\n");
-       seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
-                                            "yes" : "no");
-       seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-       seq_printf(m, "ivsize       : %u\n", aead->ivsize);
-       seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
-       seq_printf(m, "geniv        : %s\n", aead->geniv);
+       aead->free(aead);
 }
 
-const struct crypto_type crypto_nivaead_type = {
+static const struct crypto_type crypto_aead_type = {
        .extsize = crypto_alg_extsize,
        .init_tfm = crypto_aead_init_tfm,
+       .free = crypto_aead_free_instance,
 #ifdef CONFIG_PROC_FS
-       .show = crypto_nivaead_show,
+       .show = crypto_aead_show,
 #endif
-       .report = crypto_nivaead_report,
-       .maskclear = ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV),
-       .maskset = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV,
+       .report = crypto_aead_report,
+       .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+       .maskset = CRYPTO_ALG_TYPE_MASK,
        .type = CRYPTO_ALG_TYPE_AEAD,
        .tfmsize = offsetof(struct crypto_aead, base),
 };
-EXPORT_SYMBOL_GPL(crypto_nivaead_type);
-
-static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
-                              const char *name, u32 type, u32 mask)
-{
-       spawn->base.frontend = &crypto_nivaead_type;
-       return crypto_grab_spawn(&spawn->base, name, type, mask);
-}
 
 static int aead_geniv_setkey(struct crypto_aead *tfm,
                             const u8 *key, unsigned int keylen)
@@ -411,169 +188,6 @@ static int aead_geniv_setauthsize(struct crypto_aead *tfm,
        return crypto_aead_setauthsize(ctx->child, authsize);
 }
 
-static void compat_encrypt_complete2(struct aead_request *req, int err)
-{
-       struct compat_request_ctx *rctx = aead_request_ctx(req);
-       struct aead_givcrypt_request *subreq = &rctx->subreq;
-       struct crypto_aead *geniv;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       if (err)
-               goto out;
-
-       geniv = crypto_aead_reqtfm(req);
-       scatterwalk_map_and_copy(subreq->giv, rctx->ivsg, 0,
-                                crypto_aead_ivsize(geniv), 1);
-
-out:
-       kzfree(subreq->giv);
-}
-
-static void compat_encrypt_complete(struct crypto_async_request *base, int err)
-{
-       struct aead_request *req = base->data;
-
-       compat_encrypt_complete2(req, err);
-       aead_request_complete(req, err);
-}
-
-static int compat_encrypt(struct aead_request *req)
-{
-       struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
-       struct compat_request_ctx *rctx = aead_request_ctx(req);
-       struct aead_givcrypt_request *subreq = &rctx->subreq;
-       unsigned int ivsize = crypto_aead_ivsize(geniv);
-       struct scatterlist *src, *dst;
-       crypto_completion_t compl;
-       void *data;
-       u8 *info;
-       __be64 seq;
-       int err;
-
-       if (req->cryptlen < ivsize)
-               return -EINVAL;
-
-       compl = req->base.complete;
-       data = req->base.data;
-
-       rctx->ivsg = scatterwalk_ffwd(rctx->ivbuf, req->dst, req->assoclen);
-       info = PageHighMem(sg_page(rctx->ivsg)) ? NULL : sg_virt(rctx->ivsg);
-
-       if (!info) {
-               info = kmalloc(ivsize, req->base.flags &
-                                      CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
-                                                                 GFP_ATOMIC);
-               if (!info)
-                       return -ENOMEM;
-
-               compl = compat_encrypt_complete;
-               data = req;
-       }
-
-       memcpy(&seq, req->iv + ivsize - sizeof(seq), sizeof(seq));
-
-       src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen + ivsize);
-       dst = req->src == req->dst ?
-             src : scatterwalk_ffwd(rctx->dst, rctx->ivsg, ivsize);
-
-       aead_givcrypt_set_tfm(subreq, ctx->child);
-       aead_givcrypt_set_callback(subreq, req->base.flags,
-                                  req->base.complete, req->base.data);
-       aead_givcrypt_set_crypt(subreq, src, dst,
-                               req->cryptlen - ivsize, req->iv);
-       aead_givcrypt_set_assoc(subreq, req->src, req->assoclen);
-       aead_givcrypt_set_giv(subreq, info, be64_to_cpu(seq));
-
-       err = crypto_aead_givencrypt(subreq);
-       if (unlikely(PageHighMem(sg_page(rctx->ivsg))))
-               compat_encrypt_complete2(req, err);
-       return err;
-}
-
-static int compat_decrypt(struct aead_request *req)
-{
-       struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
-       struct compat_request_ctx *rctx = aead_request_ctx(req);
-       struct aead_request *subreq = &rctx->subreq.areq;
-       unsigned int ivsize = crypto_aead_ivsize(geniv);
-       struct scatterlist *src, *dst;
-       crypto_completion_t compl;
-       void *data;
-
-       if (req->cryptlen < ivsize)
-               return -EINVAL;
-
-       aead_request_set_tfm(subreq, ctx->child);
-
-       compl = req->base.complete;
-       data = req->base.data;
-
-       src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen + ivsize);
-       dst = req->src == req->dst ?
-             src : scatterwalk_ffwd(rctx->dst, req->dst,
-                                    req->assoclen + ivsize);
-
-       aead_request_set_callback(subreq, req->base.flags, compl, data);
-       aead_request_set_crypt(subreq, src, dst,
-                              req->cryptlen - ivsize, req->iv);
-       aead_request_set_assoc(subreq, req->src, req->assoclen);
-
-       scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
-
-       return crypto_aead_decrypt(subreq);
-}
-
-static int compat_encrypt_first(struct aead_request *req)
-{
-       struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
-       int err = 0;
-
-       spin_lock_bh(&ctx->lock);
-       if (geniv->encrypt != compat_encrypt_first)
-               goto unlock;
-
-       geniv->encrypt = compat_encrypt;
-
-unlock:
-       spin_unlock_bh(&ctx->lock);
-
-       if (err)
-               return err;
-
-       return compat_encrypt(req);
-}
-
-static int aead_geniv_init_compat(struct crypto_tfm *tfm)
-{
-       struct crypto_aead *geniv = __crypto_aead_cast(tfm);
-       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
-       int err;
-
-       spin_lock_init(&ctx->lock);
-
-       crypto_aead_set_reqsize(geniv, sizeof(struct compat_request_ctx));
-
-       err = aead_geniv_init(tfm);
-
-       ctx->child = geniv->child;
-       geniv->child = geniv;
-
-       return err;
-}
-
-static void aead_geniv_exit_compat(struct crypto_tfm *tfm)
-{
-       struct crypto_aead *geniv = __crypto_aead_cast(tfm);
-       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
-
-       crypto_free_aead(ctx->child);
-}
-
 struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
                                       struct rtattr **tb, u32 type, u32 mask)
 {
@@ -590,8 +204,7 @@ struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
        if (IS_ERR(algt))
                return ERR_CAST(algt);
 
-       if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
-           algt->mask)
+       if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
                return ERR_PTR(-EINVAL);
 
        name = crypto_attr_alg_name(tb[1]);
@@ -608,9 +221,7 @@ struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
        mask |= crypto_requires_sync(algt->type, algt->mask);
 
        crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
-       err = (algt->mask & CRYPTO_ALG_GENIV) ?
-             crypto_grab_nivaead(spawn, name, type, mask) :
-             crypto_grab_aead(spawn, name, type, mask);
+       err = crypto_grab_aead(spawn, name, type, mask);
        if (err)
                goto err_free_inst;
 
@@ -623,43 +234,6 @@ struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
        if (ivsize < sizeof(u64))
                goto err_drop_alg;
 
-       /*
-        * This is only true if we're constructing an algorithm with its
-        * default IV generator.  For the default generator we elide the
-        * template name and double-check the IV generator.
-        */
-       if (algt->mask & CRYPTO_ALG_GENIV) {
-               if (!alg->base.cra_aead.encrypt)
-                       goto err_drop_alg;
-               if (strcmp(tmpl->name, alg->base.cra_aead.geniv))
-                       goto err_drop_alg;
-
-               memcpy(inst->alg.base.cra_name, alg->base.cra_name,
-                      CRYPTO_MAX_ALG_NAME);
-               memcpy(inst->alg.base.cra_driver_name,
-                      alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME);
-
-               inst->alg.base.cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                          CRYPTO_ALG_GENIV;
-               inst->alg.base.cra_flags |= alg->base.cra_flags &
-                                           CRYPTO_ALG_ASYNC;
-               inst->alg.base.cra_priority = alg->base.cra_priority;
-               inst->alg.base.cra_blocksize = alg->base.cra_blocksize;
-               inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
-               inst->alg.base.cra_type = &crypto_aead_type;
-
-               inst->alg.base.cra_aead.ivsize = ivsize;
-               inst->alg.base.cra_aead.maxauthsize = maxauthsize;
-
-               inst->alg.base.cra_aead.setkey = alg->base.cra_aead.setkey;
-               inst->alg.base.cra_aead.setauthsize =
-                       alg->base.cra_aead.setauthsize;
-               inst->alg.base.cra_aead.encrypt = alg->base.cra_aead.encrypt;
-               inst->alg.base.cra_aead.decrypt = alg->base.cra_aead.decrypt;
-
-               goto out;
-       }
-
        err = -ENAMETOOLONG;
        if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
                     "%s(%s)", tmpl->name, alg->base.cra_name) >=
@@ -682,12 +256,6 @@ struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
        inst->alg.ivsize = ivsize;
        inst->alg.maxauthsize = maxauthsize;
 
-       inst->alg.encrypt = compat_encrypt_first;
-       inst->alg.decrypt = compat_decrypt;
-
-       inst->alg.base.cra_init = aead_geniv_init_compat;
-       inst->alg.base.cra_exit = aead_geniv_exit_compat;
-
 out:
        return inst;
 
@@ -707,147 +275,58 @@ void aead_geniv_free(struct aead_instance *inst)
 }
 EXPORT_SYMBOL_GPL(aead_geniv_free);
 
-int aead_geniv_init(struct crypto_tfm *tfm)
+int aead_init_geniv(struct crypto_aead *aead)
 {
-       struct crypto_instance *inst = (void *)tfm->__crt_alg;
+       struct aead_geniv_ctx *ctx = crypto_aead_ctx(aead);
+       struct aead_instance *inst = aead_alg_instance(aead);
        struct crypto_aead *child;
-       struct crypto_aead *aead;
-
-       aead = __crypto_aead_cast(tfm);
-
-       child = crypto_spawn_aead(crypto_instance_ctx(inst));
-       if (IS_ERR(child))
-               return PTR_ERR(child);
-
-       aead->child = child;
-       aead->reqsize += crypto_aead_reqsize(child);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(aead_geniv_init);
-
-void aead_geniv_exit(struct crypto_tfm *tfm)
-{
-       crypto_free_aead(__crypto_aead_cast(tfm)->child);
-}
-EXPORT_SYMBOL_GPL(aead_geniv_exit);
-
-static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
-{
-       struct rtattr *tb[3];
-       struct {
-               struct rtattr attr;
-               struct crypto_attr_type data;
-       } ptype;
-       struct {
-               struct rtattr attr;
-               struct crypto_attr_alg data;
-       } palg;
-       struct crypto_template *tmpl;
-       struct crypto_instance *inst;
-       struct crypto_alg *larval;
-       const char *geniv;
        int err;
 
-       larval = crypto_larval_lookup(alg->cra_driver_name,
-                                     CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
-                                     CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-       err = PTR_ERR(larval);
-       if (IS_ERR(larval))
-               goto out;
-
-       err = -EAGAIN;
-       if (!crypto_is_larval(larval))
-               goto drop_larval;
-
-       ptype.attr.rta_len = sizeof(ptype);
-       ptype.attr.rta_type = CRYPTOA_TYPE;
-       ptype.data.type = type | CRYPTO_ALG_GENIV;
-       /* GENIV tells the template that we're making a default geniv. */
-       ptype.data.mask = mask | CRYPTO_ALG_GENIV;
-       tb[0] = &ptype.attr;
-
-       palg.attr.rta_len = sizeof(palg);
-       palg.attr.rta_type = CRYPTOA_ALG;
-       /* Must use the exact name to locate ourselves. */
-       memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
-       tb[1] = &palg.attr;
-
-       tb[2] = NULL;
+       spin_lock_init(&ctx->lock);
 
-       geniv = alg->cra_aead.geniv;
+       err = crypto_get_default_rng();
+       if (err)
+               goto out;
 
-       tmpl = crypto_lookup_template(geniv);
-       err = -ENOENT;
-       if (!tmpl)
-               goto kill_larval;
+       err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
+                                  crypto_aead_ivsize(aead));
+       crypto_put_default_rng();
+       if (err)
+               goto out;
 
-       if (tmpl->create) {
-               err = tmpl->create(tmpl, tb);
-               if (err)
-                       goto put_tmpl;
-               goto ok;
-       }
+       ctx->null = crypto_get_default_null_skcipher();
+       err = PTR_ERR(ctx->null);
+       if (IS_ERR(ctx->null))
+               goto out;
 
-       inst = tmpl->alloc(tb);
-       err = PTR_ERR(inst);
-       if (IS_ERR(inst))
-               goto put_tmpl;
+       child = crypto_spawn_aead(aead_instance_ctx(inst));
+       err = PTR_ERR(child);
+       if (IS_ERR(child))
+               goto drop_null;
 
-       err = crypto_register_instance(tmpl, inst);
-       if (err) {
-               tmpl->free(inst);
-               goto put_tmpl;
-       }
+       ctx->child = child;
+       crypto_aead_set_reqsize(aead, crypto_aead_reqsize(child) +
+                                     sizeof(struct aead_request));
 
-ok:
-       /* Redo the lookup to use the instance we just registered. */
-       err = -EAGAIN;
+       err = 0;
 
-put_tmpl:
-       crypto_tmpl_put(tmpl);
-kill_larval:
-       crypto_larval_kill(larval);
-drop_larval:
-       crypto_mod_put(larval);
 out:
-       crypto_mod_put(alg);
        return err;
+
+drop_null:
+       crypto_put_default_null_skcipher();
+       goto out;
 }
+EXPORT_SYMBOL_GPL(aead_init_geniv);
 
-struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
+void aead_exit_geniv(struct crypto_aead *tfm)
 {
-       struct crypto_alg *alg;
-
-       alg = crypto_alg_mod_lookup(name, type, mask);
-       if (IS_ERR(alg))
-               return alg;
-
-       if (alg->cra_type == &crypto_aead_type)
-               return alg;
-
-       if (!alg->cra_aead.ivsize)
-               return alg;
-
-       crypto_mod_put(alg);
-       alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED,
-                                   mask & ~CRYPTO_ALG_TESTED);
-       if (IS_ERR(alg))
-               return alg;
-
-       if (alg->cra_type == &crypto_aead_type) {
-               if (~alg->cra_flags & (type ^ ~mask) & CRYPTO_ALG_TESTED) {
-                       crypto_mod_put(alg);
-                       alg = ERR_PTR(-ENOENT);
-               }
-               return alg;
-       }
-
-       BUG_ON(!alg->cra_aead.ivsize);
+       struct aead_geniv_ctx *ctx = crypto_aead_ctx(tfm);
 
-       return ERR_PTR(crypto_nivaead_default(alg, type, mask));
+       crypto_free_aead(ctx->child);
+       crypto_put_default_null_skcipher();
 }
-EXPORT_SYMBOL_GPL(crypto_lookup_aead);
+EXPORT_SYMBOL_GPL(aead_exit_geniv);
 
 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
                     u32 type, u32 mask)
@@ -870,7 +349,7 @@ static int aead_prepare_alg(struct aead_alg *alg)
        if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
                return -EINVAL;
 
-       base->cra_type = &crypto_new_aead_type;
+       base->cra_type = &crypto_aead_type;
        base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
        base->cra_flags |= CRYPTO_ALG_TYPE_AEAD;
 
index 3c079b7f23f6bada906f9d444a50cd15b0831d65..d130b41dbaea244000c35328d7eba7b463158bc8 100644 (file)
@@ -67,12 +67,22 @@ static int crypto_check_alg(struct crypto_alg *alg)
        return crypto_set_driver_name(alg);
 }
 
+static void crypto_free_instance(struct crypto_instance *inst)
+{
+       if (!inst->alg.cra_type->free) {
+               inst->tmpl->free(inst);
+               return;
+       }
+
+       inst->alg.cra_type->free(inst);
+}
+
 static void crypto_destroy_instance(struct crypto_alg *alg)
 {
        struct crypto_instance *inst = (void *)alg;
        struct crypto_template *tmpl = inst->tmpl;
 
-       tmpl->free(inst);
+       crypto_free_instance(inst);
        crypto_tmpl_put(tmpl);
 }
 
@@ -481,7 +491,7 @@ void crypto_unregister_template(struct crypto_template *tmpl)
 
        hlist_for_each_entry_safe(inst, n, list, list) {
                BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1);
-               tmpl->free(inst);
+               crypto_free_instance(inst);
        }
        crypto_remove_final(&users);
 }
@@ -892,7 +902,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(crypto_enqueue_request);
 
-void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset)
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
 {
        struct list_head *request;
 
@@ -907,14 +917,7 @@ void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset)
        request = queue->list.next;
        list_del(request);
 
-       return (char *)list_entry(request, struct crypto_async_request, list) -
-              offset;
-}
-EXPORT_SYMBOL_GPL(__crypto_dequeue_request);
-
-struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
-{
-       return __crypto_dequeue_request(queue, 0);
+       return list_entry(request, struct crypto_async_request, list);
 }
 EXPORT_SYMBOL_GPL(crypto_dequeue_request);
 
index 76fc0b23fc6cfd4c33188cd6e5b7454603b7a751..6e39d9c05b98a532400f83d173ab9884cbb43a96 100644 (file)
@@ -248,13 +248,11 @@ static int cryptomgr_schedule_test(struct crypto_alg *alg)
        type = alg->cra_flags;
 
        /* This piece of crap needs to disappear into per-type test hooks. */
-       if ((!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
-              CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
-            ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
-             CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
-                                         alg->cra_ablkcipher.ivsize)) ||
-           (!((type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) &&
-            alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize))
+       if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
+             CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
+           ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+            CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
+                                        alg->cra_ablkcipher.ivsize))
                type |= CRYPTO_ALG_TESTED;
 
        param->type = type;
index e0408a480d2f4eb8f818c9590ec9a3d7d166e25d..0aa6fdfb448a8c4081e06aa9dcb041433dc280a5 100644 (file)
@@ -90,6 +90,7 @@ static void aead_put_sgl(struct sock *sk)
                put_page(sg_page(sg + i));
                sg_assign_page(sg + i, NULL);
        }
+       sg_init_table(sg, ALG_MAX_PAGES);
        sgl->cur = 0;
        ctx->used = 0;
        ctx->more = 0;
@@ -514,8 +515,7 @@ static struct proto_ops algif_aead_ops = {
 
 static void *aead_bind(const char *name, u32 type, u32 mask)
 {
-       return crypto_alloc_aead(name, type | CRYPTO_ALG_AEAD_NEW,
-                                mask | CRYPTO_ALG_AEAD_NEW);
+       return crypto_alloc_aead(name, type, mask);
 }
 
 static void aead_release(void *private)
index 3e852299afb434de793afedc5bc6d570150d8ae5..55a354d572513b642566b50db7252d3aecdceb38 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Authenc: Simple AEAD wrapper for IPsec
  *
- * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
  *
  * 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
@@ -14,6 +14,7 @@
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/authenc.h>
+#include <crypto/null.h>
 #include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-typedef u8 *(*authenc_ahash_t)(struct aead_request *req, unsigned int flags);
-
 struct authenc_instance_ctx {
        struct crypto_ahash_spawn auth;
        struct crypto_skcipher_spawn enc;
+       unsigned int reqoff;
 };
 
 struct crypto_authenc_ctx {
-       unsigned int reqoff;
        struct crypto_ahash *auth;
        struct crypto_ablkcipher *enc;
+       struct crypto_blkcipher *null;
 };
 
 struct authenc_request_ctx {
-       unsigned int cryptlen;
-       struct scatterlist *sg;
-       struct scatterlist asg[2];
-       struct scatterlist cipher[2];
-       crypto_completion_t complete;
-       crypto_completion_t update_complete;
+       struct scatterlist src[2];
+       struct scatterlist dst[2];
        char tail[];
 };
 
@@ -119,189 +115,35 @@ badkey:
        goto out;
 }
 
-static void authenc_geniv_ahash_update_done(struct crypto_async_request *areq,
-                                           int err)
-{
-       struct aead_request *req = areq->data;
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
-                               areq_ctx->cryptlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               goto out;
-
-       scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
-                                areq_ctx->cryptlen,
-                                crypto_aead_authsize(authenc), 1);
-
-out:
-       authenc_request_complete(req, err);
-}
-
 static void authenc_geniv_ahash_done(struct crypto_async_request *areq, int err)
 {
        struct aead_request *req = areq->data;
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct aead_instance *inst = aead_alg_instance(authenc);
+       struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
 
        if (err)
                goto out;
 
-       scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
-                                areq_ctx->cryptlen,
+       scatterwalk_map_and_copy(ahreq->result, req->dst,
+                                req->assoclen + req->cryptlen,
                                 crypto_aead_authsize(authenc), 1);
 
 out:
        aead_request_complete(req, err);
 }
 
-static void authenc_verify_ahash_update_done(struct crypto_async_request *areq,
-                                            int err)
-{
-       u8 *ihash;
-       unsigned int authsize;
-       struct ablkcipher_request *abreq;
-       struct aead_request *req = areq->data;
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-       unsigned int cryptlen = req->cryptlen;
-
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
-                               areq_ctx->cryptlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               goto out;
-
-       authsize = crypto_aead_authsize(authenc);
-       cryptlen -= authsize;
-       ihash = ahreq->result + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
-
-       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
-       if (err)
-               goto out;
-
-       abreq = aead_request_ctx(req);
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    cryptlen, req->iv);
-
-       err = crypto_ablkcipher_decrypt(abreq);
-
-out:
-       authenc_request_complete(req, err);
-}
-
-static void authenc_verify_ahash_done(struct crypto_async_request *areq,
-                                     int err)
-{
-       u8 *ihash;
-       unsigned int authsize;
-       struct ablkcipher_request *abreq;
-       struct aead_request *req = areq->data;
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-       unsigned int cryptlen = req->cryptlen;
-
-       if (err)
-               goto out;
-
-       authsize = crypto_aead_authsize(authenc);
-       cryptlen -= authsize;
-       ihash = ahreq->result + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
-
-       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
-       if (err)
-               goto out;
-
-       abreq = aead_request_ctx(req);
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    cryptlen, req->iv);
-
-       err = crypto_ablkcipher_decrypt(abreq);
-
-out:
-       authenc_request_complete(req, err);
-}
-
-static u8 *crypto_authenc_ahash_fb(struct aead_request *req, unsigned int flags)
-{
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct crypto_ahash *auth = ctx->auth;
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-       u8 *hash = areq_ctx->tail;
-       int err;
-
-       hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
-                           crypto_ahash_alignmask(auth) + 1);
-
-       ahash_request_set_tfm(ahreq, auth);
-
-       err = crypto_ahash_init(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       ahash_request_set_crypt(ahreq, req->assoc, hash, req->assoclen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
-                                  areq_ctx->update_complete, req);
-
-       err = crypto_ahash_update(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, hash,
-                               areq_ctx->cryptlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       return hash;
-}
-
-static u8 *crypto_authenc_ahash(struct aead_request *req, unsigned int flags)
+static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+       struct aead_instance *inst = aead_alg_instance(authenc);
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
        struct crypto_ahash *auth = ctx->auth;
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
        u8 *hash = areq_ctx->tail;
        int err;
 
@@ -309,66 +151,18 @@ static u8 *crypto_authenc_ahash(struct aead_request *req, unsigned int flags)
                           crypto_ahash_alignmask(auth) + 1);
 
        ahash_request_set_tfm(ahreq, auth);
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, hash,
-                               areq_ctx->cryptlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
-                                  areq_ctx->complete, req);
+       ahash_request_set_crypt(ahreq, req->dst, hash,
+                               req->assoclen + req->cryptlen);
+       ahash_request_set_callback(ahreq, flags,
+                                  authenc_geniv_ahash_done, req);
 
        err = crypto_ahash_digest(ahreq);
        if (err)
-               return ERR_PTR(err);
-
-       return hash;
-}
-
-static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
-                                unsigned int flags)
-{
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct scatterlist *dst = req->dst;
-       struct scatterlist *assoc = req->assoc;
-       struct scatterlist *cipher = areq_ctx->cipher;
-       struct scatterlist *asg = areq_ctx->asg;
-       unsigned int ivsize = crypto_aead_ivsize(authenc);
-       unsigned int cryptlen = req->cryptlen;
-       authenc_ahash_t authenc_ahash_fn = crypto_authenc_ahash_fb;
-       struct page *dstp;
-       u8 *vdst;
-       u8 *hash;
-
-       dstp = sg_page(dst);
-       vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
-
-       if (ivsize) {
-               sg_init_table(cipher, 2);
-               sg_set_buf(cipher, iv, ivsize);
-               scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
-               dst = cipher;
-               cryptlen += ivsize;
-       }
-
-       if (req->assoclen && sg_is_last(assoc)) {
-               authenc_ahash_fn = crypto_authenc_ahash;
-               sg_init_table(asg, 2);
-               sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
-               scatterwalk_crypto_chain(asg, dst, 0, 2);
-               dst = asg;
-               cryptlen += req->assoclen;
-       }
-
-       areq_ctx->cryptlen = cryptlen;
-       areq_ctx->sg = dst;
-
-       areq_ctx->complete = authenc_geniv_ahash_done;
-       areq_ctx->update_complete = authenc_geniv_ahash_update_done;
-
-       hash = authenc_ahash_fn(req, flags);
-       if (IS_ERR(hash))
-               return PTR_ERR(hash);
+               return err;
 
-       scatterwalk_map_and_copy(hash, dst, cryptlen,
+       scatterwalk_map_and_copy(hash, req->dst, req->assoclen + req->cryptlen,
                                 crypto_aead_authsize(authenc), 1);
+
        return 0;
 }
 
@@ -377,180 +171,155 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
 {
        struct aead_request *areq = req->data;
 
-       if (!err) {
-               struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
-               struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-               struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq);
-               struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
-                                                           + ctx->reqoff);
-               u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc);
+       if (err)
+               goto out;
 
-               err = crypto_authenc_genicv(areq, iv, 0);
-       }
+       err = crypto_authenc_genicv(areq, 0);
 
+out:
        authenc_request_complete(areq, err);
 }
 
+static int crypto_authenc_copy_assoc(struct aead_request *req)
+{
+       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct blkcipher_desc desc = {
+               .tfm = ctx->null,
+       };
+
+       return crypto_blkcipher_encrypt(&desc, req->dst, req->src,
+                                       req->assoclen);
+}
+
 static int crypto_authenc_encrypt(struct aead_request *req)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+       struct aead_instance *inst = aead_alg_instance(authenc);
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
        struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
        struct crypto_ablkcipher *enc = ctx->enc;
-       struct scatterlist *dst = req->dst;
        unsigned int cryptlen = req->cryptlen;
-       struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
-                                                   ctx->reqoff);
-       u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
+       struct ablkcipher_request *abreq = (void *)(areq_ctx->tail +
+                                                   ictx->reqoff);
+       struct scatterlist *src, *dst;
        int err;
 
+       sg_init_table(areq_ctx->src, 2);
+       src = scatterwalk_ffwd(areq_ctx->src, req->src, req->assoclen);
+       dst = src;
+
+       if (req->src != req->dst) {
+               err = crypto_authenc_copy_assoc(req);
+               if (err)
+                       return err;
+
+               sg_init_table(areq_ctx->dst, 2);
+               dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
+       }
+
        ablkcipher_request_set_tfm(abreq, enc);
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                        crypto_authenc_encrypt_done, req);
-       ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
-
-       memcpy(iv, req->iv, crypto_aead_ivsize(authenc));
+       ablkcipher_request_set_crypt(abreq, src, dst, cryptlen, req->iv);
 
        err = crypto_ablkcipher_encrypt(abreq);
        if (err)
                return err;
 
-       return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+       return crypto_authenc_genicv(req, aead_request_flags(req));
 }
 
-static void crypto_authenc_givencrypt_done(struct crypto_async_request *req,
-                                          int err)
+static int crypto_authenc_decrypt_tail(struct aead_request *req,
+                                      unsigned int flags)
 {
-       struct aead_request *areq = req->data;
-
-       if (!err) {
-               struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
-
-               err = crypto_authenc_genicv(areq, greq->giv, 0);
-       }
+       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+       struct aead_instance *inst = aead_alg_instance(authenc);
+       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
+       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
+       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
+       struct ablkcipher_request *abreq = (void *)(areq_ctx->tail +
+                                                   ictx->reqoff);
+       unsigned int authsize = crypto_aead_authsize(authenc);
+       u8 *ihash = ahreq->result + authsize;
+       struct scatterlist *src, *dst;
 
-       authenc_request_complete(areq, err);
-}
+       scatterwalk_map_and_copy(ihash, req->src, ahreq->nbytes, authsize, 0);
 
-static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
-{
-       struct crypto_aead *authenc = aead_givcrypt_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct aead_request *areq = &req->areq;
-       struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
-       u8 *iv = req->giv;
-       int err;
+       if (crypto_memneq(ihash, ahreq->result, authsize))
+               return -EBADMSG;
 
-       skcipher_givcrypt_set_tfm(greq, ctx->enc);
-       skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
-                                      crypto_authenc_givencrypt_done, areq);
-       skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
-                                   areq->iv);
-       skcipher_givcrypt_set_giv(greq, iv, req->seq);
+       sg_init_table(areq_ctx->src, 2);
+       src = scatterwalk_ffwd(areq_ctx->src, req->src, req->assoclen);
+       dst = src;
 
-       err = crypto_skcipher_givencrypt(greq);
-       if (err)
-               return err;
+       if (req->src != req->dst) {
+               sg_init_table(areq_ctx->dst, 2);
+               dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
+       }
 
-       return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
-}
+       ablkcipher_request_set_tfm(abreq, ctx->enc);
+       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+                                       req->base.complete, req->base.data);
+       ablkcipher_request_set_crypt(abreq, src, dst,
+                                    req->cryptlen - authsize, req->iv);
 
-static int crypto_authenc_verify(struct aead_request *req,
-                                authenc_ahash_t authenc_ahash_fn)
-{
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       u8 *ohash;
-       u8 *ihash;
-       unsigned int authsize;
-
-       areq_ctx->complete = authenc_verify_ahash_done;
-       areq_ctx->update_complete = authenc_verify_ahash_update_done;
-
-       ohash = authenc_ahash_fn(req, CRYPTO_TFM_REQ_MAY_SLEEP);
-       if (IS_ERR(ohash))
-               return PTR_ERR(ohash);
-
-       authsize = crypto_aead_authsize(authenc);
-       ihash = ohash + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
-       return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
+       return crypto_ablkcipher_decrypt(abreq);
 }
 
-static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
-                                 unsigned int cryptlen)
+static void authenc_verify_ahash_done(struct crypto_async_request *areq,
+                                     int err)
 {
-       struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct scatterlist *src = req->src;
-       struct scatterlist *assoc = req->assoc;
-       struct scatterlist *cipher = areq_ctx->cipher;
-       struct scatterlist *asg = areq_ctx->asg;
-       unsigned int ivsize = crypto_aead_ivsize(authenc);
-       authenc_ahash_t authenc_ahash_fn = crypto_authenc_ahash_fb;
-       struct page *srcp;
-       u8 *vsrc;
-
-       srcp = sg_page(src);
-       vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
-
-       if (ivsize) {
-               sg_init_table(cipher, 2);
-               sg_set_buf(cipher, iv, ivsize);
-               scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
-               src = cipher;
-               cryptlen += ivsize;
-       }
+       struct aead_request *req = areq->data;
 
-       if (req->assoclen && sg_is_last(assoc)) {
-               authenc_ahash_fn = crypto_authenc_ahash;
-               sg_init_table(asg, 2);
-               sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
-               scatterwalk_crypto_chain(asg, src, 0, 2);
-               src = asg;
-               cryptlen += req->assoclen;
-       }
+       if (err)
+               goto out;
 
-       areq_ctx->cryptlen = cryptlen;
-       areq_ctx->sg = src;
+       err = crypto_authenc_decrypt_tail(req, 0);
 
-       return crypto_authenc_verify(req, authenc_ahash_fn);
+out:
+       authenc_request_complete(req, err);
 }
 
 static int crypto_authenc_decrypt(struct aead_request *req)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-       struct ablkcipher_request *abreq = aead_request_ctx(req);
-       unsigned int cryptlen = req->cryptlen;
        unsigned int authsize = crypto_aead_authsize(authenc);
-       u8 *iv = req->iv;
+       struct aead_instance *inst = aead_alg_instance(authenc);
+       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+       struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
+       struct crypto_ahash *auth = ctx->auth;
+       struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
+       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
+       u8 *hash = areq_ctx->tail;
        int err;
 
-       if (cryptlen < authsize)
-               return -EINVAL;
-       cryptlen -= authsize;
+       hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
+                          crypto_ahash_alignmask(auth) + 1);
 
-       err = crypto_authenc_iverify(req, iv, cryptlen);
+       ahash_request_set_tfm(ahreq, auth);
+       ahash_request_set_crypt(ahreq, req->src, hash,
+                               req->assoclen + req->cryptlen - authsize);
+       ahash_request_set_callback(ahreq, aead_request_flags(req),
+                                  authenc_verify_ahash_done, req);
+
+       err = crypto_ahash_digest(ahreq);
        if (err)
                return err;
 
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
-
-       return crypto_ablkcipher_decrypt(abreq);
+       return crypto_authenc_decrypt_tail(req, aead_request_flags(req));
 }
 
-static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
+static int crypto_authenc_init_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
-       struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst);
-       struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct aead_instance *inst = aead_alg_instance(tfm);
+       struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
+       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(tfm);
        struct crypto_ahash *auth;
        struct crypto_ablkcipher *enc;
+       struct crypto_blkcipher *null;
        int err;
 
        auth = crypto_spawn_ahash(&ictx->auth);
@@ -562,42 +331,57 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
        if (IS_ERR(enc))
                goto err_free_ahash;
 
+       null = crypto_get_default_null_skcipher();
+       err = PTR_ERR(null);
+       if (IS_ERR(null))
+               goto err_free_skcipher;
+
        ctx->auth = auth;
        ctx->enc = enc;
+       ctx->null = null;
 
-       ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
-                           crypto_ahash_alignmask(auth),
-                           crypto_ahash_alignmask(auth) + 1) +
-                     crypto_ablkcipher_ivsize(enc);
-
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
+       crypto_aead_set_reqsize(
+               tfm,
                sizeof(struct authenc_request_ctx) +
-               ctx->reqoff +
+               ictx->reqoff +
                max_t(unsigned int,
-                       crypto_ahash_reqsize(auth) +
-                       sizeof(struct ahash_request),
-                       sizeof(struct skcipher_givcrypt_request) +
-                       crypto_ablkcipher_reqsize(enc)));
+                     crypto_ahash_reqsize(auth) +
+                     sizeof(struct ahash_request),
+                     sizeof(struct ablkcipher_request) +
+                     crypto_ablkcipher_reqsize(enc)));
 
        return 0;
 
+err_free_skcipher:
+       crypto_free_ablkcipher(enc);
 err_free_ahash:
        crypto_free_ahash(auth);
        return err;
 }
 
-static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_authenc_exit_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_authenc_ctx *ctx = crypto_aead_ctx(tfm);
 
        crypto_free_ahash(ctx->auth);
        crypto_free_ablkcipher(ctx->enc);
+       crypto_put_default_null_skcipher();
 }
 
-static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
+static void crypto_authenc_free(struct aead_instance *inst)
+{
+       struct authenc_instance_ctx *ctx = aead_instance_ctx(inst);
+
+       crypto_drop_skcipher(&ctx->enc);
+       crypto_drop_ahash(&ctx->auth);
+       kfree(inst);
+}
+
+static int crypto_authenc_create(struct crypto_template *tmpl,
+                                struct rtattr **tb)
 {
        struct crypto_attr_type *algt;
-       struct crypto_instance *inst;
+       struct aead_instance *inst;
        struct hash_alg_common *auth;
        struct crypto_alg *auth_base;
        struct crypto_alg *enc;
@@ -607,15 +391,15 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
 
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
-               return ERR_CAST(algt);
+               return PTR_ERR(algt);
 
        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
                               CRYPTO_ALG_TYPE_AHASH_MASK);
        if (IS_ERR(auth))
-               return ERR_CAST(auth);
+               return PTR_ERR(auth);
 
        auth_base = &auth->base;
 
@@ -629,13 +413,14 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
        if (!inst)
                goto out_put_auth;
 
-       ctx = crypto_instance_ctx(inst);
+       ctx = aead_instance_ctx(inst);
 
-       err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
+       err = crypto_init_ahash_spawn(&ctx->auth, auth,
+                                     aead_crypto_instance(inst));
        if (err)
                goto err_free_inst;
 
-       crypto_set_skcipher_spawn(&ctx->enc, inst);
+       crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst));
        err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
                                   crypto_requires_sync(algt->type,
                                                        algt->mask));
@@ -644,41 +429,47 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
 
        enc = crypto_skcipher_spawn_alg(&ctx->enc);
 
+       ctx->reqoff = ALIGN(2 * auth->digestsize + auth_base->cra_alignmask,
+                           auth_base->cra_alignmask + 1);
+
        err = -ENAMETOOLONG;
-       if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+       if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
                     "authenc(%s,%s)", auth_base->cra_name, enc->cra_name) >=
            CRYPTO_MAX_ALG_NAME)
                goto err_drop_enc;
 
-       if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+       if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
                     "authenc(%s,%s)", auth_base->cra_driver_name,
                     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
                goto err_drop_enc;
 
-       inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-       inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
-       inst->alg.cra_priority = enc->cra_priority *
-                                10 + auth_base->cra_priority;
-       inst->alg.cra_blocksize = enc->cra_blocksize;
-       inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
-       inst->alg.cra_type = &crypto_aead_type;
+       inst->alg.base.cra_flags = enc->cra_flags & CRYPTO_ALG_ASYNC;
+       inst->alg.base.cra_priority = enc->cra_priority * 10 +
+                                     auth_base->cra_priority;
+       inst->alg.base.cra_blocksize = enc->cra_blocksize;
+       inst->alg.base.cra_alignmask = auth_base->cra_alignmask |
+                                      enc->cra_alignmask;
+       inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
+
+       inst->alg.ivsize = enc->cra_ablkcipher.ivsize;
+       inst->alg.maxauthsize = auth->digestsize;
 
-       inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
-       inst->alg.cra_aead.maxauthsize = auth->digestsize;
+       inst->alg.init = crypto_authenc_init_tfm;
+       inst->alg.exit = crypto_authenc_exit_tfm;
 
-       inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
+       inst->alg.setkey = crypto_authenc_setkey;
+       inst->alg.encrypt = crypto_authenc_encrypt;
+       inst->alg.decrypt = crypto_authenc_decrypt;
 
-       inst->alg.cra_init = crypto_authenc_init_tfm;
-       inst->alg.cra_exit = crypto_authenc_exit_tfm;
+       inst->free = crypto_authenc_free;
 
-       inst->alg.cra_aead.setkey = crypto_authenc_setkey;
-       inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
-       inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
-       inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt;
+       err = aead_register_instance(tmpl, inst);
+       if (err)
+               goto err_drop_enc;
 
 out:
        crypto_mod_put(auth_base);
-       return inst;
+       return err;
 
 err_drop_enc:
        crypto_drop_skcipher(&ctx->enc);
@@ -687,23 +478,12 @@ err_drop_auth:
 err_free_inst:
        kfree(inst);
 out_put_auth:
-       inst = ERR_PTR(err);
        goto out;
 }
 
-static void crypto_authenc_free(struct crypto_instance *inst)
-{
-       struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst);
-
-       crypto_drop_skcipher(&ctx->enc);
-       crypto_drop_ahash(&ctx->auth);
-       kfree(inst);
-}
-
 static struct crypto_template crypto_authenc_tmpl = {
        .name = "authenc",
-       .alloc = crypto_authenc_alloc,
-       .free = crypto_authenc_free,
+       .create = crypto_authenc_create,
        .module = THIS_MODULE,
 };
 
index a3da6770bc9ed2bf66d59e8e74461829eeb4fe4e..0c0468869e25b51035cf363fd3f3e2f7903330fb 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2010 secunet Security Networks AG
  * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
+ * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
  *
  * 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
@@ -16,6 +17,7 @@
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/authenc.h>
+#include <crypto/null.h>
 #include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -34,19 +36,12 @@ struct crypto_authenc_esn_ctx {
        unsigned int reqoff;
        struct crypto_ahash *auth;
        struct crypto_ablkcipher *enc;
+       struct crypto_blkcipher *null;
 };
 
 struct authenc_esn_request_ctx {
-       unsigned int cryptlen;
-       unsigned int headlen;
-       unsigned int trailen;
-       struct scatterlist *sg;
-       struct scatterlist hsg[2];
-       struct scatterlist tsg[1];
-       struct scatterlist cipher[2];
-       crypto_completion_t complete;
-       crypto_completion_t update_complete;
-       crypto_completion_t update_complete2;
+       struct scatterlist src[2];
+       struct scatterlist dst[2];
        char tail[];
 };
 
@@ -56,6 +51,15 @@ static void authenc_esn_request_complete(struct aead_request *req, int err)
                aead_request_complete(req, err);
 }
 
+static int crypto_authenc_esn_setauthsize(struct crypto_aead *authenc_esn,
+                                         unsigned int authsize)
+{
+       if (authsize > 0 && authsize < 4)
+               return -EINVAL;
+
+       return 0;
+}
+
 static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
                                     unsigned int keylen)
 {
@@ -93,556 +97,242 @@ badkey:
        goto out;
 }
 
-static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
-                                               int err)
-{
-       struct aead_request *req = areq->data;
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
-                               areq_ctx->cryptlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->update_complete2, req);
-
-       err = crypto_ahash_update(ahreq);
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
-                               areq_ctx->trailen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               goto out;
-
-       scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
-                                areq_ctx->cryptlen,
-                                crypto_aead_authsize(authenc_esn), 1);
-
-out:
-       authenc_esn_request_complete(req, err);
-}
-
-static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
-                                                int err)
+static int crypto_authenc_esn_genicv_tail(struct aead_request *req,
+                                         unsigned int flags)
 {
-       struct aead_request *req = areq->data;
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
-                               areq_ctx->trailen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               goto out;
+       struct crypto_ahash *auth = ctx->auth;
+       u8 *hash = PTR_ALIGN((u8 *)areq_ctx->tail,
+                            crypto_ahash_alignmask(auth) + 1);
+       unsigned int authsize = crypto_aead_authsize(authenc_esn);
+       unsigned int assoclen = req->assoclen;
+       unsigned int cryptlen = req->cryptlen;
+       struct scatterlist *dst = req->dst;
+       u32 tmp[2];
 
-       scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
-                                areq_ctx->cryptlen,
-                                crypto_aead_authsize(authenc_esn), 1);
+       /* Move high-order bits of sequence number back. */
+       scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
+       scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
+       scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
 
-out:
-       authenc_esn_request_complete(req, err);
+       scatterwalk_map_and_copy(hash, dst, assoclen + cryptlen, authsize, 1);
+       return 0;
 }
 
-
 static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
                                         int err)
 {
        struct aead_request *req = areq->data;
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
-       if (err)
-               goto out;
-
-       scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
-                                areq_ctx->cryptlen,
-                                crypto_aead_authsize(authenc_esn), 1);
-
-out:
+       err = err ?: crypto_authenc_esn_genicv_tail(req, 0);
        aead_request_complete(req, err);
 }
 
-
-static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
-                                                int err)
+static int crypto_authenc_esn_genicv(struct aead_request *req,
+                                    unsigned int flags)
 {
-       u8 *ihash;
-       unsigned int authsize;
-       struct ablkcipher_request *abreq;
-       struct aead_request *req = areq->data;
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-       unsigned int cryptlen = req->cryptlen;
-
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
-                               areq_ctx->cryptlen);
-
-       ahash_request_set_callback(ahreq,
-                                  aead_request_flags(req) &
-                                  CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->update_complete2, req);
-
-       err = crypto_ahash_update(ahreq);
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
-                               areq_ctx->trailen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               goto out;
-
-       authsize = crypto_aead_authsize(authenc_esn);
-       cryptlen -= authsize;
-       ihash = ahreq->result + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
-
-       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
-       if (err)
-               goto out;
-
-       abreq = aead_request_ctx(req);
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    cryptlen, req->iv);
-
-       err = crypto_ablkcipher_decrypt(abreq);
-
-out:
-       authenc_esn_request_complete(req, err);
-}
-
-static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
-                                                 int err)
-{
-       u8 *ihash;
-       unsigned int authsize;
-       struct ablkcipher_request *abreq;
-       struct aead_request *req = areq->data;
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+       struct crypto_ahash *auth = ctx->auth;
+       u8 *hash = PTR_ALIGN((u8 *)areq_ctx->tail,
+                            crypto_ahash_alignmask(auth) + 1);
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       unsigned int authsize = crypto_aead_authsize(authenc_esn);
+       unsigned int assoclen = req->assoclen;
        unsigned int cryptlen = req->cryptlen;
+       struct scatterlist *dst = req->dst;
+       u32 tmp[2];
 
-       if (err)
-               goto out;
-
-       ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
-                               areq_ctx->trailen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) &
-                                         CRYPTO_TFM_REQ_MAY_SLEEP,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               goto out;
-
-       authsize = crypto_aead_authsize(authenc_esn);
-       cryptlen -= authsize;
-       ihash = ahreq->result + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
+       if (!authsize)
+               return 0;
 
-       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
-       if (err)
-               goto out;
+       /* Move high-order bits of sequence number to the end. */
+       scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
+       scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
+       scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
 
-       abreq = aead_request_ctx(req);
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    cryptlen, req->iv);
+       sg_init_table(areq_ctx->dst, 2);
+       dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
 
-       err = crypto_ablkcipher_decrypt(abreq);
+       ahash_request_set_tfm(ahreq, auth);
+       ahash_request_set_crypt(ahreq, dst, hash, assoclen + cryptlen);
+       ahash_request_set_callback(ahreq, flags,
+                                  authenc_esn_geniv_ahash_done, req);
 
-out:
-       authenc_esn_request_complete(req, err);
+       return crypto_ahash_digest(ahreq) ?:
+              crypto_authenc_esn_genicv_tail(req, aead_request_flags(req));
 }
 
 
-static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
-                                         int err)
+static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
+                                           int err)
 {
-       u8 *ihash;
-       unsigned int authsize;
-       struct ablkcipher_request *abreq;
-       struct aead_request *req = areq->data;
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-       unsigned int cryptlen = req->cryptlen;
-
-       if (err)
-               goto out;
-
-       authsize = crypto_aead_authsize(authenc_esn);
-       cryptlen -= authsize;
-       ihash = ahreq->result + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
-
-       err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
-       if (err)
-               goto out;
-
-       abreq = aead_request_ctx(req);
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst,
-                                    cryptlen, req->iv);
+       struct aead_request *areq = req->data;
 
-       err = crypto_ablkcipher_decrypt(abreq);
+       if (!err)
+               err = crypto_authenc_esn_genicv(areq, 0);
 
-out:
-       authenc_esn_request_complete(req, err);
+       authenc_esn_request_complete(areq, err);
 }
 
-static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
-                                   unsigned int flags)
+static int crypto_authenc_esn_copy(struct aead_request *req, unsigned int len)
 {
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct crypto_ahash *auth = ctx->auth;
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
-       u8 *hash = areq_ctx->tail;
-       int err;
-
-       hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
-                           crypto_ahash_alignmask(auth) + 1);
-
-       ahash_request_set_tfm(ahreq, auth);
+       struct blkcipher_desc desc = {
+               .tfm = ctx->null,
+       };
 
-       err = crypto_ahash_init(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
-                                  areq_ctx->update_complete, req);
-
-       err = crypto_ahash_update(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
-                                  areq_ctx->update_complete2, req);
-
-       err = crypto_ahash_update(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
-                               areq_ctx->trailen);
-       ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
-                                  areq_ctx->complete, req);
-
-       err = crypto_ahash_finup(ahreq);
-       if (err)
-               return ERR_PTR(err);
-
-       return hash;
+       return crypto_blkcipher_encrypt(&desc, req->dst, req->src, len);
 }
 
-static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
-                                    unsigned int flags)
+static int crypto_authenc_esn_encrypt(struct aead_request *req)
 {
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct scatterlist *dst = req->dst;
-       struct scatterlist *assoc = req->assoc;
-       struct scatterlist *cipher = areq_ctx->cipher;
-       struct scatterlist *hsg = areq_ctx->hsg;
-       struct scatterlist *tsg = areq_ctx->tsg;
-       struct scatterlist *assoc1;
-       struct scatterlist *assoc2;
-       unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
+       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+       struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+                                                   + ctx->reqoff);
+       struct crypto_ablkcipher *enc = ctx->enc;
+       unsigned int assoclen = req->assoclen;
        unsigned int cryptlen = req->cryptlen;
-       struct page *dstp;
-       u8 *vdst;
-       u8 *hash;
-
-       dstp = sg_page(dst);
-       vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
-
-       if (ivsize) {
-               sg_init_table(cipher, 2);
-               sg_set_buf(cipher, iv, ivsize);
-               scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
-               dst = cipher;
-               cryptlen += ivsize;
-       }
-
-       if (sg_is_last(assoc))
-               return -EINVAL;
-
-       assoc1 = assoc + 1;
-       if (sg_is_last(assoc1))
-               return -EINVAL;
-
-       assoc2 = assoc + 2;
-       if (!sg_is_last(assoc2))
-               return -EINVAL;
-
-       sg_init_table(hsg, 2);
-       sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
-       sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
-
-       sg_init_table(tsg, 1);
-       sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
-
-       areq_ctx->cryptlen = cryptlen;
-       areq_ctx->headlen = assoc->length + assoc2->length;
-       areq_ctx->trailen = assoc1->length;
-       areq_ctx->sg = dst;
-
-       areq_ctx->complete = authenc_esn_geniv_ahash_done;
-       areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done;
-       areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2;
+       struct scatterlist *src, *dst;
+       int err;
 
-       hash = crypto_authenc_esn_ahash(req, flags);
-       if (IS_ERR(hash))
-               return PTR_ERR(hash);
+       sg_init_table(areq_ctx->src, 2);
+       src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen);
+       dst = src;
 
-       scatterwalk_map_and_copy(hash, dst, cryptlen,
-                                crypto_aead_authsize(authenc_esn), 1);
-       return 0;
-}
+       if (req->src != req->dst) {
+               err = crypto_authenc_esn_copy(req, assoclen);
+               if (err)
+                       return err;
 
-
-static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
-                                           int err)
-{
-       struct aead_request *areq = req->data;
-
-       if (!err) {
-               struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq);
-               struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-               struct ablkcipher_request *abreq = aead_request_ctx(areq);
-               u8 *iv = (u8 *)(abreq + 1) +
-                        crypto_ablkcipher_reqsize(ctx->enc);
-
-               err = crypto_authenc_esn_genicv(areq, iv, 0);
+               sg_init_table(areq_ctx->dst, 2);
+               dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, assoclen);
        }
 
-       authenc_esn_request_complete(areq, err);
-}
-
-static int crypto_authenc_esn_encrypt(struct aead_request *req)
-{
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct crypto_ablkcipher *enc = ctx->enc;
-       struct scatterlist *dst = req->dst;
-       unsigned int cryptlen = req->cryptlen;
-       struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
-                                                   + ctx->reqoff);
-       u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
-       int err;
-
        ablkcipher_request_set_tfm(abreq, enc);
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                        crypto_authenc_esn_encrypt_done, req);
-       ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
-
-       memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
+       ablkcipher_request_set_crypt(abreq, src, dst, cryptlen, req->iv);
 
        err = crypto_ablkcipher_encrypt(abreq);
        if (err)
                return err;
 
-       return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+       return crypto_authenc_esn_genicv(req, aead_request_flags(req));
 }
 
-static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
-                                              int err)
+static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
+                                          unsigned int flags)
 {
-       struct aead_request *areq = req->data;
-
-       if (!err) {
-               struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
-
-               err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
-       }
+       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+       unsigned int authsize = crypto_aead_authsize(authenc_esn);
+       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+       struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+                                                   + ctx->reqoff);
+       struct crypto_ahash *auth = ctx->auth;
+       u8 *ohash = PTR_ALIGN((u8 *)areq_ctx->tail,
+                             crypto_ahash_alignmask(auth) + 1);
+       unsigned int cryptlen = req->cryptlen - authsize;
+       unsigned int assoclen = req->assoclen;
+       struct scatterlist *dst = req->dst;
+       u8 *ihash = ohash + crypto_ahash_digestsize(auth);
+       u32 tmp[2];
 
-       authenc_esn_request_complete(areq, err);
-}
+       /* Move high-order bits of sequence number back. */
+       scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
+       scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
+       scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
 
-static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
-{
-       struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct aead_request *areq = &req->areq;
-       struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
-       u8 *iv = req->giv;
-       int err;
+       if (crypto_memneq(ihash, ohash, authsize))
+               return -EBADMSG;
 
-       skcipher_givcrypt_set_tfm(greq, ctx->enc);
-       skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
-                                      crypto_authenc_esn_givencrypt_done, areq);
-       skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
-                                   areq->iv);
-       skcipher_givcrypt_set_giv(greq, iv, req->seq);
+       sg_init_table(areq_ctx->dst, 2);
+       dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
 
-       err = crypto_skcipher_givencrypt(greq);
-       if (err)
-               return err;
+       ablkcipher_request_set_tfm(abreq, ctx->enc);
+       ablkcipher_request_set_callback(abreq, flags,
+                                       req->base.complete, req->base.data);
+       ablkcipher_request_set_crypt(abreq, dst, dst, cryptlen, req->iv);
 
-       return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+       return crypto_ablkcipher_decrypt(abreq);
 }
 
-static int crypto_authenc_esn_verify(struct aead_request *req)
+static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
+                                         int err)
 {
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       u8 *ohash;
-       u8 *ihash;
-       unsigned int authsize;
-
-       areq_ctx->complete = authenc_esn_verify_ahash_done;
-       areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
-
-       ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
-       if (IS_ERR(ohash))
-               return PTR_ERR(ohash);
+       struct aead_request *req = areq->data;
 
-       authsize = crypto_aead_authsize(authenc_esn);
-       ihash = ohash + authsize;
-       scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
-                                authsize, 0);
-       return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
+       err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
+       aead_request_complete(req, err);
 }
 
-static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
-                                     unsigned int cryptlen)
+static int crypto_authenc_esn_decrypt(struct aead_request *req)
 {
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
-       struct scatterlist *src = req->src;
-       struct scatterlist *assoc = req->assoc;
-       struct scatterlist *cipher = areq_ctx->cipher;
-       struct scatterlist *hsg = areq_ctx->hsg;
-       struct scatterlist *tsg = areq_ctx->tsg;
-       struct scatterlist *assoc1;
-       struct scatterlist *assoc2;
-       unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
-       struct page *srcp;
-       u8 *vsrc;
-
-       srcp = sg_page(src);
-       vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
-
-       if (ivsize) {
-               sg_init_table(cipher, 2);
-               sg_set_buf(cipher, iv, ivsize);
-               scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
-               src = cipher;
-               cryptlen += ivsize;
-       }
-
-       if (sg_is_last(assoc))
-               return -EINVAL;
-
-       assoc1 = assoc + 1;
-       if (sg_is_last(assoc1))
-               return -EINVAL;
+       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+       struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+       unsigned int authsize = crypto_aead_authsize(authenc_esn);
+       struct crypto_ahash *auth = ctx->auth;
+       u8 *ohash = PTR_ALIGN((u8 *)areq_ctx->tail,
+                             crypto_ahash_alignmask(auth) + 1);
+       unsigned int assoclen = req->assoclen;
+       unsigned int cryptlen = req->cryptlen;
+       u8 *ihash = ohash + crypto_ahash_digestsize(auth);
+       struct scatterlist *dst = req->dst;
+       u32 tmp[2];
+       int err;
 
-       assoc2 = assoc + 2;
-       if (!sg_is_last(assoc2))
-               return -EINVAL;
+       cryptlen -= authsize;
 
-       sg_init_table(hsg, 2);
-       sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
-       sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+       if (req->src != dst) {
+               err = crypto_authenc_esn_copy(req, assoclen + cryptlen);
+               if (err)
+                       return err;
+       }
 
-       sg_init_table(tsg, 1);
-       sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+       scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
+                                authsize, 0);
 
-       areq_ctx->cryptlen = cryptlen;
-       areq_ctx->headlen = assoc->length + assoc2->length;
-       areq_ctx->trailen = assoc1->length;
-       areq_ctx->sg = src;
+       if (!authsize)
+               goto tail;
 
-       areq_ctx->complete = authenc_esn_verify_ahash_done;
-       areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
-       areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2;
+       /* Move high-order bits of sequence number to the end. */
+       scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
+       scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
+       scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
 
-       return crypto_authenc_esn_verify(req);
-}
+       sg_init_table(areq_ctx->dst, 2);
+       dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
 
-static int crypto_authenc_esn_decrypt(struct aead_request *req)
-{
-       struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
-       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
-       struct ablkcipher_request *abreq = aead_request_ctx(req);
-       unsigned int cryptlen = req->cryptlen;
-       unsigned int authsize = crypto_aead_authsize(authenc_esn);
-       u8 *iv = req->iv;
-       int err;
-
-       if (cryptlen < authsize)
-               return -EINVAL;
-       cryptlen -= authsize;
+       ahash_request_set_tfm(ahreq, auth);
+       ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);
+       ahash_request_set_callback(ahreq, aead_request_flags(req),
+                                  authenc_esn_verify_ahash_done, req);
 
-       err = crypto_authenc_esn_iverify(req, iv, cryptlen);
+       err = crypto_ahash_digest(ahreq);
        if (err)
                return err;
 
-       ablkcipher_request_set_tfm(abreq, ctx->enc);
-       ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-                                       req->base.complete, req->base.data);
-       ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
-
-       return crypto_ablkcipher_decrypt(abreq);
+tail:
+       return crypto_authenc_esn_decrypt_tail(req, aead_request_flags(req));
 }
 
-static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
+static int crypto_authenc_esn_init_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
-       struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst);
-       struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct aead_instance *inst = aead_alg_instance(tfm);
+       struct authenc_esn_instance_ctx *ictx = aead_instance_ctx(inst);
+       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm);
        struct crypto_ahash *auth;
        struct crypto_ablkcipher *enc;
+       struct crypto_blkcipher *null;
        int err;
 
        auth = crypto_spawn_ahash(&ictx->auth);
@@ -654,15 +344,20 @@ static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
        if (IS_ERR(enc))
                goto err_free_ahash;
 
+       null = crypto_get_default_null_skcipher();
+       err = PTR_ERR(null);
+       if (IS_ERR(null))
+               goto err_free_skcipher;
+
        ctx->auth = auth;
        ctx->enc = enc;
+       ctx->null = null;
 
-       ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
-                           crypto_ahash_alignmask(auth),
-                           crypto_ahash_alignmask(auth) + 1) +
-                     crypto_ablkcipher_ivsize(enc);
+       ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth),
+                           crypto_ahash_alignmask(auth) + 1);
 
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
+       crypto_aead_set_reqsize(
+               tfm,
                sizeof(struct authenc_esn_request_ctx) +
                ctx->reqoff +
                max_t(unsigned int,
@@ -673,23 +368,36 @@ static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
 
        return 0;
 
+err_free_skcipher:
+       crypto_free_ablkcipher(enc);
 err_free_ahash:
        crypto_free_ahash(auth);
        return err;
 }
 
-static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_authenc_esn_exit_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(tfm);
 
        crypto_free_ahash(ctx->auth);
        crypto_free_ablkcipher(ctx->enc);
+       crypto_put_default_null_skcipher();
 }
 
-static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
+static void crypto_authenc_esn_free(struct aead_instance *inst)
+{
+       struct authenc_esn_instance_ctx *ctx = aead_instance_ctx(inst);
+
+       crypto_drop_skcipher(&ctx->enc);
+       crypto_drop_ahash(&ctx->auth);
+       kfree(inst);
+}
+
+static int crypto_authenc_esn_create(struct crypto_template *tmpl,
+                                    struct rtattr **tb)
 {
        struct crypto_attr_type *algt;
-       struct crypto_instance *inst;
+       struct aead_instance *inst;
        struct hash_alg_common *auth;
        struct crypto_alg *auth_base;
        struct crypto_alg *enc;
@@ -699,15 +407,15 @@ static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
 
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
-               return ERR_CAST(algt);
+               return PTR_ERR(algt);
 
        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
                               CRYPTO_ALG_TYPE_AHASH_MASK);
        if (IS_ERR(auth))
-               return ERR_CAST(auth);
+               return PTR_ERR(auth);
 
        auth_base = &auth->base;
 
@@ -721,13 +429,14 @@ static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
        if (!inst)
                goto out_put_auth;
 
-       ctx = crypto_instance_ctx(inst);
+       ctx = aead_instance_ctx(inst);
 
-       err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
+       err = crypto_init_ahash_spawn(&ctx->auth, auth,
+                                     aead_crypto_instance(inst));
        if (err)
                goto err_free_inst;
 
-       crypto_set_skcipher_spawn(&ctx->enc, inst);
+       crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst));
        err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
                                   crypto_requires_sync(algt->type,
                                                        algt->mask));
@@ -737,40 +446,44 @@ static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
        enc = crypto_skcipher_spawn_alg(&ctx->enc);
 
        err = -ENAMETOOLONG;
-       if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-                    "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
-           CRYPTO_MAX_ALG_NAME)
+       if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+                    "authencesn(%s,%s)", auth_base->cra_name,
+                    enc->cra_name) >= CRYPTO_MAX_ALG_NAME)
                goto err_drop_enc;
 
-       if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+       if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
                     "authencesn(%s,%s)", auth_base->cra_driver_name,
                     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
                goto err_drop_enc;
 
-       inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-       inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
-       inst->alg.cra_priority = enc->cra_priority *
-                                10 + auth_base->cra_priority;
-       inst->alg.cra_blocksize = enc->cra_blocksize;
-       inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
-       inst->alg.cra_type = &crypto_aead_type;
+       inst->alg.base.cra_flags = enc->cra_flags & CRYPTO_ALG_ASYNC;
+       inst->alg.base.cra_priority = enc->cra_priority * 10 +
+                                     auth_base->cra_priority;
+       inst->alg.base.cra_blocksize = enc->cra_blocksize;
+       inst->alg.base.cra_alignmask = auth_base->cra_alignmask |
+                                      enc->cra_alignmask;
+       inst->alg.base.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
+
+       inst->alg.ivsize = enc->cra_ablkcipher.ivsize;
+       inst->alg.maxauthsize = auth->digestsize;
 
-       inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
-       inst->alg.cra_aead.maxauthsize = auth->digestsize;
+       inst->alg.init = crypto_authenc_esn_init_tfm;
+       inst->alg.exit = crypto_authenc_esn_exit_tfm;
 
-       inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
+       inst->alg.setkey = crypto_authenc_esn_setkey;
+       inst->alg.setauthsize = crypto_authenc_esn_setauthsize;
+       inst->alg.encrypt = crypto_authenc_esn_encrypt;
+       inst->alg.decrypt = crypto_authenc_esn_decrypt;
 
-       inst->alg.cra_init = crypto_authenc_esn_init_tfm;
-       inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
+       inst->free = crypto_authenc_esn_free,
 
-       inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey;
-       inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt;
-       inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt;
-       inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt;
+       err = aead_register_instance(tmpl, inst);
+       if (err)
+               goto err_drop_enc;
 
 out:
        crypto_mod_put(auth_base);
-       return inst;
+       return err;
 
 err_drop_enc:
        crypto_drop_skcipher(&ctx->enc);
@@ -779,23 +492,12 @@ err_drop_auth:
 err_free_inst:
        kfree(inst);
 out_put_auth:
-       inst = ERR_PTR(err);
        goto out;
 }
 
-static void crypto_authenc_esn_free(struct crypto_instance *inst)
-{
-       struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
-
-       crypto_drop_skcipher(&ctx->enc);
-       crypto_drop_ahash(&ctx->auth);
-       kfree(inst);
-}
-
 static struct crypto_template crypto_authenc_esn_tmpl = {
        .name = "authencesn",
-       .alloc = crypto_authenc_esn_alloc,
-       .free = crypto_authenc_esn_free,
+       .create = crypto_authenc_esn_create,
        .module = THIS_MODULE,
 };
 
index a4d1a5eda18b4e9758ec899fdf48c6f1359a8c14..cc31ea4335bf3640b25499cb3b5aea21e65ae778 100644 (file)
@@ -36,14 +36,20 @@ struct crypto_rfc4309_ctx {
        u8 nonce[3];
 };
 
+struct crypto_rfc4309_req_ctx {
+       struct scatterlist src[3];
+       struct scatterlist dst[3];
+       struct aead_request subreq;
+};
+
 struct crypto_ccm_req_priv_ctx {
        u8 odata[16];
        u8 idata[16];
        u8 auth_tag[16];
        u32 ilen;
        u32 flags;
-       struct scatterlist src[2];
-       struct scatterlist dst[2];
+       struct scatterlist src[3];
+       struct scatterlist dst[3];
        struct ablkcipher_request abreq;
 };
 
@@ -265,7 +271,7 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
        /* format associated data and compute into mac */
        if (assoclen) {
                pctx->ilen = format_adata(idata, assoclen);
-               get_data_to_compute(cipher, pctx, req->assoc, req->assoclen);
+               get_data_to_compute(cipher, pctx, req->src, req->assoclen);
        } else {
                pctx->ilen = 0;
        }
@@ -286,7 +292,8 @@ static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
        u8 *odata = pctx->odata;
 
        if (!err)
-               scatterwalk_map_and_copy(odata, req->dst, req->cryptlen,
+               scatterwalk_map_and_copy(odata, req->dst,
+                                        req->assoclen + req->cryptlen,
                                         crypto_aead_authsize(aead), 1);
        aead_request_complete(req, err);
 }
@@ -300,6 +307,41 @@ static inline int crypto_ccm_check_iv(const u8 *iv)
        return 0;
 }
 
+static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)
+{
+       struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
+       struct scatterlist *sg;
+       u8 *iv = req->iv;
+       int err;
+
+       err = crypto_ccm_check_iv(iv);
+       if (err)
+               return err;
+
+       pctx->flags = aead_request_flags(req);
+
+        /* Note: rfc 3610 and NIST 800-38C require counter of
+        * zero to encrypt auth tag.
+        */
+       memset(iv + 15 - iv[0], 0, iv[0] + 1);
+
+       sg_init_table(pctx->src, 3);
+       sg_set_buf(pctx->src, tag, 16);
+       sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
+       if (sg != pctx->src + 1)
+               sg_chain(pctx->src, 2, sg);
+
+       if (req->src != req->dst) {
+               sg_init_table(pctx->dst, 3);
+               sg_set_buf(pctx->dst, tag, 16);
+               sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
+               if (sg != pctx->dst + 1)
+                       sg_chain(pctx->dst, 2, sg);
+       }
+
+       return 0;
+}
+
 static int crypto_ccm_encrypt(struct aead_request *req)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
@@ -312,32 +354,17 @@ static int crypto_ccm_encrypt(struct aead_request *req)
        u8 *iv = req->iv;
        int err;
 
-       err = crypto_ccm_check_iv(iv);
+       err = crypto_ccm_init_crypt(req, odata);
        if (err)
                return err;
 
-       pctx->flags = aead_request_flags(req);
-
-       err = crypto_ccm_auth(req, req->src, cryptlen);
+       err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
        if (err)
                return err;
 
-        /* Note: rfc 3610 and NIST 800-38C require counter of
-        * zero to encrypt auth tag.
-        */
-       memset(iv + 15 - iv[0], 0, iv[0] + 1);
-
-       sg_init_table(pctx->src, 2);
-       sg_set_buf(pctx->src, odata, 16);
-       scatterwalk_sg_chain(pctx->src, 2, req->src);
-
        dst = pctx->src;
-       if (req->src != req->dst) {
-               sg_init_table(pctx->dst, 2);
-               sg_set_buf(pctx->dst, odata, 16);
-               scatterwalk_sg_chain(pctx->dst, 2, req->dst);
+       if (req->src != req->dst)
                dst = pctx->dst;
-       }
 
        ablkcipher_request_set_tfm(abreq, ctx->ctr);
        ablkcipher_request_set_callback(abreq, pctx->flags,
@@ -348,7 +375,7 @@ static int crypto_ccm_encrypt(struct aead_request *req)
                return err;
 
        /* copy authtag to end of dst */
-       scatterwalk_map_and_copy(odata, req->dst, cryptlen,
+       scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,
                                 crypto_aead_authsize(aead), 1);
        return err;
 }
@@ -361,9 +388,14 @@ static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
        unsigned int authsize = crypto_aead_authsize(aead);
        unsigned int cryptlen = req->cryptlen - authsize;
+       struct scatterlist *dst;
+
+       pctx->flags = 0;
+
+       dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
 
        if (!err) {
-               err = crypto_ccm_auth(req, req->dst, cryptlen);
+               err = crypto_ccm_auth(req, dst, cryptlen);
                if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
                        err = -EBADMSG;
        }
@@ -384,31 +416,18 @@ static int crypto_ccm_decrypt(struct aead_request *req)
        u8 *iv = req->iv;
        int err;
 
-       if (cryptlen < authsize)
-               return -EINVAL;
        cryptlen -= authsize;
 
-       err = crypto_ccm_check_iv(iv);
+       err = crypto_ccm_init_crypt(req, authtag);
        if (err)
                return err;
 
-       pctx->flags = aead_request_flags(req);
-
-       scatterwalk_map_and_copy(authtag, req->src, cryptlen, authsize, 0);
-
-       memset(iv + 15 - iv[0], 0, iv[0] + 1);
-
-       sg_init_table(pctx->src, 2);
-       sg_set_buf(pctx->src, authtag, 16);
-       scatterwalk_sg_chain(pctx->src, 2, req->src);
+       scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,
+                                authsize, 0);
 
        dst = pctx->src;
-       if (req->src != req->dst) {
-               sg_init_table(pctx->dst, 2);
-               sg_set_buf(pctx->dst, authtag, 16);
-               scatterwalk_sg_chain(pctx->dst, 2, req->dst);
+       if (req->src != req->dst)
                dst = pctx->dst;
-       }
 
        ablkcipher_request_set_tfm(abreq, ctx->ctr);
        ablkcipher_request_set_callback(abreq, pctx->flags,
@@ -418,7 +437,7 @@ static int crypto_ccm_decrypt(struct aead_request *req)
        if (err)
                return err;
 
-       err = crypto_ccm_auth(req, req->dst, cryptlen);
+       err = crypto_ccm_auth(req, sg_next(dst), cryptlen);
        if (err)
                return err;
 
@@ -429,11 +448,11 @@ static int crypto_ccm_decrypt(struct aead_request *req)
        return err;
 }
 
-static int crypto_ccm_init_tfm(struct crypto_tfm *tfm)
+static int crypto_ccm_init_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_instance *inst = (void *)tfm->__crt_alg;
-       struct ccm_instance_ctx *ictx = crypto_instance_ctx(inst);
-       struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct aead_instance *inst = aead_alg_instance(tfm);
+       struct ccm_instance_ctx *ictx = aead_instance_ctx(inst);
+       struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
        struct crypto_cipher *cipher;
        struct crypto_ablkcipher *ctr;
        unsigned long align;
@@ -451,9 +470,10 @@ static int crypto_ccm_init_tfm(struct crypto_tfm *tfm)
        ctx->cipher = cipher;
        ctx->ctr = ctr;
 
-       align = crypto_tfm_alg_alignmask(tfm);
+       align = crypto_aead_alignmask(tfm);
        align &= ~(crypto_tfm_ctx_alignment() - 1);
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
+       crypto_aead_set_reqsize(
+               tfm,
                align + sizeof(struct crypto_ccm_req_priv_ctx) +
                crypto_ablkcipher_reqsize(ctr));
 
@@ -464,21 +484,31 @@ err_free_cipher:
        return err;
 }
 
-static void crypto_ccm_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
 
        crypto_free_cipher(ctx->cipher);
        crypto_free_ablkcipher(ctx->ctr);
 }
 
-static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
-                                                      const char *full_name,
-                                                      const char *ctr_name,
-                                                      const char *cipher_name)
+static void crypto_ccm_free(struct aead_instance *inst)
+{
+       struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
+
+       crypto_drop_spawn(&ctx->cipher);
+       crypto_drop_skcipher(&ctx->ctr);
+       kfree(inst);
+}
+
+static int crypto_ccm_create_common(struct crypto_template *tmpl,
+                                   struct rtattr **tb,
+                                   const char *full_name,
+                                   const char *ctr_name,
+                                   const char *cipher_name)
 {
        struct crypto_attr_type *algt;
-       struct crypto_instance *inst;
+       struct aead_instance *inst;
        struct crypto_alg *ctr;
        struct crypto_alg *cipher;
        struct ccm_instance_ctx *ictx;
@@ -486,15 +516,15 @@ static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
 
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
-               return ERR_CAST(algt);
+               return PTR_ERR(algt);
 
        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        cipher = crypto_alg_mod_lookup(cipher_name,  CRYPTO_ALG_TYPE_CIPHER,
                                       CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(cipher))
-               return ERR_CAST(cipher);
+               return PTR_ERR(cipher);
 
        err = -EINVAL;
        if (cipher->cra_blocksize != 16)
@@ -505,14 +535,15 @@ static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
        if (!inst)
                goto out_put_cipher;
 
-       ictx = crypto_instance_ctx(inst);
+       ictx = aead_instance_ctx(inst);
 
-       err = crypto_init_spawn(&ictx->cipher, cipher, inst,
+       err = crypto_init_spawn(&ictx->cipher, cipher,
+                               aead_crypto_instance(inst),
                                CRYPTO_ALG_TYPE_MASK);
        if (err)
                goto err_free_inst;
 
-       crypto_set_skcipher_spawn(&ictx->ctr, inst);
+       crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst));
        err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
                                   crypto_requires_sync(algt->type,
                                                        algt->mask));
@@ -531,33 +562,39 @@ static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
                goto err_drop_ctr;
 
        err = -ENAMETOOLONG;
-       if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+       if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
                     "ccm_base(%s,%s)", ctr->cra_driver_name,
                     cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
                goto err_drop_ctr;
 
-       memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
-
-       inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-       inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
-       inst->alg.cra_priority = cipher->cra_priority + ctr->cra_priority;
-       inst->alg.cra_blocksize = 1;
-       inst->alg.cra_alignmask = cipher->cra_alignmask | ctr->cra_alignmask |
-                                 (__alignof__(u32) - 1);
-       inst->alg.cra_type = &crypto_aead_type;
-       inst->alg.cra_aead.ivsize = 16;
-       inst->alg.cra_aead.maxauthsize = 16;
-       inst->alg.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
-       inst->alg.cra_init = crypto_ccm_init_tfm;
-       inst->alg.cra_exit = crypto_ccm_exit_tfm;
-       inst->alg.cra_aead.setkey = crypto_ccm_setkey;
-       inst->alg.cra_aead.setauthsize = crypto_ccm_setauthsize;
-       inst->alg.cra_aead.encrypt = crypto_ccm_encrypt;
-       inst->alg.cra_aead.decrypt = crypto_ccm_decrypt;
+       memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
+
+       inst->alg.base.cra_flags = ctr->cra_flags & CRYPTO_ALG_ASYNC;
+       inst->alg.base.cra_priority = (cipher->cra_priority +
+                                      ctr->cra_priority) / 2;
+       inst->alg.base.cra_blocksize = 1;
+       inst->alg.base.cra_alignmask = cipher->cra_alignmask |
+                                      ctr->cra_alignmask |
+                                      (__alignof__(u32) - 1);
+       inst->alg.ivsize = 16;
+       inst->alg.maxauthsize = 16;
+       inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
+       inst->alg.init = crypto_ccm_init_tfm;
+       inst->alg.exit = crypto_ccm_exit_tfm;
+       inst->alg.setkey = crypto_ccm_setkey;
+       inst->alg.setauthsize = crypto_ccm_setauthsize;
+       inst->alg.encrypt = crypto_ccm_encrypt;
+       inst->alg.decrypt = crypto_ccm_decrypt;
+
+       inst->free = crypto_ccm_free;
+
+       err = aead_register_instance(tmpl, inst);
+       if (err)
+               goto err_drop_ctr;
 
-out:
+out_put_cipher:
        crypto_mod_put(cipher);
-       return inst;
+       return err;
 
 err_drop_ctr:
        crypto_drop_skcipher(&ictx->ctr);
@@ -565,12 +602,10 @@ err_drop_cipher:
        crypto_drop_spawn(&ictx->cipher);
 err_free_inst:
        kfree(inst);
-out_put_cipher:
-       inst = ERR_PTR(err);
-       goto out;
+       goto out_put_cipher;
 }
 
-static struct crypto_instance *crypto_ccm_alloc(struct rtattr **tb)
+static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
 {
        const char *cipher_name;
        char ctr_name[CRYPTO_MAX_ALG_NAME];
@@ -578,36 +613,28 @@ static struct crypto_instance *crypto_ccm_alloc(struct rtattr **tb)
 
        cipher_name = crypto_attr_alg_name(tb[1]);
        if (IS_ERR(cipher_name))
-               return ERR_CAST(cipher_name);
+               return PTR_ERR(cipher_name);
 
        if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
                     cipher_name) >= CRYPTO_MAX_ALG_NAME)
-               return ERR_PTR(-ENAMETOOLONG);
+               return -ENAMETOOLONG;
 
        if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
            CRYPTO_MAX_ALG_NAME)
-               return ERR_PTR(-ENAMETOOLONG);
+               return -ENAMETOOLONG;
 
-       return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
-}
-
-static void crypto_ccm_free(struct crypto_instance *inst)
-{
-       struct ccm_instance_ctx *ctx = crypto_instance_ctx(inst);
-
-       crypto_drop_spawn(&ctx->cipher);
-       crypto_drop_skcipher(&ctx->ctr);
-       kfree(inst);
+       return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
+                                       cipher_name);
 }
 
 static struct crypto_template crypto_ccm_tmpl = {
        .name = "ccm",
-       .alloc = crypto_ccm_alloc,
-       .free = crypto_ccm_free,
+       .create = crypto_ccm_create,
        .module = THIS_MODULE,
 };
 
-static struct crypto_instance *crypto_ccm_base_alloc(struct rtattr **tb)
+static int crypto_ccm_base_create(struct crypto_template *tmpl,
+                                 struct rtattr **tb)
 {
        const char *ctr_name;
        const char *cipher_name;
@@ -615,23 +642,23 @@ static struct crypto_instance *crypto_ccm_base_alloc(struct rtattr **tb)
 
        ctr_name = crypto_attr_alg_name(tb[1]);
        if (IS_ERR(ctr_name))
-               return ERR_CAST(ctr_name);
+               return PTR_ERR(ctr_name);
 
        cipher_name = crypto_attr_alg_name(tb[2]);
        if (IS_ERR(cipher_name))
-               return ERR_CAST(cipher_name);
+               return PTR_ERR(cipher_name);
 
        if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
                     ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
-               return ERR_PTR(-ENAMETOOLONG);
+               return -ENAMETOOLONG;
 
-       return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
+       return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
+                                       cipher_name);
 }
 
 static struct crypto_template crypto_ccm_base_tmpl = {
        .name = "ccm_base",
-       .alloc = crypto_ccm_base_alloc,
-       .free = crypto_ccm_free,
+       .create = crypto_ccm_base_create,
        .module = THIS_MODULE,
 };
 
@@ -677,10 +704,12 @@ static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
 
 static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
 {
-       struct aead_request *subreq = aead_request_ctx(req);
+       struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
+       struct aead_request *subreq = &rctx->subreq;
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
        struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
        struct crypto_aead *child = ctx->child;
+       struct scatterlist *sg;
        u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
                           crypto_aead_alignmask(child) + 1);
 
@@ -690,17 +719,38 @@ static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
        memcpy(iv + 1, ctx->nonce, 3);
        memcpy(iv + 4, req->iv, 8);
 
+       scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0);
+
+       sg_init_table(rctx->src, 3);
+       sg_set_buf(rctx->src, iv + 16, req->assoclen - 8);
+       sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
+       if (sg != rctx->src + 1)
+               sg_chain(rctx->src, 2, sg);
+
+       if (req->src != req->dst) {
+               sg_init_table(rctx->dst, 3);
+               sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8);
+               sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
+               if (sg != rctx->dst + 1)
+                       sg_chain(rctx->dst, 2, sg);
+       }
+
        aead_request_set_tfm(subreq, child);
        aead_request_set_callback(subreq, req->base.flags, req->base.complete,
                                  req->base.data);
-       aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
-       aead_request_set_assoc(subreq, req->assoc, req->assoclen);
+       aead_request_set_crypt(subreq, rctx->src,
+                              req->src == req->dst ? rctx->src : rctx->dst,
+                              req->cryptlen, iv);
+       aead_request_set_ad(subreq, req->assoclen - 8);
 
        return subreq;
 }
 
 static int crypto_rfc4309_encrypt(struct aead_request *req)
 {
+       if (req->assoclen != 16 && req->assoclen != 20)
+               return -EINVAL;
+
        req = crypto_rfc4309_crypt(req);
 
        return crypto_aead_encrypt(req);
@@ -708,16 +758,19 @@ static int crypto_rfc4309_encrypt(struct aead_request *req)
 
 static int crypto_rfc4309_decrypt(struct aead_request *req)
 {
+       if (req->assoclen != 16 && req->assoclen != 20)
+               return -EINVAL;
+
        req = crypto_rfc4309_crypt(req);
 
        return crypto_aead_decrypt(req);
 }
 
-static int crypto_rfc4309_init_tfm(struct crypto_tfm *tfm)
+static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_instance *inst = (void *)tfm->__crt_alg;
-       struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
-       struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct aead_instance *inst = aead_alg_instance(tfm);
+       struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
+       struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
        struct crypto_aead *aead;
        unsigned long align;
 
@@ -729,115 +782,118 @@ static int crypto_rfc4309_init_tfm(struct crypto_tfm *tfm)
 
        align = crypto_aead_alignmask(aead);
        align &= ~(crypto_tfm_ctx_alignment() - 1);
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-               sizeof(struct aead_request) +
+       crypto_aead_set_reqsize(
+               tfm,
+               sizeof(struct crypto_rfc4309_req_ctx) +
                ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
-               align + 16);
+               align + 32);
 
        return 0;
 }
 
-static void crypto_rfc4309_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
 {
-       struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
 
        crypto_free_aead(ctx->child);
 }
 
-static struct crypto_instance *crypto_rfc4309_alloc(struct rtattr **tb)
+static void crypto_rfc4309_free(struct aead_instance *inst)
+{
+       crypto_drop_aead(aead_instance_ctx(inst));
+       kfree(inst);
+}
+
+static int crypto_rfc4309_create(struct crypto_template *tmpl,
+                                struct rtattr **tb)
 {
        struct crypto_attr_type *algt;
-       struct crypto_instance *inst;
+       struct aead_instance *inst;
        struct crypto_aead_spawn *spawn;
-       struct crypto_alg *alg;
+       struct aead_alg *alg;
        const char *ccm_name;
        int err;
 
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
-               return ERR_CAST(algt);
+               return PTR_ERR(algt);
 
        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        ccm_name = crypto_attr_alg_name(tb[1]);
        if (IS_ERR(ccm_name))
-               return ERR_CAST(ccm_name);
+               return PTR_ERR(ccm_name);
 
        inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
        if (!inst)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
-       spawn = crypto_instance_ctx(inst);
-       crypto_set_aead_spawn(spawn, inst);
+       spawn = aead_instance_ctx(inst);
+       crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
        err = crypto_grab_aead(spawn, ccm_name, 0,
                               crypto_requires_sync(algt->type, algt->mask));
        if (err)
                goto out_free_inst;
 
-       alg = crypto_aead_spawn_alg(spawn);
+       alg = crypto_spawn_aead_alg(spawn);
 
        err = -EINVAL;
 
        /* We only support 16-byte blocks. */
-       if (alg->cra_aead.ivsize != 16)
+       if (crypto_aead_alg_ivsize(alg) != 16)
                goto out_drop_alg;
 
        /* Not a stream cipher? */
-       if (alg->cra_blocksize != 1)
+       if (alg->base.cra_blocksize != 1)
                goto out_drop_alg;
 
        err = -ENAMETOOLONG;
-       if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-                    "rfc4309(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
-           snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-                    "rfc4309(%s)", alg->cra_driver_name) >=
+       if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+                    "rfc4309(%s)", alg->base.cra_name) >=
+           CRYPTO_MAX_ALG_NAME ||
+           snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+                    "rfc4309(%s)", alg->base.cra_driver_name) >=
            CRYPTO_MAX_ALG_NAME)
                goto out_drop_alg;
 
-       inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-       inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
-       inst->alg.cra_priority = alg->cra_priority;
-       inst->alg.cra_blocksize = 1;
-       inst->alg.cra_alignmask = alg->cra_alignmask;
-       inst->alg.cra_type = &crypto_nivaead_type;
+       inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
+       inst->alg.base.cra_priority = alg->base.cra_priority;
+       inst->alg.base.cra_blocksize = 1;
+       inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
 
-       inst->alg.cra_aead.ivsize = 8;
-       inst->alg.cra_aead.maxauthsize = 16;
+       inst->alg.ivsize = 8;
+       inst->alg.maxauthsize = 16;
 
-       inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
+       inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
 
-       inst->alg.cra_init = crypto_rfc4309_init_tfm;
-       inst->alg.cra_exit = crypto_rfc4309_exit_tfm;
+       inst->alg.init = crypto_rfc4309_init_tfm;
+       inst->alg.exit = crypto_rfc4309_exit_tfm;
 
-       inst->alg.cra_aead.setkey = crypto_rfc4309_setkey;
-       inst->alg.cra_aead.setauthsize = crypto_rfc4309_setauthsize;
-       inst->alg.cra_aead.encrypt = crypto_rfc4309_encrypt;
-       inst->alg.cra_aead.decrypt = crypto_rfc4309_decrypt;
+       inst->alg.setkey = crypto_rfc4309_setkey;
+       inst->alg.setauthsize = crypto_rfc4309_setauthsize;
+       inst->alg.encrypt = crypto_rfc4309_encrypt;
+       inst->alg.decrypt = crypto_rfc4309_decrypt;
 
-       inst->alg.cra_aead.geniv = "seqiv";
+       inst->free = crypto_rfc4309_free;
+
+       err = aead_register_instance(tmpl, inst);
+       if (err)
+               goto out_drop_alg;
 
 out:
-       return inst;
+       return err;
 
 out_drop_alg:
        crypto_drop_aead(spawn);
 out_free_inst:
        kfree(inst);
-       inst = ERR_PTR(err);
        goto out;
 }
 
-static void crypto_rfc4309_free(struct crypto_instance *inst)
-{
-       crypto_drop_spawn(crypto_instance_ctx(inst));
-       kfree(inst);
-}
-
 static struct crypto_template crypto_rfc4309_tmpl = {
        .name = "rfc4309",
-       .alloc = crypto_rfc4309_alloc,
-       .free = crypto_rfc4309_free,
+       .create = crypto_rfc4309_create,
        .module = THIS_MODULE,
 };
 
index fa42e708aa9616d82ec18191a505fcc7e24abab4..da9c89968223673e08160fd6656cd0907437e070 100644 (file)
 #include <linux/crypto.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-
-#define CHACHA20_NONCE_SIZE 16
-#define CHACHA20_KEY_SIZE   32
-#define CHACHA20_BLOCK_SIZE 64
-
-struct chacha20_ctx {
-       u32 key[8];
-};
+#include <crypto/chacha20.h>
 
 static inline u32 rotl32(u32 v, u8 n)
 {
@@ -108,7 +101,7 @@ static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src,
        }
 }
 
-static void chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv)
+void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv)
 {
        static const char constant[16] = "expand 32-byte k";
 
@@ -129,8 +122,9 @@ static void chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv)
        state[14] = le32_to_cpuvp(iv +  8);
        state[15] = le32_to_cpuvp(iv + 12);
 }
+EXPORT_SYMBOL_GPL(crypto_chacha20_init);
 
-static int chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
+int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
                           unsigned int keysize)
 {
        struct chacha20_ctx *ctx = crypto_tfm_ctx(tfm);
@@ -144,8 +138,9 @@ static int chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(crypto_chacha20_setkey);
 
-static int chacha20_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+int crypto_chacha20_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                          struct scatterlist *src, unsigned int nbytes)
 {
        struct blkcipher_walk walk;
@@ -155,7 +150,7 @@ static int chacha20_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
        blkcipher_walk_init(&walk, dst, src, nbytes);
        err = blkcipher_walk_virt_block(desc, &walk, CHACHA20_BLOCK_SIZE);
 
-       chacha20_init(state, crypto_blkcipher_ctx(desc->tfm), walk.iv);
+       crypto_chacha20_init(state, crypto_blkcipher_ctx(desc->tfm), walk.iv);
 
        while (walk.nbytes >= CHACHA20_BLOCK_SIZE) {
                chacha20_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr,
@@ -172,6 +167,7 @@ static int chacha20_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
 
        return err;
 }
+EXPORT_SYMBOL_GPL(crypto_chacha20_crypt);
 
 static struct crypto_alg alg = {
        .cra_name               = "chacha20",
@@ -187,11 +183,11 @@ static struct crypto_alg alg = {
                .blkcipher = {
                        .min_keysize    = CHACHA20_KEY_SIZE,
                        .max_keysize    = CHACHA20_KEY_SIZE,
-                       .ivsize         = CHACHA20_NONCE_SIZE,
+                       .ivsize         = CHACHA20_IV_SIZE,
                        .geniv          = "seqiv",
-                       .setkey         = chacha20_setkey,
-                       .encrypt        = chacha20_crypt,
-                       .decrypt        = chacha20_crypt,
+                       .setkey         = crypto_chacha20_setkey,
+                       .encrypt        = crypto_chacha20_crypt,
+                       .decrypt        = crypto_chacha20_crypt,
                },
        },
 };
index 7b46ed799a64cdc6710408a16a847147ccd58290..99c3cce0129035b5c41e2e8b4ebdab5ecd9fde2e 100644 (file)
@@ -13,6 +13,8 @@
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/scatterwalk.h>
+#include <crypto/chacha20.h>
+#include <crypto/poly1305.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 
 #include "internal.h"
 
-#define POLY1305_BLOCK_SIZE    16
-#define POLY1305_DIGEST_SIZE   16
-#define POLY1305_KEY_SIZE      32
-#define CHACHA20_KEY_SIZE      32
-#define CHACHA20_IV_SIZE       16
 #define CHACHAPOLY_IV_SIZE     12
 
 struct chachapoly_instance_ctx {
@@ -60,12 +57,16 @@ struct chacha_req {
 };
 
 struct chachapoly_req_ctx {
+       struct scatterlist src[2];
+       struct scatterlist dst[2];
        /* the key we generate for Poly1305 using Chacha20 */
        u8 key[POLY1305_KEY_SIZE];
        /* calculated Poly1305 tag */
        u8 tag[POLY1305_DIGEST_SIZE];
        /* length of data to en/decrypt, without ICV */
        unsigned int cryptlen;
+       /* Actual AD, excluding IV */
+       unsigned int assoclen;
        union {
                struct poly_req poly;
                struct chacha_req chacha;
@@ -98,7 +99,9 @@ static int poly_verify_tag(struct aead_request *req)
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
        u8 tag[sizeof(rctx->tag)];
 
-       scatterwalk_map_and_copy(tag, req->src, rctx->cryptlen, sizeof(tag), 0);
+       scatterwalk_map_and_copy(tag, req->src,
+                                req->assoclen + rctx->cryptlen,
+                                sizeof(tag), 0);
        if (crypto_memneq(tag, rctx->tag, sizeof(tag)))
                return -EBADMSG;
        return 0;
@@ -108,7 +111,8 @@ static int poly_copy_tag(struct aead_request *req)
 {
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
 
-       scatterwalk_map_and_copy(rctx->tag, req->dst, rctx->cryptlen,
+       scatterwalk_map_and_copy(rctx->tag, req->dst,
+                                req->assoclen + rctx->cryptlen,
                                 sizeof(rctx->tag), 1);
        return 0;
 }
@@ -123,14 +127,24 @@ static int chacha_decrypt(struct aead_request *req)
        struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
        struct chacha_req *creq = &rctx->u.chacha;
+       struct scatterlist *src, *dst;
        int err;
 
        chacha_iv(creq->iv, req, 1);
 
+       sg_init_table(rctx->src, 2);
+       src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
+       dst = src;
+
+       if (req->src != req->dst) {
+               sg_init_table(rctx->dst, 2);
+               dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
+       }
+
        ablkcipher_request_set_callback(&creq->req, aead_request_flags(req),
                                        chacha_decrypt_done, req);
        ablkcipher_request_set_tfm(&creq->req, ctx->chacha);
-       ablkcipher_request_set_crypt(&creq->req, req->src, req->dst,
+       ablkcipher_request_set_crypt(&creq->req, src, dst,
                                     rctx->cryptlen, creq->iv);
        err = crypto_ablkcipher_decrypt(&creq->req);
        if (err)
@@ -156,14 +170,15 @@ static void poly_tail_done(struct crypto_async_request *areq, int err)
 
 static int poly_tail(struct aead_request *req)
 {
-       struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
        struct poly_req *preq = &rctx->u.poly;
        __le64 len;
        int err;
 
        sg_init_table(preq->src, 1);
-       len = cpu_to_le64(req->assoclen);
+       len = cpu_to_le64(rctx->assoclen);
        memcpy(&preq->tail.assoclen, &len, sizeof(len));
        len = cpu_to_le64(rctx->cryptlen);
        memcpy(&preq->tail.cryptlen, &len, sizeof(len));
@@ -228,6 +243,9 @@ static int poly_cipher(struct aead_request *req)
        if (rctx->cryptlen == req->cryptlen) /* encrypting */
                crypt = req->dst;
 
+       sg_init_table(rctx->src, 2);
+       crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen);
+
        ahash_request_set_callback(&preq->req, aead_request_flags(req),
                                   poly_cipher_done, req);
        ahash_request_set_tfm(&preq->req, ctx->poly);
@@ -253,7 +271,7 @@ static int poly_adpad(struct aead_request *req)
        unsigned int padlen, bs = POLY1305_BLOCK_SIZE;
        int err;
 
-       padlen = (bs - (req->assoclen % bs)) % bs;
+       padlen = (bs - (rctx->assoclen % bs)) % bs;
        memset(preq->pad, 0, sizeof(preq->pad));
        sg_init_table(preq->src, 1);
        sg_set_buf(preq->src, preq->pad, padlen);
@@ -285,7 +303,7 @@ static int poly_ad(struct aead_request *req)
        ahash_request_set_callback(&preq->req, aead_request_flags(req),
                                   poly_ad_done, req);
        ahash_request_set_tfm(&preq->req, ctx->poly);
-       ahash_request_set_crypt(&preq->req, req->assoc, NULL, req->assoclen);
+       ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen);
 
        err = crypto_ahash_update(&preq->req);
        if (err)
@@ -351,11 +369,20 @@ static void poly_genkey_done(struct crypto_async_request *areq, int err)
 
 static int poly_genkey(struct aead_request *req)
 {
-       struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
+       struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+       struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
        struct chacha_req *creq = &rctx->u.chacha;
        int err;
 
+       rctx->assoclen = req->assoclen;
+
+       if (crypto_aead_ivsize(tfm) == 8) {
+               if (rctx->assoclen < 8)
+                       return -EINVAL;
+               rctx->assoclen -= 8;
+       }
+
        sg_init_table(creq->src, 1);
        memset(rctx->key, 0, sizeof(rctx->key));
        sg_set_buf(creq->src, rctx->key, sizeof(rctx->key));
@@ -385,14 +412,24 @@ static int chacha_encrypt(struct aead_request *req)
        struct chachapoly_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
        struct chacha_req *creq = &rctx->u.chacha;
+       struct scatterlist *src, *dst;
        int err;
 
        chacha_iv(creq->iv, req, 1);
 
+       sg_init_table(rctx->src, 2);
+       src = scatterwalk_ffwd(rctx->src, req->src, req->assoclen);
+       dst = src;
+
+       if (req->src != req->dst) {
+               sg_init_table(rctx->dst, 2);
+               dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
+       }
+
        ablkcipher_request_set_callback(&creq->req, aead_request_flags(req),
                                        chacha_encrypt_done, req);
        ablkcipher_request_set_tfm(&creq->req, ctx->chacha);
-       ablkcipher_request_set_crypt(&creq->req, req->src, req->dst,
+       ablkcipher_request_set_crypt(&creq->req, src, dst,
                                     req->cryptlen, creq->iv);
        err = crypto_ablkcipher_encrypt(&creq->req);
        if (err)
@@ -426,8 +463,6 @@ static int chachapoly_decrypt(struct aead_request *req)
 {
        struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
 
-       if (req->cryptlen < POLY1305_DIGEST_SIZE)
-               return -EINVAL;
        rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE;
 
        /* decrypt call chain:
@@ -476,11 +511,11 @@ static int chachapoly_setauthsize(struct crypto_aead *tfm,
        return 0;
 }
 
-static int chachapoly_init(struct crypto_tfm *tfm)
+static int chachapoly_init(struct crypto_aead *tfm)
 {
-       struct crypto_instance *inst = (void *)tfm->__crt_alg;
-       struct chachapoly_instance_ctx *ictx = crypto_instance_ctx(inst);
-       struct chachapoly_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct aead_instance *inst = aead_alg_instance(tfm);
+       struct chachapoly_instance_ctx *ictx = aead_instance_ctx(inst);
+       struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
        struct crypto_ablkcipher *chacha;
        struct crypto_ahash *poly;
        unsigned long align;
@@ -499,77 +534,87 @@ static int chachapoly_init(struct crypto_tfm *tfm)
        ctx->poly = poly;
        ctx->saltlen = ictx->saltlen;
 
-       align = crypto_tfm_alg_alignmask(tfm);
+       align = crypto_aead_alignmask(tfm);
        align &= ~(crypto_tfm_ctx_alignment() - 1);
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-                               align + offsetof(struct chachapoly_req_ctx, u) +
-                               max(offsetof(struct chacha_req, req) +
-                                   sizeof(struct ablkcipher_request) +
-                                   crypto_ablkcipher_reqsize(chacha),
-                                   offsetof(struct poly_req, req) +
-                                   sizeof(struct ahash_request) +
-                                   crypto_ahash_reqsize(poly)));
+       crypto_aead_set_reqsize(
+               tfm,
+               align + offsetof(struct chachapoly_req_ctx, u) +
+               max(offsetof(struct chacha_req, req) +
+                   sizeof(struct ablkcipher_request) +
+                   crypto_ablkcipher_reqsize(chacha),
+                   offsetof(struct poly_req, req) +
+                   sizeof(struct ahash_request) +
+                   crypto_ahash_reqsize(poly)));
 
        return 0;
 }
 
-static void chachapoly_exit(struct crypto_tfm *tfm)
+static void chachapoly_exit(struct crypto_aead *tfm)
 {
-       struct chachapoly_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct chachapoly_ctx *ctx = crypto_aead_ctx(tfm);
 
        crypto_free_ahash(ctx->poly);
        crypto_free_ablkcipher(ctx->chacha);
 }
 
-static struct crypto_instance *chachapoly_alloc(struct rtattr **tb,
-                                               const char *name,
-                                               unsigned int ivsize)
+static void chachapoly_free(struct aead_instance *inst)
+{
+       struct chachapoly_instance_ctx *ctx = aead_instance_ctx(inst);
+
+       crypto_drop_skcipher(&ctx->chacha);
+       crypto_drop_ahash(&ctx->poly);
+       kfree(inst);
+}
+
+static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
+                            const char *name, unsigned int ivsize)
 {
        struct crypto_attr_type *algt;
-       struct crypto_instance *inst;
+       struct aead_instance *inst;
        struct crypto_alg *chacha;
        struct crypto_alg *poly;
-       struct ahash_alg *poly_ahash;
+       struct hash_alg_common *poly_hash;
        struct chachapoly_instance_ctx *ctx;
        const char *chacha_name, *poly_name;
        int err;
 
        if (ivsize > CHACHAPOLY_IV_SIZE)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
-               return ERR_CAST(algt);
+               return PTR_ERR(algt);
 
        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
        chacha_name = crypto_attr_alg_name(tb[1]);
        if (IS_ERR(chacha_name))
-               return ERR_CAST(chacha_name);
+               return PTR_ERR(chacha_name);
        poly_name = crypto_attr_alg_name(tb[2]);
        if (IS_ERR(poly_name))
-               return ERR_CAST(poly_name);
+               return PTR_ERR(poly_name);
 
        poly = crypto_find_alg(poly_name, &crypto_ahash_type,
                               CRYPTO_ALG_TYPE_HASH,
                               CRYPTO_ALG_TYPE_AHASH_MASK);
        if (IS_ERR(poly))
-               return ERR_CAST(poly);
+               return PTR_ERR(poly);
 
        err = -ENOMEM;
        inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
        if (!inst)
                goto out_put_poly;
 
-       ctx = crypto_instance_ctx(inst);
+       ctx = aead_instance_ctx(inst);
        ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize;
-       poly_ahash = container_of(poly, struct ahash_alg, halg.base);
-       err = crypto_init_ahash_spawn(&ctx->poly, &poly_ahash->halg, inst);
+       poly_hash = __crypto_hash_alg_common(poly);
+       err = crypto_init_ahash_spawn(&ctx->poly, poly_hash,
+                                     aead_crypto_instance(inst));
        if (err)
                goto err_free_inst;
 
-       crypto_set_skcipher_spawn(&ctx->chacha, inst);
+       crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst));
        err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0,
                                   crypto_requires_sync(algt->type,
                                                        algt->mask));
@@ -587,37 +632,42 @@ static struct crypto_instance *chachapoly_alloc(struct rtattr **tb,
                goto out_drop_chacha;
 
        err = -ENAMETOOLONG;
-       if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+       if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
                     "%s(%s,%s)", name, chacha_name,
                     poly_name) >= CRYPTO_MAX_ALG_NAME)
                goto out_drop_chacha;
-       if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+       if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
                     "%s(%s,%s)", name, chacha->cra_driver_name,
                     poly->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
                goto out_drop_chacha;
 
-       inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-       inst->alg.cra_flags |= (chacha->cra_flags |
-                               poly->cra_flags) & CRYPTO_ALG_ASYNC;
-       inst->alg.cra_priority = (chacha->cra_priority +
-                                 poly->cra_priority) / 2;
-       inst->alg.cra_blocksize = 1;
-       inst->alg.cra_alignmask = chacha->cra_alignmask | poly->cra_alignmask;
-       inst->alg.cra_type = &crypto_nivaead_type;
-       inst->alg.cra_aead.ivsize = ivsize;
-       inst->alg.cra_aead.maxauthsize = POLY1305_DIGEST_SIZE;
-       inst->alg.cra_ctxsize = sizeof(struct chachapoly_ctx) + ctx->saltlen;
-       inst->alg.cra_init = chachapoly_init;
-       inst->alg.cra_exit = chachapoly_exit;
-       inst->alg.cra_aead.encrypt = chachapoly_encrypt;
-       inst->alg.cra_aead.decrypt = chachapoly_decrypt;
-       inst->alg.cra_aead.setkey = chachapoly_setkey;
-       inst->alg.cra_aead.setauthsize = chachapoly_setauthsize;
-       inst->alg.cra_aead.geniv = "seqiv";
-
-out:
+       inst->alg.base.cra_flags = (chacha->cra_flags | poly->cra_flags) &
+                                  CRYPTO_ALG_ASYNC;
+       inst->alg.base.cra_priority = (chacha->cra_priority +
+                                      poly->cra_priority) / 2;
+       inst->alg.base.cra_blocksize = 1;
+       inst->alg.base.cra_alignmask = chacha->cra_alignmask |
+                                      poly->cra_alignmask;
+       inst->alg.base.cra_ctxsize = sizeof(struct chachapoly_ctx) +
+                                    ctx->saltlen;
+       inst->alg.ivsize = ivsize;
+       inst->alg.maxauthsize = POLY1305_DIGEST_SIZE;
+       inst->alg.init = chachapoly_init;
+       inst->alg.exit = chachapoly_exit;
+       inst->alg.encrypt = chachapoly_encrypt;
+       inst->alg.decrypt = chachapoly_decrypt;
+       inst->alg.setkey = chachapoly_setkey;
+       inst->alg.setauthsize = chachapoly_setauthsize;
+
+       inst->free = chachapoly_free;
+
+       err = aead_register_instance(tmpl, inst);
+       if (err)
+               goto out_drop_chacha;
+
+out_put_poly:
        crypto_mod_put(poly);
-       return inst;
+       return err;
 
 out_drop_chacha:
        crypto_drop_skcipher(&ctx->chacha);
@@ -625,41 +675,28 @@ err_drop_poly:
        crypto_drop_ahash(&ctx->poly);
 err_free_inst:
        kfree(inst);
-out_put_poly:
-       inst = ERR_PTR(err);
-       goto out;
-}
-
-static struct crypto_instance *rfc7539_alloc(struct rtattr **tb)
-{
-       return chachapoly_alloc(tb, "rfc7539", 12);
+       goto out_put_poly;
 }
 
-static struct crypto_instance *rfc7539esp_alloc(struct rtattr **tb)
+static int rfc7539_create(struct crypto_template *tmpl, struct rtattr **tb)
 {
-       return chachapoly_alloc(tb, "rfc7539esp", 8);
+       return chachapoly_create(tmpl, tb, "rfc7539", 12);
 }
 
-static void chachapoly_free(struct crypto_instance *inst)
+static int rfc7539esp_create(struct crypto_template *tmpl, struct rtattr **tb)
 {
-       struct chachapoly_instance_ctx *ctx = crypto_instance_ctx(inst);
-
-       crypto_drop_skcipher(&ctx->chacha);
-       crypto_drop_ahash(&ctx->poly);
-       kfree(inst);
+       return chachapoly_create(tmpl, tb, "rfc7539esp", 8);
 }
 
 static struct crypto_template rfc7539_tmpl = {
        .name = "rfc7539",
-       .alloc = rfc7539_alloc,
-       .free = chachapoly_free,
+       .create = rfc7539_create,
        .module = THIS_MODULE,
 };
 
 static struct crypto_template rfc7539esp_tmpl = {
        .name = "rfc7539esp",
-       .alloc = rfc7539esp_alloc,
-       .free = chachapoly_free,
+       .create = rfc7539esp_create,
        .module = THIS_MODULE,
 };
 
@@ -690,6 +727,5 @@ module_exit(chacha20poly1305_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
 MODULE_DESCRIPTION("ChaCha20-Poly1305 AEAD");
-MODULE_ALIAS_CRYPTO("chacha20poly1305");
 MODULE_ALIAS_CRYPTO("rfc7539");
 MODULE_ALIAS_CRYPTO("rfc7539esp");
index 22ba81f76764aff2edd614ad8fad2914df33a8a9..c81861b1350b60a1c2def7695dd16d7b0db39ade 100644 (file)
@@ -176,10 +176,9 @@ static inline void cryptd_check_internal(struct rtattr **tb, u32 *type,
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
                return;
-       if ((algt->type & CRYPTO_ALG_INTERNAL))
-               *type |= CRYPTO_ALG_INTERNAL;
-       if ((algt->mask & CRYPTO_ALG_INTERNAL))
-               *mask |= CRYPTO_ALG_INTERNAL;
+
+       *type |= algt->type & CRYPTO_ALG_INTERNAL;
+       *mask |= algt->mask & CRYPTO_ALG_INTERNAL;
 }
 
 static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent,
@@ -688,16 +687,18 @@ static void cryptd_aead_crypt(struct aead_request *req,
                        int (*crypt)(struct aead_request *req))
 {
        struct cryptd_aead_request_ctx *rctx;
+       crypto_completion_t compl;
+
        rctx = aead_request_ctx(req);
+       compl = rctx->complete;
 
        if (unlikely(err == -EINPROGRESS))
                goto out;
        aead_request_set_tfm(req, child);
        err = crypt( req );
-       req->base.complete = rctx->complete;
 out:
        local_bh_disable();
-       rctx->complete(&req->base, err);
+       compl(&req->base, err);
        local_bh_enable();
 }
 
@@ -708,7 +709,7 @@ static void cryptd_aead_encrypt(struct crypto_async_request *areq, int err)
        struct aead_request *req;
 
        req = container_of(areq, struct aead_request, base);
-       cryptd_aead_crypt(req, child, err, crypto_aead_crt(child)->encrypt);
+       cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->encrypt);
 }
 
 static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err)
@@ -718,7 +719,7 @@ static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err)
        struct aead_request *req;
 
        req = container_of(areq, struct aead_request, base);
-       cryptd_aead_crypt(req, child, err, crypto_aead_crt(child)->decrypt);
+       cryptd_aead_crypt(req, child, err, crypto_aead_alg(child)->decrypt);
 }
 
 static int cryptd_aead_enqueue(struct aead_request *req,
@@ -756,7 +757,9 @@ static int cryptd_aead_init_tfm(struct crypto_aead *tfm)
                return PTR_ERR(cipher);
 
        ctx->child = cipher;
-       crypto_aead_set_reqsize(tfm, sizeof(struct cryptd_aead_request_ctx));
+       crypto_aead_set_reqsize(
+               tfm, max((unsigned)sizeof(struct cryptd_aead_request_ctx),
+                        crypto_aead_reqsize(cipher)));
        return 0;
 }
 
@@ -775,7 +778,7 @@ static int cryptd_create_aead(struct crypto_template *tmpl,
        struct aead_alg *alg;
        const char *name;
        u32 type = 0;
-       u32 mask = 0;
+       u32 mask = CRYPTO_ALG_ASYNC;
        int err;
 
        cryptd_check_internal(tb, &type, &mask);
index 08ea2867fc8a370d9eb0f1cd0365783f5a5e4f2c..d94d99ffe8b9b6cecf2c8348241ea17738e9b457 100644 (file)
@@ -25,7 +25,6 @@
 #include <net/netlink.h>
 #include <linux/security.h>
 #include <net/net_namespace.h>
-#include <crypto/internal/aead.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/internal/rng.h>
 #include <crypto/akcipher.h>
@@ -385,34 +384,6 @@ static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
        return ERR_PTR(err);
 }
 
-static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type,
-                                              u32 mask)
-{
-       int err;
-       struct crypto_alg *alg;
-
-       type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-       type |= CRYPTO_ALG_TYPE_AEAD;
-       mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-       mask |= CRYPTO_ALG_TYPE_MASK;
-
-       for (;;) {
-               alg = crypto_lookup_aead(name,  type, mask);
-               if (!IS_ERR(alg))
-                       return alg;
-
-               err = PTR_ERR(alg);
-               if (err != -EAGAIN)
-                       break;
-               if (signal_pending(current)) {
-                       err = -EINTR;
-                       break;
-               }
-       }
-
-       return ERR_PTR(err);
-}
-
 static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
                          struct nlattr **attrs)
 {
@@ -446,9 +417,6 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
                name = p->cru_name;
 
        switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) {
-       case CRYPTO_ALG_TYPE_AEAD:
-               alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask);
-               break;
        case CRYPTO_ALG_TYPE_GIVCIPHER:
        case CRYPTO_ALG_TYPE_BLKCIPHER:
        case CRYPTO_ALG_TYPE_ABLKCIPHER:
index b6e43dc6135653eddb3e31f9659d54bc774bc6d1..b96a84560b67790845321250e1f1a799557bb4b8 100644 (file)
@@ -19,8 +19,6 @@
  */
 
 #include <crypto/internal/geniv.h>
-#include <crypto/null.h>
-#include <crypto/rng.h>
 #include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/init.h>
 
 #define MAX_IV_SIZE 16
 
-struct echainiv_ctx {
-       /* aead_geniv_ctx must be first the element */
-       struct aead_geniv_ctx geniv;
-       struct crypto_blkcipher *null;
-       u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
-};
-
 static DEFINE_PER_CPU(u32 [MAX_IV_SIZE / sizeof(u32)], echainiv_iv);
 
 /* We don't care if we get preempted and read/write IVs from the next CPU. */
@@ -103,7 +94,7 @@ static void echainiv_encrypt_complete(struct crypto_async_request *base,
 static int echainiv_encrypt(struct aead_request *req)
 {
        struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct echainiv_ctx *ctx = crypto_aead_ctx(geniv);
+       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
        struct aead_request *subreq = aead_request_ctx(req);
        crypto_completion_t compl;
        void *data;
@@ -114,7 +105,7 @@ static int echainiv_encrypt(struct aead_request *req)
        if (req->cryptlen < ivsize)
                return -EINVAL;
 
-       aead_request_set_tfm(subreq, ctx->geniv.child);
+       aead_request_set_tfm(subreq, ctx->child);
 
        compl = echainiv_encrypt_complete;
        data = req;
@@ -145,8 +136,8 @@ static int echainiv_encrypt(struct aead_request *req)
 
        aead_request_set_callback(subreq, req->base.flags, compl, data);
        aead_request_set_crypt(subreq, req->dst, req->dst,
-                              req->cryptlen - ivsize, info);
-       aead_request_set_ad(subreq, req->assoclen + ivsize);
+                              req->cryptlen, info);
+       aead_request_set_ad(subreq, req->assoclen);
 
        crypto_xor(info, ctx->salt, ivsize);
        scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
@@ -160,16 +151,16 @@ static int echainiv_encrypt(struct aead_request *req)
 static int echainiv_decrypt(struct aead_request *req)
 {
        struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct echainiv_ctx *ctx = crypto_aead_ctx(geniv);
+       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
        struct aead_request *subreq = aead_request_ctx(req);
        crypto_completion_t compl;
        void *data;
        unsigned int ivsize = crypto_aead_ivsize(geniv);
 
-       if (req->cryptlen < ivsize + crypto_aead_authsize(geniv))
+       if (req->cryptlen < ivsize)
                return -EINVAL;
 
-       aead_request_set_tfm(subreq, ctx->geniv.child);
+       aead_request_set_tfm(subreq, ctx->child);
 
        compl = req->base.complete;
        data = req->base.data;
@@ -180,61 +171,10 @@ static int echainiv_decrypt(struct aead_request *req)
        aead_request_set_ad(subreq, req->assoclen + ivsize);
 
        scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
-       if (req->src != req->dst)
-               scatterwalk_map_and_copy(req->iv, req->dst,
-                                        req->assoclen, ivsize, 1);
 
        return crypto_aead_decrypt(subreq);
 }
 
-static int echainiv_init(struct crypto_tfm *tfm)
-{
-       struct crypto_aead *geniv = __crypto_aead_cast(tfm);
-       struct echainiv_ctx *ctx = crypto_aead_ctx(geniv);
-       int err;
-
-       spin_lock_init(&ctx->geniv.lock);
-
-       crypto_aead_set_reqsize(geniv, sizeof(struct aead_request));
-
-       err = crypto_get_default_rng();
-       if (err)
-               goto out;
-
-       err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
-                                  crypto_aead_ivsize(geniv));
-       crypto_put_default_rng();
-       if (err)
-               goto out;
-
-       ctx->null = crypto_get_default_null_skcipher();
-       err = PTR_ERR(ctx->null);
-       if (IS_ERR(ctx->null))
-               goto out;
-
-       err = aead_geniv_init(tfm);
-       if (err)
-               goto drop_null;
-
-       ctx->geniv.child = geniv->child;
-       geniv->child = geniv;
-
-out:
-       return err;
-
-drop_null:
-       crypto_put_default_null_skcipher();
-       goto out;
-}
-
-static void echainiv_exit(struct crypto_tfm *tfm)
-{
-       struct echainiv_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       crypto_free_aead(ctx->geniv.child);
-       crypto_put_default_null_skcipher();
-}
-
 static int echainiv_aead_create(struct crypto_template *tmpl,
                                struct rtattr **tb)
 {
@@ -251,9 +191,6 @@ static int echainiv_aead_create(struct crypto_template *tmpl,
        spawn = aead_instance_ctx(inst);
        alg = crypto_spawn_aead_alg(spawn);
 
-       if (alg->base.cra_aead.encrypt)
-               goto done;
-
        err = -EINVAL;
        if (inst->alg.ivsize & (sizeof(u32) - 1) ||
            inst->alg.ivsize > MAX_IV_SIZE)
@@ -262,14 +199,15 @@ static int echainiv_aead_create(struct crypto_template *tmpl,
        inst->alg.encrypt = echainiv_encrypt;
        inst->alg.decrypt = echainiv_decrypt;
 
-       inst->alg.base.cra_init = echainiv_init;
-       inst->alg.base.cra_exit = echainiv_exit;
+       inst->alg.init = aead_init_geniv;
+       inst->alg.exit = aead_exit_geniv;
 
        inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
-       inst->alg.base.cra_ctxsize = sizeof(struct echainiv_ctx);
+       inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
        inst->alg.base.cra_ctxsize += inst->alg.ivsize;
 
-done:
+       inst->free = aead_geniv_free;
+
        err = aead_register_instance(tmpl, inst);
        if (err)
                goto free_inst;
index 7d32d4720564315f57a2766f5e1813d536d9ee69..ddb4f29b2fe6b0fc917ac9f3b4c2134a5b3c52e4 100644 (file)
@@ -38,6 +38,12 @@ struct crypto_rfc4106_ctx {
        u8 nonce[4];
 };
 
+struct crypto_rfc4106_req_ctx {
+       struct scatterlist src[3];
+       struct scatterlist dst[3];
+       struct aead_request subreq;
+};
+
 struct crypto_rfc4543_instance_ctx {
        struct crypto_aead_spawn aead;
 };
@@ -601,6 +607,15 @@ static void crypto_gcm_exit_tfm(struct crypto_aead *tfm)
        crypto_free_ablkcipher(ctx->ctr);
 }
 
+static void crypto_gcm_free(struct aead_instance *inst)
+{
+       struct gcm_instance_ctx *ctx = aead_instance_ctx(inst);
+
+       crypto_drop_skcipher(&ctx->ctr);
+       crypto_drop_ahash(&ctx->ghash);
+       kfree(inst);
+}
+
 static int crypto_gcm_create_common(struct crypto_template *tmpl,
                                    struct rtattr **tb,
                                    const char *full_name,
@@ -689,6 +704,8 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl,
        inst->alg.encrypt = crypto_gcm_encrypt;
        inst->alg.decrypt = crypto_gcm_decrypt;
 
+       inst->free = crypto_gcm_free;
+
        err = aead_register_instance(tmpl, inst);
        if (err)
                goto out_put_ctr;
@@ -728,19 +745,9 @@ static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb)
                                        ctr_name, "ghash");
 }
 
-static void crypto_gcm_free(struct crypto_instance *inst)
-{
-       struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst);
-
-       crypto_drop_skcipher(&ctx->ctr);
-       crypto_drop_ahash(&ctx->ghash);
-       kfree(aead_instance(inst));
-}
-
 static struct crypto_template crypto_gcm_tmpl = {
        .name = "gcm",
        .create = crypto_gcm_create,
-       .free = crypto_gcm_free,
        .module = THIS_MODULE,
 };
 
@@ -770,7 +777,6 @@ static int crypto_gcm_base_create(struct crypto_template *tmpl,
 static struct crypto_template crypto_gcm_base_tmpl = {
        .name = "gcm_base",
        .create = crypto_gcm_base_create,
-       .free = crypto_gcm_free,
        .module = THIS_MODULE,
 };
 
@@ -816,27 +822,50 @@ static int crypto_rfc4106_setauthsize(struct crypto_aead *parent,
 
 static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
 {
-       struct aead_request *subreq = aead_request_ctx(req);
+       struct crypto_rfc4106_req_ctx *rctx = aead_request_ctx(req);
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
        struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
+       struct aead_request *subreq = &rctx->subreq;
        struct crypto_aead *child = ctx->child;
+       struct scatterlist *sg;
        u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
                           crypto_aead_alignmask(child) + 1);
 
+       scatterwalk_map_and_copy(iv + 12, req->src, 0, req->assoclen - 8, 0);
+
        memcpy(iv, ctx->nonce, 4);
        memcpy(iv + 4, req->iv, 8);
 
+       sg_init_table(rctx->src, 3);
+       sg_set_buf(rctx->src, iv + 12, req->assoclen - 8);
+       sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
+       if (sg != rctx->src + 1)
+               sg_chain(rctx->src, 2, sg);
+
+       if (req->src != req->dst) {
+               sg_init_table(rctx->dst, 3);
+               sg_set_buf(rctx->dst, iv + 12, req->assoclen - 8);
+               sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
+               if (sg != rctx->dst + 1)
+                       sg_chain(rctx->dst, 2, sg);
+       }
+
        aead_request_set_tfm(subreq, child);
        aead_request_set_callback(subreq, req->base.flags, req->base.complete,
                                  req->base.data);
-       aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
-       aead_request_set_ad(subreq, req->assoclen);
+       aead_request_set_crypt(subreq, rctx->src,
+                              req->src == req->dst ? rctx->src : rctx->dst,
+                              req->cryptlen, iv);
+       aead_request_set_ad(subreq, req->assoclen - 8);
 
        return subreq;
 }
 
 static int crypto_rfc4106_encrypt(struct aead_request *req)
 {
+       if (req->assoclen != 16 && req->assoclen != 20)
+               return -EINVAL;
+
        req = crypto_rfc4106_crypt(req);
 
        return crypto_aead_encrypt(req);
@@ -844,6 +873,9 @@ static int crypto_rfc4106_encrypt(struct aead_request *req)
 
 static int crypto_rfc4106_decrypt(struct aead_request *req)
 {
+       if (req->assoclen != 16 && req->assoclen != 20)
+               return -EINVAL;
+
        req = crypto_rfc4106_crypt(req);
 
        return crypto_aead_decrypt(req);
@@ -867,9 +899,9 @@ static int crypto_rfc4106_init_tfm(struct crypto_aead *tfm)
        align &= ~(crypto_tfm_ctx_alignment() - 1);
        crypto_aead_set_reqsize(
                tfm,
-               sizeof(struct aead_request) +
+               sizeof(struct crypto_rfc4106_req_ctx) +
                ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
-               align + 12);
+               align + 24);
 
        return 0;
 }
@@ -881,6 +913,12 @@ static void crypto_rfc4106_exit_tfm(struct crypto_aead *tfm)
        crypto_free_aead(ctx->child);
 }
 
+static void crypto_rfc4106_free(struct aead_instance *inst)
+{
+       crypto_drop_aead(aead_instance_ctx(inst));
+       kfree(inst);
+}
+
 static int crypto_rfc4106_create(struct crypto_template *tmpl,
                                 struct rtattr **tb)
 {
@@ -934,7 +972,7 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl,
            CRYPTO_MAX_ALG_NAME)
                goto out_drop_alg;
 
-       inst->alg.base.cra_flags |= alg->base.cra_flags & CRYPTO_ALG_ASYNC;
+       inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
        inst->alg.base.cra_priority = alg->base.cra_priority;
        inst->alg.base.cra_blocksize = 1;
        inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
@@ -952,6 +990,8 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl,
        inst->alg.encrypt = crypto_rfc4106_encrypt;
        inst->alg.decrypt = crypto_rfc4106_decrypt;
 
+       inst->free = crypto_rfc4106_free;
+
        err = aead_register_instance(tmpl, inst);
        if (err)
                goto out_drop_alg;
@@ -966,16 +1006,9 @@ out_free_inst:
        goto out;
 }
 
-static void crypto_rfc4106_free(struct crypto_instance *inst)
-{
-       crypto_drop_aead(crypto_instance_ctx(inst));
-       kfree(aead_instance(inst));
-}
-
 static struct crypto_template crypto_rfc4106_tmpl = {
        .name = "rfc4106",
        .create = crypto_rfc4106_create,
-       .free = crypto_rfc4106_free,
        .module = THIS_MODULE,
 };
 
@@ -1114,6 +1147,15 @@ static void crypto_rfc4543_exit_tfm(struct crypto_aead *tfm)
        crypto_put_default_null_skcipher();
 }
 
+static void crypto_rfc4543_free(struct aead_instance *inst)
+{
+       struct crypto_rfc4543_instance_ctx *ctx = aead_instance_ctx(inst);
+
+       crypto_drop_aead(&ctx->aead);
+
+       kfree(inst);
+}
+
 static int crypto_rfc4543_create(struct crypto_template *tmpl,
                                struct rtattr **tb)
 {
@@ -1187,6 +1229,8 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl,
        inst->alg.encrypt = crypto_rfc4543_encrypt;
        inst->alg.decrypt = crypto_rfc4543_decrypt;
 
+       inst->free = crypto_rfc4543_free,
+
        err = aead_register_instance(tmpl, inst);
        if (err)
                goto out_drop_alg;
@@ -1201,19 +1245,9 @@ out_free_inst:
        goto out;
 }
 
-static void crypto_rfc4543_free(struct crypto_instance *inst)
-{
-       struct crypto_rfc4543_instance_ctx *ctx = crypto_instance_ctx(inst);
-
-       crypto_drop_aead(&ctx->aead);
-
-       kfree(aead_instance(inst));
-}
-
 static struct crypto_template crypto_rfc4543_tmpl = {
        .name = "rfc4543",
        .create = crypto_rfc4543_create,
-       .free = crypto_rfc4543_free,
        .module = THIS_MODULE,
 };
 
index b32d834144cdce724613dda889cec09484af7384..ceea83d13168f648e2ca22f635504992c24ba7f2 100644 (file)
@@ -79,7 +79,7 @@ int jent_fips_enabled(void)
 
 void jent_panic(char *s)
 {
-       panic(s);
+       panic("%s", s);
 }
 
 void jent_memcpy(void *dest, const void *src, unsigned int n)
index 45e7d515567294506142904fd771005c8e1ca70c..ee9cfb99fe256af06ae7ad5d946c3b76d90de1e9 100644 (file)
@@ -274,11 +274,16 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb,
                              u32 type, u32 mask)
 {
        struct pcrypt_instance_ctx *ctx;
+       struct crypto_attr_type *algt;
        struct aead_instance *inst;
        struct aead_alg *alg;
        const char *name;
        int err;
 
+       algt = crypto_get_attr_type(tb);
+       if (IS_ERR(algt))
+               return PTR_ERR(algt);
+
        name = crypto_attr_alg_name(tb[1]);
        if (IS_ERR(name))
                return PTR_ERR(name);
@@ -299,6 +304,8 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb,
        if (err)
                goto out_drop_aead;
 
+       inst->alg.base.cra_flags = CRYPTO_ALG_ASYNC;
+
        inst->alg.ivsize = crypto_aead_alg_ivsize(alg);
        inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
 
index 387b5c887a8035cfff51cc0c57eb8a3668235eee..2df9835dfbc0c6e039c522460926cee88991809a 100644 (file)
 
 #include <crypto/algapi.h>
 #include <crypto/internal/hash.h>
+#include <crypto/poly1305.h>
 #include <linux/crypto.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#define POLY1305_BLOCK_SIZE    16
-#define POLY1305_KEY_SIZE      32
-#define POLY1305_DIGEST_SIZE   16
-
-struct poly1305_desc_ctx {
-       /* key */
-       u32 r[5];
-       /* finalize key */
-       u32 s[4];
-       /* accumulator */
-       u32 h[5];
-       /* partial buffer */
-       u8 buf[POLY1305_BLOCK_SIZE];
-       /* bytes used in partial buffer */
-       unsigned int buflen;
-       /* r key has been set */
-       bool rset;
-       /* s key has been set */
-       bool sset;
-};
-
 static inline u64 mlt(u64 a, u64 b)
 {
        return a * b;
@@ -58,7 +38,7 @@ static inline u32 le32_to_cpuvp(const void *p)
        return le32_to_cpup(p);
 }
 
-static int poly1305_init(struct shash_desc *desc)
+int crypto_poly1305_init(struct shash_desc *desc)
 {
        struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
 
@@ -69,8 +49,9 @@ static int poly1305_init(struct shash_desc *desc)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(crypto_poly1305_init);
 
-static int poly1305_setkey(struct crypto_shash *tfm,
+int crypto_poly1305_setkey(struct crypto_shash *tfm,
                           const u8 *key, unsigned int keylen)
 {
        /* Poly1305 requires a unique key for each tag, which implies that
@@ -79,6 +60,7 @@ static int poly1305_setkey(struct crypto_shash *tfm,
         * the update() call. */
        return -ENOTSUPP;
 }
+EXPORT_SYMBOL_GPL(crypto_poly1305_setkey);
 
 static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
 {
@@ -98,16 +80,10 @@ static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key)
        dctx->s[3] = le32_to_cpuvp(key + 12);
 }
 
-static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
-                                   const u8 *src, unsigned int srclen,
-                                   u32 hibit)
+unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
+                                       const u8 *src, unsigned int srclen)
 {
-       u32 r0, r1, r2, r3, r4;
-       u32 s1, s2, s3, s4;
-       u32 h0, h1, h2, h3, h4;
-       u64 d0, d1, d2, d3, d4;
-
-       if (unlikely(!dctx->sset)) {
+       if (!dctx->sset) {
                if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
                        poly1305_setrkey(dctx, src);
                        src += POLY1305_BLOCK_SIZE;
@@ -121,6 +97,25 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
                        dctx->sset = true;
                }
        }
+       return srclen;
+}
+EXPORT_SYMBOL_GPL(crypto_poly1305_setdesckey);
+
+static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
+                                   const u8 *src, unsigned int srclen,
+                                   u32 hibit)
+{
+       u32 r0, r1, r2, r3, r4;
+       u32 s1, s2, s3, s4;
+       u32 h0, h1, h2, h3, h4;
+       u64 d0, d1, d2, d3, d4;
+       unsigned int datalen;
+
+       if (unlikely(!dctx->sset)) {
+               datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
+               src += srclen - datalen;
+               srclen = datalen;
+       }
 
        r0 = dctx->r[0];
        r1 = dctx->r[1];
@@ -181,7 +176,7 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx,
        return srclen;
 }
 
-static int poly1305_update(struct shash_desc *desc,
+int crypto_poly1305_update(struct shash_desc *desc,
                           const u8 *src, unsigned int srclen)
 {
        struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
@@ -214,8 +209,9 @@ static int poly1305_update(struct shash_desc *desc,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(crypto_poly1305_update);
 
-static int poly1305_final(struct shash_desc *desc, u8 *dst)
+int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
 {
        struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
        __le32 *mac = (__le32 *)dst;
@@ -282,13 +278,14 @@ static int poly1305_final(struct shash_desc *desc, u8 *dst)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(crypto_poly1305_final);
 
 static struct shash_alg poly1305_alg = {
        .digestsize     = POLY1305_DIGEST_SIZE,
-       .init           = poly1305_init,
-       .update         = poly1305_update,
-       .final          = poly1305_final,
-       .setkey         = poly1305_setkey,
+       .init           = crypto_poly1305_init,
+       .update         = crypto_poly1305_update,
+       .final          = crypto_poly1305_final,
+       .setkey         = crypto_poly1305_setkey,
        .descsize       = sizeof(struct poly1305_desc_ctx),
        .base           = {
                .cra_name               = "poly1305",
index 752af0656f2e60e9e4c56ea8bcb065bca63ebde4..466003e1a8cf20b501425ef8049cdc71b3f262bb 100644 (file)
@@ -267,12 +267,36 @@ err_free_m:
        return ret;
 }
 
+static int rsa_check_key_length(unsigned int len)
+{
+       switch (len) {
+       case 512:
+       case 1024:
+       case 1536:
+       case 2048:
+       case 3072:
+       case 4096:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
                      unsigned int keylen)
 {
        struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+       int ret;
 
-       return rsa_parse_key(pkey, key, keylen);
+       ret = rsa_parse_key(pkey, key, keylen);
+       if (ret)
+               return ret;
+
+       if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
+               rsa_free_key(pkey);
+               ret = -EINVAL;
+       }
+       return ret;
 }
 
 static void rsa_exit_tfm(struct crypto_akcipher *tfm)
index 3e8e0a9e5a8e5e7a6ea89e5364db73d2a754b0a5..8d96ce969b4480601b125a14db850f5edda38ddc 100644 (file)
@@ -28,7 +28,7 @@ int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
                return -ENOMEM;
 
        /* In FIPS mode only allow key size 2K & 3K */
-       if (fips_enabled && (mpi_get_size(key->n) != 256 ||
+       if (fips_enabled && (mpi_get_size(key->n) != 256 &&
                             mpi_get_size(key->n) != 384)) {
                pr_err("RSA: key size not allowed in FIPS mode\n");
                mpi_free(key->n);
@@ -62,7 +62,7 @@ int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
                return -ENOMEM;
 
        /* In FIPS mode only allow key size 2K & 3K */
-       if (fips_enabled && (mpi_get_size(key->d) != 256 ||
+       if (fips_enabled && (mpi_get_size(key->d) != 256 &&
                             mpi_get_size(key->d) != 384)) {
                pr_err("RSA: key size not allowed in FIPS mode\n");
                mpi_free(key->d);
index 122c56e3491b9819b20cc34871a8cb4f6d6fdaac..15a749a5cab72ea53d597cfa1983a2a175154cc2 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <crypto/internal/geniv.h>
 #include <crypto/internal/skcipher.h>
-#include <crypto/null.h>
 #include <crypto/rng.h>
 #include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
-struct seqniv_request_ctx {
-       struct scatterlist dst[2];
-       struct aead_request subreq;
-};
-
 struct seqiv_ctx {
        spinlock_t lock;
        u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
 };
 
-struct seqiv_aead_ctx {
-       /* aead_geniv_ctx must be first the element */
-       struct aead_geniv_ctx geniv;
-       struct crypto_blkcipher *null;
-       u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
-};
-
 static void seqiv_free(struct crypto_instance *inst);
 
 static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err)
@@ -71,32 +58,6 @@ static void seqiv_complete(struct crypto_async_request *base, int err)
        skcipher_givcrypt_complete(req, err);
 }
 
-static void seqiv_aead_complete2(struct aead_givcrypt_request *req, int err)
-{
-       struct aead_request *subreq = aead_givcrypt_reqctx(req);
-       struct crypto_aead *geniv;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       if (err)
-               goto out;
-
-       geniv = aead_givcrypt_reqtfm(req);
-       memcpy(req->areq.iv, subreq->iv, crypto_aead_ivsize(geniv));
-
-out:
-       kfree(subreq->iv);
-}
-
-static void seqiv_aead_complete(struct crypto_async_request *base, int err)
-{
-       struct aead_givcrypt_request *req = base->data;
-
-       seqiv_aead_complete2(req, err);
-       aead_givcrypt_complete(req, err);
-}
-
 static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err)
 {
        struct aead_request *subreq = aead_request_ctx(req);
@@ -124,50 +85,6 @@ static void seqiv_aead_encrypt_complete(struct crypto_async_request *base,
        aead_request_complete(req, err);
 }
 
-static void seqniv_aead_encrypt_complete2(struct aead_request *req, int err)
-{
-       unsigned int ivsize = 8;
-       u8 data[20];
-
-       if (err == -EINPROGRESS)
-               return;
-
-       /* Swap IV and ESP header back to correct order. */
-       scatterwalk_map_and_copy(data, req->dst, 0, req->assoclen + ivsize, 0);
-       scatterwalk_map_and_copy(data + ivsize, req->dst, 0, req->assoclen, 1);
-       scatterwalk_map_and_copy(data, req->dst, req->assoclen, ivsize, 1);
-}
-
-static void seqniv_aead_encrypt_complete(struct crypto_async_request *base,
-                                       int err)
-{
-       struct aead_request *req = base->data;
-
-       seqniv_aead_encrypt_complete2(req, err);
-       aead_request_complete(req, err);
-}
-
-static void seqniv_aead_decrypt_complete2(struct aead_request *req, int err)
-{
-       u8 data[4];
-
-       if (err == -EINPROGRESS)
-               return;
-
-       /* Move ESP header back to correct location. */
-       scatterwalk_map_and_copy(data, req->dst, 16, req->assoclen - 8, 0);
-       scatterwalk_map_and_copy(data, req->dst, 8, req->assoclen - 8, 1);
-}
-
-static void seqniv_aead_decrypt_complete(struct crypto_async_request *base,
-                                        int err)
-{
-       struct aead_request *req = base->data;
-
-       seqniv_aead_decrypt_complete2(req, err);
-       aead_request_complete(req, err);
-}
-
 static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq,
                        unsigned int ivsize)
 {
@@ -227,112 +144,10 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
        return err;
 }
 
-static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
-{
-       struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
-       struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
-       struct aead_request *areq = &req->areq;
-       struct aead_request *subreq = aead_givcrypt_reqctx(req);
-       crypto_completion_t compl;
-       void *data;
-       u8 *info;
-       unsigned int ivsize;
-       int err;
-
-       aead_request_set_tfm(subreq, aead_geniv_base(geniv));
-
-       compl = areq->base.complete;
-       data = areq->base.data;
-       info = areq->iv;
-
-       ivsize = crypto_aead_ivsize(geniv);
-
-       if (unlikely(!IS_ALIGNED((unsigned long)info,
-                                crypto_aead_alignmask(geniv) + 1))) {
-               info = kmalloc(ivsize, areq->base.flags &
-                                      CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
-                                                                 GFP_ATOMIC);
-               if (!info)
-                       return -ENOMEM;
-
-               compl = seqiv_aead_complete;
-               data = req;
-       }
-
-       aead_request_set_callback(subreq, areq->base.flags, compl, data);
-       aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
-                              info);
-       aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
-
-       seqiv_geniv(ctx, info, req->seq, ivsize);
-       memcpy(req->giv, info, ivsize);
-
-       err = crypto_aead_encrypt(subreq);
-       if (unlikely(info != areq->iv))
-               seqiv_aead_complete2(req, err);
-       return err;
-}
-
-static int seqniv_aead_encrypt(struct aead_request *req)
-{
-       struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
-       struct seqniv_request_ctx *rctx = aead_request_ctx(req);
-       struct aead_request *subreq = &rctx->subreq;
-       struct scatterlist *dst;
-       crypto_completion_t compl;
-       void *data;
-       unsigned int ivsize = 8;
-       u8 buf[20] __attribute__ ((aligned(__alignof__(u32))));
-       int err;
-
-       if (req->cryptlen < ivsize)
-               return -EINVAL;
-
-       /* ESP AD is at most 12 bytes (ESN). */
-       if (req->assoclen > 12)
-               return -EINVAL;
-
-       aead_request_set_tfm(subreq, ctx->geniv.child);
-
-       compl = seqniv_aead_encrypt_complete;
-       data = req;
-
-       if (req->src != req->dst) {
-               struct blkcipher_desc desc = {
-                       .tfm = ctx->null,
-               };
-
-               err = crypto_blkcipher_encrypt(&desc, req->dst, req->src,
-                                              req->assoclen + req->cryptlen);
-               if (err)
-                       return err;
-       }
-
-       dst = scatterwalk_ffwd(rctx->dst, req->dst, ivsize);
-
-       aead_request_set_callback(subreq, req->base.flags, compl, data);
-       aead_request_set_crypt(subreq, dst, dst,
-                              req->cryptlen - ivsize, req->iv);
-       aead_request_set_ad(subreq, req->assoclen);
-
-       memcpy(buf, req->iv, ivsize);
-       crypto_xor(buf, ctx->salt, ivsize);
-       memcpy(req->iv, buf, ivsize);
-
-       /* Swap order of IV and ESP AD for ICV generation. */
-       scatterwalk_map_and_copy(buf + ivsize, req->dst, 0, req->assoclen, 0);
-       scatterwalk_map_and_copy(buf, req->dst, 0, req->assoclen + ivsize, 1);
-
-       err = crypto_aead_encrypt(subreq);
-       seqniv_aead_encrypt_complete2(req, err);
-       return err;
-}
-
 static int seqiv_aead_encrypt(struct aead_request *req)
 {
        struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
+       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
        struct aead_request *subreq = aead_request_ctx(req);
        crypto_completion_t compl;
        void *data;
@@ -343,7 +158,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
        if (req->cryptlen < ivsize)
                return -EINVAL;
 
-       aead_request_set_tfm(subreq, ctx->geniv.child);
+       aead_request_set_tfm(subreq, ctx->child);
 
        compl = req->base.complete;
        data = req->base.data;
@@ -387,67 +202,10 @@ static int seqiv_aead_encrypt(struct aead_request *req)
        return err;
 }
 
-static int seqniv_aead_decrypt(struct aead_request *req)
-{
-       struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
-       struct seqniv_request_ctx *rctx = aead_request_ctx(req);
-       struct aead_request *subreq = &rctx->subreq;
-       struct scatterlist *dst;
-       crypto_completion_t compl;
-       void *data;
-       unsigned int ivsize = 8;
-       u8 buf[20];
-       int err;
-
-       if (req->cryptlen < ivsize + crypto_aead_authsize(geniv))
-               return -EINVAL;
-
-       aead_request_set_tfm(subreq, ctx->geniv.child);
-
-       compl = req->base.complete;
-       data = req->base.data;
-
-       if (req->assoclen > 12)
-               return -EINVAL;
-       else if (req->assoclen > 8) {
-               compl = seqniv_aead_decrypt_complete;
-               data = req;
-       }
-
-       if (req->src != req->dst) {
-               struct blkcipher_desc desc = {
-                       .tfm = ctx->null,
-               };
-
-               err = crypto_blkcipher_encrypt(&desc, req->dst, req->src,
-                                              req->assoclen + req->cryptlen);
-               if (err)
-                       return err;
-       }
-
-       /* Move ESP AD forward for ICV generation. */
-       scatterwalk_map_and_copy(buf, req->dst, 0, req->assoclen + ivsize, 0);
-       memcpy(req->iv, buf + req->assoclen, ivsize);
-       scatterwalk_map_and_copy(buf, req->dst, ivsize, req->assoclen, 1);
-
-       dst = scatterwalk_ffwd(rctx->dst, req->dst, ivsize);
-
-       aead_request_set_callback(subreq, req->base.flags, compl, data);
-       aead_request_set_crypt(subreq, dst, dst,
-                              req->cryptlen - ivsize, req->iv);
-       aead_request_set_ad(subreq, req->assoclen);
-
-       err = crypto_aead_decrypt(subreq);
-       if (req->assoclen > 8)
-               seqniv_aead_decrypt_complete2(req, err);
-       return err;
-}
-
 static int seqiv_aead_decrypt(struct aead_request *req)
 {
        struct crypto_aead *geniv = crypto_aead_reqtfm(req);
-       struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
+       struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
        struct aead_request *subreq = aead_request_ctx(req);
        crypto_completion_t compl;
        void *data;
@@ -456,7 +214,7 @@ static int seqiv_aead_decrypt(struct aead_request *req)
        if (req->cryptlen < ivsize + crypto_aead_authsize(geniv))
                return -EINVAL;
 
-       aead_request_set_tfm(subreq, ctx->geniv.child);
+       aead_request_set_tfm(subreq, ctx->child);
 
        compl = req->base.complete;
        data = req->base.data;
@@ -467,9 +225,6 @@ static int seqiv_aead_decrypt(struct aead_request *req)
        aead_request_set_ad(subreq, req->assoclen + ivsize);
 
        scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
-       if (req->src != req->dst)
-               scatterwalk_map_and_copy(req->iv, req->dst,
-                                        req->assoclen, ivsize, 1);
 
        return crypto_aead_decrypt(subreq);
 }
@@ -495,85 +250,6 @@ static int seqiv_init(struct crypto_tfm *tfm)
        return err ?: skcipher_geniv_init(tfm);
 }
 
-static int seqiv_old_aead_init(struct crypto_tfm *tfm)
-{
-       struct crypto_aead *geniv = __crypto_aead_cast(tfm);
-       struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
-       int err;
-
-       spin_lock_init(&ctx->lock);
-
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-                               sizeof(struct aead_request));
-       err = 0;
-       if (!crypto_get_default_rng()) {
-               geniv->givencrypt = seqiv_aead_givencrypt;
-               err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
-                                          crypto_aead_ivsize(geniv));
-               crypto_put_default_rng();
-       }
-
-       return err ?: aead_geniv_init(tfm);
-}
-
-static int seqiv_aead_init_common(struct crypto_tfm *tfm, unsigned int reqsize)
-{
-       struct crypto_aead *geniv = __crypto_aead_cast(tfm);
-       struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
-       int err;
-
-       spin_lock_init(&ctx->geniv.lock);
-
-       crypto_aead_set_reqsize(geniv, sizeof(struct aead_request));
-
-       err = crypto_get_default_rng();
-       if (err)
-               goto out;
-
-       err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
-                                  crypto_aead_ivsize(geniv));
-       crypto_put_default_rng();
-       if (err)
-               goto out;
-
-       ctx->null = crypto_get_default_null_skcipher();
-       err = PTR_ERR(ctx->null);
-       if (IS_ERR(ctx->null))
-               goto out;
-
-       err = aead_geniv_init(tfm);
-       if (err)
-               goto drop_null;
-
-       ctx->geniv.child = geniv->child;
-       geniv->child = geniv;
-
-out:
-       return err;
-
-drop_null:
-       crypto_put_default_null_skcipher();
-       goto out;
-}
-
-static int seqiv_aead_init(struct crypto_tfm *tfm)
-{
-       return seqiv_aead_init_common(tfm, sizeof(struct aead_request));
-}
-
-static int seqniv_aead_init(struct crypto_tfm *tfm)
-{
-       return seqiv_aead_init_common(tfm, sizeof(struct seqniv_request_ctx));
-}
-
-static void seqiv_aead_exit(struct crypto_tfm *tfm)
-{
-       struct seqiv_aead_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       crypto_free_aead(ctx->geniv.child);
-       crypto_put_default_null_skcipher();
-}
-
 static int seqiv_ablkcipher_create(struct crypto_template *tmpl,
                                   struct rtattr **tb)
 {
@@ -609,33 +285,6 @@ free_inst:
        goto out;
 }
 
-static int seqiv_old_aead_create(struct crypto_template *tmpl,
-                                struct aead_instance *aead)
-{
-       struct crypto_instance *inst = aead_crypto_instance(aead);
-       int err = -EINVAL;
-
-       if (inst->alg.cra_aead.ivsize < sizeof(u64))
-               goto free_inst;
-
-       inst->alg.cra_init = seqiv_old_aead_init;
-       inst->alg.cra_exit = aead_geniv_exit;
-
-       inst->alg.cra_ctxsize = inst->alg.cra_aead.ivsize;
-       inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
-
-       err = crypto_register_instance(tmpl, inst);
-       if (err)
-               goto free_inst;
-
-out:
-       return err;
-
-free_inst:
-       aead_geniv_free(aead);
-       goto out;
-}
-
 static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb)
 {
        struct aead_instance *inst;
@@ -650,15 +299,9 @@ static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb)
 
        inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
 
-       if (inst->alg.base.cra_aead.encrypt)
-               return seqiv_old_aead_create(tmpl, inst);
-
        spawn = aead_instance_ctx(inst);
        alg = crypto_spawn_aead_alg(spawn);
 
-       if (alg->base.cra_aead.encrypt)
-               goto done;
-
        err = -EINVAL;
        if (inst->alg.ivsize != sizeof(u64))
                goto free_inst;
@@ -666,13 +309,12 @@ static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb)
        inst->alg.encrypt = seqiv_aead_encrypt;
        inst->alg.decrypt = seqiv_aead_decrypt;
 
-       inst->alg.base.cra_init = seqiv_aead_init;
-       inst->alg.base.cra_exit = seqiv_aead_exit;
+       inst->alg.init = aead_init_geniv;
+       inst->alg.exit = aead_exit_geniv;
 
-       inst->alg.base.cra_ctxsize = sizeof(struct seqiv_aead_ctx);
-       inst->alg.base.cra_ctxsize += inst->alg.base.cra_aead.ivsize;
+       inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
+       inst->alg.base.cra_ctxsize += inst->alg.ivsize;
 
-done:
        err = aead_register_instance(tmpl, inst);
        if (err)
                goto free_inst;
@@ -702,51 +344,6 @@ static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb)
        return err;
 }
 
-static int seqniv_create(struct crypto_template *tmpl, struct rtattr **tb)
-{
-       struct aead_instance *inst;
-       struct crypto_aead_spawn *spawn;
-       struct aead_alg *alg;
-       int err;
-
-       inst = aead_geniv_alloc(tmpl, tb, 0, 0);
-       err = PTR_ERR(inst);
-       if (IS_ERR(inst))
-               goto out;
-
-       spawn = aead_instance_ctx(inst);
-       alg = crypto_spawn_aead_alg(spawn);
-
-       if (alg->base.cra_aead.encrypt)
-               goto done;
-
-       err = -EINVAL;
-       if (inst->alg.ivsize != sizeof(u64))
-               goto free_inst;
-
-       inst->alg.encrypt = seqniv_aead_encrypt;
-       inst->alg.decrypt = seqniv_aead_decrypt;
-
-       inst->alg.base.cra_init = seqniv_aead_init;
-       inst->alg.base.cra_exit = seqiv_aead_exit;
-
-       inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
-       inst->alg.base.cra_ctxsize = sizeof(struct seqiv_aead_ctx);
-       inst->alg.base.cra_ctxsize += inst->alg.ivsize;
-
-done:
-       err = aead_register_instance(tmpl, inst);
-       if (err)
-               goto free_inst;
-
-out:
-       return err;
-
-free_inst:
-       aead_geniv_free(inst);
-       goto out;
-}
-
 static void seqiv_free(struct crypto_instance *inst)
 {
        if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
@@ -762,36 +359,13 @@ static struct crypto_template seqiv_tmpl = {
        .module = THIS_MODULE,
 };
 
-static struct crypto_template seqniv_tmpl = {
-       .name = "seqniv",
-       .create = seqniv_create,
-       .free = seqiv_free,
-       .module = THIS_MODULE,
-};
-
 static int __init seqiv_module_init(void)
 {
-       int err;
-
-       err = crypto_register_template(&seqiv_tmpl);
-       if (err)
-               goto out;
-
-       err = crypto_register_template(&seqniv_tmpl);
-       if (err)
-               goto out_undo_niv;
-
-out:
-       return err;
-
-out_undo_niv:
-       crypto_unregister_template(&seqiv_tmpl);
-       goto out;
+       return crypto_register_template(&seqiv_tmpl);
 }
 
 static void __exit seqiv_module_exit(void)
 {
-       crypto_unregister_template(&seqniv_tmpl);
        crypto_unregister_template(&seqiv_tmpl);
 }
 
@@ -801,4 +375,3 @@ module_exit(seqiv_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Sequence Number IV Generator");
 MODULE_ALIAS_CRYPTO("seqiv");
-MODULE_ALIAS_CRYPTO("seqniv");
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
new file mode 100644 (file)
index 0000000..dd5fc1b
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Symmetric key cipher operations.
+ *
+ * Generic encrypt/decrypt wrapper for ciphers, handles operations across
+ * multiple page boundaries by using temporary blocks.  In user context,
+ * the kernel is given a chance to schedule us once per page.
+ *
+ * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/internal/skcipher.h>
+#include <linux/bug.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg)
+{
+       if (alg->cra_type == &crypto_blkcipher_type)
+               return sizeof(struct crypto_blkcipher *);
+
+       BUG_ON(alg->cra_type != &crypto_ablkcipher_type &&
+              alg->cra_type != &crypto_givcipher_type);
+
+       return sizeof(struct crypto_ablkcipher *);
+}
+
+static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm,
+                                    const u8 *key, unsigned int keylen)
+{
+       struct crypto_blkcipher **ctx = crypto_skcipher_ctx(tfm);
+       struct crypto_blkcipher *blkcipher = *ctx;
+       int err;
+
+       crypto_blkcipher_clear_flags(blkcipher, ~0);
+       crypto_blkcipher_set_flags(blkcipher, crypto_skcipher_get_flags(tfm) &
+                                             CRYPTO_TFM_REQ_MASK);
+       err = crypto_blkcipher_setkey(blkcipher, key, keylen);
+       crypto_skcipher_set_flags(tfm, crypto_blkcipher_get_flags(blkcipher) &
+                                      CRYPTO_TFM_RES_MASK);
+
+       return err;
+}
+
+static int skcipher_crypt_blkcipher(struct skcipher_request *req,
+                                   int (*crypt)(struct blkcipher_desc *,
+                                                struct scatterlist *,
+                                                struct scatterlist *,
+                                                unsigned int))
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+       struct crypto_blkcipher **ctx = crypto_skcipher_ctx(tfm);
+       struct blkcipher_desc desc = {
+               .tfm = *ctx,
+               .info = req->iv,
+               .flags = req->base.flags,
+       };
+
+
+       return crypt(&desc, req->dst, req->src, req->cryptlen);
+}
+
+static int skcipher_encrypt_blkcipher(struct skcipher_request *req)
+{
+       struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+       struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
+       struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+       return skcipher_crypt_blkcipher(req, alg->encrypt);
+}
+
+static int skcipher_decrypt_blkcipher(struct skcipher_request *req)
+{
+       struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+       struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
+       struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+       return skcipher_crypt_blkcipher(req, alg->decrypt);
+}
+
+static void crypto_exit_skcipher_ops_blkcipher(struct crypto_tfm *tfm)
+{
+       struct crypto_blkcipher **ctx = crypto_tfm_ctx(tfm);
+
+       crypto_free_blkcipher(*ctx);
+}
+
+int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm)
+{
+       struct crypto_alg *calg = tfm->__crt_alg;
+       struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
+       struct crypto_blkcipher **ctx = crypto_tfm_ctx(tfm);
+       struct crypto_blkcipher *blkcipher;
+       struct crypto_tfm *btfm;
+
+       if (!crypto_mod_get(calg))
+               return -EAGAIN;
+
+       btfm = __crypto_alloc_tfm(calg, CRYPTO_ALG_TYPE_BLKCIPHER,
+                                       CRYPTO_ALG_TYPE_MASK);
+       if (IS_ERR(btfm)) {
+               crypto_mod_put(calg);
+               return PTR_ERR(btfm);
+       }
+
+       blkcipher = __crypto_blkcipher_cast(btfm);
+       *ctx = blkcipher;
+       tfm->exit = crypto_exit_skcipher_ops_blkcipher;
+
+       skcipher->setkey = skcipher_setkey_blkcipher;
+       skcipher->encrypt = skcipher_encrypt_blkcipher;
+       skcipher->decrypt = skcipher_decrypt_blkcipher;
+
+       skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher);
+
+       return 0;
+}
+
+static int skcipher_setkey_ablkcipher(struct crypto_skcipher *tfm,
+                                     const u8 *key, unsigned int keylen)
+{
+       struct crypto_ablkcipher **ctx = crypto_skcipher_ctx(tfm);
+       struct crypto_ablkcipher *ablkcipher = *ctx;
+       int err;
+
+       crypto_ablkcipher_clear_flags(ablkcipher, ~0);
+       crypto_ablkcipher_set_flags(ablkcipher,
+                                   crypto_skcipher_get_flags(tfm) &
+                                   CRYPTO_TFM_REQ_MASK);
+       err = crypto_ablkcipher_setkey(ablkcipher, key, keylen);
+       crypto_skcipher_set_flags(tfm,
+                                 crypto_ablkcipher_get_flags(ablkcipher) &
+                                 CRYPTO_TFM_RES_MASK);
+
+       return err;
+}
+
+static int skcipher_crypt_ablkcipher(struct skcipher_request *req,
+                                    int (*crypt)(struct ablkcipher_request *))
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+       struct crypto_ablkcipher **ctx = crypto_skcipher_ctx(tfm);
+       struct ablkcipher_request *subreq = skcipher_request_ctx(req);
+
+       ablkcipher_request_set_tfm(subreq, *ctx);
+       ablkcipher_request_set_callback(subreq, skcipher_request_flags(req),
+                                       req->base.complete, req->base.data);
+       ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
+                                    req->iv);
+
+       return crypt(subreq);
+}
+
+static int skcipher_encrypt_ablkcipher(struct skcipher_request *req)
+{
+       struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+       struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
+       struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
+
+       return skcipher_crypt_ablkcipher(req, alg->encrypt);
+}
+
+static int skcipher_decrypt_ablkcipher(struct skcipher_request *req)
+{
+       struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+       struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
+       struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
+
+       return skcipher_crypt_ablkcipher(req, alg->decrypt);
+}
+
+static void crypto_exit_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
+{
+       struct crypto_ablkcipher **ctx = crypto_tfm_ctx(tfm);
+
+       crypto_free_ablkcipher(*ctx);
+}
+
+int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
+{
+       struct crypto_alg *calg = tfm->__crt_alg;
+       struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
+       struct crypto_ablkcipher **ctx = crypto_tfm_ctx(tfm);
+       struct crypto_ablkcipher *ablkcipher;
+       struct crypto_tfm *abtfm;
+
+       if (!crypto_mod_get(calg))
+               return -EAGAIN;
+
+       abtfm = __crypto_alloc_tfm(calg, 0, 0);
+       if (IS_ERR(abtfm)) {
+               crypto_mod_put(calg);
+               return PTR_ERR(abtfm);
+       }
+
+       ablkcipher = __crypto_ablkcipher_cast(abtfm);
+       *ctx = ablkcipher;
+       tfm->exit = crypto_exit_skcipher_ops_ablkcipher;
+
+       skcipher->setkey = skcipher_setkey_ablkcipher;
+       skcipher->encrypt = skcipher_encrypt_ablkcipher;
+       skcipher->decrypt = skcipher_decrypt_ablkcipher;
+
+       skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+       skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) +
+                           sizeof(struct ablkcipher_request);
+
+       return 0;
+}
+
+static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
+{
+       if (tfm->__crt_alg->cra_type == &crypto_blkcipher_type)
+               return crypto_init_skcipher_ops_blkcipher(tfm);
+
+       BUG_ON(tfm->__crt_alg->cra_type != &crypto_ablkcipher_type &&
+              tfm->__crt_alg->cra_type != &crypto_givcipher_type);
+
+       return crypto_init_skcipher_ops_ablkcipher(tfm);
+}
+
+static const struct crypto_type crypto_skcipher_type2 = {
+       .extsize = crypto_skcipher_extsize,
+       .init_tfm = crypto_skcipher_init_tfm,
+       .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+       .maskset = CRYPTO_ALG_TYPE_BLKCIPHER_MASK,
+       .type = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .tfmsize = offsetof(struct crypto_skcipher, base),
+};
+
+struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name,
+                                             u32 type, u32 mask)
+{
+       return crypto_alloc_tfm(alg_name, &crypto_skcipher_type2, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_skcipher);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Symmetric key cipher type");
index 9f6f10b498ba4aab02849c760b1da61bd5a7fd99..2b00b617daab537dba7657b6fbc569d440db931f 100644 (file)
@@ -73,6 +73,22 @@ static char *check[] = {
        "lzo", "cts", "zlib", NULL
 };
 
+struct tcrypt_result {
+       struct completion completion;
+       int err;
+};
+
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+       struct tcrypt_result *res = req->data;
+
+       if (err == -EINPROGRESS)
+               return;
+
+       res->err = err;
+       complete(&res->completion);
+}
+
 static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
                               struct scatterlist *sg, int blen, int secs)
 {
@@ -143,6 +159,20 @@ out:
        return ret;
 }
 
+static inline int do_one_aead_op(struct aead_request *req, int ret)
+{
+       if (ret == -EINPROGRESS || ret == -EBUSY) {
+               struct tcrypt_result *tr = req->base.data;
+
+               ret = wait_for_completion_interruptible(&tr->completion);
+               if (!ret)
+                       ret = tr->err;
+               reinit_completion(&tr->completion);
+       }
+
+       return ret;
+}
+
 static int test_aead_jiffies(struct aead_request *req, int enc,
                                int blen, int secs)
 {
@@ -153,9 +183,9 @@ static int test_aead_jiffies(struct aead_request *req, int enc,
        for (start = jiffies, end = start + secs * HZ, bcount = 0;
             time_before(jiffies, end); bcount++) {
                if (enc)
-                       ret = crypto_aead_encrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
                else
-                       ret = crypto_aead_decrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
 
                if (ret)
                        return ret;
@@ -177,9 +207,9 @@ static int test_aead_cycles(struct aead_request *req, int enc, int blen)
        /* Warm-up run. */
        for (i = 0; i < 4; i++) {
                if (enc)
-                       ret = crypto_aead_encrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
                else
-                       ret = crypto_aead_decrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
 
                if (ret)
                        goto out;
@@ -191,9 +221,9 @@ static int test_aead_cycles(struct aead_request *req, int enc, int blen)
 
                start = get_cycles();
                if (enc)
-                       ret = crypto_aead_encrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
                else
-                       ret = crypto_aead_decrypt(req);
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
                end = get_cycles();
 
                if (ret)
@@ -286,6 +316,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
        char *axbuf[XBUFSIZE];
        unsigned int *b_size;
        unsigned int iv_len;
+       struct tcrypt_result result;
 
        iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
        if (!iv)
@@ -321,6 +352,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
                goto out_notfm;
        }
 
+       init_completion(&result.completion);
        printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
                        get_driver_name(crypto_aead, tfm), e);
 
@@ -331,6 +363,9 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
                goto out_noreq;
        }
 
+       aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                 tcrypt_complete, &result);
+
        i = 0;
        do {
                b_size = aead_sizes;
@@ -749,22 +784,6 @@ out:
        crypto_free_hash(tfm);
 }
 
-struct tcrypt_result {
-       struct completion completion;
-       int err;
-};
-
-static void tcrypt_complete(struct crypto_async_request *req, int err)
-{
-       struct tcrypt_result *res = req->data;
-
-       if (err == -EINPROGRESS)
-               return;
-
-       res->err = err;
-       complete(&res->completion);
-}
-
 static inline int do_one_ahash_op(struct ahash_request *req, int ret)
 {
        if (ret == -EINPROGRESS || ret == -EBUSY) {
@@ -1759,14 +1778,27 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
 
        case 211:
                test_aead_speed("rfc4106(gcm(aes))", ENCRYPT, sec,
+                               NULL, 0, 16, 16, aead_speed_template_20);
+               test_aead_speed("gcm(aes)", ENCRYPT, sec,
                                NULL, 0, 16, 8, aead_speed_template_20);
                break;
 
        case 212:
                test_aead_speed("rfc4309(ccm(aes))", ENCRYPT, sec,
-                               NULL, 0, 16, 8, aead_speed_template_19);
+                               NULL, 0, 16, 16, aead_speed_template_19);
+               break;
+
+       case 213:
+               test_aead_speed("rfc7539esp(chacha20,poly1305)", ENCRYPT, sec,
+                               NULL, 0, 16, 8, aead_speed_template_36);
+               break;
+
+       case 214:
+               test_cipher_speed("chacha20", ENCRYPT, sec, NULL, 0,
+                                 speed_template_32);
                break;
 
+
        case 300:
                if (alg) {
                        test_hash_speed(alg, sec, generic_hash_speed_template);
@@ -1855,6 +1887,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
                test_hash_speed("crct10dif", sec, generic_hash_speed_template);
                if (mode > 300 && mode < 400) break;
 
+       case 321:
+               test_hash_speed("poly1305", sec, poly1305_speed_template);
+               if (mode > 300 && mode < 400) break;
+
        case 399:
                break;
 
index 6cc1b856871b96d5b0d9064fc6ae028649fe89b6..f0bfee1bb293809355d1c7455042fc5e7753b826 100644 (file)
@@ -61,12 +61,14 @@ static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
 static u8 speed_template_32_48[] = {32, 48, 0};
 static u8 speed_template_32_48_64[] = {32, 48, 64, 0};
 static u8 speed_template_32_64[] = {32, 64, 0};
+static u8 speed_template_32[] = {32, 0};
 
 /*
  * AEAD speed tests
  */
 static u8 aead_speed_template_19[] = {19, 0};
 static u8 aead_speed_template_20[] = {20, 0};
+static u8 aead_speed_template_36[] = {36, 0};
 
 /*
  * Digest speed tests
@@ -127,4 +129,22 @@ static struct hash_speed hash_speed_template_16[] = {
        {  .blen = 0,   .plen = 0,      .klen = 0, }
 };
 
+static struct hash_speed poly1305_speed_template[] = {
+       { .blen = 96,   .plen = 16, },
+       { .blen = 96,   .plen = 32, },
+       { .blen = 96,   .plen = 96, },
+       { .blen = 288,  .plen = 16, },
+       { .blen = 288,  .plen = 32, },
+       { .blen = 288,  .plen = 288, },
+       { .blen = 1056, .plen = 32, },
+       { .blen = 1056, .plen = 1056, },
+       { .blen = 2080, .plen = 32, },
+       { .blen = 2080, .plen = 2080, },
+       { .blen = 4128, .plen = 4128, },
+       { .blen = 8224, .plen = 8224, },
+
+       /* End marker */
+       {  .blen = 0,   .plen = 0, }
+};
+
 #endif /* _CRYPTO_TCRYPT_H */
index d0a42bd3aae926fcfef0624c6497452e9a0741c5..35c2de13697182ba22190ea6d0c05d46c6b905be 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <crypto/aead.h>
 #include <crypto/hash.h>
+#include <crypto/skcipher.h>
 #include <linux/err.h>
 #include <linux/fips.h>
 #include <linux/module.h>
@@ -921,15 +922,15 @@ out_nobuf:
        return ret;
 }
 
-static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
+static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
                           struct cipher_testvec *template, unsigned int tcount,
                           const bool diff_dst, const int align_offset)
 {
        const char *algo =
-               crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+               crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm));
        unsigned int i, j, k, n, temp;
        char *q;
-       struct ablkcipher_request *req;
+       struct skcipher_request *req;
        struct scatterlist sg[8];
        struct scatterlist sgout[8];
        const char *e, *d;
@@ -958,15 +959,15 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
 
        init_completion(&result.completion);
 
-       req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+       req = skcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req) {
                pr_err("alg: skcipher%s: Failed to allocate request for %s\n",
                       d, algo);
                goto out;
        }
 
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       tcrypt_complete, &result);
+       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     tcrypt_complete, &result);
 
        j = 0;
        for (i = 0; i < tcount; i++) {
@@ -987,15 +988,16 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
                data += align_offset;
                memcpy(data, template[i].input, template[i].ilen);
 
-               crypto_ablkcipher_clear_flags(tfm, ~0);
+               crypto_skcipher_clear_flags(tfm, ~0);
                if (template[i].wk)
-                       crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+                       crypto_skcipher_set_flags(tfm,
+                                                 CRYPTO_TFM_REQ_WEAK_KEY);
 
-               ret = crypto_ablkcipher_setkey(tfm, template[i].key,
-                                              template[i].klen);
+               ret = crypto_skcipher_setkey(tfm, template[i].key,
+                                            template[i].klen);
                if (!ret == template[i].fail) {
                        pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
-                              d, j, algo, crypto_ablkcipher_get_flags(tfm));
+                              d, j, algo, crypto_skcipher_get_flags(tfm));
                        goto out;
                } else if (ret)
                        continue;
@@ -1007,10 +1009,10 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
                        sg_init_one(&sgout[0], data, template[i].ilen);
                }
 
-               ablkcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
-                                            template[i].ilen, iv);
-               ret = enc ? crypto_ablkcipher_encrypt(req) :
-                           crypto_ablkcipher_decrypt(req);
+               skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+                                          template[i].ilen, iv);
+               ret = enc ? crypto_skcipher_encrypt(req) :
+                           crypto_skcipher_decrypt(req);
 
                switch (ret) {
                case 0:
@@ -1054,15 +1056,16 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
                        memset(iv, 0, MAX_IVLEN);
 
                j++;
-               crypto_ablkcipher_clear_flags(tfm, ~0);
+               crypto_skcipher_clear_flags(tfm, ~0);
                if (template[i].wk)
-                       crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+                       crypto_skcipher_set_flags(tfm,
+                                                 CRYPTO_TFM_REQ_WEAK_KEY);
 
-               ret = crypto_ablkcipher_setkey(tfm, template[i].key,
-                                              template[i].klen);
+               ret = crypto_skcipher_setkey(tfm, template[i].key,
+                                            template[i].klen);
                if (!ret == template[i].fail) {
                        pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
-                              d, j, algo, crypto_ablkcipher_get_flags(tfm));
+                              d, j, algo, crypto_skcipher_get_flags(tfm));
                        goto out;
                } else if (ret)
                        continue;
@@ -1100,11 +1103,11 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
                        temp += template[i].tap[k];
                }
 
-               ablkcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
-                                            template[i].ilen, iv);
+               skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+                                          template[i].ilen, iv);
 
-               ret = enc ? crypto_ablkcipher_encrypt(req) :
-                           crypto_ablkcipher_decrypt(req);
+               ret = enc ? crypto_skcipher_encrypt(req) :
+                           crypto_skcipher_decrypt(req);
 
                switch (ret) {
                case 0:
@@ -1157,7 +1160,7 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
        ret = 0;
 
 out:
-       ablkcipher_request_free(req);
+       skcipher_request_free(req);
        if (diff_dst)
                testmgr_free_buf(xoutbuf);
 out_nooutbuf:
@@ -1166,7 +1169,7 @@ out_nobuf:
        return ret;
 }
 
-static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
+static int test_skcipher(struct crypto_skcipher *tfm, int enc,
                         struct cipher_testvec *template, unsigned int tcount)
 {
        unsigned int alignmask;
@@ -1578,10 +1581,10 @@ out:
 static int alg_test_skcipher(const struct alg_test_desc *desc,
                             const char *driver, u32 type, u32 mask)
 {
-       struct crypto_ablkcipher *tfm;
+       struct crypto_skcipher *tfm;
        int err = 0;
 
-       tfm = crypto_alloc_ablkcipher(driver, type | CRYPTO_ALG_INTERNAL, mask);
+       tfm = crypto_alloc_skcipher(driver, type | CRYPTO_ALG_INTERNAL, mask);
        if (IS_ERR(tfm)) {
                printk(KERN_ERR "alg: skcipher: Failed to load transform for "
                       "%s: %ld\n", driver, PTR_ERR(tfm));
@@ -1600,7 +1603,7 @@ static int alg_test_skcipher(const struct alg_test_desc *desc,
                                    desc->suite.cipher.dec.count);
 
 out:
-       crypto_free_ablkcipher(tfm);
+       crypto_free_skcipher(tfm);
        return err;
 }
 
@@ -2476,6 +2479,7 @@ static const struct alg_test_desc alg_test_descs[] = {
                }
        }, {
                .alg = "cmac(aes)",
+               .fips_allowed = 1,
                .test = alg_test_hash,
                .suite = {
                        .hash = {
@@ -2485,6 +2489,7 @@ static const struct alg_test_desc alg_test_descs[] = {
                }
        }, {
                .alg = "cmac(des3_ede)",
+               .fips_allowed = 1,
                .test = alg_test_hash,
                .suite = {
                        .hash = {
index 868edf11704142deec8e05c44a2edfb37661ad27..64b8a8082645da7ddb69f1dda35f52b4f746a486 100644 (file)
@@ -14504,6 +14504,9 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
                .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
                          "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
                .rlen   = 16,
+               .also_non_np = 1,
+               .np     = 8,
+               .tap    = { 3, 2, 3, 2, 3, 1, 1, 1 },
        }, {
                .key    = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
                          "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
@@ -14723,6 +14726,9 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
                .ilen   = 16,
                .result = "Single block msg",
                .rlen   = 16,
+               .also_non_np = 1,
+               .np     = 8,
+               .tap    = { 3, 2, 3, 2, 3, 1, 1, 1 },
        }, {
                .key    = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
                          "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
@@ -15032,6 +15038,9 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 16,
                .iv     = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
                          "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+               .assoc  = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+                         "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+               .alen   = 16,
                .input  = "Single block msg",
                .ilen   = 16,
                .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
@@ -15057,6 +15066,9 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 16,
                .iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
                          "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+               .assoc  = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
+                         "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+               .alen   = 16,
                .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"
@@ -15087,6 +15099,9 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 16,
                .iv     = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb"
                          "\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
+               .assoc  = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb"
+                         "\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
+               .alen   = 16,
                .input  = "This is a 48-byte message (exactly 3 AES blocks)",
                .ilen   = 48,
                .result = "\xd0\xa0\x2b\x38\x36\x45\x17\x53"
@@ -15116,6 +15131,9 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 16,
                .iv     = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c"
                          "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
+               .assoc  = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c"
+                         "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
+               .alen   = 16,
                .input  = "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
                          "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
                          "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
@@ -15154,8 +15172,10 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 16,
                .iv     = "\xe9\x6e\x8c\x08\xab\x46\x57\x63"
                          "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\xe9\x6e\x8c\x08\xab\x46\x57\x63"
+                         "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93",
+               .alen   = 24,
                .input  = "\x08\x00\x0e\xbd\xa7\x0a\x00\x00"
                          "\x8e\x9c\x08\x3d\xb9\x5b\x07\x00"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -15199,6 +15219,9 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 24,
                .iv     = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .alen   = 16,
                .input  = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
                          "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
                          "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
@@ -15239,6 +15262,9 @@ static struct aead_testvec hmac_sha1_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 20 + 32,
                .iv     = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .alen   = 16,
                .input  = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
                          "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
                          "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
@@ -15374,6 +15400,9 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 16,
                .iv     = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
                          "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+               .assoc  = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+                         "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+               .alen   = 16,
                .input  = "Single block msg",
                .ilen   = 16,
                .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
@@ -15401,6 +15430,9 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 16,
                .iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
                          "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+               .assoc  = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
+                         "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+               .alen   = 16,
                .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"
@@ -15433,6 +15465,9 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 16,
                .iv     = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb"
                          "\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
+               .assoc  = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb"
+                         "\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
+               .alen   = 16,
                .input  = "This is a 48-byte message (exactly 3 AES blocks)",
                .ilen   = 48,
                .result = "\xd0\xa0\x2b\x38\x36\x45\x17\x53"
@@ -15464,6 +15499,9 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 16,
                .iv     = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c"
                          "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
+               .assoc  = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c"
+                         "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
+               .alen   = 16,
                .input  = "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
                          "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
                          "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
@@ -15504,8 +15542,10 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 16,
                .iv     = "\xe9\x6e\x8c\x08\xab\x46\x57\x63"
                          "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\xe9\x6e\x8c\x08\xab\x46\x57\x63"
+                         "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93",
+               .alen   = 24,
                .input  = "\x08\x00\x0e\xbd\xa7\x0a\x00\x00"
                          "\x8e\x9c\x08\x3d\xb9\x5b\x07\x00"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -15551,6 +15591,9 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 24,
                .iv     = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .alen   = 16,
                .input  = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
                          "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
                          "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
@@ -15593,6 +15636,9 @@ static struct aead_testvec hmac_sha256_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 32 + 32,
                .iv     = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .alen   = 16,
                .input  = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
                          "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
                          "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
@@ -15641,6 +15687,9 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 16,
                .iv     = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
                          "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+               .assoc  = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+                         "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+               .alen   = 16,
                .input  = "Single block msg",
                .ilen   = 16,
                .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
@@ -15676,6 +15725,9 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 16,
                .iv     = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
                          "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+               .assoc  = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
+                         "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
+               .alen   = 16,
                .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"
@@ -15716,6 +15768,9 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 16,
                .iv     = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb"
                          "\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
+               .assoc  = "\xc7\x82\xdc\x4c\x09\x8c\x66\xcb"
+                         "\xd9\xcd\x27\xd8\x25\x68\x2c\x81",
+               .alen   = 16,
                .input  = "This is a 48-byte message (exactly 3 AES blocks)",
                .ilen   = 48,
                .result = "\xd0\xa0\x2b\x38\x36\x45\x17\x53"
@@ -15755,6 +15810,9 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 16,
                .iv     = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c"
                          "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
+               .assoc  = "\x8c\xe8\x2e\xef\xbe\xa0\xda\x3c"
+                         "\x44\x69\x9e\xd7\xdb\x51\xb7\xd9",
+               .alen   = 16,
                .input  = "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
                          "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
                          "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
@@ -15803,8 +15861,10 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 16,
                .iv     = "\xe9\x6e\x8c\x08\xab\x46\x57\x63"
                          "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\xe9\x6e\x8c\x08\xab\x46\x57\x63"
+                         "\xfd\x09\x8d\x45\xdd\x3f\xf8\x93",
+               .alen   = 24,
                .input  = "\x08\x00\x0e\xbd\xa7\x0a\x00\x00"
                          "\x8e\x9c\x08\x3d\xb9\x5b\x07\x00"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -15858,6 +15918,9 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 24,
                .iv     = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .alen   = 16,
                .input  = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
                          "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
                          "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
@@ -15908,6 +15971,9 @@ static struct aead_testvec hmac_sha512_aes_cbc_enc_tv_temp[] = {
                .klen   = 8 + 64 + 32,
                .iv     = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+               .alen   = 16,
                .input  = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
                          "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
                          "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
@@ -15955,8 +16021,9 @@ static struct aead_testvec hmac_sha1_des_cbc_enc_tv_temp[] = {
                          "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24",
                .klen   = 8 + 20 + 8,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16015,8 +16082,9 @@ static struct aead_testvec hmac_sha224_des_cbc_enc_tv_temp[] = {
                          "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24",
                .klen   = 8 + 24 + 8,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16076,8 +16144,9 @@ static struct aead_testvec hmac_sha256_des_cbc_enc_tv_temp[] = {
                          "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24",
                .klen   = 8 + 32 + 8,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16140,8 +16209,9 @@ static struct aead_testvec hmac_sha384_des_cbc_enc_tv_temp[] = {
                          "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24",
                .klen   = 8 + 48 + 8,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16208,8 +16278,9 @@ static struct aead_testvec hmac_sha512_des_cbc_enc_tv_temp[] = {
                          "\xE9\xC0\xFF\x2E\x76\x0B\x64\x24",
                .klen   = 8 + 64 + 8,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16275,8 +16346,9 @@ static struct aead_testvec hmac_sha1_des3_ede_cbc_enc_tv_temp[] = {
                          "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8",
                .klen   = 8 + 20 + 24,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                  "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16337,8 +16409,9 @@ static struct aead_testvec hmac_sha224_des3_ede_cbc_enc_tv_temp[] = {
                          "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8",
                .klen   = 8 + 24 + 24,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16400,8 +16473,9 @@ static struct aead_testvec hmac_sha256_des3_ede_cbc_enc_tv_temp[] = {
                          "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8",
                .klen   = 8 + 32 + 24,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16466,8 +16540,9 @@ static struct aead_testvec hmac_sha384_des3_ede_cbc_enc_tv_temp[] = {
                          "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8",
                .klen   = 8 + 48 + 24,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-       .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -16536,8 +16611,9 @@ static struct aead_testvec hmac_sha512_des3_ede_cbc_enc_tv_temp[] = {
                          "\xEA\xC2\x84\xE8\x14\x95\xDB\xE8",
                .klen   = 8 + 64 + 24,
                .iv     = "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
-               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x43\x21\x00\x00\x00\x01"
+                         "\x7D\x33\x88\x93\x0F\x93\xB2\x42",
+               .alen   = 16,
                .input  = "\x6f\x54\x20\x6f\x61\x4d\x79\x6e"
                          "\x53\x20\x63\x65\x65\x72\x73\x74"
                          "\x54\x20\x6f\x6f\x4d\x20\x6e\x61"
@@ -20129,149 +20205,150 @@ static struct aead_testvec aes_gcm_dec_tv_template[] = {
 };
 
 static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
-        { /* Generated using Crypto++ */
+       { /* Generated using Crypto++ */
                .key    = zeroed_string,
                .klen   = 20,
-                .iv     = zeroed_string,
-                .input  = zeroed_string,
-                .ilen   = 16,
-                .assoc  = zeroed_string,
-                .alen   = 8,
+               .iv     = zeroed_string,
+               .input  = zeroed_string,
+               .ilen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
                .result = "\x03\x88\xDA\xCE\x60\xB6\xA3\x92"
-                          "\xF3\x28\xC2\xB9\x71\xB2\xFE\x78"
-                          "\x97\xFE\x4C\x23\x37\x42\x01\xE0"
-                          "\x81\x9F\x8D\xC5\xD7\x41\xA0\x1B",
+                         "\xF3\x28\xC2\xB9\x71\xB2\xFE\x78"
+                         "\x97\xFE\x4C\x23\x37\x42\x01\xE0"
+                         "\x81\x9F\x8D\xC5\xD7\x41\xA0\x1B",
                .rlen   = 32,
-        },{
+       },{
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
-                          "\x00\x00\x00\x00",
-                .input  = zeroed_string,
-                .ilen   = 16,
-                .assoc  = zeroed_string,
-                .alen   = 8,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = zeroed_string,
+               .ilen   = 16,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
                .result = "\xC0\x0D\x8B\x42\x0F\x8F\x34\x18"
-                          "\x88\xB1\xC5\xBC\xC5\xB6\xD6\x28"
-                          "\x6A\x9D\xDF\x11\x5E\xFE\x5E\x9D"
-                          "\x2F\x70\x44\x92\xF7\xF2\xE3\xEF",
+                         "\x88\xB1\xC5\xBC\xC5\xB6\xD6\x28"
+                         "\x6A\x9D\xDF\x11\x5E\xFE\x5E\x9D"
+                         "\x2F\x70\x44\x92\xF7\xF2\xE3\xEF",
                .rlen   = 32,
 
-        }, {
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = zeroed_string,
-                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .ilen   = 16,
-                .assoc  = zeroed_string,
-                .alen   = 8,
+               .iv     = zeroed_string,
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
                .result = "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
-                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
-                          "\x0B\x8F\x88\x69\x17\xE6\xB4\x3C"
-                          "\xB1\x68\xFD\x14\x52\x64\x61\xB2",
+                         "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                         "\x0B\x8F\x88\x69\x17\xE6\xB4\x3C"
+                         "\xB1\x68\xFD\x14\x52\x64\x61\xB2",
                .rlen   = 32,
-        }, {
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = zeroed_string,
-                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .ilen   = 16,
-                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .alen   = 8,
+               .iv     = zeroed_string,
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
                .result = "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
-                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
-                          "\x90\x92\xB7\xE3\x5F\xA3\x9A\x63"
-                          "\x7E\xD7\x1F\xD8\xD3\x7C\x4B\xF5",
+                         "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                         "\x90\x92\xB7\xE3\x5F\xA3\x9A\x63"
+                         "\x7E\xD7\x1F\xD8\xD3\x7C\x4B\xF5",
                .rlen   = 32,
-        }, {
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
-                          "\x00\x00\x00\x00",
-                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .ilen   = 16,
-                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .alen   = 8,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
                .result = "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
-                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
-                          "\x64\x50\xF9\x32\x13\xFB\x74\x61"
-                          "\xF4\xED\x52\xD3\xC5\x10\x55\x3C",
+                         "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                         "\x64\x50\xF9\x32\x13\xFB\x74\x61"
+                         "\xF4\xED\x52\xD3\xC5\x10\x55\x3C",
                .rlen   = 32,
-        }, {
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
-                          "\x00\x00\x00\x00",
-                .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .ilen   = 64,
-                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .alen   = 8,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 64,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
                .result = "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
-                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
-                          "\x98\x14\xA1\x42\x37\x80\xFD\x90"
-                          "\x68\x12\x01\xA8\x91\x89\xB9\x83"
-                          "\x5B\x11\x77\x12\x9B\xFF\x24\x89"
-                          "\x94\x5F\x18\x12\xBA\x27\x09\x39"
-                          "\x99\x96\x76\x42\x15\x1C\xCD\xCB"
-                          "\xDC\xD3\xDA\x65\x73\xAF\x80\xCD"
-                          "\xD2\xB6\xC2\x4A\x76\xC2\x92\x85"
-                          "\xBD\xCF\x62\x98\x58\x14\xE5\xBD",
+                         "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                         "\x98\x14\xA1\x42\x37\x80\xFD\x90"
+                         "\x68\x12\x01\xA8\x91\x89\xB9\x83"
+                         "\x5B\x11\x77\x12\x9B\xFF\x24\x89"
+                         "\x94\x5F\x18\x12\xBA\x27\x09\x39"
+                         "\x99\x96\x76\x42\x15\x1C\xCD\xCB"
+                         "\xDC\xD3\xDA\x65\x73\xAF\x80\xCD"
+                         "\xD2\xB6\xC2\x4A\x76\xC2\x92\x85"
+                         "\xBD\xCF\x62\x98\x58\x14\xE5\xBD",
                .rlen   = 80,
-        }, {
+       }, {
                .key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef"
-                          "\x00\x00\x00\x00",
-                .input  = "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff",
-                .ilen   = 192,
-                .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-                          "\xaa\xaa\xaa\xaa",
-                .alen   = 12,
+               .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef",
+               .input  = "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff",
+               .ilen   = 192,
+               .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                         "\xaa\xaa\xaa\xaa\x00\x00\x45\x67"
+                         "\x89\xab\xcd\xef",
+               .alen   = 20,
                .result = "\xC1\x76\x33\x85\xE2\x9B\x5F\xDE"
                          "\xDE\x89\x3D\x42\xE7\xC9\x69\x8A"
                          "\x44\x6D\xC3\x88\x46\x2E\xC2\x01"
@@ -20316,8 +20393,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x00\x21\x00\x01\x01\x02\x02\x01",
                .ilen   = 72,
                .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
-                         "\x00\x00\x00\x00",
-               .alen   = 12,
+                         "\x00\x00\x00\x00\x49\x56\xED\x7E"
+                         "\x3B\x24\x4C\xFE",
+               .alen   = 20,
                .result = "\xFE\xCF\x53\x7E\x72\x9D\x5B\x07"
                          "\xDC\x30\xDF\x52\x8D\xD2\x2B\x76"
                          "\x8D\x1B\x98\x73\x66\x96\xA6\xFD"
@@ -20345,8 +20423,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x65\x72\x63\x69\x74\x79\x02\x64"
                          "\x6B\x00\x00\x01\x00\x01\x00\x01",
                .ilen   = 64,
-               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A",
-               .alen   = 8,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
                .result = "\xDE\xB2\x2C\xD9\xB0\x7C\x72\xC1"
                          "\x6E\x3A\x65\xBE\xEB\x8D\xF3\x04"
                          "\xA5\xA5\x89\x7D\x33\xAE\x53\x0F"
@@ -20374,8 +20453,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x02\x04\x05\xB4\x01\x01\x04\x02"
                          "\x01\x02\x02\x01",
                .ilen   = 52,
-               .assoc  = "\x4A\x2C\xBF\xE3\x00\x00\x00\x02",
-               .alen   = 8,
+               .assoc  = "\x4A\x2C\xBF\xE3\x00\x00\x00\x02"
+                         "\x01\x02\x03\x04\x05\x06\x07\x08",
+               .alen   = 16,
                .result = "\xFF\x42\x5C\x9B\x72\x45\x99\xDF"
                          "\x7A\x3B\xCD\x51\x01\x94\xE0\x0D"
                          "\x6A\x78\x10\x7F\x1B\x0B\x1C\xBF"
@@ -20401,8 +20481,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x75\x76\x77\x61\x62\x63\x64\x65"
                          "\x66\x67\x68\x69\x01\x02\x02\x01",
                .ilen   = 64,
-               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
                .result = "\x46\x88\xDA\xF2\xF9\x73\xA3\x92"
                          "\x73\x29\x09\xC3\x31\xD5\x6D\x60"
                          "\xF6\x94\xAB\xAA\x41\x4B\x5E\x7F"
@@ -20430,8 +20511,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x66\x67\x68\x69\x01\x02\x02\x01",
                .ilen   = 64,
                .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .result = "\xFB\xA2\xCA\xA4\x85\x3C\xF9\xF0"
                          "\xF2\x2C\xB1\x0D\x86\xDD\x83\xB0"
                          "\xFE\xC7\x56\x91\xCF\x1A\x04\xB0"
@@ -20455,8 +20537,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x01\x02\x02\x01",
                .ilen   = 28,
                .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .result = "\xFB\xA2\xCA\x84\x5E\x5D\xF9\xF0"
                          "\xF2\x2C\x3E\x6E\x86\xDD\x83\x1E"
                          "\x1F\xC6\x57\x92\xCD\x1A\xF9\x13"
@@ -20477,8 +20560,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\xCB\x71\x26\x02\xDD\x6B\xB0\x3E"
                          "\x50\x10\x16\xD0\x75\x68\x00\x01",
                .ilen   = 40,
-               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A",
-               .alen   = 8,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
                .result = "\xA5\xB1\xF8\x06\x60\x29\xAE\xA4"
                          "\x0E\x59\x8B\x81\x22\xDE\x02\x42"
                          "\x09\x38\xB3\xAB\x33\xF8\x28\xE6"
@@ -20505,8 +20589,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x23\x01\x01\x01",
                .ilen   = 76,
                .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
-                         "\x00\x00\x00\x01",
-               .alen   = 12,
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
                .result = "\x18\xA6\xFD\x42\xF7\x2C\xBF\x4A"
                          "\xB2\xA2\xEA\x90\x1F\x73\xD8\x14"
                          "\xE3\xE7\xF2\x43\xD9\x54\x12\xE1"
@@ -20535,8 +20620,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x50\x10\x1F\x64\x6D\x54\x00\x01",
                .ilen   = 40,
                .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
-                         "\xDD\x0D\xB9\x9B",
-               .alen   = 12,
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
                .result = "\xF2\xD6\x9E\xCD\xBD\x5A\x0D\x5B"
                          "\x8D\x5E\xF3\x8B\xAD\x4D\xA5\x8D"
                          "\x1F\x27\x8F\xDE\x98\xEF\x67\x54"
@@ -20563,8 +20649,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x15\x01\x01\x01",
                .ilen   = 76,
                .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .result = "\xFB\xA2\xCA\xD1\x2F\xC1\xF9\xF0"
                          "\x0D\x3C\xEB\xF3\x05\x41\x0D\xB8"
                          "\x3D\x77\x84\xB6\x07\x32\x3D\x22"
@@ -20597,8 +20684,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x72\x72\x6F\x77\x01\x02\x02\x01",
                .ilen   = 72,
                .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
-                         "\xDD\x0D\xB9\x9B",
-               .alen   = 12,
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
                .result = "\xD4\xB7\xED\x86\xA1\x77\x7F\x2E"
                          "\xA1\x3D\x69\x73\xD3\x24\xC6\x9E"
                          "\x7B\x43\xF8\x26\xFB\x56\x83\x12"
@@ -20619,8 +20707,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                .iv     = "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
                .input  = "\x01\x02\x02\x01",
                .ilen   = 4,
-               .assoc  = "\x33\x54\x67\xAE\xFF\xFF\xFF\xFF",
-               .alen   = 8,
+               .assoc  = "\x33\x54\x67\xAE\xFF\xFF\xFF\xFF"
+                         "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
+               .alen   = 16,
                .result = "\x43\x7F\x86\x6B\xCB\x3F\x69\x9F"
                          "\xE9\xB0\x82\x2B\xAC\x96\x1C\x45"
                          "\x04\xBE\xF2\x70",
@@ -20636,8 +20725,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x62\x65\x00\x01",
                .ilen   = 20,
                .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
-                         "\x00\x00\x00\x01",
-               .alen   = 12,
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
                .result = "\x29\xC9\xFC\x69\xA1\x97\xD0\x38"
                          "\xCC\xDD\x14\xE2\xDD\xFC\xAA\x05"
                          "\x43\x33\x21\x64\x41\x25\x03\x52"
@@ -20661,8 +20751,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x01\x02\x02\x01",
                .ilen   = 52,
                .assoc  = "\x79\x6B\x69\x63\xFF\xFF\xFF\xFF"
-                         "\xFF\xFF\xFF\xFF",
-               .alen   = 12,
+                         "\xFF\xFF\xFF\xFF\x33\x30\x21\x69"
+                         "\x67\x65\x74\x6D",
+               .alen   = 20,
                .result = "\xF9\x7A\xB2\xAA\x35\x6D\x8E\xDC"
                          "\xE1\x76\x44\xAC\x8C\x78\xE2\x5D"
                          "\xD2\x4D\xED\xBB\x29\xEB\xF1\xB6"
@@ -20688,8 +20779,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x01\x02\x02\x01",
                .ilen   = 52,
                .assoc  = "\x3F\x7E\xF6\x42\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .result = "\xFB\xA2\xCA\xA8\xC6\xC5\xF9\xF0"
                          "\xF2\x2C\xA5\x4A\x06\x12\x10\xAD"
                          "\x3F\x6E\x57\x91\xCF\x1A\xCA\x21"
@@ -20712,8 +20804,9 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
                          "\x71\x72\x73\x74\x01\x02\x02\x01",
                .ilen   = 32,
                .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
-                         "\x00\x00\x00\x07",
-               .alen   = 12,
+                         "\x00\x00\x00\x07\x48\x55\xEC\x7D"
+                         "\x3A\x23\x4B\xFD",
+               .alen   = 20,
                .result = "\x74\x75\x2E\x8A\xEB\x5D\x87\x3C"
                          "\xD7\xC0\xF4\xAC\xC3\x6C\x4B\xFF"
                          "\x84\xB7\xD7\xB9\x8F\x0C\xA8\xB6"
@@ -20725,122 +20818,122 @@ static struct aead_testvec aes_gcm_rfc4106_enc_tv_template[] = {
 };
 
 static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
-        { /* Generated using Crypto++ */
+       { /* Generated using Crypto++ */
                .key    = zeroed_string,
                .klen   = 20,
-                .iv     = zeroed_string,
+               .iv     = zeroed_string,
                .input  = "\x03\x88\xDA\xCE\x60\xB6\xA3\x92"
-                          "\xF3\x28\xC2\xB9\x71\xB2\xFE\x78"
-                          "\x97\xFE\x4C\x23\x37\x42\x01\xE0"
-                          "\x81\x9F\x8D\xC5\xD7\x41\xA0\x1B",
+                         "\xF3\x28\xC2\xB9\x71\xB2\xFE\x78"
+                         "\x97\xFE\x4C\x23\x37\x42\x01\xE0"
+                         "\x81\x9F\x8D\xC5\xD7\x41\xA0\x1B",
                .ilen   = 32,
-                .assoc  = zeroed_string,
-                .alen   = 8,
-                .result = zeroed_string,
-                .rlen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
+               .result = zeroed_string,
+               .rlen   = 16,
 
-        },{
+       },{
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
-                          "\x00\x00\x00\x00",
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
                .input  = "\xC0\x0D\x8B\x42\x0F\x8F\x34\x18"
-                          "\x88\xB1\xC5\xBC\xC5\xB6\xD6\x28"
-                          "\x6A\x9D\xDF\x11\x5E\xFE\x5E\x9D"
-                          "\x2F\x70\x44\x92\xF7\xF2\xE3\xEF",
+                         "\x88\xB1\xC5\xBC\xC5\xB6\xD6\x28"
+                         "\x6A\x9D\xDF\x11\x5E\xFE\x5E\x9D"
+                         "\x2F\x70\x44\x92\xF7\xF2\xE3\xEF",
                .ilen   = 32,
-                .assoc  = zeroed_string,
-                .alen   = 8,
-                .result = zeroed_string,
-                .rlen   = 16,
-        }, {
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .result = zeroed_string,
+               .rlen   = 16,
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = zeroed_string,
+               .iv     = zeroed_string,
                .input  = "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
-                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
-                          "\x0B\x8F\x88\x69\x17\xE6\xB4\x3C"
-                          "\xB1\x68\xFD\x14\x52\x64\x61\xB2",
+                         "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                         "\x0B\x8F\x88\x69\x17\xE6\xB4\x3C"
+                         "\xB1\x68\xFD\x14\x52\x64\x61\xB2",
                .ilen   = 32,
-                .assoc  = zeroed_string,
-                .alen   = 8,
-                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .rlen   = 16,
-        }, {
+               .assoc  = zeroed_string,
+               .alen   = 16,
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 16,
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = zeroed_string,
+               .iv     = zeroed_string,
                .input  = "\x4B\xB1\xB5\xE3\x25\x71\x70\xDE"
-                          "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
-                          "\x90\x92\xB7\xE3\x5F\xA3\x9A\x63"
-                          "\x7E\xD7\x1F\xD8\xD3\x7C\x4B\xF5",
+                         "\x7F\xC9\x9C\xA5\x14\x19\xF2\xAC"
+                         "\x90\x92\xB7\xE3\x5F\xA3\x9A\x63"
+                         "\x7E\xD7\x1F\xD8\xD3\x7C\x4B\xF5",
                .ilen   = 32,
-                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .alen   = 8,
-                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .rlen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 16,
 
-        }, {
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
-                          "\x00\x00\x00\x00",
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
                .input  = "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
-                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
-                          "\x64\x50\xF9\x32\x13\xFB\x74\x61"
-                          "\xF4\xED\x52\xD3\xC5\x10\x55\x3C",
+                         "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                         "\x64\x50\xF9\x32\x13\xFB\x74\x61"
+                         "\xF4\xED\x52\xD3\xC5\x10\x55\x3C",
                .ilen   = 32,
-                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .alen   = 8,
-                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .rlen   = 16,
-        }, {
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 16,
+       }, {
                .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
                          "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01"
-                          "\x00\x00\x00\x00",
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
                .input  = "\xC1\x0C\x8A\x43\x0E\x8E\x35\x19"
-                          "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
-                          "\x98\x14\xA1\x42\x37\x80\xFD\x90"
-                          "\x68\x12\x01\xA8\x91\x89\xB9\x83"
-                          "\x5B\x11\x77\x12\x9B\xFF\x24\x89"
-                          "\x94\x5F\x18\x12\xBA\x27\x09\x39"
-                          "\x99\x96\x76\x42\x15\x1C\xCD\xCB"
-                          "\xDC\xD3\xDA\x65\x73\xAF\x80\xCD"
-                          "\xD2\xB6\xC2\x4A\x76\xC2\x92\x85"
-                          "\xBD\xCF\x62\x98\x58\x14\xE5\xBD",
+                         "\x89\xB0\xC4\xBD\xC4\xB7\xD7\x29"
+                         "\x98\x14\xA1\x42\x37\x80\xFD\x90"
+                         "\x68\x12\x01\xA8\x91\x89\xB9\x83"
+                         "\x5B\x11\x77\x12\x9B\xFF\x24\x89"
+                         "\x94\x5F\x18\x12\xBA\x27\x09\x39"
+                         "\x99\x96\x76\x42\x15\x1C\xCD\xCB"
+                         "\xDC\xD3\xDA\x65\x73\xAF\x80\xCD"
+                         "\xD2\xB6\xC2\x4A\x76\xC2\x92\x85"
+                         "\xBD\xCF\x62\x98\x58\x14\xE5\xBD",
                .ilen   = 80,
-                .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .alen   = 8,
-                .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01"
-                          "\x01\x01\x01\x01\x01\x01\x01\x01",
-                .rlen   = 64,
-        }, {
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 64,
+       }, {
                .key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                          "\x00\x00\x00\x00",
+                         "\x00\x00\x00\x00",
                .klen   = 20,
-                .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef"
-                          "\x00\x00\x00\x00",
+               .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef",
                .input  = "\xC1\x76\x33\x85\xE2\x9B\x5F\xDE"
                          "\xDE\x89\x3D\x42\xE7\xC9\x69\x8A"
                          "\x44\x6D\xC3\x88\x46\x2E\xC2\x01"
@@ -20868,34 +20961,35 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x37\x08\x1C\xCF\xBA\x5D\x71\x46"
                          "\x80\x72\xB0\x4C\x82\x0D\x60\x3C",
                .ilen   = 208,
-                .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-                          "\xaa\xaa\xaa\xaa",
-                .alen   = 12,
-                .result = "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff"
-                          "\xff\xff\xff\xff\xff\xff\xff\xff",
-                .rlen   = 192,
+               .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                         "\xaa\xaa\xaa\xaa\x00\x00\x45\x67"
+                         "\x89\xab\xcd\xef",
+               .alen   = 20,
+               .result = "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff",
+               .rlen   = 192,
        }, {
                .key    = "\x4C\x80\xCD\xEF\xBB\x5D\x10\xDA"
                          "\x90\x6A\xC7\x3C\x36\x13\xA6\x34"
@@ -20913,8 +21007,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x00\x21\x00\x01\x01\x02\x02\x01",
                .rlen   = 72,
                .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
-                         "\x00\x00\x00\x00",
-               .alen   = 12,
+                         "\x00\x00\x00\x00\x49\x56\xED\x7E"
+                         "\x3B\x24\x4C\xFE",
+               .alen   = 20,
                .input  = "\xFE\xCF\x53\x7E\x72\x9D\x5B\x07"
                          "\xDC\x30\xDF\x52\x8D\xD2\x2B\x76"
                          "\x8D\x1B\x98\x73\x66\x96\xA6\xFD"
@@ -20942,8 +21037,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x65\x72\x63\x69\x74\x79\x02\x64"
                          "\x6B\x00\x00\x01\x00\x01\x00\x01",
                .rlen   = 64,
-               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A",
-               .alen   = 8,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
                .input  = "\xDE\xB2\x2C\xD9\xB0\x7C\x72\xC1"
                          "\x6E\x3A\x65\xBE\xEB\x8D\xF3\x04"
                          "\xA5\xA5\x89\x7D\x33\xAE\x53\x0F"
@@ -20971,8 +21067,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x02\x04\x05\xB4\x01\x01\x04\x02"
                          "\x01\x02\x02\x01",
                .rlen   = 52,
-               .assoc  = "\x4A\x2C\xBF\xE3\x00\x00\x00\x02",
-               .alen   = 8,
+               .assoc  = "\x4A\x2C\xBF\xE3\x00\x00\x00\x02"
+                         "\x01\x02\x03\x04\x05\x06\x07\x08",
+               .alen   = 16,
                .input  = "\xFF\x42\x5C\x9B\x72\x45\x99\xDF"
                          "\x7A\x3B\xCD\x51\x01\x94\xE0\x0D"
                          "\x6A\x78\x10\x7F\x1B\x0B\x1C\xBF"
@@ -20998,8 +21095,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x75\x76\x77\x61\x62\x63\x64\x65"
                          "\x66\x67\x68\x69\x01\x02\x02\x01",
                .rlen   = 64,
-               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x01",
-               .alen   = 8,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
                .input  = "\x46\x88\xDA\xF2\xF9\x73\xA3\x92"
                          "\x73\x29\x09\xC3\x31\xD5\x6D\x60"
                          "\xF6\x94\xAB\xAA\x41\x4B\x5E\x7F"
@@ -21027,8 +21125,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x66\x67\x68\x69\x01\x02\x02\x01",
                .rlen   = 64,
                .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .input  = "\xFB\xA2\xCA\xA4\x85\x3C\xF9\xF0"
                          "\xF2\x2C\xB1\x0D\x86\xDD\x83\xB0"
                          "\xFE\xC7\x56\x91\xCF\x1A\x04\xB0"
@@ -21052,8 +21151,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x01\x02\x02\x01",
                .rlen   = 28,
                .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .input  = "\xFB\xA2\xCA\x84\x5E\x5D\xF9\xF0"
                          "\xF2\x2C\x3E\x6E\x86\xDD\x83\x1E"
                          "\x1F\xC6\x57\x92\xCD\x1A\xF9\x13"
@@ -21074,8 +21174,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\xCB\x71\x26\x02\xDD\x6B\xB0\x3E"
                          "\x50\x10\x16\xD0\x75\x68\x00\x01",
                .rlen   = 40,
-               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A",
-               .alen   = 8,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
                .input  = "\xA5\xB1\xF8\x06\x60\x29\xAE\xA4"
                          "\x0E\x59\x8B\x81\x22\xDE\x02\x42"
                          "\x09\x38\xB3\xAB\x33\xF8\x28\xE6"
@@ -21102,8 +21203,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x23\x01\x01\x01",
                .rlen   = 76,
                .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
-                         "\x00\x00\x00\x01",
-               .alen   = 12,
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
                .input  = "\x18\xA6\xFD\x42\xF7\x2C\xBF\x4A"
                          "\xB2\xA2\xEA\x90\x1F\x73\xD8\x14"
                          "\xE3\xE7\xF2\x43\xD9\x54\x12\xE1"
@@ -21132,8 +21234,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x50\x10\x1F\x64\x6D\x54\x00\x01",
                .rlen   = 40,
                .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
-                         "\xDD\x0D\xB9\x9B",
-               .alen   = 12,
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
                .input  = "\xF2\xD6\x9E\xCD\xBD\x5A\x0D\x5B"
                          "\x8D\x5E\xF3\x8B\xAD\x4D\xA5\x8D"
                          "\x1F\x27\x8F\xDE\x98\xEF\x67\x54"
@@ -21160,8 +21263,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x15\x01\x01\x01",
                .rlen   = 76,
                .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .input  = "\xFB\xA2\xCA\xD1\x2F\xC1\xF9\xF0"
                          "\x0D\x3C\xEB\xF3\x05\x41\x0D\xB8"
                          "\x3D\x77\x84\xB6\x07\x32\x3D\x22"
@@ -21194,8 +21298,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x72\x72\x6F\x77\x01\x02\x02\x01",
                .rlen   = 72,
                .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
-                         "\xDD\x0D\xB9\x9B",
-               .alen   = 12,
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
                .input  = "\xD4\xB7\xED\x86\xA1\x77\x7F\x2E"
                          "\xA1\x3D\x69\x73\xD3\x24\xC6\x9E"
                          "\x7B\x43\xF8\x26\xFB\x56\x83\x12"
@@ -21216,8 +21321,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                .iv     = "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
                .result = "\x01\x02\x02\x01",
                .rlen   = 4,
-               .assoc  = "\x33\x54\x67\xAE\xFF\xFF\xFF\xFF",
-               .alen   = 8,
+               .assoc  = "\x33\x54\x67\xAE\xFF\xFF\xFF\xFF"
+                         "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
+               .alen   = 16,
                .input  = "\x43\x7F\x86\x6B\xCB\x3F\x69\x9F"
                          "\xE9\xB0\x82\x2B\xAC\x96\x1C\x45"
                          "\x04\xBE\xF2\x70",
@@ -21233,8 +21339,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x62\x65\x00\x01",
                .rlen   = 20,
                .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
-                         "\x00\x00\x00\x01",
-               .alen   = 12,
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
                .input  = "\x29\xC9\xFC\x69\xA1\x97\xD0\x38"
                          "\xCC\xDD\x14\xE2\xDD\xFC\xAA\x05"
                          "\x43\x33\x21\x64\x41\x25\x03\x52"
@@ -21258,8 +21365,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x01\x02\x02\x01",
                .rlen   = 52,
                .assoc  = "\x79\x6B\x69\x63\xFF\xFF\xFF\xFF"
-                         "\xFF\xFF\xFF\xFF",
-               .alen   = 12,
+                         "\xFF\xFF\xFF\xFF\x33\x30\x21\x69"
+                         "\x67\x65\x74\x6D",
+               .alen   = 20,
                .input  = "\xF9\x7A\xB2\xAA\x35\x6D\x8E\xDC"
                          "\xE1\x76\x44\xAC\x8C\x78\xE2\x5D"
                          "\xD2\x4D\xED\xBB\x29\xEB\xF1\xB6"
@@ -21285,8 +21393,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x01\x02\x02\x01",
                .rlen   = 52,
                .assoc  = "\x3F\x7E\xF6\x42\x10\x10\x10\x10"
-                         "\x10\x10\x10\x10",
-               .alen   = 12,
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
                .input  = "\xFB\xA2\xCA\xA8\xC6\xC5\xF9\xF0"
                          "\xF2\x2C\xA5\x4A\x06\x12\x10\xAD"
                          "\x3F\x6E\x57\x91\xCF\x1A\xCA\x21"
@@ -21309,8 +21418,9 @@ static struct aead_testvec aes_gcm_rfc4106_dec_tv_template[] = {
                          "\x71\x72\x73\x74\x01\x02\x02\x01",
                .rlen   = 32,
                .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
-                         "\x00\x00\x00\x07",
-               .alen   = 12,
+                         "\x00\x00\x00\x07\x48\x55\xEC\x7D"
+                         "\x3A\x23\x4B\xFD",
+               .alen   = 20,
                .input  = "\x74\x75\x2E\x8A\xEB\x5D\x87\x3C"
                          "\xD7\xC0\xF4\xAC\xC3\x6C\x4B\xFF"
                          "\x84\xB7\xD7\xB9\x8F\x0C\xA8\xB6"
@@ -21538,10 +21648,7 @@ static struct aead_testvec aes_ccm_enc_tv_template[] = {
                          "\xba",
                .rlen   = 33,
        }, {
-               /*
-                * This is the same vector as aes_ccm_rfc4309_enc_tv_template[0]
-                * below but rewritten to use the ccm algorithm directly.
-                */
+               /* This is taken from FIPS CAVS. */
                .key    = "\x83\xac\x54\x66\xc2\xeb\xe5\x05"
                          "\x2e\x01\xd1\xfc\x5d\x82\x66\x2e",
                .klen   = 16,
@@ -21559,214 +21666,51 @@ static struct aead_testvec aes_ccm_enc_tv_template[] = {
                          "\xda\x24\xea\xd9\xa1\x39\x98\xfd"
                          "\xa4\xbe\xd9\xf2\x1a\x6d\x22\xa8",
                .rlen   = 48,
-       }
-};
-
-static struct aead_testvec aes_ccm_dec_tv_template[] = {
-       { /* From RFC 3610 */
-               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
-                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
-               .klen   = 16,
-               .iv     = "\x01\x00\x00\x00\x03\x02\x01\x00"
-                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
-               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07",
-               .alen   = 8,
-               .input  = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
-                         "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
-                         "\x6d\x5f\x6b\x61\xda\xc3\x84\x17"
-                         "\xe8\xd1\x2c\xfd\xf9\x26\xe0",
-               .ilen   = 31,
-               .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                         "\x10\x11\x12\x13\x14\x15\x16\x17"
-                         "\x18\x19\x1a\x1b\x1c\x1d\x1e",
-               .rlen   = 23,
        }, {
-               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
-                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+               .key    = "\x1e\x2c\x7e\x01\x41\x9a\xef\xc0"
+                         "\x0d\x58\x96\x6e\x5c\xa2\x4b\xd3",
                .klen   = 16,
-               .iv     = "\x01\x00\x00\x00\x07\x06\x05\x04"
-                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
-               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
-                         "\x08\x09\x0a\x0b",
-               .alen   = 12,
-               .input  = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
-                         "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
-                         "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07"
-                         "\x7d\x9c\x2d\x93",
-               .ilen   = 28,
-               .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
-                         "\x14\x15\x16\x17\x18\x19\x1a\x1b"
-                         "\x1c\x1d\x1e\x1f",
-               .rlen   = 20,
+               .iv     = "\x03\x4f\xa3\x19\xd3\x01\x5a\xd8"
+                         "\x30\x60\x15\x56\x00\x00\x00\x00",
+               .assoc  = "\xda\xe6\x28\x9c\x45\x2d\xfd\x63"
+                         "\x5e\xda\x4c\xb6\xe6\xfc\xf9\xb7"
+                         "\x0c\x56\xcb\xe4\xe0\x05\x7a\xe1"
+                         "\x0a\x63\x09\x78\xbc\x2c\x55\xde",
+               .alen   = 32,
+               .input  = "\x87\xa3\x36\xfd\x96\xb3\x93\x78"
+                         "\xa9\x28\x63\xba\x12\xa3\x14\x85"
+                         "\x57\x1e\x06\xc9\x7b\x21\xef\x76"
+                         "\x7f\x38\x7e\x8e\x29\xa4\x3e\x7e",
+               .ilen   = 32,
+               .result = "\x8a\x1e\x11\xf0\x02\x6b\xe2\x19"
+                         "\xfc\x70\xc4\x6d\x8e\xb7\x99\xab"
+                         "\xc5\x4b\xa2\xac\xd3\xf3\x48\xff"
+                         "\x3b\xb5\xce\x53\xef\xde\xbb\x02"
+                         "\xa9\x86\x15\x6c\x13\xfe\xda\x0a"
+                         "\x22\xb8\x29\x3d\xd8\x39\x9a\x23",
+               .rlen   = 48,
        }, {
-               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
-                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
-               .klen   = 16,
-               .iv     = "\x01\x00\x00\x00\x0b\x0a\x09\x08"
-                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
-               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07",
-               .alen   = 8,
-               .input  = "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
-                         "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
-                         "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
-                         "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1"
-                         "\x7e\x5f\x4e",
-               .ilen   = 35,
-               .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                         "\x10\x11\x12\x13\x14\x15\x16\x17"
-                         "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
-                         "\x20",
-               .rlen   = 25,
-       }, {
-               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
-                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
-               .klen   = 16,
-               .iv     = "\x01\x00\x00\x00\x0c\x0b\x0a\x09"
-                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
-               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
-                         "\x08\x09\x0a\x0b",
-               .alen   = 12,
-               .input  = "\x07\x34\x25\x94\x15\x77\x85\x15"
-                         "\x2b\x07\x40\x98\x33\x0a\xbb\x14"
-                         "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b"
-                         "\x4d\x99\x99\x88\xdd",
-               .ilen   = 29,
-               .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
-                         "\x14\x15\x16\x17\x18\x19\x1a\x1b"
-                         "\x1c\x1d\x1e",
-               .rlen   = 19,
-       }, {
-               .key    = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
-                         "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
-               .klen   = 16,
-               .iv     = "\x01\x00\x33\x56\x8e\xf7\xb2\x63"
-                         "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
-               .assoc  = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb",
-               .alen   = 8,
-               .input  = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa"
-                         "\xa0\x72\x6c\x55\xd3\x78\x06\x12"
-                         "\x98\xc8\x5c\x92\x81\x4a\xbc\x33"
-                         "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a",
-               .ilen   = 32,
-               .result = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a"
-                         "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf"
-                         "\xb7\x9c\x70\x28\x94\x9c\xd0\xec",
-               .rlen   = 24,
-       }, {
-               .key    = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
-                         "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
-               .klen   = 16,
-               .iv     = "\x01\x00\xd5\x60\x91\x2d\x3f\x70"
-                         "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
-               .assoc  = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81"
-                         "\x20\xea\x60\xc0",
-               .alen   = 12,
-               .input  = "\x00\x97\x69\xec\xab\xdf\x48\x62"
-                         "\x55\x94\xc5\x92\x51\xe6\x03\x57"
-                         "\x22\x67\x5e\x04\xc8\x47\x09\x9e"
-                         "\x5a\xe0\x70\x45\x51",
-               .ilen   = 29,
-               .result = "\x64\x35\xac\xba\xfb\x11\xa8\x2e"
-                         "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9"
-                         "\x3a\x80\x3b\xa8\x7f",
-               .rlen   = 21,
-       }, {
-               .key    = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
-                         "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
-               .klen   = 16,
-               .iv     = "\x01\x00\x42\xff\xf8\xf1\x95\x1c"
-                         "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
-               .assoc  = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8",
-               .alen   = 8,
-               .input  = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6"
-                         "\xdb\x38\x6a\x99\xac\x1a\xef\x23"
-                         "\xad\xe0\xb5\x29\x39\xcb\x6a\x63"
-                         "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
-                         "\xba",
-               .ilen   = 33,
-               .result = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01"
-                         "\x8e\x5e\x67\x01\xc9\x17\x87\x65"
-                         "\x98\x09\xd6\x7d\xbe\xdd\x18",
-               .rlen   = 23,
-       },
-};
-
-/*
- * rfc4309 refers to section 8 of rfc3610 for test vectors, but they all
- * use a 13-byte nonce, we only support an 11-byte nonce. Similarly, all of
- * Special Publication 800-38C's test vectors also use nonce lengths our
- * implementation doesn't support. The following are taken from fips cavs
- * fax files on hand at Red Hat.
- *
- * nb: actual key lengths are (klen - 3), the last 3 bytes are actually
- * part of the nonce which combine w/the iv, but need to be input this way.
- */
-static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
-       {
-               .key    = "\x83\xac\x54\x66\xc2\xeb\xe5\x05"
-                         "\x2e\x01\xd1\xfc\x5d\x82\x66\x2e"
-                         "\x96\xac\x59",
-               .klen   = 19,
-               .iv     = "\x30\x07\xa1\xe2\xa2\xc7\x55\x24",
-               .alen   = 0,
-               .input  = "\x19\xc8\x81\xf6\xe9\x86\xff\x93"
-                         "\x0b\x78\x67\xe5\xbb\xb7\xfc\x6e"
-                         "\x83\x77\xb3\xa6\x0c\x8c\x9f\x9c"
-                         "\x35\x2e\xad\xe0\x62\xf9\x91\xa1",
-               .ilen   = 32,
-               .result = "\xab\x6f\xe1\x69\x1d\x19\x99\xa8"
-                         "\x92\xa0\xc4\x6f\x7e\xe2\x8b\xb1"
-                         "\x70\xbb\x8c\xa6\x4c\x6e\x97\x8a"
-                         "\x57\x2b\xbe\x5d\x98\xa6\xb1\x32"
-                         "\xda\x24\xea\xd9\xa1\x39\x98\xfd"
-                         "\xa4\xbe\xd9\xf2\x1a\x6d\x22\xa8",
-               .rlen   = 48,
-       }, {
-               .key    = "\x1e\x2c\x7e\x01\x41\x9a\xef\xc0"
-                         "\x0d\x58\x96\x6e\x5c\xa2\x4b\xd3"
-                         "\x4f\xa3\x19",
-               .klen   = 19,
-               .iv     = "\xd3\x01\x5a\xd8\x30\x60\x15\x56",
-               .assoc  = "\xda\xe6\x28\x9c\x45\x2d\xfd\x63"
-                         "\x5e\xda\x4c\xb6\xe6\xfc\xf9\xb7"
-                         "\x0c\x56\xcb\xe4\xe0\x05\x7a\xe1"
-                         "\x0a\x63\x09\x78\xbc\x2c\x55\xde",
-               .alen   = 32,
-               .input  = "\x87\xa3\x36\xfd\x96\xb3\x93\x78"
-                         "\xa9\x28\x63\xba\x12\xa3\x14\x85"
-                         "\x57\x1e\x06\xc9\x7b\x21\xef\x76"
-                         "\x7f\x38\x7e\x8e\x29\xa4\x3e\x7e",
-               .ilen   = 32,
-               .result = "\x8a\x1e\x11\xf0\x02\x6b\xe2\x19"
-                         "\xfc\x70\xc4\x6d\x8e\xb7\x99\xab"
-                         "\xc5\x4b\xa2\xac\xd3\xf3\x48\xff"
-                         "\x3b\xb5\xce\x53\xef\xde\xbb\x02"
-                         "\xa9\x86\x15\x6c\x13\xfe\xda\x0a"
-                         "\x22\xb8\x29\x3d\xd8\x39\x9a\x23",
-               .rlen   = 48,
-       }, {
-               .key    = "\xf4\x6b\xc2\x75\x62\xfe\xb4\xe1"
-                         "\xa3\xf0\xff\xdd\x4e\x4b\x12\x75"
-                         "\x53\x14\x73\x66\x8d\x88\xf6\x80"
-                         "\xa0\x20\x35",
-               .klen   = 27,
-               .iv     = "\x26\xf2\x21\x8d\x50\x20\xda\xe2",
-               .assoc  = "\x5b\x9e\x13\x67\x02\x5e\xef\xc1"
-                         "\x6c\xf9\xd7\x1e\x52\x8f\x7a\x47"
-                         "\xe9\xd4\xcf\x20\x14\x6e\xf0\x2d"
-                         "\xd8\x9e\x2b\x56\x10\x23\x56\xe7",
-               .alen   = 32,
-               .ilen   = 0,
-               .result = "\x36\xea\x7a\x70\x08\xdc\x6a\xbc"
-                         "\xad\x0c\x7a\x63\xf6\x61\xfd\x9b",
-               .rlen   = 16,
+               .key    = "\xf4\x6b\xc2\x75\x62\xfe\xb4\xe1"
+                         "\xa3\xf0\xff\xdd\x4e\x4b\x12\x75"
+                         "\x53\x14\x73\x66\x8d\x88\xf6\x80",
+               .klen   = 24,
+               .iv     = "\x03\xa0\x20\x35\x26\xf2\x21\x8d"
+                         "\x50\x20\xda\xe2\x00\x00\x00\x00",
+               .assoc  = "\x5b\x9e\x13\x67\x02\x5e\xef\xc1"
+                         "\x6c\xf9\xd7\x1e\x52\x8f\x7a\x47"
+                         "\xe9\xd4\xcf\x20\x14\x6e\xf0\x2d"
+                         "\xd8\x9e\x2b\x56\x10\x23\x56\xe7",
+               .alen   = 32,
+               .result = "\x36\xea\x7a\x70\x08\xdc\x6a\xbc"
+                         "\xad\x0c\x7a\x63\xf6\x61\xfd\x9b",
+               .rlen   = 16,
        }, {
                .key    = "\x56\xdf\x5c\x8f\x26\x3f\x0e\x42"
                          "\xef\x7a\xd3\xce\xfc\x84\x60\x62"
-                         "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01"
-                         "\xd6\x3c\x8c",
-               .klen   = 27,
-               .iv     = "\x86\x84\xb6\xcd\xef\x09\x2e\x94",
+                         "\xca\xb4\x40\xaf\x5f\xc9\xc9\x01",
+               .klen   = 24,
+               .iv     = "\x03\xd6\x3c\x8c\x86\x84\xb6\xcd"
+                         "\xef\x09\x2e\x94\x00\x00\x00\x00",
                .assoc  = "\x02\x65\x78\x3c\xe9\x21\x30\x91"
                          "\xb1\xb9\xda\x76\x9a\x78\x6d\x95"
                          "\xf2\x88\x32\xa3\xf2\x50\xcb\x4c"
@@ -21788,10 +21732,10 @@ static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
                .key    = "\xe0\x8d\x99\x71\x60\xd7\x97\x1a"
                          "\xbd\x01\x99\xd5\x8a\xdf\x71\x3a"
                          "\xd3\xdf\x24\x4b\x5e\x3d\x4b\x4e"
-                         "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b"
-                         "\x1e\x29\x91",
-               .klen   = 35,
-               .iv     = "\xad\x8e\xc1\x53\x0a\xcf\x2d\xbe",
+                         "\x30\x7a\xb9\xd8\x53\x0a\x5e\x2b",
+               .klen   = 32,
+               .iv     = "\x03\x1e\x29\x91\xad\x8e\xc1\x53"
+                         "\x0a\xcf\x2d\xbe\x00\x00\x00\x00",
                .assoc  = "\x19\xb6\x1f\x57\xc4\xf3\xf0\x8b"
                          "\x78\x2b\x94\x02\x29\x0f\x42\x27"
                          "\x6b\x75\xcb\x98\x34\x08\x7e\x79"
@@ -21812,10 +21756,10 @@ static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
                .key    = "\x7c\xc8\x18\x3b\x8d\x99\xe0\x7c"
                          "\x45\x41\xb8\xbd\x5c\xa7\xc2\x32"
                          "\x8a\xb8\x02\x59\xa4\xfe\xa9\x2c"
-                         "\x09\x75\x9a\x9b\x3c\x9b\x27\x39"
-                         "\xf9\xd9\x4e",
-               .klen   = 35,
-               .iv     = "\x63\xb5\x3d\x9d\x43\xf6\x1e\x50",
+                         "\x09\x75\x9a\x9b\x3c\x9b\x27\x39",
+               .klen   = 32,
+               .iv     = "\x03\xf9\xd9\x4e\x63\xb5\x3d\x9d"
+                         "\x43\xf6\x1e\x50",
                .assoc  = "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b"
                          "\x13\x02\x01\x0c\x83\x4c\x96\x35"
                          "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94"
@@ -21837,10 +21781,10 @@ static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
                .key    = "\xab\xd0\xe9\x33\x07\x26\xe5\x83"
                          "\x8c\x76\x95\xd4\xb6\xdc\xf3\x46"
                          "\xf9\x8f\xad\xe3\x02\x13\x83\x77"
-                         "\x3f\xb0\xf1\xa1\xa1\x22\x0f\x2b"
-                         "\x24\xa7\x8b",
-               .klen   = 35,
-               .iv     = "\x07\xcb\xcc\x0e\xe6\x33\xbf\xf5",
+                         "\x3f\xb0\xf1\xa1\xa1\x22\x0f\x2b",
+               .klen   = 32,
+               .iv     = "\x03\x24\xa7\x8b\x07\xcb\xcc\x0e"
+                         "\xe6\x33\xbf\xf5\x00\x00\x00\x00",
                .assoc  = "\xd4\xdb\x30\x1d\x03\xfe\xfd\x5f"
                          "\x87\xd4\x8c\xb6\xb6\xf1\x7a\x5d"
                          "\xab\x90\x65\x8d\x8e\xca\x4d\x4f"
@@ -21858,16 +21802,142 @@ static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
                          "\x5c\xda\xb2\x33\xe5\x13\xe2\x0d"
                          "\x74\xd1\xef\xb5\x0f\x3a\xb5\xf8",
                .rlen   = 48,
-       },
+       }
 };
 
-static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
-       {
+static struct aead_testvec aes_ccm_dec_tv_template[] = {
+       { /* From RFC 3610 */
+               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+               .klen   = 16,
+               .iv     = "\x01\x00\x00\x00\x03\x02\x01\x00"
+                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07",
+               .alen   = 8,
+               .input  = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
+                         "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
+                         "\x6d\x5f\x6b\x61\xda\xc3\x84\x17"
+                         "\xe8\xd1\x2c\xfd\xf9\x26\xe0",
+               .ilen   = 31,
+               .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                         "\x10\x11\x12\x13\x14\x15\x16\x17"
+                         "\x18\x19\x1a\x1b\x1c\x1d\x1e",
+               .rlen   = 23,
+       }, {
+               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+               .klen   = 16,
+               .iv     = "\x01\x00\x00\x00\x07\x06\x05\x04"
+                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b",
+               .alen   = 12,
+               .input  = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
+                         "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
+                         "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07"
+                         "\x7d\x9c\x2d\x93",
+               .ilen   = 28,
+               .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
+                         "\x14\x15\x16\x17\x18\x19\x1a\x1b"
+                         "\x1c\x1d\x1e\x1f",
+               .rlen   = 20,
+       }, {
+               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+               .klen   = 16,
+               .iv     = "\x01\x00\x00\x00\x0b\x0a\x09\x08"
+                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07",
+               .alen   = 8,
+               .input  = "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
+                         "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
+                         "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
+                         "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1"
+                         "\x7e\x5f\x4e",
+               .ilen   = 35,
+               .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                         "\x10\x11\x12\x13\x14\x15\x16\x17"
+                         "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+                         "\x20",
+               .rlen   = 25,
+       }, {
+               .key    = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+                         "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+               .klen   = 16,
+               .iv     = "\x01\x00\x00\x00\x0c\x0b\x0a\x09"
+                         "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
+               .assoc  = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b",
+               .alen   = 12,
+               .input  = "\x07\x34\x25\x94\x15\x77\x85\x15"
+                         "\x2b\x07\x40\x98\x33\x0a\xbb\x14"
+                         "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b"
+                         "\x4d\x99\x99\x88\xdd",
+               .ilen   = 29,
+               .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
+                         "\x14\x15\x16\x17\x18\x19\x1a\x1b"
+                         "\x1c\x1d\x1e",
+               .rlen   = 19,
+       }, {
+               .key    = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
+                         "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+               .klen   = 16,
+               .iv     = "\x01\x00\x33\x56\x8e\xf7\xb2\x63"
+                         "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
+               .assoc  = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb",
+               .alen   = 8,
+               .input  = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa"
+                         "\xa0\x72\x6c\x55\xd3\x78\x06\x12"
+                         "\x98\xc8\x5c\x92\x81\x4a\xbc\x33"
+                         "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a",
+               .ilen   = 32,
+               .result = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a"
+                         "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf"
+                         "\xb7\x9c\x70\x28\x94\x9c\xd0\xec",
+               .rlen   = 24,
+       }, {
+               .key    = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
+                         "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+               .klen   = 16,
+               .iv     = "\x01\x00\xd5\x60\x91\x2d\x3f\x70"
+                         "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
+               .assoc  = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81"
+                         "\x20\xea\x60\xc0",
+               .alen   = 12,
+               .input  = "\x00\x97\x69\xec\xab\xdf\x48\x62"
+                         "\x55\x94\xc5\x92\x51\xe6\x03\x57"
+                         "\x22\x67\x5e\x04\xc8\x47\x09\x9e"
+                         "\x5a\xe0\x70\x45\x51",
+               .ilen   = 29,
+               .result = "\x64\x35\xac\xba\xfb\x11\xa8\x2e"
+                         "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9"
+                         "\x3a\x80\x3b\xa8\x7f",
+               .rlen   = 21,
+       }, {
+               .key    = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
+                         "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+               .klen   = 16,
+               .iv     = "\x01\x00\x42\xff\xf8\xf1\x95\x1c"
+                         "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
+               .assoc  = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8",
+               .alen   = 8,
+               .input  = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6"
+                         "\xdb\x38\x6a\x99\xac\x1a\xef\x23"
+                         "\xad\xe0\xb5\x29\x39\xcb\x6a\x63"
+                         "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
+                         "\xba",
+               .ilen   = 33,
+               .result = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01"
+                         "\x8e\x5e\x67\x01\xc9\x17\x87\x65"
+                         "\x98\x09\xd6\x7d\xbe\xdd\x18",
+               .rlen   = 23,
+       }, {
+               /* This is taken from FIPS CAVS. */
                .key    = "\xab\x2f\x8a\x74\xb7\x1c\xd2\xb1"
-                         "\xff\x80\x2e\x48\x7d\x82\xf8\xb9"
-                         "\xc6\xfb\x7d",
-               .klen   = 19,
-               .iv     = "\x80\x0d\x13\xab\xd8\xa6\xb2\xd8",
+                         "\xff\x80\x2e\x48\x7d\x82\xf8\xb9",
+               .klen   = 16,
+               .iv     = "\x03\xc6\xfb\x7d\x80\x0d\x13\xab"
+                         "\xd8\xa6\xb2\xd8\x00\x00\x00\x00",
                .alen   = 0,
                .input  = "\xd5\xe8\x93\x9f\xc7\x89\x2e\x2b",
                .ilen   = 8,
@@ -21876,10 +21946,10 @@ static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
                .novrfy = 1,
        }, {
                .key    = "\xab\x2f\x8a\x74\xb7\x1c\xd2\xb1"
-                         "\xff\x80\x2e\x48\x7d\x82\xf8\xb9"
-                         "\xaf\x94\x87",
-               .klen   = 19,
-               .iv     = "\x78\x35\x82\x81\x7f\x88\x94\x68",
+                         "\xff\x80\x2e\x48\x7d\x82\xf8\xb9",
+               .klen   = 16,
+               .iv     = "\x03\xaf\x94\x87\x78\x35\x82\x81"
+                         "\x7f\x88\x94\x68\x00\x00\x00\x00",
                .alen   = 0,
                .input  = "\x41\x3c\xb8\x87\x73\xcb\xf3\xf3",
                .ilen   = 8,
@@ -21887,10 +21957,10 @@ static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
                .rlen   = 0,
        }, {
                .key    = "\x61\x0e\x8c\xae\xe3\x23\xb6\x38"
-                         "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8"
-                         "\xc6\xfb\x7d",
-               .klen   = 19,
-               .iv     = "\x80\x0d\x13\xab\xd8\xa6\xb2\xd8",
+                         "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8",
+               .klen   = 16,
+               .iv     = "\x03\xc6\xfb\x7d\x80\x0d\x13\xab"
+                         "\xd8\xa6\xb2\xd8\x00\x00\x00\x00",
                .assoc  = "\xf3\x94\x87\x78\x35\x82\x81\x7f"
                          "\x88\x94\x68\xb1\x78\x6b\x2b\xd6"
                          "\x04\x1f\x4e\xed\x78\xd5\x33\x66"
@@ -21911,10 +21981,10 @@ static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
                .novrfy = 1,
        }, {
                .key    = "\x61\x0e\x8c\xae\xe3\x23\xb6\x38"
-                         "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8"
-                         "\x05\xe0\xc9",
-               .klen   = 19,
-               .iv     = "\x0f\xed\x34\xea\x97\xd4\x3b\xdf",
+                         "\x76\x1c\xf6\x3a\x67\xa3\x9c\xd8",
+               .klen   = 16,
+               .iv     = "\x03\x05\xe0\xc9\x0f\xed\x34\xea"
+                         "\x97\xd4\x3b\xdf\x00\x00\x00\x00",
                .assoc  = "\x49\x5c\x50\x1f\x1d\x94\xcc\x81"
                          "\xba\xb7\xb6\x03\xaf\xa5\xc1\xa1"
                          "\xd8\x5c\x42\x68\xe0\x6c\xda\x89"
@@ -21935,10 +22005,10 @@ static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
        }, {
                .key    = "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
                          "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
-                         "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
-                         "\xee\x49\x83",
-               .klen   = 27,
-               .iv     = "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+                         "\xa4\x48\x93\x39\x26\x71\x4a\xc6",
+               .klen   = 24,
+               .iv     = "\x03\xee\x49\x83\xe9\xa9\xff\xe9"
+                         "\x57\xba\xfd\x9e\x00\x00\x00\x00",
                .assoc  = "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
                          "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
                          "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
@@ -21949,114 +22019,1348 @@ static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[] = {
                .result = "\x00",
                .rlen   = 0,
        }, {
-               .key    = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
-                         "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
-                         "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
-                         "\xee\x49\x83",
+               .key    = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+                         "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+                         "\x29\xa0\xba\x9e\x48\x78\xd1\xba",
+               .klen   = 24,
+               .iv     = "\x03\xee\x49\x83\xe9\xa9\xff\xe9"
+                         "\x57\xba\xfd\x9e\x00\x00\x00\x00",
+               .assoc  = "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
+                         "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+                         "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
+                         "\x11\xc4\xc6\xdb\x00\x56\x36\x61",
+               .alen   = 32,
+               .input  = "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7"
+                         "\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
+                         "\x66\xca\x61\x1e\x96\x7a\x61\xb3"
+                         "\x1c\x16\x45\x52\xba\x04\x9c\x9f"
+                         "\xb1\xd2\x40\xbc\x52\x7c\x6f\xb1",
+               .ilen   = 40,
+               .result = "\x85\x34\x66\x42\xc8\x92\x0f\x36"
+                         "\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
+                         "\x0a\x85\xcc\x02\xad\x7a\x96\xe9"
+                         "\x65\x43\xa4\xc3\x0f\xdc\x55\x81",
+               .rlen   = 32,
+       }, {
+               .key    = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+                         "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+                         "\x29\xa0\xba\x9e\x48\x78\xd1\xba",
+               .klen   = 24,
+               .iv     = "\x03\xd1\xfc\x57\x9c\xfe\xb8\x9c"
+                         "\xad\x71\xaa\x1f\x00\x00\x00\x00",
+               .assoc  = "\x86\x67\xa5\xa9\x14\x5f\x0d\xc6"
+                         "\xff\x14\xc7\x44\xbf\x6c\x3a\xc3"
+                         "\xff\xb6\x81\xbd\xe2\xd5\x06\xc7"
+                         "\x3c\xa1\x52\x13\x03\x8a\x23\x3a",
+               .alen   = 32,
+               .input  = "\x3f\x66\xb0\x9d\xe5\x4b\x38\x00"
+                         "\xc6\x0e\x6e\xe5\xd6\x98\xa6\x37"
+                         "\x8c\x26\x33\xc6\xb2\xa2\x17\xfa"
+                         "\x64\x19\xc0\x30\xd7\xfc\x14\x6b"
+                         "\xe3\x33\xc2\x04\xb0\x37\xbe\x3f"
+                         "\xa9\xb4\x2d\x68\x03\xa3\x44\xef",
+               .ilen   = 48,
+               .result = "\x02\x87\x4d\x28\x80\x6e\xb2\xed"
+                         "\x99\x2a\xa8\xca\x04\x25\x45\x90"
+                         "\x1d\xdd\x5a\xd9\xe4\xdb\x9c\x9c"
+                         "\x49\xe9\x01\xfe\xa7\x80\x6d\x6b",
+               .rlen   = 32,
+               .novrfy = 1,
+       }, {
+               .key    = "\xa4\x4b\x54\x29\x0a\xb8\x6d\x01"
+                         "\x5b\x80\x2a\xcf\x25\xc4\xb7\x5c"
+                         "\x20\x2c\xad\x30\xc2\x2b\x41\xfb"
+                         "\x0e\x85\xbc\x33\xad\x0f\x2b\xff",
+               .klen   = 32,
+               .iv     = "\x03\xee\x49\x83\xe9\xa9\xff\xe9"
+                         "\x57\xba\xfd\x9e\x00\x00\x00\x00",
+               .alen   = 0,
+               .input  = "\x1f\xb8\x8f\xa3\xdd\x54\x00\xf2",
+               .ilen   = 8,
+               .result = "\x00",
+               .rlen   = 0,
+       }, {
+               .key    = "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
+                         "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
+                         "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
+                         "\xae\x8f\x11\x4c\xc2\x9c\x4a\xbb",
+               .klen   = 32,
+               .iv     = "\x03\x85\x34\x66\x42\xc8\x92\x0f"
+                         "\x36\x58\xe0\x6b\x00\x00\x00\x00",
+               .alen   = 0,
+               .input  = "\x48\x01\x5e\x02\x24\x04\x66\x47"
+                         "\xa1\xea\x6f\xaf\xe8\xfc\xfb\xdd"
+                         "\xa5\xa9\x87\x8d\x84\xee\x2e\x77"
+                         "\xbb\x86\xb9\xf5\x5c\x6c\xff\xf6"
+                         "\x72\xc3\x8e\xf7\x70\xb1\xb2\x07"
+                         "\xbc\xa8\xa3\xbd\x83\x7c\x1d\x2a",
+               .ilen   = 48,
+               .result = "\xdc\x56\xf2\x71\xb0\xb1\xa0\x6c"
+                         "\xf0\x97\x3a\xfb\x6d\xe7\x32\x99"
+                         "\x3e\xaf\x70\x5e\xb2\x4d\xea\x39"
+                         "\x89\xd4\x75\x7a\x63\xb1\xda\x93",
+               .rlen   = 32,
+               .novrfy = 1,
+       }, {
+               .key    = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
+                         "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+                         "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
+                         "\x0d\x1a\x53\x3b\xb5\xe3\xf8\x8b",
+               .klen   = 32,
+               .iv     = "\x03\xcf\x76\x3f\xd9\x95\x75\x8f"
+                         "\x44\x89\x40\x7b\x00\x00\x00\x00",
+               .assoc  = "\x8f\x86\x6c\x4d\x1d\xc5\x39\x88"
+                         "\xc8\xf3\x5c\x52\x10\x63\x6f\x2b"
+                         "\x8a\x2a\xc5\x6f\x30\x23\x58\x7b"
+                         "\xfb\x36\x03\x11\xb4\xd9\xf2\xfe",
+               .alen   = 32,
+               .input  = "\x48\x58\xd6\xf3\xad\x63\x58\xbf"
+                         "\xae\xc7\x5e\xae\x83\x8f\x7b\xe4"
+                         "\x78\x5c\x4c\x67\x71\x89\x94\xbf"
+                         "\x47\xf1\x63\x7e\x1c\x59\xbd\xc5"
+                         "\x7f\x44\x0a\x0c\x01\x18\x07\x92"
+                         "\xe1\xd3\x51\xce\x32\x6d\x0c\x5b",
+               .ilen   = 48,
+               .result = "\xc2\x54\xc8\xde\x78\x87\x77\x40"
+                         "\x49\x71\xe4\xb7\xe7\xcb\x76\x61"
+                         "\x0a\x41\xb9\xe9\xc0\x76\x54\xab"
+                         "\x04\x49\x3b\x19\x93\x57\x25\x5d",
+               .rlen   = 32,
+       },
+};
+
+/*
+ * rfc4309 refers to section 8 of rfc3610 for test vectors, but they all
+ * use a 13-byte nonce, we only support an 11-byte nonce.  Worse,
+ * they use AD lengths which are not valid ESP header lengths.
+ *
+ * These vectors are copied/generated from the ones for rfc4106 with
+ * the key truncated by one byte..
+ */
+static struct aead_testvec aes_ccm_rfc4309_enc_tv_template[] = {
+       { /* Generated using Crypto++ */
+               .key    = zeroed_string,
+               .klen   = 19,
+               .iv     = zeroed_string,
+               .input  = zeroed_string,
+               .ilen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
+               .result = "\x2E\x9A\xCA\x6B\xDA\x54\xFC\x6F"
+                         "\x12\x50\xE8\xDE\x81\x3C\x63\x08"
+                         "\x1A\x22\xBA\x75\xEE\xD4\xD5\xB5"
+                         "\x27\x50\x01\xAC\x03\x33\x39\xFB",
+               .rlen   = 32,
+       },{
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = zeroed_string,
+               .ilen   = 16,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .result = "\xCF\xB9\x99\x17\xC8\x86\x0E\x7F"
+                         "\x7E\x76\xF8\xE6\xF8\xCC\x1F\x17"
+                         "\x6A\xE0\x53\x9F\x4B\x73\x7E\xDA"
+                         "\x08\x09\x4E\xC4\x1E\xAD\xC6\xB0",
+               .rlen   = 32,
+
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = zeroed_string,
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
+               .result = "\x33\xDE\x73\xBC\xA6\xCE\x4E\xA6"
+                         "\x61\xF4\xF5\x41\x03\x4A\xE3\x86"
+                         "\xA1\xE2\xC2\x42\x2B\x81\x70\x40"
+                         "\xFD\x7F\x76\xD1\x03\x07\xBB\x0C",
+               .rlen   = 32,
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = zeroed_string,
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
+               .result = "\x33\xDE\x73\xBC\xA6\xCE\x4E\xA6"
+                         "\x61\xF4\xF5\x41\x03\x4A\xE3\x86"
+                         "\x5B\xC0\x73\xE0\x2B\x73\x68\xC9"
+                         "\x2D\x8C\x58\xC2\x90\x3D\xB0\x3E",
+               .rlen   = 32,
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .result = "\xCE\xB8\x98\x16\xC9\x87\x0F\x7E"
+                         "\x7F\x77\xF9\xE7\xF9\xCD\x1E\x16"
+                         "\x43\x8E\x76\x57\x3B\xB4\x05\xE8"
+                         "\xA9\x9B\xBF\x25\xE0\x4F\xC0\xED",
+               .rlen   = 32,
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .ilen   = 64,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .result = "\xCE\xB8\x98\x16\xC9\x87\x0F\x7E"
+                         "\x7F\x77\xF9\xE7\xF9\xCD\x1E\x16"
+                         "\x9C\xA4\x97\x83\x3F\x01\xA5\xF4"
+                         "\x43\x09\xE7\xB8\xE9\xD1\xD7\x02"
+                         "\x9B\xAB\x39\x18\xEB\x94\x34\x36"
+                         "\xE6\xC5\xC8\x9B\x00\x81\x9E\x49"
+                         "\x1D\x78\xE1\x48\xE3\xE9\xEA\x8E"
+                         "\x3A\x2B\x67\x5D\x35\x6A\x0F\xDB"
+                         "\x02\x73\xDD\xE7\x30\x4A\x30\x54"
+                         "\x1A\x9D\x09\xCA\xC8\x1C\x32\x5F",
+               .rlen   = 80,
+       }, {
+               .key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef",
+               .input  = "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff",
+               .ilen   = 192,
+               .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                         "\xaa\xaa\xaa\xaa\x00\x00\x45\x67"
+                         "\x89\xab\xcd\xef",
+               .alen   = 20,
+               .result = "\x64\x17\xDC\x24\x9D\x92\xBA\x5E"
+                         "\x7C\x64\x6D\x33\x46\x77\xAC\xB1"
+                         "\x5C\x9E\xE2\xC7\x27\x11\x3E\x95"
+                         "\x7D\xBE\x28\xC8\xC1\xCA\x5E\x8C"
+                         "\xB4\xE2\xDE\x9F\x53\x59\x26\xDB"
+                         "\x0C\xD4\xE4\x07\x9A\xE6\x3E\x01"
+                         "\x58\x0D\x3E\x3D\xD5\x21\xEB\x04"
+                         "\x06\x9D\x5F\xB9\x02\x49\x1A\x2B"
+                         "\xBA\xF0\x4E\x3B\x85\x50\x5B\x09"
+                         "\xFE\xEC\xFC\x54\xEC\x0C\xE2\x79"
+                         "\x8A\x2F\x5F\xD7\x05\x5D\xF1\x6D"
+                         "\x22\xEB\xD1\x09\x80\x3F\x5A\x70"
+                         "\xB2\xB9\xD3\x63\x99\xC2\x4D\x1B"
+                         "\x36\x12\x00\x89\xAA\x5D\x55\xDA"
+                         "\x1D\x5B\xD8\x3C\x5F\x09\xD2\xE6"
+                         "\x39\x41\x5C\xF0\xBE\x26\x4E\x5F"
+                         "\x2B\x50\x44\x52\xC2\x10\x7D\x38"
+                         "\x82\x64\x83\x0C\xAE\x49\xD0\xE5"
+                         "\x4F\xE5\x66\x4C\x58\x7A\xEE\x43"
+                         "\x3B\x51\xFE\xBA\x24\x8A\xFE\xDC"
+                         "\x19\x6D\x60\x66\x61\xF9\x9A\x3F"
+                         "\x75\xFC\x38\x53\x5B\xB5\xCD\x52"
+                         "\x4F\xE5\xE4\xC9\xFE\x10\xCB\x98"
+                         "\xF0\x06\x5B\x07\xAB\xBB\xF4\x0E"
+                         "\x2D\xC2\xDD\x5D\xDD\x22\x9A\xCC"
+                         "\x39\xAB\x63\xA5\x3D\x9C\x51\x8A",
+               .rlen   = 208,
+       }, { /* From draft-mcgrew-gcm-test-01 */
+               .key    = "\x4C\x80\xCD\xEF\xBB\x5D\x10\xDA"
+                         "\x90\x6A\xC7\x3C\x36\x13\xA6\x34"
+                         "\x2E\x44\x3B",
+               .klen   = 19,
+               .iv     = "\x49\x56\xED\x7E\x3B\x24\x4C\xFE",
+               .input  = "\x45\x00\x00\x48\x69\x9A\x00\x00"
+                         "\x80\x11\x4D\xB7\xC0\xA8\x01\x02"
+                         "\xC0\xA8\x01\x01\x0A\x9B\xF1\x56"
+                         "\x38\xD3\x01\x00\x00\x01\x00\x00"
+                         "\x00\x00\x00\x00\x04\x5F\x73\x69"
+                         "\x70\x04\x5F\x75\x64\x70\x03\x73"
+                         "\x69\x70\x09\x63\x79\x62\x65\x72"
+                         "\x63\x69\x74\x79\x02\x64\x6B\x00"
+                         "\x00\x21\x00\x01\x01\x02\x02\x01",
+               .ilen   = 72,
+               .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
+                         "\x00\x00\x00\x00\x49\x56\xED\x7E"
+                         "\x3B\x24\x4C\xFE",
+               .alen   = 20,
+               .result = "\x89\xBA\x3E\xEF\xE6\xD6\xCF\xDB"
+                         "\x83\x60\xF5\xBA\x3A\x56\x79\xE6"
+                         "\x7E\x0C\x53\xCF\x9E\x87\xE0\x4E"
+                         "\x1A\x26\x01\x24\xC7\x2E\x3D\xBF"
+                         "\x29\x2C\x91\xC1\xB8\xA8\xCF\xE0"
+                         "\x39\xF8\x53\x6D\x31\x22\x2B\xBF"
+                         "\x98\x81\xFC\x34\xEE\x85\x36\xCD"
+                         "\x26\xDB\x6C\x7A\x0C\x77\x8A\x35"
+                         "\x18\x85\x54\xB2\xBC\xDD\x3F\x43"
+                         "\x61\x06\x8A\xDF\x86\x3F\xB4\xAC"
+                         "\x97\xDC\xBD\xFD\x92\x10\xC5\xFF",
+               .rlen   = 88,
+       }, {
+               .key    = "\xFE\xFF\xE9\x92\x86\x65\x73\x1C"
+                         "\x6D\x6A\x8F\x94\x67\x30\x83\x08"
+                         "\xCA\xFE\xBA",
+               .klen   = 19,
+               .iv     = "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .input  = "\x45\x00\x00\x3E\x69\x8F\x00\x00"
+                         "\x80\x11\x4D\xCC\xC0\xA8\x01\x02"
+                         "\xC0\xA8\x01\x01\x0A\x98\x00\x35"
+                         "\x00\x2A\x23\x43\xB2\xD0\x01\x00"
+                         "\x00\x01\x00\x00\x00\x00\x00\x00"
+                         "\x03\x73\x69\x70\x09\x63\x79\x62"
+                         "\x65\x72\x63\x69\x74\x79\x02\x64"
+                         "\x6B\x00\x00\x01\x00\x01\x00\x01",
+               .ilen   = 64,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
+               .result = "\x4B\xC2\x70\x60\x64\xD2\xF3\xC8"
+                         "\xE5\x26\x8A\xDE\xB8\x7E\x7D\x16"
+                         "\x56\xC7\xD2\x88\xBA\x8D\x58\xAF"
+                         "\xF5\x71\xB6\x37\x84\xA7\xB1\x99"
+                         "\x51\x5C\x0D\xA0\x27\xDE\xE7\x2D"
+                         "\xEF\x25\x88\x1F\x1D\x77\x11\xFF"
+                         "\xDB\xED\xEE\x56\x16\xC5\x5C\x9B"
+                         "\x00\x62\x1F\x68\x4E\x7C\xA0\x97"
+                         "\x10\x72\x7E\x53\x13\x3B\x68\xE4"
+                         "\x30\x99\x91\x79\x09\xEA\xFF\x6A",
+               .rlen   = 80,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\x11\x22\x33",
+               .klen   = 35,
+               .iv     = "\x01\x02\x03\x04\x05\x06\x07\x08",
+               .input  = "\x45\x00\x00\x30\x69\xA6\x40\x00"
+                         "\x80\x06\x26\x90\xC0\xA8\x01\x02"
+                         "\x93\x89\x15\x5E\x0A\x9E\x00\x8B"
+                         "\x2D\xC5\x7E\xE0\x00\x00\x00\x00"
+                         "\x70\x02\x40\x00\x20\xBF\x00\x00"
+                         "\x02\x04\x05\xB4\x01\x01\x04\x02"
+                         "\x01\x02\x02\x01",
+               .ilen   = 52,
+               .assoc  = "\x4A\x2C\xBF\xE3\x00\x00\x00\x02"
+                         "\x01\x02\x03\x04\x05\x06\x07\x08",
+               .alen   = 16,
+               .result = "\xD6\x31\x0D\x2B\x3D\x6F\xBD\x2F"
+                         "\x58\x41\x7E\xFF\x9A\x9E\x09\xB4"
+                         "\x1A\xF7\xF6\x42\x31\xCD\xBF\xAD"
+                         "\x27\x0E\x2C\xF2\xDB\x10\xDF\x55"
+                         "\x8F\x0D\xD7\xAC\x23\xBD\x42\x10"
+                         "\xD0\xB2\xAF\xD8\x37\xAC\x6B\x0B"
+                         "\x11\xD4\x0B\x12\xEC\xB4\xB1\x92"
+                         "\x23\xA6\x10\xB0\x26\xD6\xD9\x26"
+                         "\x5A\x48\x6A\x3E",
+               .rlen   = 68,
+       }, {
+               .key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .input  = "\x45\x00\x00\x3C\x99\xC5\x00\x00"
+                         "\x80\x01\xCB\x7A\x40\x67\x93\x18"
+                         "\x01\x01\x01\x01\x08\x00\x07\x5C"
+                         "\x02\x00\x44\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x75\x76\x77\x61\x62\x63\x64\x65"
+                         "\x66\x67\x68\x69\x01\x02\x02\x01",
+               .ilen   = 64,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
+               .result = "\x6B\x9A\xCA\x57\x43\x91\xFC\x6F"
+                         "\x92\x51\x23\xA4\xC1\x5B\xF0\x10"
+                         "\xF3\x13\xF4\xF8\xA1\x9A\xB4\xDC"
+                         "\x89\xC8\xF8\x42\x62\x95\xB7\xCB"
+                         "\xB8\xF5\x0F\x1B\x2E\x94\xA2\xA7"
+                         "\xBF\xFB\x8A\x92\x13\x63\xD1\x3C"
+                         "\x08\xF5\xE8\xA6\xAA\xF6\x34\xF9"
+                         "\x42\x05\xAF\xB3\xE7\x9A\xFC\xEE"
+                         "\x36\x25\xC1\x10\x12\x1C\xCA\x82"
+                         "\xEA\xE6\x63\x5A\x57\x28\xA9\x9A",
+               .rlen   = 80,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .input  = "\x45\x00\x00\x3C\x99\xC3\x00\x00"
+                         "\x80\x01\xCB\x7C\x40\x67\x93\x18"
+                         "\x01\x01\x01\x01\x08\x00\x08\x5C"
+                         "\x02\x00\x43\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x75\x76\x77\x61\x62\x63\x64\x65"
+                         "\x66\x67\x68\x69\x01\x02\x02\x01",
+               .ilen   = 64,
+               .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .result = "\x6A\x6B\x45\x2B\x7C\x67\x52\xF6"
+                         "\x10\x60\x40\x62\x6B\x4F\x97\x8E"
+                         "\x0B\xB2\x22\x97\xCB\x21\xE0\x90"
+                         "\xA2\xE7\xD1\x41\x30\xE4\x4B\x1B"
+                         "\x79\x01\x58\x50\x01\x06\xE1\xE0"
+                         "\x2C\x83\x79\xD3\xDE\x46\x97\x1A"
+                         "\x30\xB8\xE5\xDF\xD7\x12\x56\x75"
+                         "\xD0\x95\xB7\xB8\x91\x42\xF7\xFD"
+                         "\x97\x57\xCA\xC1\x20\xD0\x86\xB9"
+                         "\x66\x9D\xB4\x2B\x96\x22\xAC\x67",
+               .rlen   = 80,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .input  = "\x45\x00\x00\x1C\x42\xA2\x00\x00"
+                         "\x80\x01\x44\x1F\x40\x67\x93\xB6"
+                         "\xE0\x00\x00\x02\x0A\x00\xF5\xFF"
+                         "\x01\x02\x02\x01",
+               .ilen   = 28,
+               .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .result = "\x6A\x6B\x45\x0B\xA7\x06\x52\xF6"
+                         "\x10\x60\xCF\x01\x6B\x4F\x97\x20"
+                         "\xEA\xB3\x23\x94\xC9\x21\x1D\x33"
+                         "\xA1\xE5\x90\x40\x05\x37\x45\x70"
+                         "\xB5\xD6\x09\x0A\x23\x73\x33\xF9"
+                         "\x08\xB4\x22\xE4",
+               .rlen   = 44,
+       }, {
+               .key    = "\xFE\xFF\xE9\x92\x86\x65\x73\x1C"
+                         "\x6D\x6A\x8F\x94\x67\x30\x83\x08"
+                         "\xFE\xFF\xE9\x92\x86\x65\x73\x1C"
+                         "\xCA\xFE\xBA",
+               .klen   = 27,
+               .iv     = "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .input  = "\x45\x00\x00\x28\xA4\xAD\x40\x00"
+                         "\x40\x06\x78\x80\x0A\x01\x03\x8F"
+                         "\x0A\x01\x06\x12\x80\x23\x06\xB8"
+                         "\xCB\x71\x26\x02\xDD\x6B\xB0\x3E"
+                         "\x50\x10\x16\xD0\x75\x68\x00\x01",
+               .ilen   = 40,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
+               .result = "\x05\x22\x15\xD1\x52\x56\x85\x04"
+                         "\xA8\x5C\x5D\x6D\x7E\x6E\xF5\xFA"
+                         "\xEA\x16\x37\x50\xF3\xDF\x84\x3B"
+                         "\x2F\x32\x18\x57\x34\x2A\x8C\x23"
+                         "\x67\xDF\x6D\x35\x7B\x54\x0D\xFB"
+                         "\x34\xA5\x9F\x6C\x48\x30\x1E\x22"
+                         "\xFE\xB1\x22\x17\x17\x8A\xB9\x5B",
+               .rlen   = 56,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xDE\xCA\xF8",
+               .klen   = 19,
+               .iv     = "\xCA\xFE\xDE\xBA\xCE\xFA\xCE\x74",
+               .input  = "\x45\x00\x00\x49\x33\xBA\x00\x00"
+                         "\x7F\x11\x91\x06\xC3\xFB\x1D\x10"
+                         "\xC2\xB1\xD3\x26\xC0\x28\x31\xCE"
+                         "\x00\x35\xDD\x7B\x80\x03\x02\xD5"
+                         "\x00\x00\x4E\x20\x00\x1E\x8C\x18"
+                         "\xD7\x5B\x81\xDC\x91\xBA\xA0\x47"
+                         "\x6B\x91\xB9\x24\xB2\x80\x38\x9D"
+                         "\x92\xC9\x63\xBA\xC0\x46\xEC\x95"
+                         "\x9B\x62\x66\xC0\x47\x22\xB1\x49"
+                         "\x23\x01\x01\x01",
+               .ilen   = 76,
+               .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
+               .result = "\x92\xD0\x53\x79\x33\x38\xD5\xF3"
+                         "\x7D\xE4\x7A\x8E\x86\x03\xC9\x90"
+                         "\x96\x35\xAB\x9C\xFB\xE8\xA3\x76"
+                         "\xE9\xE9\xE2\xD1\x2E\x11\x0E\x00"
+                         "\xFA\xCE\xB5\x9E\x02\xA7\x7B\xEA"
+                         "\x71\x9A\x58\xFB\xA5\x8A\xE1\xB7"
+                         "\x9C\x39\x9D\xE3\xB5\x6E\x69\xE6"
+                         "\x63\xC9\xDB\x05\x69\x51\x12\xAD"
+                         "\x3E\x00\x32\x73\x86\xF2\xEE\xF5"
+                         "\x0F\xE8\x81\x7E\x84\xD3\xC0\x0D"
+                         "\x76\xD6\x55\xC6\xB4\xC2\x34\xC7"
+                         "\x12\x25\x0B\xF9",
+               .rlen   = 92,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\x73\x61\x6C",
+               .klen   = 35,
+               .iv     = "\x61\x6E\x64\x01\x69\x76\x65\x63",
+               .input  = "\x45\x08\x00\x28\x73\x2C\x00\x00"
+                         "\x40\x06\xE9\xF9\x0A\x01\x06\x12"
+                         "\x0A\x01\x03\x8F\x06\xB8\x80\x23"
+                         "\xDD\x6B\xAF\xBE\xCB\x71\x26\x02"
+                         "\x50\x10\x1F\x64\x6D\x54\x00\x01",
+               .ilen   = 40,
+               .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
+               .result = "\xCC\x74\xB7\xD3\xB0\x38\x50\x42"
+                         "\x2C\x64\x87\x46\x1E\x34\x10\x05"
+                         "\x29\x6B\xBB\x36\xE9\x69\xAD\x92"
+                         "\x82\xA1\x10\x6A\xEB\x0F\xDC\x7D"
+                         "\x08\xBA\xF3\x91\xCA\xAA\x61\xDA"
+                         "\x62\xF4\x14\x61\x5C\x9D\xB5\xA7"
+                         "\xEE\xD7\xB9\x7E\x87\x99\x9B\x7D",
+               .rlen   = 56,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .input  = "\x45\x00\x00\x49\x33\x3E\x00\x00"
+                         "\x7F\x11\x91\x82\xC3\xFB\x1D\x10"
+                         "\xC2\xB1\xD3\x26\xC0\x28\x31\xCE"
+                         "\x00\x35\xCB\x45\x80\x03\x02\x5B"
+                         "\x00\x00\x01\xE0\x00\x1E\x8C\x18"
+                         "\xD6\x57\x59\xD5\x22\x84\xA0\x35"
+                         "\x2C\x71\x47\x5C\x88\x80\x39\x1C"
+                         "\x76\x4D\x6E\x5E\xE0\x49\x6B\x32"
+                         "\x5A\xE2\x70\xC0\x38\x99\x49\x39"
+                         "\x15\x01\x01\x01",
+               .ilen   = 76,
+               .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .result = "\x6A\x6B\x45\x5E\xD6\x9A\x52\xF6"
+                         "\xEF\x70\x1A\x9C\xE8\xD3\x19\x86"
+                         "\xC8\x02\xF0\xB0\x03\x09\xD9\x02"
+                         "\xA0\xD2\x59\x04\xD1\x85\x2A\x24"
+                         "\x1C\x67\x3E\xD8\x68\x72\x06\x94"
+                         "\x97\xBA\x4F\x76\x8D\xB0\x44\x5B"
+                         "\x69\xBF\xD5\xE2\x3D\xF1\x0B\x0C"
+                         "\xC0\xBF\xB1\x8F\x70\x09\x9E\xCE"
+                         "\xA5\xF2\x55\x58\x84\xFA\xF9\xB5"
+                         "\x23\xF4\x84\x40\x74\x14\x8A\x6B"
+                         "\xDB\xD7\x67\xED\xA4\x93\xF3\x47"
+                         "\xCC\xF7\x46\x6F",
+               .rlen   = 92,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\x73\x61\x6C",
+               .klen   = 35,
+               .iv     = "\x61\x6E\x64\x01\x69\x76\x65\x63",
+               .input  = "\x63\x69\x73\x63\x6F\x01\x72\x75"
+                         "\x6C\x65\x73\x01\x74\x68\x65\x01"
+                         "\x6E\x65\x74\x77\x65\x01\x64\x65"
+                         "\x66\x69\x6E\x65\x01\x74\x68\x65"
+                         "\x74\x65\x63\x68\x6E\x6F\x6C\x6F"
+                         "\x67\x69\x65\x73\x01\x74\x68\x61"
+                         "\x74\x77\x69\x6C\x6C\x01\x64\x65"
+                         "\x66\x69\x6E\x65\x74\x6F\x6D\x6F"
+                         "\x72\x72\x6F\x77\x01\x02\x02\x01",
+               .ilen   = 72,
+               .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
+               .result = "\xEA\x15\xC4\x98\xAC\x15\x22\x37"
+                         "\x00\x07\x1D\xBE\x60\x5D\x73\x16"
+                         "\x4D\x0F\xCC\xCE\x8A\xD0\x49\xD4"
+                         "\x39\xA3\xD1\xB1\x21\x0A\x92\x1A"
+                         "\x2C\xCF\x8F\x9D\xC9\x91\x0D\xB4"
+                         "\x15\xFC\xBC\xA5\xC5\xBF\x54\xE5"
+                         "\x1C\xC7\x32\x41\x07\x7B\x2C\xB6"
+                         "\x5C\x23\x7C\x93\xEA\xEF\x23\x1C"
+                         "\x73\xF4\xE7\x12\x84\x4C\x37\x0A"
+                         "\x4A\x8F\x06\x37\x48\xF9\xF9\x05"
+                         "\x55\x13\x40\xC3\xD5\x55\x3A\x3D",
+               .rlen   = 88,
+       }, {
+               .key    = "\x7D\x77\x3D\x00\xC1\x44\xC5\x25"
+                         "\xAC\x61\x9D\x18\xC8\x4A\x3F\x47"
+                         "\xD9\x66\x42",
+               .klen   = 19,
+               .iv     = "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
+               .input  = "\x01\x02\x02\x01",
+               .ilen   = 4,
+               .assoc  = "\x33\x54\x67\xAE\xFF\xFF\xFF\xFF"
+                         "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
+               .alen   = 16,
+               .result = "\x4C\x72\x63\x30\x2F\xE6\x56\xDD"
+                         "\xD0\xD8\x60\x9D\x8B\xEF\x85\x90"
+                         "\xF7\x61\x24\x62",
+               .rlen   = 20,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xDE\xCA\xF8",
+               .klen   = 19,
+               .iv     = "\xCA\xFE\xDE\xBA\xCE\xFA\xCE\x74",
+               .input  = "\x74\x6F\x01\x62\x65\x01\x6F\x72"
+                         "\x01\x6E\x6F\x74\x01\x74\x6F\x01"
+                         "\x62\x65\x00\x01",
+               .ilen   = 20,
+               .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
+               .result = "\xA3\xBF\x52\x52\x65\x83\xBA\x81"
+                         "\x03\x9B\x84\xFC\x44\x8C\xBB\x81"
+                         "\x36\xE1\x78\xBB\xA5\x49\x3A\xD0"
+                         "\xF0\x6B\x21\xAF\x98\xC0\x34\xDC"
+                         "\x17\x17\x65\xAD",
+               .rlen   = 36,
+       }, {
+               .key    = "\x6C\x65\x67\x61\x6C\x69\x7A\x65"
+                         "\x6D\x61\x72\x69\x6A\x75\x61\x6E"
+                         "\x61\x61\x6E\x64\x64\x6F\x69\x74"
+                         "\x62\x65\x66\x6F\x72\x65\x69\x61"
+                         "\x74\x75\x72",
+               .klen   = 35,
+               .iv     = "\x33\x30\x21\x69\x67\x65\x74\x6D",
+               .input  = "\x45\x00\x00\x30\xDA\x3A\x00\x00"
+                         "\x80\x01\xDF\x3B\xC0\xA8\x00\x05"
+                         "\xC0\xA8\x00\x01\x08\x00\xC6\xCD"
+                         "\x02\x00\x07\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x01\x02\x02\x01",
+               .ilen   = 52,
+               .assoc  = "\x79\x6B\x69\x63\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\x33\x30\x21\x69"
+                         "\x67\x65\x74\x6D",
+               .alen   = 20,
+               .result = "\x96\xFD\x86\xF8\xD1\x98\xFF\x10"
+                         "\xAB\x8C\xDA\x8A\x5A\x08\x38\x1A"
+                         "\x48\x59\x80\x18\x1A\x18\x1A\x04"
+                         "\xC9\x0D\xE3\xE7\x0E\xA4\x0B\x75"
+                         "\x92\x9C\x52\x5C\x0B\xFB\xF8\xAF"
+                         "\x16\xC3\x35\xA8\xE7\xCE\x84\x04"
+                         "\xEB\x40\x6B\x7A\x8E\x75\xBB\x42"
+                         "\xE0\x63\x4B\x21\x44\xA2\x2B\x2B"
+                         "\x39\xDB\xC8\xDC",
+               .rlen   = 68,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .input  = "\x45\x00\x00\x30\xDA\x3A\x00\x00"
+                         "\x80\x01\xDF\x3B\xC0\xA8\x00\x05"
+                         "\xC0\xA8\x00\x01\x08\x00\xC6\xCD"
+                         "\x02\x00\x07\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x01\x02\x02\x01",
+               .ilen   = 52,
+               .assoc  = "\x3F\x7E\xF6\x42\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .result = "\x6A\x6B\x45\x27\x3F\x9E\x52\xF6"
+                         "\x10\x60\x54\x25\xEB\x80\x04\x93"
+                         "\xCA\x1B\x23\x97\xCB\x21\x2E\x01"
+                         "\xA2\xE7\x95\x41\x30\xE4\x4B\x1B"
+                         "\x79\x01\x58\x50\x01\x06\xE1\xE0"
+                         "\x2C\x83\x79\xD3\xDE\x46\x97\x1A"
+                         "\x44\xCC\x90\xBF\x00\x94\x94\x92"
+                         "\x20\x17\x0C\x1B\x55\xDE\x7E\x68"
+                         "\xF4\x95\x5D\x4F",
+               .rlen   = 68,
+       }, {
+               .key    = "\x4C\x80\xCD\xEF\xBB\x5D\x10\xDA"
+                         "\x90\x6A\xC7\x3C\x36\x13\xA6\x34"
+                         "\x22\x43\x3C",
+               .klen   = 19,
+               .iv     = "\x48\x55\xEC\x7D\x3A\x23\x4B\xFD",
+               .input  = "\x08\x00\xC6\xCD\x02\x00\x07\x00"
+                         "\x61\x62\x63\x64\x65\x66\x67\x68"
+                         "\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70"
+                         "\x71\x72\x73\x74\x01\x02\x02\x01",
+               .ilen   = 32,
+               .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
+                         "\x00\x00\x00\x07\x48\x55\xEC\x7D"
+                         "\x3A\x23\x4B\xFD",
+               .alen   = 20,
+               .result = "\x67\xE9\x28\xB3\x1C\xA4\x6D\x02"
+                         "\xF0\xB5\x37\xB6\x6B\x2F\xF5\x4F"
+                         "\xF8\xA3\x4C\x53\xB8\x12\x09\xBF"
+                         "\x58\x7D\xCF\x29\xA3\x41\x68\x6B"
+                         "\xCE\xE8\x79\x85\x3C\xB0\x3A\x8F"
+                         "\x16\xB0\xA1\x26\xC9\xBC\xBC\xA6",
+               .rlen   = 48,
+       }
+};
+
+static struct aead_testvec aes_ccm_rfc4309_dec_tv_template[]   = {
+       { /* Generated using Crypto++ */
+               .key    = zeroed_string,
+               .klen   = 19,
+               .iv     = zeroed_string,
+               .result = zeroed_string,
+               .rlen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
+               .input  = "\x2E\x9A\xCA\x6B\xDA\x54\xFC\x6F"
+                         "\x12\x50\xE8\xDE\x81\x3C\x63\x08"
+                         "\x1A\x22\xBA\x75\xEE\xD4\xD5\xB5"
+                         "\x27\x50\x01\xAC\x03\x33\x39\xFB",
+               .ilen   = 32,
+       },{
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .result = zeroed_string,
+               .rlen   = 16,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .input  = "\xCF\xB9\x99\x17\xC8\x86\x0E\x7F"
+                         "\x7E\x76\xF8\xE6\xF8\xCC\x1F\x17"
+                         "\x6A\xE0\x53\x9F\x4B\x73\x7E\xDA"
+                         "\x08\x09\x4E\xC4\x1E\xAD\xC6\xB0",
+               .ilen   = 32,
+
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = zeroed_string,
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 16,
+               .assoc  = zeroed_string,
+               .alen   = 16,
+               .input  = "\x33\xDE\x73\xBC\xA6\xCE\x4E\xA6"
+                         "\x61\xF4\xF5\x41\x03\x4A\xE3\x86"
+                         "\xA1\xE2\xC2\x42\x2B\x81\x70\x40"
+                         "\xFD\x7F\x76\xD1\x03\x07\xBB\x0C",
+               .ilen   = 32,
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = zeroed_string,
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
+               .input  = "\x33\xDE\x73\xBC\xA6\xCE\x4E\xA6"
+                         "\x61\xF4\xF5\x41\x03\x4A\xE3\x86"
+                         "\x5B\xC0\x73\xE0\x2B\x73\x68\xC9"
+                         "\x2D\x8C\x58\xC2\x90\x3D\xB0\x3E",
+               .ilen   = 32,
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 16,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .input  = "\xCE\xB8\x98\x16\xC9\x87\x0F\x7E"
+                         "\x7F\x77\xF9\xE7\xF9\xCD\x1E\x16"
+                         "\x43\x8E\x76\x57\x3B\xB4\x05\xE8"
+                         "\xA9\x9B\xBF\x25\xE0\x4F\xC0\xED",
+               .ilen   = 32,
+       }, {
+               .key    = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
+                         "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .result = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x01\x01\x01\x01\x01\x01\x01\x01",
+               .rlen   = 64,
+               .assoc  = "\x01\x01\x01\x01\x01\x01\x01\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .alen   = 16,
+               .input  = "\xCE\xB8\x98\x16\xC9\x87\x0F\x7E"
+                         "\x7F\x77\xF9\xE7\xF9\xCD\x1E\x16"
+                         "\x9C\xA4\x97\x83\x3F\x01\xA5\xF4"
+                         "\x43\x09\xE7\xB8\xE9\xD1\xD7\x02"
+                         "\x9B\xAB\x39\x18\xEB\x94\x34\x36"
+                         "\xE6\xC5\xC8\x9B\x00\x81\x9E\x49"
+                         "\x1D\x78\xE1\x48\xE3\xE9\xEA\x8E"
+                         "\x3A\x2B\x67\x5D\x35\x6A\x0F\xDB"
+                         "\x02\x73\xDD\xE7\x30\x4A\x30\x54"
+                         "\x1A\x9D\x09\xCA\xC8\x1C\x32\x5F",
+               .ilen   = 80,
+       }, {
+               .key    = "\x00\x01\x02\x03\x04\x05\x06\x07"
+                         "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x45\x67\x89\xab\xcd\xef",
+               .result = "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff"
+                         "\xff\xff\xff\xff\xff\xff\xff\xff",
+               .rlen   = 192,
+               .assoc  = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                         "\xaa\xaa\xaa\xaa\x00\x00\x45\x67"
+                         "\x89\xab\xcd\xef",
+               .alen   = 20,
+               .input  = "\x64\x17\xDC\x24\x9D\x92\xBA\x5E"
+                         "\x7C\x64\x6D\x33\x46\x77\xAC\xB1"
+                         "\x5C\x9E\xE2\xC7\x27\x11\x3E\x95"
+                         "\x7D\xBE\x28\xC8\xC1\xCA\x5E\x8C"
+                         "\xB4\xE2\xDE\x9F\x53\x59\x26\xDB"
+                         "\x0C\xD4\xE4\x07\x9A\xE6\x3E\x01"
+                         "\x58\x0D\x3E\x3D\xD5\x21\xEB\x04"
+                         "\x06\x9D\x5F\xB9\x02\x49\x1A\x2B"
+                         "\xBA\xF0\x4E\x3B\x85\x50\x5B\x09"
+                         "\xFE\xEC\xFC\x54\xEC\x0C\xE2\x79"
+                         "\x8A\x2F\x5F\xD7\x05\x5D\xF1\x6D"
+                         "\x22\xEB\xD1\x09\x80\x3F\x5A\x70"
+                         "\xB2\xB9\xD3\x63\x99\xC2\x4D\x1B"
+                         "\x36\x12\x00\x89\xAA\x5D\x55\xDA"
+                         "\x1D\x5B\xD8\x3C\x5F\x09\xD2\xE6"
+                         "\x39\x41\x5C\xF0\xBE\x26\x4E\x5F"
+                         "\x2B\x50\x44\x52\xC2\x10\x7D\x38"
+                         "\x82\x64\x83\x0C\xAE\x49\xD0\xE5"
+                         "\x4F\xE5\x66\x4C\x58\x7A\xEE\x43"
+                         "\x3B\x51\xFE\xBA\x24\x8A\xFE\xDC"
+                         "\x19\x6D\x60\x66\x61\xF9\x9A\x3F"
+                         "\x75\xFC\x38\x53\x5B\xB5\xCD\x52"
+                         "\x4F\xE5\xE4\xC9\xFE\x10\xCB\x98"
+                         "\xF0\x06\x5B\x07\xAB\xBB\xF4\x0E"
+                         "\x2D\xC2\xDD\x5D\xDD\x22\x9A\xCC"
+                         "\x39\xAB\x63\xA5\x3D\x9C\x51\x8A",
+               .ilen   = 208,
+       }, { /* From draft-mcgrew-gcm-test-01 */
+               .key    = "\x4C\x80\xCD\xEF\xBB\x5D\x10\xDA"
+                         "\x90\x6A\xC7\x3C\x36\x13\xA6\x34"
+                         "\x2E\x44\x3B",
+               .klen   = 19,
+               .iv     = "\x49\x56\xED\x7E\x3B\x24\x4C\xFE",
+               .result = "\x45\x00\x00\x48\x69\x9A\x00\x00"
+                         "\x80\x11\x4D\xB7\xC0\xA8\x01\x02"
+                         "\xC0\xA8\x01\x01\x0A\x9B\xF1\x56"
+                         "\x38\xD3\x01\x00\x00\x01\x00\x00"
+                         "\x00\x00\x00\x00\x04\x5F\x73\x69"
+                         "\x70\x04\x5F\x75\x64\x70\x03\x73"
+                         "\x69\x70\x09\x63\x79\x62\x65\x72"
+                         "\x63\x69\x74\x79\x02\x64\x6B\x00"
+                         "\x00\x21\x00\x01\x01\x02\x02\x01",
+               .rlen   = 72,
+               .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
+                         "\x00\x00\x00\x00\x49\x56\xED\x7E"
+                         "\x3B\x24\x4C\xFE",
+               .alen   = 20,
+               .input  = "\x89\xBA\x3E\xEF\xE6\xD6\xCF\xDB"
+                         "\x83\x60\xF5\xBA\x3A\x56\x79\xE6"
+                         "\x7E\x0C\x53\xCF\x9E\x87\xE0\x4E"
+                         "\x1A\x26\x01\x24\xC7\x2E\x3D\xBF"
+                         "\x29\x2C\x91\xC1\xB8\xA8\xCF\xE0"
+                         "\x39\xF8\x53\x6D\x31\x22\x2B\xBF"
+                         "\x98\x81\xFC\x34\xEE\x85\x36\xCD"
+                         "\x26\xDB\x6C\x7A\x0C\x77\x8A\x35"
+                         "\x18\x85\x54\xB2\xBC\xDD\x3F\x43"
+                         "\x61\x06\x8A\xDF\x86\x3F\xB4\xAC"
+                         "\x97\xDC\xBD\xFD\x92\x10\xC5\xFF",
+               .ilen   = 88,
+       }, {
+               .key    = "\xFE\xFF\xE9\x92\x86\x65\x73\x1C"
+                         "\x6D\x6A\x8F\x94\x67\x30\x83\x08"
+                         "\xCA\xFE\xBA",
+               .klen   = 19,
+               .iv     = "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .result = "\x45\x00\x00\x3E\x69\x8F\x00\x00"
+                         "\x80\x11\x4D\xCC\xC0\xA8\x01\x02"
+                         "\xC0\xA8\x01\x01\x0A\x98\x00\x35"
+                         "\x00\x2A\x23\x43\xB2\xD0\x01\x00"
+                         "\x00\x01\x00\x00\x00\x00\x00\x00"
+                         "\x03\x73\x69\x70\x09\x63\x79\x62"
+                         "\x65\x72\x63\x69\x74\x79\x02\x64"
+                         "\x6B\x00\x00\x01\x00\x01\x00\x01",
+               .rlen   = 64,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
+               .input  = "\x4B\xC2\x70\x60\x64\xD2\xF3\xC8"
+                         "\xE5\x26\x8A\xDE\xB8\x7E\x7D\x16"
+                         "\x56\xC7\xD2\x88\xBA\x8D\x58\xAF"
+                         "\xF5\x71\xB6\x37\x84\xA7\xB1\x99"
+                         "\x51\x5C\x0D\xA0\x27\xDE\xE7\x2D"
+                         "\xEF\x25\x88\x1F\x1D\x77\x11\xFF"
+                         "\xDB\xED\xEE\x56\x16\xC5\x5C\x9B"
+                         "\x00\x62\x1F\x68\x4E\x7C\xA0\x97"
+                         "\x10\x72\x7E\x53\x13\x3B\x68\xE4"
+                         "\x30\x99\x91\x79\x09\xEA\xFF\x6A",
+               .ilen   = 80,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\x11\x22\x33",
+               .klen   = 35,
+               .iv     = "\x01\x02\x03\x04\x05\x06\x07\x08",
+               .result = "\x45\x00\x00\x30\x69\xA6\x40\x00"
+                         "\x80\x06\x26\x90\xC0\xA8\x01\x02"
+                         "\x93\x89\x15\x5E\x0A\x9E\x00\x8B"
+                         "\x2D\xC5\x7E\xE0\x00\x00\x00\x00"
+                         "\x70\x02\x40\x00\x20\xBF\x00\x00"
+                         "\x02\x04\x05\xB4\x01\x01\x04\x02"
+                         "\x01\x02\x02\x01",
+               .rlen   = 52,
+               .assoc  = "\x4A\x2C\xBF\xE3\x00\x00\x00\x02"
+                         "\x01\x02\x03\x04\x05\x06\x07\x08",
+               .alen   = 16,
+               .input  = "\xD6\x31\x0D\x2B\x3D\x6F\xBD\x2F"
+                         "\x58\x41\x7E\xFF\x9A\x9E\x09\xB4"
+                         "\x1A\xF7\xF6\x42\x31\xCD\xBF\xAD"
+                         "\x27\x0E\x2C\xF2\xDB\x10\xDF\x55"
+                         "\x8F\x0D\xD7\xAC\x23\xBD\x42\x10"
+                         "\xD0\xB2\xAF\xD8\x37\xAC\x6B\x0B"
+                         "\x11\xD4\x0B\x12\xEC\xB4\xB1\x92"
+                         "\x23\xA6\x10\xB0\x26\xD6\xD9\x26"
+                         "\x5A\x48\x6A\x3E",
+               .ilen   = 68,
+       }, {
+               .key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00",
+               .klen   = 19,
+               .iv     = "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .result = "\x45\x00\x00\x3C\x99\xC5\x00\x00"
+                         "\x80\x01\xCB\x7A\x40\x67\x93\x18"
+                         "\x01\x01\x01\x01\x08\x00\x07\x5C"
+                         "\x02\x00\x44\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x75\x76\x77\x61\x62\x63\x64\x65"
+                         "\x66\x67\x68\x69\x01\x02\x02\x01",
+               .rlen   = 64,
+               .assoc  = "\x00\x00\x00\x00\x00\x00\x00\x01"
+                         "\x00\x00\x00\x00\x00\x00\x00\x00",
+               .alen   = 16,
+               .input  = "\x6B\x9A\xCA\x57\x43\x91\xFC\x6F"
+                         "\x92\x51\x23\xA4\xC1\x5B\xF0\x10"
+                         "\xF3\x13\xF4\xF8\xA1\x9A\xB4\xDC"
+                         "\x89\xC8\xF8\x42\x62\x95\xB7\xCB"
+                         "\xB8\xF5\x0F\x1B\x2E\x94\xA2\xA7"
+                         "\xBF\xFB\x8A\x92\x13\x63\xD1\x3C"
+                         "\x08\xF5\xE8\xA6\xAA\xF6\x34\xF9"
+                         "\x42\x05\xAF\xB3\xE7\x9A\xFC\xEE"
+                         "\x36\x25\xC1\x10\x12\x1C\xCA\x82"
+                         "\xEA\xE6\x63\x5A\x57\x28\xA9\x9A",
+               .ilen   = 80,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .result = "\x45\x00\x00\x3C\x99\xC3\x00\x00"
+                         "\x80\x01\xCB\x7C\x40\x67\x93\x18"
+                         "\x01\x01\x01\x01\x08\x00\x08\x5C"
+                         "\x02\x00\x43\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x75\x76\x77\x61\x62\x63\x64\x65"
+                         "\x66\x67\x68\x69\x01\x02\x02\x01",
+               .rlen   = 64,
+               .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .input  = "\x6A\x6B\x45\x2B\x7C\x67\x52\xF6"
+                         "\x10\x60\x40\x62\x6B\x4F\x97\x8E"
+                         "\x0B\xB2\x22\x97\xCB\x21\xE0\x90"
+                         "\xA2\xE7\xD1\x41\x30\xE4\x4B\x1B"
+                         "\x79\x01\x58\x50\x01\x06\xE1\xE0"
+                         "\x2C\x83\x79\xD3\xDE\x46\x97\x1A"
+                         "\x30\xB8\xE5\xDF\xD7\x12\x56\x75"
+                         "\xD0\x95\xB7\xB8\x91\x42\xF7\xFD"
+                         "\x97\x57\xCA\xC1\x20\xD0\x86\xB9"
+                         "\x66\x9D\xB4\x2B\x96\x22\xAC\x67",
+               .ilen   = 80,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .result = "\x45\x00\x00\x1C\x42\xA2\x00\x00"
+                         "\x80\x01\x44\x1F\x40\x67\x93\xB6"
+                         "\xE0\x00\x00\x02\x0A\x00\xF5\xFF"
+                         "\x01\x02\x02\x01",
+               .rlen   = 28,
+               .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .input  = "\x6A\x6B\x45\x0B\xA7\x06\x52\xF6"
+                         "\x10\x60\xCF\x01\x6B\x4F\x97\x20"
+                         "\xEA\xB3\x23\x94\xC9\x21\x1D\x33"
+                         "\xA1\xE5\x90\x40\x05\x37\x45\x70"
+                         "\xB5\xD6\x09\x0A\x23\x73\x33\xF9"
+                         "\x08\xB4\x22\xE4",
+               .ilen   = 44,
+       }, {
+               .key    = "\xFE\xFF\xE9\x92\x86\x65\x73\x1C"
+                         "\x6D\x6A\x8F\x94\x67\x30\x83\x08"
+                         "\xFE\xFF\xE9\x92\x86\x65\x73\x1C"
+                         "\xCA\xFE\xBA",
                .klen   = 27,
-               .iv     = "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
-               .assoc  = "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1"
-                         "\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
-                         "\xa4\xf0\x13\x05\xd1\x77\x99\x67"
-                         "\x11\xc4\xc6\xdb\x00\x56\x36\x61",
-               .alen   = 32,
-               .input  = "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7"
-                         "\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
-                         "\x66\xca\x61\x1e\x96\x7a\x61\xb3"
-                         "\x1c\x16\x45\x52\xba\x04\x9c\x9f"
-                         "\xb1\xd2\x40\xbc\x52\x7c\x6f\xb1",
-               .ilen   = 40,
-               .result = "\x85\x34\x66\x42\xc8\x92\x0f\x36"
-                         "\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
-                         "\x0a\x85\xcc\x02\xad\x7a\x96\xe9"
-                         "\x65\x43\xa4\xc3\x0f\xdc\x55\x81",
-               .rlen   = 32,
+               .iv     = "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .result = "\x45\x00\x00\x28\xA4\xAD\x40\x00"
+                         "\x40\x06\x78\x80\x0A\x01\x03\x8F"
+                         "\x0A\x01\x06\x12\x80\x23\x06\xB8"
+                         "\xCB\x71\x26\x02\xDD\x6B\xB0\x3E"
+                         "\x50\x10\x16\xD0\x75\x68\x00\x01",
+               .rlen   = 40,
+               .assoc  = "\x00\x00\xA5\xF8\x00\x00\x00\x0A"
+                         "\xFA\xCE\xDB\xAD\xDE\xCA\xF8\x88",
+               .alen   = 16,
+               .input  = "\x05\x22\x15\xD1\x52\x56\x85\x04"
+                         "\xA8\x5C\x5D\x6D\x7E\x6E\xF5\xFA"
+                         "\xEA\x16\x37\x50\xF3\xDF\x84\x3B"
+                         "\x2F\x32\x18\x57\x34\x2A\x8C\x23"
+                         "\x67\xDF\x6D\x35\x7B\x54\x0D\xFB"
+                         "\x34\xA5\x9F\x6C\x48\x30\x1E\x22"
+                         "\xFE\xB1\x22\x17\x17\x8A\xB9\x5B",
+               .ilen   = 56,
        }, {
-               .key    = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
-                         "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
-                         "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
-                         "\xd1\xfc\x57",
-               .klen   = 27,
-               .iv     = "\x9c\xfe\xb8\x9c\xad\x71\xaa\x1f",
-               .assoc  = "\x86\x67\xa5\xa9\x14\x5f\x0d\xc6"
-                         "\xff\x14\xc7\x44\xbf\x6c\x3a\xc3"
-                         "\xff\xb6\x81\xbd\xe2\xd5\x06\xc7"
-                         "\x3c\xa1\x52\x13\x03\x8a\x23\x3a",
-               .alen   = 32,
-               .input  = "\x3f\x66\xb0\x9d\xe5\x4b\x38\x00"
-                         "\xc6\x0e\x6e\xe5\xd6\x98\xa6\x37"
-                         "\x8c\x26\x33\xc6\xb2\xa2\x17\xfa"
-                         "\x64\x19\xc0\x30\xd7\xfc\x14\x6b"
-                         "\xe3\x33\xc2\x04\xb0\x37\xbe\x3f"
-                         "\xa9\xb4\x2d\x68\x03\xa3\x44\xef",
-               .ilen   = 48,
-               .result = "\x02\x87\x4d\x28\x80\x6e\xb2\xed"
-                         "\x99\x2a\xa8\xca\x04\x25\x45\x90"
-                         "\x1d\xdd\x5a\xd9\xe4\xdb\x9c\x9c"
-                         "\x49\xe9\x01\xfe\xa7\x80\x6d\x6b",
-               .rlen   = 32,
-               .novrfy = 1,
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xDE\xCA\xF8",
+               .klen   = 19,
+               .iv     = "\xCA\xFE\xDE\xBA\xCE\xFA\xCE\x74",
+               .result = "\x45\x00\x00\x49\x33\xBA\x00\x00"
+                         "\x7F\x11\x91\x06\xC3\xFB\x1D\x10"
+                         "\xC2\xB1\xD3\x26\xC0\x28\x31\xCE"
+                         "\x00\x35\xDD\x7B\x80\x03\x02\xD5"
+                         "\x00\x00\x4E\x20\x00\x1E\x8C\x18"
+                         "\xD7\x5B\x81\xDC\x91\xBA\xA0\x47"
+                         "\x6B\x91\xB9\x24\xB2\x80\x38\x9D"
+                         "\x92\xC9\x63\xBA\xC0\x46\xEC\x95"
+                         "\x9B\x62\x66\xC0\x47\x22\xB1\x49"
+                         "\x23\x01\x01\x01",
+               .rlen   = 76,
+               .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
+               .input  = "\x92\xD0\x53\x79\x33\x38\xD5\xF3"
+                         "\x7D\xE4\x7A\x8E\x86\x03\xC9\x90"
+                         "\x96\x35\xAB\x9C\xFB\xE8\xA3\x76"
+                         "\xE9\xE9\xE2\xD1\x2E\x11\x0E\x00"
+                         "\xFA\xCE\xB5\x9E\x02\xA7\x7B\xEA"
+                         "\x71\x9A\x58\xFB\xA5\x8A\xE1\xB7"
+                         "\x9C\x39\x9D\xE3\xB5\x6E\x69\xE6"
+                         "\x63\xC9\xDB\x05\x69\x51\x12\xAD"
+                         "\x3E\x00\x32\x73\x86\xF2\xEE\xF5"
+                         "\x0F\xE8\x81\x7E\x84\xD3\xC0\x0D"
+                         "\x76\xD6\x55\xC6\xB4\xC2\x34\xC7"
+                         "\x12\x25\x0B\xF9",
+               .ilen   = 92,
        }, {
-               .key    = "\xa4\x4b\x54\x29\x0a\xb8\x6d\x01"
-                         "\x5b\x80\x2a\xcf\x25\xc4\xb7\x5c"
-                         "\x20\x2c\xad\x30\xc2\x2b\x41\xfb"
-                         "\x0e\x85\xbc\x33\xad\x0f\x2b\xff"
-                         "\xee\x49\x83",
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\x73\x61\x6C",
                .klen   = 35,
-               .iv     = "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
-               .alen   = 0,
-               .input  = "\x1f\xb8\x8f\xa3\xdd\x54\x00\xf2",
-               .ilen   = 8,
-               .result = "\x00",
-               .rlen   = 0,
+               .iv     = "\x61\x6E\x64\x01\x69\x76\x65\x63",
+               .result = "\x45\x08\x00\x28\x73\x2C\x00\x00"
+                         "\x40\x06\xE9\xF9\x0A\x01\x06\x12"
+                         "\x0A\x01\x03\x8F\x06\xB8\x80\x23"
+                         "\xDD\x6B\xAF\xBE\xCB\x71\x26\x02"
+                         "\x50\x10\x1F\x64\x6D\x54\x00\x01",
+               .rlen   = 40,
+               .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
+               .input  = "\xCC\x74\xB7\xD3\xB0\x38\x50\x42"
+                         "\x2C\x64\x87\x46\x1E\x34\x10\x05"
+                         "\x29\x6B\xBB\x36\xE9\x69\xAD\x92"
+                         "\x82\xA1\x10\x6A\xEB\x0F\xDC\x7D"
+                         "\x08\xBA\xF3\x91\xCA\xAA\x61\xDA"
+                         "\x62\xF4\x14\x61\x5C\x9D\xB5\xA7"
+                         "\xEE\xD7\xB9\x7E\x87\x99\x9B\x7D",
+               .ilen   = 56,
        }, {
-               .key    = "\x39\xbb\xa7\xbe\x59\x97\x9e\x73"
-                         "\xa2\xbc\x6b\x98\xd7\x75\x7f\xe3"
-                         "\xa4\x48\x93\x39\x26\x71\x4a\xc6"
-                         "\xae\x8f\x11\x4c\xc2\x9c\x4a\xbb"
-                         "\x85\x34\x66",
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .result = "\x45\x00\x00\x49\x33\x3E\x00\x00"
+                         "\x7F\x11\x91\x82\xC3\xFB\x1D\x10"
+                         "\xC2\xB1\xD3\x26\xC0\x28\x31\xCE"
+                         "\x00\x35\xCB\x45\x80\x03\x02\x5B"
+                         "\x00\x00\x01\xE0\x00\x1E\x8C\x18"
+                         "\xD6\x57\x59\xD5\x22\x84\xA0\x35"
+                         "\x2C\x71\x47\x5C\x88\x80\x39\x1C"
+                         "\x76\x4D\x6E\x5E\xE0\x49\x6B\x32"
+                         "\x5A\xE2\x70\xC0\x38\x99\x49\x39"
+                         "\x15\x01\x01\x01",
+               .rlen   = 76,
+               .assoc  = "\x42\xF6\x7E\x3F\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .input  = "\x6A\x6B\x45\x5E\xD6\x9A\x52\xF6"
+                         "\xEF\x70\x1A\x9C\xE8\xD3\x19\x86"
+                         "\xC8\x02\xF0\xB0\x03\x09\xD9\x02"
+                         "\xA0\xD2\x59\x04\xD1\x85\x2A\x24"
+                         "\x1C\x67\x3E\xD8\x68\x72\x06\x94"
+                         "\x97\xBA\x4F\x76\x8D\xB0\x44\x5B"
+                         "\x69\xBF\xD5\xE2\x3D\xF1\x0B\x0C"
+                         "\xC0\xBF\xB1\x8F\x70\x09\x9E\xCE"
+                         "\xA5\xF2\x55\x58\x84\xFA\xF9\xB5"
+                         "\x23\xF4\x84\x40\x74\x14\x8A\x6B"
+                         "\xDB\xD7\x67\xED\xA4\x93\xF3\x47"
+                         "\xCC\xF7\x46\x6F",
+               .ilen   = 92,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\x73\x61\x6C",
                .klen   = 35,
-               .iv     = "\x42\xc8\x92\x0f\x36\x58\xe0\x6b",
-               .alen   = 0,
-               .input  = "\x48\x01\x5e\x02\x24\x04\x66\x47"
-                         "\xa1\xea\x6f\xaf\xe8\xfc\xfb\xdd"
-                         "\xa5\xa9\x87\x8d\x84\xee\x2e\x77"
-                         "\xbb\x86\xb9\xf5\x5c\x6c\xff\xf6"
-                         "\x72\xc3\x8e\xf7\x70\xb1\xb2\x07"
-                         "\xbc\xa8\xa3\xbd\x83\x7c\x1d\x2a",
-               .ilen   = 48,
-               .result = "\xdc\x56\xf2\x71\xb0\xb1\xa0\x6c"
-                         "\xf0\x97\x3a\xfb\x6d\xe7\x32\x99"
-                         "\x3e\xaf\x70\x5e\xb2\x4d\xea\x39"
-                         "\x89\xd4\x75\x7a\x63\xb1\xda\x93",
-               .rlen   = 32,
-               .novrfy = 1,
+               .iv     = "\x61\x6E\x64\x01\x69\x76\x65\x63",
+               .result = "\x63\x69\x73\x63\x6F\x01\x72\x75"
+                         "\x6C\x65\x73\x01\x74\x68\x65\x01"
+                         "\x6E\x65\x74\x77\x65\x01\x64\x65"
+                         "\x66\x69\x6E\x65\x01\x74\x68\x65"
+                         "\x74\x65\x63\x68\x6E\x6F\x6C\x6F"
+                         "\x67\x69\x65\x73\x01\x74\x68\x61"
+                         "\x74\x77\x69\x6C\x6C\x01\x64\x65"
+                         "\x66\x69\x6E\x65\x74\x6F\x6D\x6F"
+                         "\x72\x72\x6F\x77\x01\x02\x02\x01",
+               .rlen   = 72,
+               .assoc  = "\x17\x40\x5E\x67\x15\x6F\x31\x26"
+                         "\xDD\x0D\xB9\x9B\x61\x6E\x64\x01"
+                         "\x69\x76\x65\x63",
+               .alen   = 20,
+               .input  = "\xEA\x15\xC4\x98\xAC\x15\x22\x37"
+                         "\x00\x07\x1D\xBE\x60\x5D\x73\x16"
+                         "\x4D\x0F\xCC\xCE\x8A\xD0\x49\xD4"
+                         "\x39\xA3\xD1\xB1\x21\x0A\x92\x1A"
+                         "\x2C\xCF\x8F\x9D\xC9\x91\x0D\xB4"
+                         "\x15\xFC\xBC\xA5\xC5\xBF\x54\xE5"
+                         "\x1C\xC7\x32\x41\x07\x7B\x2C\xB6"
+                         "\x5C\x23\x7C\x93\xEA\xEF\x23\x1C"
+                         "\x73\xF4\xE7\x12\x84\x4C\x37\x0A"
+                         "\x4A\x8F\x06\x37\x48\xF9\xF9\x05"
+                         "\x55\x13\x40\xC3\xD5\x55\x3A\x3D",
+               .ilen   = 88,
        }, {
-               .key    = "\x58\x5d\xa0\x96\x65\x1a\x04\xd7"
-                         "\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
-                         "\x29\xa0\xba\x9e\x48\x78\xd1\xba"
-                         "\x0d\x1a\x53\x3b\xb5\xe3\xf8\x8b"
-                         "\xcf\x76\x3f",
+               .key    = "\x7D\x77\x3D\x00\xC1\x44\xC5\x25"
+                         "\xAC\x61\x9D\x18\xC8\x4A\x3F\x47"
+                         "\xD9\x66\x42",
+               .klen   = 19,
+               .iv     = "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
+               .result = "\x01\x02\x02\x01",
+               .rlen   = 4,
+               .assoc  = "\x33\x54\x67\xAE\xFF\xFF\xFF\xFF"
+                         "\x43\x45\x7E\x91\x82\x44\x3B\xC6",
+               .alen   = 16,
+               .input  = "\x4C\x72\x63\x30\x2F\xE6\x56\xDD"
+                         "\xD0\xD8\x60\x9D\x8B\xEF\x85\x90"
+                         "\xF7\x61\x24\x62",
+               .ilen   = 20,
+       }, {
+               .key    = "\xAB\xBC\xCD\xDE\xF0\x01\x12\x23"
+                         "\x34\x45\x56\x67\x78\x89\x9A\xAB"
+                         "\xDE\xCA\xF8",
+               .klen   = 19,
+               .iv     = "\xCA\xFE\xDE\xBA\xCE\xFA\xCE\x74",
+               .result = "\x74\x6F\x01\x62\x65\x01\x6F\x72"
+                         "\x01\x6E\x6F\x74\x01\x74\x6F\x01"
+                         "\x62\x65\x00\x01",
+               .rlen   = 20,
+               .assoc  = "\x00\x00\x01\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x01\xCA\xFE\xDE\xBA"
+                         "\xCE\xFA\xCE\x74",
+               .alen   = 20,
+               .input  = "\xA3\xBF\x52\x52\x65\x83\xBA\x81"
+                         "\x03\x9B\x84\xFC\x44\x8C\xBB\x81"
+                         "\x36\xE1\x78\xBB\xA5\x49\x3A\xD0"
+                         "\xF0\x6B\x21\xAF\x98\xC0\x34\xDC"
+                         "\x17\x17\x65\xAD",
+               .ilen   = 36,
+       }, {
+               .key    = "\x6C\x65\x67\x61\x6C\x69\x7A\x65"
+                         "\x6D\x61\x72\x69\x6A\x75\x61\x6E"
+                         "\x61\x61\x6E\x64\x64\x6F\x69\x74"
+                         "\x62\x65\x66\x6F\x72\x65\x69\x61"
+                         "\x74\x75\x72",
                .klen   = 35,
-               .iv     = "\xd9\x95\x75\x8f\x44\x89\x40\x7b",
-               .assoc  = "\x8f\x86\x6c\x4d\x1d\xc5\x39\x88"
-                         "\xc8\xf3\x5c\x52\x10\x63\x6f\x2b"
-                         "\x8a\x2a\xc5\x6f\x30\x23\x58\x7b"
-                         "\xfb\x36\x03\x11\xb4\xd9\xf2\xfe",
-               .alen   = 32,
-               .input  = "\x48\x58\xd6\xf3\xad\x63\x58\xbf"
-                         "\xae\xc7\x5e\xae\x83\x8f\x7b\xe4"
-                         "\x78\x5c\x4c\x67\x71\x89\x94\xbf"
-                         "\x47\xf1\x63\x7e\x1c\x59\xbd\xc5"
-                         "\x7f\x44\x0a\x0c\x01\x18\x07\x92"
-                         "\xe1\xd3\x51\xce\x32\x6d\x0c\x5b",
-               .ilen   = 48,
-               .result = "\xc2\x54\xc8\xde\x78\x87\x77\x40"
-                         "\x49\x71\xe4\xb7\xe7\xcb\x76\x61"
-                         "\x0a\x41\xb9\xe9\xc0\x76\x54\xab"
-                         "\x04\x49\x3b\x19\x93\x57\x25\x5d",
+               .iv     = "\x33\x30\x21\x69\x67\x65\x74\x6D",
+               .result = "\x45\x00\x00\x30\xDA\x3A\x00\x00"
+                         "\x80\x01\xDF\x3B\xC0\xA8\x00\x05"
+                         "\xC0\xA8\x00\x01\x08\x00\xC6\xCD"
+                         "\x02\x00\x07\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x01\x02\x02\x01",
+               .rlen   = 52,
+               .assoc  = "\x79\x6B\x69\x63\xFF\xFF\xFF\xFF"
+                         "\xFF\xFF\xFF\xFF\x33\x30\x21\x69"
+                         "\x67\x65\x74\x6D",
+               .alen   = 20,
+               .input  = "\x96\xFD\x86\xF8\xD1\x98\xFF\x10"
+                         "\xAB\x8C\xDA\x8A\x5A\x08\x38\x1A"
+                         "\x48\x59\x80\x18\x1A\x18\x1A\x04"
+                         "\xC9\x0D\xE3\xE7\x0E\xA4\x0B\x75"
+                         "\x92\x9C\x52\x5C\x0B\xFB\xF8\xAF"
+                         "\x16\xC3\x35\xA8\xE7\xCE\x84\x04"
+                         "\xEB\x40\x6B\x7A\x8E\x75\xBB\x42"
+                         "\xE0\x63\x4B\x21\x44\xA2\x2B\x2B"
+                         "\x39\xDB\xC8\xDC",
+               .ilen   = 68,
+       }, {
+               .key    = "\x3D\xE0\x98\x74\xB3\x88\xE6\x49"
+                         "\x19\x88\xD0\xC3\x60\x7E\xAE\x1F"
+                         "\x57\x69\x0E",
+               .klen   = 19,
+               .iv     = "\x4E\x28\x00\x00\xA2\xFC\xA1\xA3",
+               .result = "\x45\x00\x00\x30\xDA\x3A\x00\x00"
+                         "\x80\x01\xDF\x3B\xC0\xA8\x00\x05"
+                         "\xC0\xA8\x00\x01\x08\x00\xC6\xCD"
+                         "\x02\x00\x07\x00\x61\x62\x63\x64"
+                         "\x65\x66\x67\x68\x69\x6A\x6B\x6C"
+                         "\x6D\x6E\x6F\x70\x71\x72\x73\x74"
+                         "\x01\x02\x02\x01",
+               .rlen   = 52,
+               .assoc  = "\x3F\x7E\xF6\x42\x10\x10\x10\x10"
+                         "\x10\x10\x10\x10\x4E\x28\x00\x00"
+                         "\xA2\xFC\xA1\xA3",
+               .alen   = 20,
+               .input  = "\x6A\x6B\x45\x27\x3F\x9E\x52\xF6"
+                         "\x10\x60\x54\x25\xEB\x80\x04\x93"
+                         "\xCA\x1B\x23\x97\xCB\x21\x2E\x01"
+                         "\xA2\xE7\x95\x41\x30\xE4\x4B\x1B"
+                         "\x79\x01\x58\x50\x01\x06\xE1\xE0"
+                         "\x2C\x83\x79\xD3\xDE\x46\x97\x1A"
+                         "\x44\xCC\x90\xBF\x00\x94\x94\x92"
+                         "\x20\x17\x0C\x1B\x55\xDE\x7E\x68"
+                         "\xF4\x95\x5D\x4F",
+               .ilen   = 68,
+       }, {
+               .key    = "\x4C\x80\xCD\xEF\xBB\x5D\x10\xDA"
+                         "\x90\x6A\xC7\x3C\x36\x13\xA6\x34"
+                         "\x22\x43\x3C",
+               .klen   = 19,
+               .iv     = "\x48\x55\xEC\x7D\x3A\x23\x4B\xFD",
+               .result = "\x08\x00\xC6\xCD\x02\x00\x07\x00"
+                         "\x61\x62\x63\x64\x65\x66\x67\x68"
+                         "\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70"
+                         "\x71\x72\x73\x74\x01\x02\x02\x01",
                .rlen   = 32,
-       },
+               .assoc  = "\x00\x00\x43\x21\x87\x65\x43\x21"
+                         "\x00\x00\x00\x07\x48\x55\xEC\x7D"
+                         "\x3A\x23\x4B\xFD",
+               .alen   = 20,
+               .input  = "\x67\xE9\x28\xB3\x1C\xA4\x6D\x02"
+                         "\xF0\xB5\x37\xB6\x6B\x2F\xF5\x4F"
+                         "\xF8\xA3\x4C\x53\xB8\x12\x09\xBF"
+                         "\x58\x7D\xCF\x29\xA3\x41\x68\x6B"
+                         "\xCE\xE8\x79\x85\x3C\xB0\x3A\x8F"
+                         "\x16\xB0\xA1\x26\xC9\xBC\xBC\xA6",
+               .ilen   = 48,
+       }
 };
 
 /*
@@ -22343,8 +23647,9 @@ static struct aead_testvec rfc7539esp_enc_tv_template[] = {
                .klen   = 36,
                .iv     = "\x01\x02\x03\x04\x05\x06\x07\x08",
                .assoc  = "\xf3\x33\x88\x86\x00\x00\x00\x00"
-                         "\x00\x00\x4e\x91",
-               .alen   = 12,
+                         "\x00\x00\x4e\x91\x01\x02\x03\x04"
+                         "\x05\x06\x07\x08",
+               .alen   = 20,
                .input  = "\x49\x6e\x74\x65\x72\x6e\x65\x74"
                          "\x2d\x44\x72\x61\x66\x74\x73\x20"
                          "\x61\x72\x65\x20\x64\x72\x61\x66"
@@ -22430,8 +23735,9 @@ static struct aead_testvec rfc7539esp_dec_tv_template[] = {
                .klen   = 36,
                .iv     = "\x01\x02\x03\x04\x05\x06\x07\x08",
                .assoc  = "\xf3\x33\x88\x86\x00\x00\x00\x00"
-                         "\x00\x00\x4e\x91",
-               .alen   = 12,
+                         "\x00\x00\x4e\x91\x01\x02\x03\x04"
+                         "\x05\x06\x07\x08",
+               .alen   = 20,
                .input  = "\x64\xa0\x86\x15\x75\x86\x1a\xf4"
                          "\x60\xf0\x62\xc7\x9b\xe6\x43\xbd"
                          "\x5e\x80\x5c\xfd\x34\x5c\xf3\x89"
@@ -30174,7 +31480,7 @@ static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
        },
 };
 
-#define CHACHA20_ENC_TEST_VECTORS 3
+#define CHACHA20_ENC_TEST_VECTORS 4
 static struct cipher_testvec chacha20_enc_tv_template[] = {
        { /* RFC7539 A.2. Test Vector #1 */
                .key    = "\x00\x00\x00\x00\x00\x00\x00\x00"
@@ -30348,6 +31654,338 @@ static struct cipher_testvec chacha20_enc_tv_template[] = {
                          "\x87\xb5\x8d\xfd\x72\x8a\xfa\x36"
                          "\x75\x7a\x79\x7a\xc1\x88\xd1",
                .rlen   = 127,
+       }, { /* Self-made test vector for long data */
+               .key    = "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a"
+                         "\xf3\x33\x88\x86\x04\xf6\xb5\xf0"
+                         "\x47\x39\x17\xc1\x40\x2b\x80\x09"
+                         "\x9d\xca\x5c\xbc\x20\x70\x75\xc0",
+               .klen   = 32,
+               .iv     = "\x1c\x00\x00\x00\x00\x00\x00\x00"
+                         "\x00\x00\x00\x00\x00\x00\x00\x01",
+               .input  = "\x49\xee\xe0\xdc\x24\x90\x40\xcd"
+                         "\xc5\x40\x8f\x47\x05\xbc\xdd\x81"
+                         "\x47\xc6\x8d\xe6\xb1\x8f\xd7\xcb"
+                         "\x09\x0e\x6e\x22\x48\x1f\xbf\xb8"
+                         "\x5c\xf7\x1e\x8a\xc1\x23\xf2\xd4"
+                         "\x19\x4b\x01\x0f\x4e\xa4\x43\xce"
+                         "\x01\xc6\x67\xda\x03\x91\x18\x90"
+                         "\xa5\xa4\x8e\x45\x03\xb3\x2d\xac"
+                         "\x74\x92\xd3\x53\x47\xc8\xdd\x25"
+                         "\x53\x6c\x02\x03\x87\x0d\x11\x0c"
+                         "\x58\xe3\x12\x18\xfd\x2a\x5b\x40"
+                         "\x0c\x30\xf0\xb8\x3f\x43\xce\xae"
+                         "\x65\x3a\x7d\x7c\xf4\x54\xaa\xcc"
+                         "\x33\x97\xc3\x77\xba\xc5\x70\xde"
+                         "\xd7\xd5\x13\xa5\x65\xc4\x5f\x0f"
+                         "\x46\x1a\x0d\x97\xb5\xf3\xbb\x3c"
+                         "\x84\x0f\x2b\xc5\xaa\xea\xf2\x6c"
+                         "\xc9\xb5\x0c\xee\x15\xf3\x7d\xbe"
+                         "\x9f\x7b\x5a\xa6\xae\x4f\x83\xb6"
+                         "\x79\x49\x41\xf4\x58\x18\xcb\x86"
+                         "\x7f\x30\x0e\xf8\x7d\x44\x36\xea"
+                         "\x75\xeb\x88\x84\x40\x3c\xad\x4f"
+                         "\x6f\x31\x6b\xaa\x5d\xe5\xa5\xc5"
+                         "\x21\x66\xe9\xa7\xe3\xb2\x15\x88"
+                         "\x78\xf6\x79\xa1\x59\x47\x12\x4e"
+                         "\x9f\x9f\x64\x1a\xa0\x22\x5b\x08"
+                         "\xbe\x7c\x36\xc2\x2b\x66\x33\x1b"
+                         "\xdd\x60\x71\xf7\x47\x8c\x61\xc3"
+                         "\xda\x8a\x78\x1e\x16\xfa\x1e\x86"
+                         "\x81\xa6\x17\x2a\xa7\xb5\xc2\xe7"
+                         "\xa4\xc7\x42\xf1\xcf\x6a\xca\xb4"
+                         "\x45\xcf\xf3\x93\xf0\xe7\xea\xf6"
+                         "\xf4\xe6\x33\x43\x84\x93\xa5\x67"
+                         "\x9b\x16\x58\x58\x80\x0f\x2b\x5c"
+                         "\x24\x74\x75\x7f\x95\x81\xb7\x30"
+                         "\x7a\x33\xa7\xf7\x94\x87\x32\x27"
+                         "\x10\x5d\x14\x4c\x43\x29\xdd\x26"
+                         "\xbd\x3e\x3c\x0e\xfe\x0e\xa5\x10"
+                         "\xea\x6b\x64\xfd\x73\xc6\xed\xec"
+                         "\xa8\xc9\xbf\xb3\xba\x0b\x4d\x07"
+                         "\x70\xfc\x16\xfd\x79\x1e\xd7\xc5"
+                         "\x49\x4e\x1c\x8b\x8d\x79\x1b\xb1"
+                         "\xec\xca\x60\x09\x4c\x6a\xd5\x09"
+                         "\x49\x46\x00\x88\x22\x8d\xce\xea"
+                         "\xb1\x17\x11\xde\x42\xd2\x23\xc1"
+                         "\x72\x11\xf5\x50\x73\x04\x40\x47"
+                         "\xf9\x5d\xe7\xa7\x26\xb1\x7e\xb0"
+                         "\x3f\x58\xc1\x52\xab\x12\x67\x9d"
+                         "\x3f\x43\x4b\x68\xd4\x9c\x68\x38"
+                         "\x07\x8a\x2d\x3e\xf3\xaf\x6a\x4b"
+                         "\xf9\xe5\x31\x69\x22\xf9\xa6\x69"
+                         "\xc6\x9c\x96\x9a\x12\x35\x95\x1d"
+                         "\x95\xd5\xdd\xbe\xbf\x93\x53\x24"
+                         "\xfd\xeb\xc2\x0a\x64\xb0\x77\x00"
+                         "\x6f\x88\xc4\x37\x18\x69\x7c\xd7"
+                         "\x41\x92\x55\x4c\x03\xa1\x9a\x4b"
+                         "\x15\xe5\xdf\x7f\x37\x33\x72\xc1"
+                         "\x8b\x10\x67\xa3\x01\x57\x94\x25"
+                         "\x7b\x38\x71\x7e\xdd\x1e\xcc\x73"
+                         "\x55\xd2\x8e\xeb\x07\xdd\xf1\xda"
+                         "\x58\xb1\x47\x90\xfe\x42\x21\x72"
+                         "\xa3\x54\x7a\xa0\x40\xec\x9f\xdd"
+                         "\xc6\x84\x6e\xca\xae\xe3\x68\xb4"
+                         "\x9d\xe4\x78\xff\x57\xf2\xf8\x1b"
+                         "\x03\xa1\x31\xd9\xde\x8d\xf5\x22"
+                         "\x9c\xdd\x20\xa4\x1e\x27\xb1\x76"
+                         "\x4f\x44\x55\xe2\x9b\xa1\x9c\xfe"
+                         "\x54\xf7\x27\x1b\xf4\xde\x02\xf5"
+                         "\x1b\x55\x48\x5c\xdc\x21\x4b\x9e"
+                         "\x4b\x6e\xed\x46\x23\xdc\x65\xb2"
+                         "\xcf\x79\x5f\x28\xe0\x9e\x8b\xe7"
+                         "\x4c\x9d\x8a\xff\xc1\xa6\x28\xb8"
+                         "\x65\x69\x8a\x45\x29\xef\x74\x85"
+                         "\xde\x79\xc7\x08\xae\x30\xb0\xf4"
+                         "\xa3\x1d\x51\x41\xab\xce\xcb\xf6"
+                         "\xb5\xd8\x6d\xe0\x85\xe1\x98\xb3"
+                         "\x43\xbb\x86\x83\x0a\xa0\xf5\xb7"
+                         "\x04\x0b\xfa\x71\x1f\xb0\xf6\xd9"
+                         "\x13\x00\x15\xf0\xc7\xeb\x0d\x5a"
+                         "\x9f\xd7\xb9\x6c\x65\x14\x22\x45"
+                         "\x6e\x45\x32\x3e\x7e\x60\x1a\x12"
+                         "\x97\x82\x14\xfb\xaa\x04\x22\xfa"
+                         "\xa0\xe5\x7e\x8c\x78\x02\x48\x5d"
+                         "\x78\x33\x5a\x7c\xad\xdb\x29\xce"
+                         "\xbb\x8b\x61\xa4\xb7\x42\xe2\xac"
+                         "\x8b\x1a\xd9\x2f\x0b\x8b\x62\x21"
+                         "\x83\x35\x7e\xad\x73\xc2\xb5\x6c"
+                         "\x10\x26\x38\x07\xe5\xc7\x36\x80"
+                         "\xe2\x23\x12\x61\xf5\x48\x4b\x2b"
+                         "\xc5\xdf\x15\xd9\x87\x01\xaa\xac"
+                         "\x1e\x7c\xad\x73\x78\x18\x63\xe0"
+                         "\x8b\x9f\x81\xd8\x12\x6a\x28\x10"
+                         "\xbe\x04\x68\x8a\x09\x7c\x1b\x1c"
+                         "\x83\x66\x80\x47\x80\xe8\xfd\x35"
+                         "\x1c\x97\x6f\xae\x49\x10\x66\xcc"
+                         "\xc6\xd8\xcc\x3a\x84\x91\x20\x77"
+                         "\x72\xe4\x24\xd2\x37\x9f\xc5\xc9"
+                         "\x25\x94\x10\x5f\x40\x00\x64\x99"
+                         "\xdc\xae\xd7\x21\x09\x78\x50\x15"
+                         "\xac\x5f\xc6\x2c\xa2\x0b\xa9\x39"
+                         "\x87\x6e\x6d\xab\xde\x08\x51\x16"
+                         "\xc7\x13\xe9\xea\xed\x06\x8e\x2c"
+                         "\xf8\x37\x8c\xf0\xa6\x96\x8d\x43"
+                         "\xb6\x98\x37\xb2\x43\xed\xde\xdf"
+                         "\x89\x1a\xe7\xeb\x9d\xa1\x7b\x0b"
+                         "\x77\xb0\xe2\x75\xc0\xf1\x98\xd9"
+                         "\x80\x55\xc9\x34\x91\xd1\x59\xe8"
+                         "\x4b\x0f\xc1\xa9\x4b\x7a\x84\x06"
+                         "\x20\xa8\x5d\xfa\xd1\xde\x70\x56"
+                         "\x2f\x9e\x91\x9c\x20\xb3\x24\xd8"
+                         "\x84\x3d\xe1\x8c\x7e\x62\x52\xe5"
+                         "\x44\x4b\x9f\xc2\x93\x03\xea\x2b"
+                         "\x59\xc5\xfa\x3f\x91\x2b\xbb\x23"
+                         "\xf5\xb2\x7b\xf5\x38\xaf\xb3\xee"
+                         "\x63\xdc\x7b\xd1\xff\xaa\x8b\xab"
+                         "\x82\x6b\x37\x04\xeb\x74\xbe\x79"
+                         "\xb9\x83\x90\xef\x20\x59\x46\xff"
+                         "\xe9\x97\x3e\x2f\xee\xb6\x64\x18"
+                         "\x38\x4c\x7a\x4a\xf9\x61\xe8\x9a"
+                         "\xa1\xb5\x01\xa6\x47\xd3\x11\xd4"
+                         "\xce\xd3\x91\x49\x88\xc7\xb8\x4d"
+                         "\xb1\xb9\x07\x6d\x16\x72\xae\x46"
+                         "\x5e\x03\xa1\x4b\xb6\x02\x30\xa8"
+                         "\x3d\xa9\x07\x2a\x7c\x19\xe7\x62"
+                         "\x87\xe3\x82\x2f\x6f\xe1\x09\xd9"
+                         "\x94\x97\xea\xdd\x58\x9e\xae\x76"
+                         "\x7e\x35\xe5\xb4\xda\x7e\xf4\xde"
+                         "\xf7\x32\x87\xcd\x93\xbf\x11\x56"
+                         "\x11\xbe\x08\x74\xe1\x69\xad\xe2"
+                         "\xd7\xf8\x86\x75\x8a\x3c\xa4\xbe"
+                         "\x70\xa7\x1b\xfc\x0b\x44\x2a\x76"
+                         "\x35\xea\x5d\x85\x81\xaf\x85\xeb"
+                         "\xa0\x1c\x61\xc2\xf7\x4f\xa5\xdc"
+                         "\x02\x7f\xf6\x95\x40\x6e\x8a\x9a"
+                         "\xf3\x5d\x25\x6e\x14\x3a\x22\xc9"
+                         "\x37\x1c\xeb\x46\x54\x3f\xa5\x91"
+                         "\xc2\xb5\x8c\xfe\x53\x08\x97\x32"
+                         "\x1b\xb2\x30\x27\xfe\x25\x5d\xdc"
+                         "\x08\x87\xd0\xe5\x94\x1a\xd4\xf1"
+                         "\xfe\xd6\xb4\xa3\xe6\x74\x81\x3c"
+                         "\x1b\xb7\x31\xa7\x22\xfd\xd4\xdd"
+                         "\x20\x4e\x7c\x51\xb0\x60\x73\xb8"
+                         "\x9c\xac\x91\x90\x7e\x01\xb0\xe1"
+                         "\x8a\x2f\x75\x1c\x53\x2a\x98\x2a"
+                         "\x06\x52\x95\x52\xb2\xe9\x25\x2e"
+                         "\x4c\xe2\x5a\x00\xb2\x13\x81\x03"
+                         "\x77\x66\x0d\xa5\x99\xda\x4e\x8c"
+                         "\xac\xf3\x13\x53\x27\x45\xaf\x64"
+                         "\x46\xdc\xea\x23\xda\x97\xd1\xab"
+                         "\x7d\x6c\x30\x96\x1f\xbc\x06\x34"
+                         "\x18\x0b\x5e\x21\x35\x11\x8d\x4c"
+                         "\xe0\x2d\xe9\x50\x16\x74\x81\xa8"
+                         "\xb4\x34\xb9\x72\x42\xa6\xcc\xbc"
+                         "\xca\x34\x83\x27\x10\x5b\x68\x45"
+                         "\x8f\x52\x22\x0c\x55\x3d\x29\x7c"
+                         "\xe3\xc0\x66\x05\x42\x91\x5f\x58"
+                         "\xfe\x4a\x62\xd9\x8c\xa9\x04\x19"
+                         "\x04\xa9\x08\x4b\x57\xfc\x67\x53"
+                         "\x08\x7c\xbc\x66\x8a\xb0\xb6\x9f"
+                         "\x92\xd6\x41\x7c\x5b\x2a\x00\x79"
+                         "\x72",
+               .ilen   = 1281,
+               .result = "\x45\xe8\xe0\xb6\x9c\xca\xfd\x87"
+                         "\xe8\x1d\x37\x96\x8a\xe3\x40\x35"
+                         "\xcf\x5e\x3a\x46\x3d\xfb\xd0\x69"
+                         "\xde\xaf\x7a\xd5\x0d\xe9\x52\xec"
+                         "\xc2\x82\xe5\x3e\x7d\xb2\x4a\xd9"
+                         "\xbb\xc3\x9f\xc0\x5d\xac\x93\x8d"
+                         "\x0e\x6f\xd3\xd7\xfb\x6a\x0d\xce"
+                         "\x92\x2c\xf7\xbb\x93\x57\xcc\xee"
+                         "\x42\x72\x6f\xc8\x4b\xd2\x76\xbf"
+                         "\xa0\xe3\x7a\x39\xf9\x5c\x8e\xfd"
+                         "\xa1\x1d\x41\xe5\x08\xc1\x1c\x11"
+                         "\x92\xfd\x39\x5c\x51\xd0\x2f\x66"
+                         "\x33\x4a\x71\x15\xfe\xee\x12\x54"
+                         "\x8c\x8f\x34\xd8\x50\x3c\x18\xa6"
+                         "\xc5\xe1\x46\x8a\xfb\x5f\x7e\x25"
+                         "\x9b\xe2\xc3\x66\x41\x2b\xb3\xa5"
+                         "\x57\x0e\x94\x17\x26\x39\xbb\x54"
+                         "\xae\x2e\x6f\x42\xfb\x4d\x89\x6f"
+                         "\x9d\xf1\x16\x2e\xe3\xe7\xfc\xe3"
+                         "\xb2\x4b\x2b\xa6\x7c\x04\x69\x3a"
+                         "\x70\x5a\xa7\xf1\x31\x64\x19\xca"
+                         "\x45\x79\xd8\x58\x23\x61\xaf\xc2"
+                         "\x52\x05\xc3\x0b\xc1\x64\x7c\x81"
+                         "\xd9\x11\xcf\xff\x02\x3d\x51\x84"
+                         "\x01\xac\xc6\x2e\x34\x2b\x09\x3a"
+                         "\xa8\x5d\x98\x0e\x89\xd9\xef\x8f"
+                         "\xd9\xd7\x7d\xdd\x63\x47\x46\x7d"
+                         "\xa1\xda\x0b\x53\x7d\x79\xcd\xc9"
+                         "\x86\xdd\x6b\x13\xa1\x9a\x70\xdd"
+                         "\x5c\xa1\x69\x3c\xe4\x5d\xe3\x8c"
+                         "\xe5\xf4\x87\x9c\x10\xcf\x0f\x0b"
+                         "\xc8\x43\xdc\xf8\x1d\x62\x5e\x5b"
+                         "\xe2\x03\x06\xc5\x71\xb6\x48\xa5"
+                         "\xf0\x0f\x2d\xd5\xa2\x73\x55\x8f"
+                         "\x01\xa7\x59\x80\x5f\x11\x6c\x40"
+                         "\xff\xb1\xf2\xc6\x7e\x01\xbb\x1c"
+                         "\x69\x9c\xc9\x3f\x71\x5f\x07\x7e"
+                         "\xdf\x6f\x99\xca\x9c\xfd\xf9\xb9"
+                         "\x49\xe7\xcc\x91\xd5\x9b\x8f\x03"
+                         "\xae\xe7\x61\x32\xef\x41\x6c\x75"
+                         "\x84\x9b\x8c\xce\x1d\x6b\x93\x21"
+                         "\x41\xec\xc6\xad\x8e\x0c\x48\xa8"
+                         "\xe2\xf5\x57\xde\xf7\x38\xfd\x4a"
+                         "\x6f\xa7\x4a\xf9\xac\x7d\xb1\x85"
+                         "\x7d\x6c\x95\x0a\x5a\xcf\x68\xd2"
+                         "\xe0\x7a\x26\xd9\xc1\x6d\x3e\xc6"
+                         "\x37\xbd\xbe\x24\x36\x77\x9f\x1b"
+                         "\xc1\x22\xf3\x79\xae\x95\x78\x66"
+                         "\x97\x11\xc0\x1a\xf1\xe8\x0d\x38"
+                         "\x09\xc2\xee\xb7\xd3\x46\x7b\x59"
+                         "\x77\x23\xe8\xb4\x92\x3d\x78\xbe"
+                         "\xe2\x25\x63\xa5\x2a\x06\x70\x92"
+                         "\x32\x63\xf9\x19\x21\x68\xe1\x0b"
+                         "\x9a\xd0\xee\x21\xdb\x1f\xe0\xde"
+                         "\x3e\x64\x02\x4d\x0e\xe0\x0a\xa9"
+                         "\xed\x19\x8c\xa8\xbf\xe3\x2e\x75"
+                         "\x24\x2b\xb0\xe5\x82\x6a\x1e\x6f"
+                         "\x71\x2a\x3a\x60\xed\x06\x0d\x17"
+                         "\xa2\xdb\x29\x1d\xae\xb2\xc4\xfb"
+                         "\x94\x04\xd8\x58\xfc\xc4\x04\x4e"
+                         "\xee\xc7\xc1\x0f\xe9\x9b\x63\x2d"
+                         "\x02\x3e\x02\x67\xe5\xd8\xbb\x79"
+                         "\xdf\xd2\xeb\x50\xe9\x0a\x02\x46"
+                         "\xdf\x68\xcf\xe7\x2b\x0a\x56\xd6"
+                         "\xf7\xbc\x44\xad\xb8\xb5\x5f\xeb"
+                         "\xbc\x74\x6b\xe8\x7e\xb0\x60\xc6"
+                         "\x0d\x96\x09\xbb\x19\xba\xe0\x3c"
+                         "\xc4\x6c\xbf\x0f\x58\xc0\x55\x62"
+                         "\x23\xa0\xff\xb5\x1c\xfd\x18\xe1"
+                         "\xcf\x6d\xd3\x52\xb4\xce\xa6\xfa"
+                         "\xaa\xfb\x1b\x0b\x42\x6d\x79\x42"
+                         "\x48\x70\x5b\x0e\xdd\x3a\xc9\x69"
+                         "\x8b\x73\x67\xf6\x95\xdb\x8c\xfb"
+                         "\xfd\xb5\x08\x47\x42\x84\x9a\xfa"
+                         "\xcc\x67\xb2\x3c\xb6\xfd\xd8\x32"
+                         "\xd6\x04\xb6\x4a\xea\x53\x4b\xf5"
+                         "\x94\x16\xad\xf0\x10\x2e\x2d\xb4"
+                         "\x8b\xab\xe5\x89\xc7\x39\x12\xf3"
+                         "\x8d\xb5\x96\x0b\x87\x5d\xa7\x7c"
+                         "\xb0\xc2\xf6\x2e\x57\x97\x2c\xdc"
+                         "\x54\x1c\x34\x72\xde\x0c\x68\x39"
+                         "\x9d\x32\xa5\x75\x92\x13\x32\xea"
+                         "\x90\x27\xbd\x5b\x1d\xb9\x21\x02"
+                         "\x1c\xcc\xba\x97\x5e\x49\x58\xe8"
+                         "\xac\x8b\xf3\xce\x3c\xf0\x00\xe9"
+                         "\x6c\xae\xe9\x77\xdf\xf4\x02\xcd"
+                         "\x55\x25\x89\x9e\x90\xf3\x6b\x8f"
+                         "\xb7\xd6\x47\x98\x26\x2f\x31\x2f"
+                         "\x8d\xbf\x54\xcd\x99\xeb\x80\xd7"
+                         "\xac\xc3\x08\xc2\xa6\x32\xf1\x24"
+                         "\x76\x7c\x4f\x78\x53\x55\xfb\x00"
+                         "\x8a\xd6\x52\x53\x25\x45\xfb\x0a"
+                         "\x6b\xb9\xbe\x3c\x5e\x11\xcc\x6a"
+                         "\xdd\xfc\xa7\xc4\x79\x4d\xbd\xfb"
+                         "\xce\x3a\xf1\x7a\xda\xeb\xfe\x64"
+                         "\x28\x3d\x0f\xee\x80\xba\x0c\xf8"
+                         "\xe9\x5b\x3a\xd4\xae\xc9\xf3\x0e"
+                         "\xe8\x5d\xc5\x5c\x0b\x20\x20\xee"
+                         "\x40\x0d\xde\x07\xa7\x14\xb4\x90"
+                         "\xb6\xbd\x3b\xae\x7d\x2b\xa7\xc7"
+                         "\xdc\x0b\x4c\x5d\x65\xb0\xd2\xc5"
+                         "\x79\x61\x23\xe0\xa2\x99\x73\x55"
+                         "\xad\xc6\xfb\xc7\x54\xb5\x98\x1f"
+                         "\x8c\x86\xc2\x3f\xbe\x5e\xea\x64"
+                         "\xa3\x60\x18\x9f\x80\xaf\x52\x74"
+                         "\x1a\xfe\x22\xc2\x92\x67\x40\x02"
+                         "\x08\xee\x67\x5b\x67\xe0\x3d\xde"
+                         "\x7a\xaf\x8e\x28\xf3\x5e\x0e\xf4"
+                         "\x48\x56\xaa\x85\x22\xd8\x36\xed"
+                         "\x3b\x3d\x68\x69\x30\xbc\x71\x23"
+                         "\xb1\x6e\x61\x03\x89\x44\x03\xf4"
+                         "\x32\xaa\x4c\x40\x9f\x69\xfb\x70"
+                         "\x91\xcc\x1f\x11\xbd\x76\x67\xe6"
+                         "\x10\x8b\x29\x39\x68\xea\x4e\x6d"
+                         "\xae\xfb\x40\xcf\xe2\xd0\x0d\x8d"
+                         "\x6f\xed\x9b\x8d\x64\x7a\x94\x8e"
+                         "\x32\x38\x78\xeb\x7d\x5f\xf9\x4d"
+                         "\x13\xbe\x21\xea\x16\xe7\x5c\xee"
+                         "\xcd\xf6\x5f\xc6\x45\xb2\x8f\x2b"
+                         "\xb5\x93\x3e\x45\xdb\xfd\xa2\x6a"
+                         "\xec\x83\x92\x99\x87\x47\xe0\x7c"
+                         "\xa2\x7b\xc4\x2a\xcd\xc0\x81\x03"
+                         "\x98\xb0\x87\xb6\x86\x13\x64\x33"
+                         "\x4c\xd7\x99\xbf\xdb\x7b\x6e\xaa"
+                         "\x76\xcc\xa0\x74\x1b\xa3\x6e\x83"
+                         "\xd4\xba\x7a\x84\x9d\x91\x71\xcd"
+                         "\x60\x2d\x56\xfd\x26\x35\xcb\xeb"
+                         "\xac\xe9\xee\xa4\xfc\x18\x5b\x91"
+                         "\xd5\xfe\x84\x45\xe0\xc7\xfd\x11"
+                         "\xe9\x00\xb6\x54\xdf\xe1\x94\xde"
+                         "\x2b\x70\x9f\x94\x7f\x15\x0e\x83"
+                         "\x63\x10\xb3\xf5\xea\xd3\xe8\xd1"
+                         "\xa5\xfc\x17\x19\x68\x9a\xbc\x17"
+                         "\x30\x43\x0a\x1a\x33\x92\xd4\x2a"
+                         "\x2e\x68\x99\xbc\x49\xf0\x68\xe3"
+                         "\xf0\x1f\xcb\xcc\xfa\xbb\x05\x56"
+                         "\x46\x84\x8b\x69\x83\x64\xc5\xe0"
+                         "\xc5\x52\x99\x07\x3c\xa6\x5c\xaf"
+                         "\xa3\xde\xd7\xdb\x43\xe6\xb7\x76"
+                         "\x4e\x4d\xd6\x71\x60\x63\x4a\x0c"
+                         "\x5f\xae\x25\x84\x22\x90\x5f\x26"
+                         "\x61\x4d\x8f\xaf\xc9\x22\xf2\x05"
+                         "\xcf\xc1\xdc\x68\xe5\x57\x8e\x24"
+                         "\x1b\x30\x59\xca\xd7\x0d\xc3\xd3"
+                         "\x52\x9e\x09\x3e\x0e\xaf\xdb\x5f"
+                         "\xc7\x2b\xde\x3a\xfd\xad\x93\x04"
+                         "\x74\x06\x89\x0e\x90\xeb\x85\xff"
+                         "\xe6\x3c\x12\x42\xf4\xfa\x80\x75"
+                         "\x5e\x4e\xd7\x2f\x93\x0b\x34\x41"
+                         "\x02\x85\x68\xd0\x03\x12\xde\x92"
+                         "\x54\x7a\x7e\xfb\x55\xe7\x88\xfb"
+                         "\xa4\xa9\xf2\xd1\xc6\x70\x06\x37"
+                         "\x25\xee\xa7\x6e\xd9\x89\x86\x50"
+                         "\x2e\x07\xdb\xfb\x2a\x86\x45\x0e"
+                         "\x91\xf4\x7c\xbb\x12\x60\xe8\x3f"
+                         "\x71\xbe\x8f\x9d\x26\xef\xd9\x89"
+                         "\xc4\x8f\xd8\xc5\x73\xd8\x84\xaa"
+                         "\x2f\xad\x22\x1e\x7e\xcf\xa2\x08"
+                         "\x23\x45\x89\x42\xa0\x30\xeb\xbf"
+                         "\xa1\xed\xad\xd5\x76\xfa\x24\x8f"
+                         "\x98",
+               .rlen   = 1281,
        },
 };
 
index 6e973b8e3a3beddbde495046088ba150240d3a94..4e2e6aaf0b88a9a054f9c2fe9eccf120236c532a 100644 (file)
@@ -184,4 +184,6 @@ source "drivers/android/Kconfig"
 
 source "drivers/nvdimm/Kconfig"
 
+source "drivers/nvmem/Kconfig"
+
 endmenu
index b64b49f6e01bfd97dcff3e63dd06dd25d295d2df..4c270f5414f0b017819d52d29bbab630a5174992 100644 (file)
@@ -165,3 +165,4 @@ obj-$(CONFIG_RAS)           += ras/
 obj-$(CONFIG_THUNDERBOLT)      += thunderbolt/
 obj-$(CONFIG_CORESIGHT)                += hwtracing/coresight/
 obj-$(CONFIG_ANDROID)          += android/
+obj-$(CONFIG_NVMEM)            += nvmem/
index 3984ea96e5f762de82fe5e4fb140999d9b434f48..a450e7af877c337aec3aff21f0676299b3699f73 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/clkdev.h>
 #include <linux/acpi.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/pm.h>
 
 #include "internal.h"
index 46b58abb08c5e05efb9111f76e788a3601f6046c..502454c24e69708dbc6a3164142e2131b74008d6 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
index ff6d8adc9cda69c4d0d1f9a22ff3481846020cbd..fb765524cc3d5acc754a60427533f1a15fb78b69 100644 (file)
@@ -153,6 +153,7 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
        {"AEI0250"},            /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
        {"AEI1240"},            /* Actiontec ISA PNP 56K X2 Fax Modem */
        {"AKY1021"},            /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+       {"ALI5123"},            /* ALi Fast Infrared Controller */
        {"AZT4001"},            /* AZT3005 PnP SOUND DEVICE */
        {"BDP3336"},            /* Best Data Products Inc. Smart One 336F PnP Modem */
        {"BRI0A49"},            /* Boca Complete Ofc Communicator 14.4 Data-FAX */
index 628a42c41ab126d12997ab02fd805df6af698c98..cf0fd96a76021778f38a24916b415e02731bfaf0 100644 (file)
@@ -702,11 +702,11 @@ static ssize_t flags_show(struct device *dev,
        u16 flags = to_nfit_memdev(dev)->flags;
 
        return sprintf(buf, "%s%s%s%s%s\n",
-                       flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save " : "",
-                       flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore " : "",
-                       flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush " : "",
-                       flags & ACPI_NFIT_MEM_ARMED ? "arm " : "",
-                       flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart " : "");
+               flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save_fail " : "",
+               flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore_fail " : "",
+               flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush_fail " : "",
+               flags & ACPI_NFIT_MEM_ARMED ? "not_armed " : "",
+               flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart_event " : "");
 }
 static DEVICE_ATTR_RO(flags);
 
@@ -849,12 +849,12 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
                if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
                        continue;
 
-               dev_info(acpi_desc->dev, "%s: failed: %s%s%s%s\n",
+               dev_info(acpi_desc->dev, "%s flags:%s%s%s%s\n",
                                nvdimm_name(nvdimm),
-                       mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save " : "",
-                       mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore " : "",
-                       mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush " : "",
-                       mem_flags & ACPI_NFIT_MEM_ARMED ? "arm " : "");
+                 mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
+                 mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
+                 mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? " flush_fail" : "",
+                 mem_flags & ACPI_NFIT_MEM_ARMED ? " not_armed" : "");
 
        }
 
@@ -1024,7 +1024,7 @@ static void wmb_blk(struct nfit_blk *nfit_blk)
                wmb_pmem();
 }
 
-static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
+static u32 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
 {
        struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
        u64 offset = nfit_blk->stat_offset + mmio->size * bw;
@@ -1032,7 +1032,7 @@ static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
        if (mmio->num_lines)
                offset = to_interleave_offset(offset, mmio);
 
-       return readq(mmio->base + offset);
+       return readl(mmio->base + offset);
 }
 
 static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
index 304eccb0ae5cf32042885ceebb4f1feeae98adce..afa16c557c170139abf5069a9b1c54b4550268b6 100644 (file)
@@ -412,7 +412,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                return 0;
        }
 
-       if (dev->irq_managed && dev->irq > 0)
+       if (pci_has_managed_irq(dev))
                return 0;
 
        entry = acpi_pci_irq_lookup(dev, pin);
@@ -457,8 +457,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                kfree(entry);
                return rc;
        }
-       dev->irq = rc;
-       dev->irq_managed = 1;
+       pci_set_managed_irq(dev, rc);
 
        if (link)
                snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -481,17 +480,9 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        u8 pin;
 
        pin = dev->pin;
-       if (!pin || !dev->irq_managed || dev->irq <= 0)
+       if (!pin || !pci_has_managed_irq(dev))
                return;
 
-       /* Keep IOAPIC pin configuration when suspending */
-       if (dev->dev.power.is_prepared)
-               return;
-#ifdef CONFIG_PM
-       if (dev->dev.power.runtime_status == RPM_SUSPENDING)
-               return;
-#endif
-
        entry = acpi_pci_irq_lookup(dev, pin);
        if (!entry)
                return;
@@ -511,6 +502,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
        if (gsi >= 0) {
                acpi_unregister_gsi(gsi);
-               dev->irq_managed = 0;
+               pci_reset_managed_irq(dev);
        }
 }
index 815f75ef24119eab28ce3c0c2047295c6e464c58..2922f1f252d58aafd2d6c233404ae7ca21abb524 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
 #include <acpi/video.h>
 
 ACPI_MODULE_NAME("video");
@@ -41,6 +42,7 @@ void acpi_video_unregister_backlight(void);
 
 static bool backlight_notifier_registered;
 static struct notifier_block backlight_nb;
+static struct work_struct backlight_notify_work;
 
 static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
 static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
@@ -262,6 +264,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
        { },
 };
 
+/* This uses a workqueue to avoid various locking ordering issues */
+static void acpi_video_backlight_notify_work(struct work_struct *work)
+{
+       if (acpi_video_get_backlight_type() != acpi_backlight_video)
+               acpi_video_unregister_backlight();
+}
+
 static int acpi_video_backlight_notify(struct notifier_block *nb,
                                       unsigned long val, void *bd)
 {
@@ -269,9 +278,8 @@ static int acpi_video_backlight_notify(struct notifier_block *nb,
 
        /* A raw bl registering may change video -> native */
        if (backlight->props.type == BACKLIGHT_RAW &&
-           val == BACKLIGHT_REGISTERED &&
-           acpi_video_get_backlight_type() != acpi_backlight_video)
-               acpi_video_unregister_backlight();
+           val == BACKLIGHT_REGISTERED)
+               schedule_work(&backlight_notify_work);
 
        return NOTIFY_OK;
 }
@@ -304,6 +312,8 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void)
                acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                                    ACPI_UINT32_MAX, find_video, NULL,
                                    &video_caps, NULL);
+               INIT_WORK(&backlight_notify_work,
+                         acpi_video_backlight_notify_work);
                backlight_nb.notifier_call = acpi_video_backlight_notify;
                backlight_nb.priority = 0;
                if (backlight_register_notifier(&backlight_nb) == 0)
index 7e62751abfacce2aaca99c7b08834f2464b46498..a46660204e3a24e54eaa9147167c3bca069829a6 100644 (file)
@@ -351,6 +351,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* JMicron 362B and 362C have an AHCI function with IDE class code */
        { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
        { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
+       /* May need to update quirk_jmicron_async_suspend() for additions */
 
        /* ATI */
        { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
@@ -1451,18 +1452,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        else if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
                ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
 
-       /*
-        * The JMicron chip 361/363 contains one SATA controller and one
-        * PATA controller,for powering on these both controllers, we must
-        * follow the sequence one by one, otherwise one of them can not be
-        * powered on successfully, so here we disable the async suspend
-        * method for these chips.
-        */
-       if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
-               (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
-               pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
-               device_disable_async_suspend(&pdev->dev);
-
        /* acquire resources */
        rc = pcim_enable_device(pdev);
        if (rc)
index ce1e3a8859815ca5724e376de6d6ab0d549c9831..14b7305d2ba0b3cc24aa101e76c87e242f01f537 100644 (file)
@@ -92,7 +92,7 @@ static inline u32 brcm_sata_readreg(void __iomem *addr)
         * Other architectures (e.g., ARM) either do not support big endian, or
         * else leave I/O in little endian mode.
         */
-       if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN))
+       if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
                return __raw_readl(addr);
        else
                return readl_relaxed(addr);
@@ -101,7 +101,7 @@ static inline u32 brcm_sata_readreg(void __iomem *addr)
 static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
 {
        /* See brcm_sata_readreg() comments */
-       if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN))
+       if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
                __raw_writel(val, addr);
        else
                writel_relaxed(val, addr);
@@ -209,6 +209,7 @@ static void brcm_sata_init(struct brcm_ahci_priv *priv)
                           priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int brcm_ahci_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
@@ -231,6 +232,7 @@ static int brcm_ahci_resume(struct device *dev)
        brcm_sata_phys_enable(priv);
        return ahci_platform_resume(dev);
 }
+#endif
 
 static struct scsi_host_template ahci_platform_sht = {
        AHCI_SHT(DRV_NAME),
index db5d9f79a247c5ceb2cb590f206927c22f6f2b7c..790e0deb278e5eb30a44bc0807a7fdd862707078 100644 (file)
@@ -694,11 +694,11 @@ static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev)
  *     RETURNS:
  *     Block address read from @tf.
  */
-u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
+u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
 {
        u64 block = 0;
 
-       if (!dev || tf->flags & ATA_TFLAG_LBA) {
+       if (tf->flags & ATA_TFLAG_LBA) {
                if (tf->flags & ATA_TFLAG_LBA48) {
                        block |= (u64)tf->hob_lbah << 40;
                        block |= (u64)tf->hob_lbam << 32;
@@ -2147,24 +2147,6 @@ static int ata_dev_config_ncq(struct ata_device *dev,
        return 0;
 }
 
-static void ata_dev_config_sense_reporting(struct ata_device *dev)
-{
-       unsigned int err_mask;
-
-       if (!ata_id_has_sense_reporting(dev->id))
-               return;
-
-       if (ata_id_sense_reporting_enabled(dev->id))
-               return;
-
-       err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1);
-       if (err_mask) {
-               ata_dev_dbg(dev,
-                           "failed to enable Sense Data Reporting, Emask 0x%x\n",
-                           err_mask);
-       }
-}
-
 /**
  *     ata_dev_configure - Configure the specified ATA/ATAPI device
  *     @dev: Target device to configure
@@ -2387,7 +2369,7 @@ int ata_dev_configure(struct ata_device *dev)
                                        dev->devslp_timing[i] = sata_setting[j];
                                }
                }
-               ata_dev_config_sense_reporting(dev);
+
                dev->cdb_len = 16;
        }
 
@@ -4248,6 +4230,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
                                                ATA_HORKAGE_ZERO_AFTER_TRIM, },
        { "Samsung SSD 8*",             NULL,   ATA_HORKAGE_NO_NCQ_TRIM |
                                                ATA_HORKAGE_ZERO_AFTER_TRIM, },
+       { "FCCT*M500*",                 NULL,   ATA_HORKAGE_NO_NCQ_TRIM |
+                                               ATA_HORKAGE_ZERO_AFTER_TRIM, },
 
        /* devices that don't properly handle TRIM commands */
        { "SuperSSpeed S238*",          NULL,   ATA_HORKAGE_NOTRIM, },
index 7465031a893c60c9e61f2c911abf218b39c81d2e..cb0508af1459ac43f4aa26f1a16d94134bd9d0bc 100644 (file)
@@ -1592,8 +1592,6 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
        tf->hob_lbah = buf[10];
        tf->nsect = buf[12];
        tf->hob_nsect = buf[13];
-       if (ata_id_has_ncq_autosense(dev->id))
-               tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16];
 
        return 0;
 }
@@ -1629,70 +1627,6 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
        return err_mask;
 }
 
-/**
- *     ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT
- *     @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to
- *     @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
- *     @dfl_sense_key: default sense key to use
- *
- *     Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK
- *     SENSE.  This function is EH helper.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep).
- *
- *     RETURNS:
- *     encoded sense data on success, 0 on failure or if sense data
- *     is not available.
- */
-static u32 ata_eh_request_sense(struct ata_queued_cmd *qc,
-                               struct scsi_cmnd *cmd)
-{
-       struct ata_device *dev = qc->dev;
-       struct ata_taskfile tf;
-       unsigned int err_mask;
-
-       if (!cmd)
-               return 0;
-
-       DPRINTK("ATA request sense\n");
-       ata_dev_warn(dev, "request sense\n");
-       if (!ata_id_sense_reporting_enabled(dev->id)) {
-               ata_dev_warn(qc->dev, "sense data reporting disabled\n");
-               return 0;
-       }
-       ata_tf_init(dev, &tf);
-
-       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
-       tf.command = ATA_CMD_REQ_SENSE_DATA;
-       tf.protocol = ATA_PROT_NODATA;
-
-       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
-       /*
-        * ACS-4 states:
-        * The device may set the SENSE DATA AVAILABLE bit to one in the
-        * STATUS field and clear the ERROR bit to zero in the STATUS field
-        * to indicate that the command returned completion without an error
-        * and the sense data described in table 306 is available.
-        *
-        * IOW the 'ATA_SENSE' bit might not be set even though valid
-        * sense data is available.
-        * So check for both.
-        */
-       if ((tf.command & ATA_SENSE) ||
-               tf.lbah != 0 || tf.lbam != 0 || tf.lbal != 0) {
-               ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal);
-               qc->flags |= ATA_QCFLAG_SENSE_VALID;
-               ata_dev_warn(dev, "sense data %02x/%02x/%02x\n",
-                            tf.lbah, tf.lbam, tf.lbal);
-       } else {
-               ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
-                            tf.command, err_mask);
-       }
-       return err_mask;
-}
-
 /**
  *     atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
  *     @dev: device to perform REQUEST_SENSE to
@@ -1855,19 +1789,6 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
        memcpy(&qc->result_tf, &tf, sizeof(tf));
        qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
        qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
-       if (qc->result_tf.auxiliary) {
-               char sense_key, asc, ascq;
-
-               sense_key = (qc->result_tf.auxiliary >> 16) & 0xff;
-               asc = (qc->result_tf.auxiliary >> 8) & 0xff;
-               ascq = qc->result_tf.auxiliary & 0xff;
-               ata_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n",
-                           sense_key, asc, ascq);
-               ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq);
-               ata_scsi_set_sense_information(qc->scsicmd, &qc->result_tf);
-               qc->flags |= ATA_QCFLAG_SENSE_VALID;
-       }
-
        ehc->i.err_mask &= ~AC_ERR_DEV;
 }
 
@@ -1897,27 +1818,6 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
                return ATA_EH_RESET;
        }
 
-       /*
-        * Sense data reporting does not work if the
-        * device fault bit is set.
-        */
-       if ((stat & ATA_SENSE) && !(stat & ATA_DF) &&
-           !(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
-               if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
-                       tmp = ata_eh_request_sense(qc, qc->scsicmd);
-                       if (tmp)
-                               qc->err_mask |= tmp;
-                       else
-                               ata_scsi_set_sense_information(qc->scsicmd, tf);
-               } else {
-                       ata_dev_warn(qc->dev, "sense data available but port frozen\n");
-               }
-       }
-
-       /* Set by NCQ autosense or request sense above */
-       if (qc->flags & ATA_QCFLAG_SENSE_VALID)
-               return 0;
-
        if (stat & (ATA_ERR | ATA_DF))
                qc->err_mask |= AC_ERR_DEV;
        else
@@ -2661,15 +2561,14 @@ static void ata_eh_link_report(struct ata_link *link)
 
 #ifdef CONFIG_ATA_VERBOSE_ERROR
                if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
-                                   ATA_SENSE | ATA_ERR)) {
+                                   ATA_ERR)) {
                        if (res->command & ATA_BUSY)
                                ata_dev_err(qc->dev, "status: { Busy }\n");
                        else
-                               ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n",
+                               ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",
                                  res->command & ATA_DRDY ? "DRDY " : "",
                                  res->command & ATA_DF ? "DF " : "",
                                  res->command & ATA_DRQ ? "DRQ " : "",
-                                 res->command & ATA_SENSE ? "SENSE " : "",
                                  res->command & ATA_ERR ? "ERR " : "");
                }
 
index 641a61a59e89c00036af65d3a31fe2cf67eb22b8..0d7f0da3a26929622080f94a2a3125c63676999e 100644 (file)
@@ -270,28 +270,13 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
            ata_scsi_park_show, ata_scsi_park_store);
 EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
 
-void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
 {
-       if (!cmd)
-               return;
-
        cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
        scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
 }
 
-void ata_scsi_set_sense_information(struct scsi_cmnd *cmd,
-                                   const struct ata_taskfile *tf)
-{
-       u64 information;
-
-       if (!cmd)
-               return;
-
-       information = ata_tf_read_block(tf, NULL);
-       scsi_set_sense_information(cmd->sense_buffer, information);
-}
-
 static ssize_t
 ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr,
                          const char *buf, size_t count)
@@ -1792,9 +1777,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
            ((cdb[2] & 0x20) || need_sense)) {
                ata_gen_passthru_sense(qc);
        } else {
-               if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
-                       cmd->result = SAM_STAT_CHECK_CONDITION;
-               } else if (!need_sense) {
+               if (!need_sense) {
                        cmd->result = SAM_STAT_GOOD;
                } else {
                        /* TODO: decide which descriptor format to use
index a998a175f9f144b50e4df782bbf7d1afd5f506cb..f840ca18a7c014f5151d22e4bc55dff9fca459de 100644 (file)
@@ -67,8 +67,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
                           u64 block, u32 n_block, unsigned int tf_flags,
                           unsigned int tag);
-extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
-                            struct ata_device *dev);
+extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
 extern unsigned ata_exec_internal(struct ata_device *dev,
                                  struct ata_taskfile *tf, const u8 *cdb,
                                  int dma_dir, void *buf, unsigned int buflen,
@@ -138,9 +137,6 @@ extern int ata_scsi_add_hosts(struct ata_host *host,
                              struct scsi_host_template *sht);
 extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
 extern int ata_scsi_offline_dev(struct ata_device *dev);
-extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq);
-extern void ata_scsi_set_sense_information(struct scsi_cmnd *cmd,
-                                          const struct ata_taskfile *tf);
 extern void ata_scsi_media_change_notify(struct ata_device *dev);
 extern void ata_scsi_hotplug(struct work_struct *work);
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
index 47e418b8c8baa0eee13b0a2843c25371a83bd338..4d1a5d2c4287f2979c34a2913c0cb4018f573776 100644 (file)
@@ -143,18 +143,6 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
        };
        const struct ata_port_info *ppi[] = { &info, NULL };
 
-       /*
-        * The JMicron chip 361/363 contains one SATA controller and one
-        * PATA controller,for powering on these both controllers, we must
-        * follow the sequence one by one, otherwise one of them can not be
-        * powered on successfully, so here we disable the async suspend
-        * method for these chips.
-        */
-       if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
-               (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
-               pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
-               device_disable_async_suspend(&pdev->dev);
-
        return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
 }
 
index 3a18a8a719b4ff1fa562a515b4701da241e4aeb7..fab504fd9cfd7ace54d772927a01650373d02206 100644 (file)
@@ -1238,8 +1238,12 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
        readl(mmio + PDC_SDRAM_CONTROL);
 
        /* Turn on for ECC */
-       pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
-                         PDC_DIMM_SPD_TYPE, &spd0);
+       if (!pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
+                              PDC_DIMM_SPD_TYPE, &spd0)) {
+               pr_err("Failed in i2c read: device=%#x, subaddr=%#x\n",
+                      PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_TYPE);
+               return 1;
+       }
        if (spd0 == 0x02) {
                data |= (0x01 << 16);
                writel(data, mmio + PDC_SDRAM_CONTROL);
@@ -1380,8 +1384,12 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
 
        /* ECC initiliazation. */
 
-       pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
-                         PDC_DIMM_SPD_TYPE, &spd0);
+       if (!pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
+                              PDC_DIMM_SPD_TYPE, &spd0)) {
+               pr_err("Failed in i2c read: device=%#x, subaddr=%#x\n",
+                      PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_TYPE);
+               return 1;
+       }
        if (spd0 == 0x02) {
                void *buf;
                VPRINTK("Start ECC initialization\n");
index 5b93852392b8c342cc3c772979a346dedd261439..816de9eaac2643c23722c89842b47373969fc2bf 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -90,17 +92,19 @@ void ks0108_displaystate(unsigned char state)
 
 void ks0108_startline(unsigned char startline)
 {
-       ks0108_writedata(min(startline,(unsigned char)63) | bit(6) | bit(7));
+       ks0108_writedata(min_t(unsigned char, startline, 63) | bit(6) |
+                        bit(7));
 }
 
 void ks0108_address(unsigned char address)
 {
-       ks0108_writedata(min(address,(unsigned char)63) | bit(6));
+       ks0108_writedata(min_t(unsigned char, address, 63) | bit(6));
 }
 
 void ks0108_page(unsigned char page)
 {
-       ks0108_writedata(min(page,(unsigned char)7) | bit(3) | bit(4) | bit(5) | bit(7));
+       ks0108_writedata(min_t(unsigned char, page, 7) | bit(3) | bit(4) |
+                        bit(5) | bit(7));
 }
 
 EXPORT_SYMBOL_GPL(ks0108_writedata);
@@ -121,52 +125,71 @@ unsigned char ks0108_isinited(void)
 }
 EXPORT_SYMBOL_GPL(ks0108_isinited);
 
-/*
- * Module Init & Exit
- */
-
-static int __init ks0108_init(void)
+static void ks0108_parport_attach(struct parport *port)
 {
-       int result;
-       int ret = -EINVAL;
-
-       ks0108_parport = parport_find_base(ks0108_port);
-       if (ks0108_parport == NULL) {
-               printk(KERN_ERR KS0108_NAME ": ERROR: "
-                       "parport didn't find %i port\n", ks0108_port);
-               goto none;
-       }
-
-       ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME,
-               NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-       if (ks0108_pardevice == NULL) {
-               printk(KERN_ERR KS0108_NAME ": ERROR: "
-                       "parport didn't register new device\n");
-               goto none;
+       struct pardev_cb ks0108_cb;
+
+       if (port->base != ks0108_port)
+               return;
+
+       memset(&ks0108_cb, 0, sizeof(ks0108_cb));
+       ks0108_cb.flags = PARPORT_DEV_EXCL;
+       ks0108_pardevice = parport_register_dev_model(port, KS0108_NAME,
+                                                     &ks0108_cb, 0);
+       if (!ks0108_pardevice) {
+               pr_err("ERROR: parport didn't register new device\n");
+               return;
        }
-
-       result = parport_claim(ks0108_pardevice);
-       if (result != 0) {
-               printk(KERN_ERR KS0108_NAME ": ERROR: "
-                       "can't claim %i parport, maybe in use\n", ks0108_port);
-               ret = result;
-               goto registered;
+       if (parport_claim(ks0108_pardevice)) {
+               pr_err("could not claim access to parport %i. Aborting.\n",
+                      ks0108_port);
+               goto err_unreg_device;
        }
 
+       ks0108_parport = port;
        ks0108_inited = 1;
-       return 0;
+       return;
 
-registered:
+err_unreg_device:
        parport_unregister_device(ks0108_pardevice);
-
-none:
-       return ret;
+       ks0108_pardevice = NULL;
 }
 
-static void __exit ks0108_exit(void)
+static void ks0108_parport_detach(struct parport *port)
 {
+       if (port->base != ks0108_port)
+               return;
+
+       if (!ks0108_pardevice) {
+               pr_err("%s: already unregistered.\n", KS0108_NAME);
+               return;
+       }
+
        parport_release(ks0108_pardevice);
        parport_unregister_device(ks0108_pardevice);
+       ks0108_pardevice = NULL;
+       ks0108_parport = NULL;
+}
+
+/*
+ * Module Init & Exit
+ */
+
+static struct parport_driver ks0108_parport_driver = {
+       .name = "ks0108",
+       .match_port = ks0108_parport_attach,
+       .detach = ks0108_parport_detach,
+       .devmodel = true,
+};
+
+static int __init ks0108_init(void)
+{
+       return parport_register_driver(&ks0108_parport_driver);
+}
+
+static void __exit ks0108_exit(void)
+{
+       parport_unregister_driver(&ks0108_parport_driver);
 }
 
 module_init(ks0108_init);
index fd3347d9f15351c4e859816c43b69bb9f59d5c98..1782f3aa386e6db3571aa3a437a2f9a9d5f72066 100644 (file)
@@ -63,7 +63,7 @@ struct driver_private {
  *     binding of drivers which were unable to get all the resources needed by
  *     the device; typically because it depends on another driver getting
  *     probed first.
- * @device - pointer back to the struct class that this structure is
+ * @device - pointer back to the struct device that this structure is
  * associated with.
  *
  * Nothing outside of the driver core should ever touch these fields.
@@ -134,6 +134,7 @@ extern int devres_release_all(struct device *dev);
 
 /* /sys/devices directory */
 extern struct kset *devices_kset;
+extern void devices_kset_move_last(struct device *dev);
 
 #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
 extern void module_add_driver(struct module *mod, struct device_driver *drv);
index dafae6d2f7ace1fd2941fcbc26ca50fa6450b0f9..fc5a558f62f974bbd769e3879ae11f6eb7297d9d 100644 (file)
@@ -533,6 +533,52 @@ static DEVICE_ATTR_RO(dev);
 /* /sys/devices/ */
 struct kset *devices_kset;
 
+/**
+ * devices_kset_move_before - Move device in the devices_kset's list.
+ * @deva: Device to move.
+ * @devb: Device @deva should come before.
+ */
+static void devices_kset_move_before(struct device *deva, struct device *devb)
+{
+       if (!devices_kset)
+               return;
+       pr_debug("devices_kset: Moving %s before %s\n",
+                dev_name(deva), dev_name(devb));
+       spin_lock(&devices_kset->list_lock);
+       list_move_tail(&deva->kobj.entry, &devb->kobj.entry);
+       spin_unlock(&devices_kset->list_lock);
+}
+
+/**
+ * devices_kset_move_after - Move device in the devices_kset's list.
+ * @deva: Device to move
+ * @devb: Device @deva should come after.
+ */
+static void devices_kset_move_after(struct device *deva, struct device *devb)
+{
+       if (!devices_kset)
+               return;
+       pr_debug("devices_kset: Moving %s after %s\n",
+                dev_name(deva), dev_name(devb));
+       spin_lock(&devices_kset->list_lock);
+       list_move(&deva->kobj.entry, &devb->kobj.entry);
+       spin_unlock(&devices_kset->list_lock);
+}
+
+/**
+ * devices_kset_move_last - move the device to the end of devices_kset's list.
+ * @dev: device to move
+ */
+void devices_kset_move_last(struct device *dev)
+{
+       if (!devices_kset)
+               return;
+       pr_debug("devices_kset: Moving %s to end of list\n", dev_name(dev));
+       spin_lock(&devices_kset->list_lock);
+       list_move_tail(&dev->kobj.entry, &devices_kset->list);
+       spin_unlock(&devices_kset->list_lock);
+}
+
 /**
  * device_create_file - create sysfs attribute file for device.
  * @dev: device.
@@ -1923,12 +1969,15 @@ int device_move(struct device *dev, struct device *new_parent,
                break;
        case DPM_ORDER_DEV_AFTER_PARENT:
                device_pm_move_after(dev, new_parent);
+               devices_kset_move_after(dev, new_parent);
                break;
        case DPM_ORDER_PARENT_BEFORE_DEV:
                device_pm_move_before(new_parent, dev);
+               devices_kset_move_before(new_parent, dev);
                break;
        case DPM_ORDER_DEV_LAST:
                device_pm_move_last(dev);
+               devices_kset_move_last(dev);
                break;
        }
 
index 78720e70617634c6301339510564ac6ed4380455..91bbb1959d8d0a831b7a7f0dc6472f2e5d4937b1 100644 (file)
@@ -41,7 +41,7 @@ static void change_cpu_under_node(struct cpu *cpu,
        cpu->node_id = to_nid;
 }
 
-static int __ref cpu_subsys_online(struct device *dev)
+static int cpu_subsys_online(struct device *dev)
 {
        struct cpu *cpu = container_of(dev, struct cpu, dev);
        int cpuid = dev->id;
index a638bbb1a27a573f7d959c20d459c73a368e8794..cc2b1d4801fd52c5117495fd10e2e48f0656d4a0 100644 (file)
@@ -304,6 +304,14 @@ static int really_probe(struct device *dev, struct device_driver *drv)
                        goto probe_failed;
        }
 
+       /*
+        * Ensure devices are listed in devices_kset in correct order
+        * It's important to move Dev to the end of devices_kset before
+        * calling .probe, because it could be recursive and parent Dev
+        * should always go first
+        */
+       devices_kset_move_last(dev);
+
        if (dev->bus->probe) {
                ret = dev->bus->probe(dev);
                if (ret)
index c8a53d1e019fbc56a3934cc06e4f3240bf799d55..87546469011741d7ce20b03bd5870e0f48eca641 100644 (file)
@@ -297,10 +297,10 @@ void * devres_get(struct device *dev, void *new_res,
        if (!dr) {
                add_dr(dev, &new_dr->node);
                dr = new_dr;
-               new_dr = NULL;
+               new_res = NULL;
        }
        spin_unlock_irqrestore(&dev->devres_lock, flags);
-       devres_free(new_dr);
+       devres_free(new_res);
 
        return dr->data;
 }
index 894bda114224d667077c25c898025b1af83c590a..8524450e75bd15d8f97327af84662b4af32fc3a7 100644 (file)
@@ -443,7 +443,7 @@ static int fw_add_devm_name(struct device *dev, const char *name)
                return -ENOMEM;
        fwn->name = kstrdup_const(name, GFP_KERNEL);
        if (!fwn->name) {
-               kfree(fwn);
+               devres_free(fwn);
                return -ENOMEM;
        }
 
index 81751a49d8bf2334612350bba52406b9af352258..56486d92c4e72bd583630baea0fba541f36c926f 100644 (file)
@@ -296,11 +296,20 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
        if (!blk)
                return -ENOMEM;
 
-       present = krealloc(rbnode->cache_present,
-                   BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL);
-       if (!present) {
-               kfree(blk);
-               return -ENOMEM;
+       if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
+               present = krealloc(rbnode->cache_present,
+                                  BITS_TO_LONGS(blklen) * sizeof(*present),
+                                  GFP_KERNEL);
+               if (!present) {
+                       kfree(blk);
+                       return -ENOMEM;
+               }
+
+               memset(present + BITS_TO_LONGS(rbnode->blklen), 0,
+                      (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen))
+                      * sizeof(*present));
+       } else {
+               present = rbnode->cache_present;
        }
 
        /* insert the register value in the correct place in the rbnode block */
index 4a2ef09e670457a06c5f1b987cd289d3ac5ce09f..f504232c1ee779079353e7ffd4b2d6831f87e61b 100644 (file)
@@ -3756,6 +3756,14 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx,
        struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
        u32 host_cap_64 = readl(dd->mmio + HOST_CAP) & HOST_CAP_64;
 
+       /*
+        * For flush requests, request_idx starts at the end of the
+        * tag space.  Since we don't support FLUSH/FUA, simply return
+        * 0 as there's nothing to be done.
+        */
+       if (request_idx >= MTIP_MAX_COMMAND_SLOTS)
+               return 0;
+
        cmd->command = dmam_alloc_coherent(&dd->pdev->dev, CMD_DMA_ALLOC_SZ,
                        &cmd->command_dma, GFP_KERNEL);
        if (!cmd->command)
index ced96777b677b9bcddd65bae004a7a51b5cf0dc3..954c0029fb3babc49d1a1f490f9d420934701e30 100644 (file)
@@ -369,8 +369,8 @@ static void purge_persistent_gnt(struct xen_blkif *blkif)
                return;
        }
 
-       if (work_pending(&blkif->persistent_purge_work)) {
-               pr_alert_ratelimited("Scheduled work from previous purge is still pending, cannot purge list\n");
+       if (work_busy(&blkif->persistent_purge_work)) {
+               pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n");
                return;
        }
 
index 6d89ed35d80c0caaf8bf57ba82c7e9f3a9194bb9..7a8a73f1fc0462feab5bad706573ff6eb4536ef7 100644 (file)
@@ -179,6 +179,7 @@ static DEFINE_SPINLOCK(minor_lock);
        ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
 
 static int blkfront_setup_indirect(struct blkfront_info *info);
+static int blkfront_gather_backend_features(struct blkfront_info *info);
 
 static int get_id_from_freelist(struct blkfront_info *info)
 {
@@ -1128,8 +1129,10 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                                 * Add the used indirect page back to the list of
                                 * available pages for indirect grefs.
                                 */
-                               indirect_page = pfn_to_page(s->indirect_grants[i]->pfn);
-                               list_add(&indirect_page->lru, &info->indirect_pages);
+                               if (!info->feature_persistent) {
+                                       indirect_page = pfn_to_page(s->indirect_grants[i]->pfn);
+                                       list_add(&indirect_page->lru, &info->indirect_pages);
+                               }
                                s->indirect_grants[i]->gref = GRANT_INVALID_REF;
                                list_add_tail(&s->indirect_grants[i]->node, &info->grants);
                        }
@@ -1519,7 +1522,7 @@ static int blkif_recover(struct blkfront_info *info)
        info->shadow_free = info->ring.req_prod_pvt;
        info->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
 
-       rc = blkfront_setup_indirect(info);
+       rc = blkfront_gather_backend_features(info);
        if (rc) {
                kfree(copy);
                return rc;
@@ -1720,20 +1723,13 @@ static void blkfront_setup_discard(struct blkfront_info *info)
 
 static int blkfront_setup_indirect(struct blkfront_info *info)
 {
-       unsigned int indirect_segments, segs;
+       unsigned int segs;
        int err, i;
 
-       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-                           "feature-max-indirect-segments", "%u", &indirect_segments,
-                           NULL);
-       if (err) {
-               info->max_indirect_segments = 0;
+       if (info->max_indirect_segments == 0)
                segs = BLKIF_MAX_SEGMENTS_PER_REQUEST;
-       } else {
-               info->max_indirect_segments = min(indirect_segments,
-                                                 xen_blkif_max_segments);
+       else
                segs = info->max_indirect_segments;
-       }
 
        err = fill_grant_buffer(info, (segs + INDIRECT_GREFS(segs)) * BLK_RING_SIZE(info));
        if (err)
@@ -1796,6 +1792,68 @@ out_of_memory:
        return -ENOMEM;
 }
 
+/*
+ * Gather all backend feature-*
+ */
+static int blkfront_gather_backend_features(struct blkfront_info *info)
+{
+       int err;
+       int barrier, flush, discard, persistent;
+       unsigned int indirect_segments;
+
+       info->feature_flush = 0;
+
+       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                       "feature-barrier", "%d", &barrier,
+                       NULL);
+
+       /*
+        * If there's no "feature-barrier" defined, then it means
+        * we're dealing with a very old backend which writes
+        * synchronously; nothing to do.
+        *
+        * If there are barriers, then we use flush.
+        */
+       if (!err && barrier)
+               info->feature_flush = REQ_FLUSH | REQ_FUA;
+       /*
+        * And if there is "feature-flush-cache" use that above
+        * barriers.
+        */
+       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                       "feature-flush-cache", "%d", &flush,
+                       NULL);
+
+       if (!err && flush)
+               info->feature_flush = REQ_FLUSH;
+
+       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                       "feature-discard", "%d", &discard,
+                       NULL);
+
+       if (!err && discard)
+               blkfront_setup_discard(info);
+
+       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                       "feature-persistent", "%u", &persistent,
+                       NULL);
+       if (err)
+               info->feature_persistent = 0;
+       else
+               info->feature_persistent = persistent;
+
+       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+                           "feature-max-indirect-segments", "%u", &indirect_segments,
+                           NULL);
+       if (err)
+               info->max_indirect_segments = 0;
+       else
+               info->max_indirect_segments = min(indirect_segments,
+                                                 xen_blkif_max_segments);
+
+       return blkfront_setup_indirect(info);
+}
+
 /*
  * Invoked when the backend is finally 'ready' (and has told produced
  * the details about the physical device - #sectors, size, etc).
@@ -1807,7 +1865,6 @@ static void blkfront_connect(struct blkfront_info *info)
        unsigned int physical_sector_size;
        unsigned int binfo;
        int err;
-       int barrier, flush, discard, persistent;
 
        switch (info->connected) {
        case BLKIF_STATE_CONNECTED:
@@ -1864,48 +1921,7 @@ static void blkfront_connect(struct blkfront_info *info)
        if (err != 1)
                physical_sector_size = sector_size;
 
-       info->feature_flush = 0;
-
-       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-                           "feature-barrier", "%d", &barrier,
-                           NULL);
-
-       /*
-        * If there's no "feature-barrier" defined, then it means
-        * we're dealing with a very old backend which writes
-        * synchronously; nothing to do.
-        *
-        * If there are barriers, then we use flush.
-        */
-       if (!err && barrier)
-               info->feature_flush = REQ_FLUSH | REQ_FUA;
-       /*
-        * And if there is "feature-flush-cache" use that above
-        * barriers.
-        */
-       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-                           "feature-flush-cache", "%d", &flush,
-                           NULL);
-
-       if (!err && flush)
-               info->feature_flush = REQ_FLUSH;
-
-       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-                           "feature-discard", "%d", &discard,
-                           NULL);
-
-       if (!err && discard)
-               blkfront_setup_discard(info);
-
-       err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-                           "feature-persistent", "%u", &persistent,
-                           NULL);
-       if (err)
-               info->feature_persistent = 0;
-       else
-               info->feature_persistent = persistent;
-
-       err = blkfront_setup_indirect(info);
+       err = blkfront_gather_backend_features(info);
        if (err) {
                xenbus_dev_fatal(info->xbdev, err, "setup_indirect at %s",
                                 info->xbdev->otherend);
index fb655e8d1e3b17bf4cda9fd09593bc7dc770f78d..763301c7828c72650f2abaa1c723425bdd3c73f4 100644 (file)
@@ -496,10 +496,9 @@ static void zram_meta_free(struct zram_meta *meta, u64 disksize)
        kfree(meta);
 }
 
-static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize)
+static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize)
 {
        size_t num_pages;
-       char pool_name[8];
        struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
 
        if (!meta)
@@ -512,7 +511,6 @@ static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize)
                goto out_error;
        }
 
-       snprintf(pool_name, sizeof(pool_name), "zram%d", device_id);
        meta->mem_pool = zs_create_pool(pool_name, GFP_NOIO | __GFP_HIGHMEM);
        if (!meta->mem_pool) {
                pr_err("Error creating memory pool\n");
@@ -1031,7 +1029,7 @@ static ssize_t disksize_store(struct device *dev,
                return -EINVAL;
 
        disksize = PAGE_ALIGN(disksize);
-       meta = zram_meta_alloc(zram->disk->first_minor, disksize);
+       meta = zram_meta_alloc(zram->disk->disk_name, disksize);
        if (!meta)
                return -ENOMEM;
 
index fdb0f9b3fe4508ab8cc7be9f14b4f775c166460a..8069b361b8dd1ce2363afff0bf4eb6eef5e5fc1c 100644 (file)
@@ -243,17 +243,15 @@ int misc_register(struct miscdevice * misc)
  *     @misc: device to unregister
  *
  *     Unregister a miscellaneous device that was previously
- *     successfully registered with misc_register(). Success
- *     is indicated by a zero return, a negative errno code
- *     indicates an error.
+ *     successfully registered with misc_register().
  */
 
-int misc_deregister(struct miscdevice *misc)
+void misc_deregister(struct miscdevice *misc)
 {
        int i = DYNAMIC_MINORS - misc->minor - 1;
 
        if (WARN_ON(list_empty(&misc->list)))
-               return -EINVAL;
+               return;
 
        mutex_lock(&misc_mtx);
        list_del(&misc->list);
@@ -261,7 +259,6 @@ int misc_deregister(struct miscdevice *misc)
        if (i < DYNAMIC_MINORS && i >= 0)
                clear_bit(i, misc_minors);
        mutex_unlock(&misc_mtx);
-       return 0;
 }
 
 EXPORT_SYMBOL(misc_register);
@@ -281,10 +278,9 @@ static char *misc_devnode(struct device *dev, umode_t *mode)
 static int __init misc_init(void)
 {
        int err;
+       struct proc_dir_entry *ret;
 
-#ifdef CONFIG_PROC_FS
-       proc_create("misc", 0, NULL, &misc_proc_fops);
-#endif
+       ret = proc_create("misc", 0, NULL, &misc_proc_fops);
        misc_class = class_create(THIS_MODULE, "misc");
        err = PTR_ERR(misc_class);
        if (IS_ERR(misc_class))
@@ -300,7 +296,8 @@ fail_printk:
        printk("unable to get major %d for misc devices\n", MISC_MAJOR);
        class_destroy(misc_class);
 fail_remove:
-       remove_proc_entry("misc", NULL);
+       if (ret)
+               remove_proc_entry("misc", NULL);
        return err;
 }
 subsys_initcall(misc_init);
index 9df78e2cc45d2951fc77815975cbeeb6633aea3a..97c2d8d433d6227f82f8524da27ecbd8929d9cd8 100644 (file)
@@ -702,7 +702,7 @@ static void atari_proc_infos(unsigned char *nvram, struct seq_file *seq,
                seq_printf(seq, "%ds%s\n", nvram[10],
                    nvram[10] < 8 ? ", no memory test" : "");
 
-       vmode = (nvram[14] << 8) || nvram[15];
+       vmode = (nvram[14] << 8) | nvram[15];
        seq_printf(seq,
            "Video mode       : %s colors, %d columns, %s %s monitor\n",
            colors[vmode & 7],
index 014c9d90d297ba57f1f83c7abbe1768042971b6b..f5a45d887a37f0aa83ed033b912faaa9a75ae957 100644 (file)
@@ -430,7 +430,7 @@ static int tosh_probe(void)
        int i,major,minor,day,year,month,flag;
        unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 };
        SMMRegisters regs;
-       void __iomem *bios = ioremap_cache(0xf0000, 0x10000);
+       void __iomem *bios = ioremap(0xf0000, 0x10000);
 
        if (!bios)
                return -ENOMEM;
index d8266bc2ae356138a70672b081a1e20b23594e2c..9418300214e985472fbd76f1c3e5cd1d1c186a2a 100644 (file)
@@ -193,14 +193,16 @@ static int xilly_probe(struct pci_dev *pdev,
        }
 
        /*
-        * In theory, an attempt to set the DMA mask to 64 and dma_using_dac=1
-        * is the right thing. But some unclever PCIe drivers report it's OK
-        * when the hardware drops those 64-bit PCIe packets. So trust
-        * nobody and use 32 bits DMA addressing in any case.
+        * Some (old and buggy?) hardware drops 64-bit addressed PCIe packets,
+        * even when the PCIe driver claims that a 64-bit mask is OK. On the
+        * other hand, on some architectures, 64-bit addressing is mandatory.
+        * So go for the 64-bit mask only when failing is the other option.
         */
 
        if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
                endpoint->dma_using_dac = 0;
+       } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               endpoint->dma_using_dac = 1;
        } else {
                dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");
                return -ENODEV;
index c4cf075a2320f7ae33327fd79e9d9525c15921c0..d08b3e5985bed4d2254c24aec6a9acb9645ff280 100644 (file)
@@ -9,7 +9,7 @@ obj-$(CONFIG_COMMON_CLK)        += clk-gate.o
 obj-$(CONFIG_COMMON_CLK)       += clk-mux.o
 obj-$(CONFIG_COMMON_CLK)       += clk-composite.o
 obj-$(CONFIG_COMMON_CLK)       += clk-fractional-divider.o
-obj-$(CONFIG_COMMON_CLK)       += clk-gpio-gate.o
+obj-$(CONFIG_COMMON_CLK)       += clk-gpio.o
 ifeq ($(CONFIG_OF), y)
 obj-$(CONFIG_COMMON_CLK)       += clk-conf.o
 endif
index 27dfa965cfedb020ebf66b635e0053ca58cefc1c..fd7247deabdc3de9cdf8ab0e4fb67d0c6775ef3e 100644 (file)
@@ -614,17 +614,12 @@ void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
        int num_parents;
        unsigned int irq;
        const char *name = np->name;
-       int i;
 
        num_parents = of_clk_get_parent_count(np);
        if (num_parents <= 0 || num_parents > 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index 5b3ded5205a29177dde69509bd72032f7fff61aa..620ea323356b62145c4f7ef7f1d19511c5832015 100644 (file)
@@ -222,7 +222,6 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
 {
        struct clk *clk;
        int num_parents;
-       int i;
        unsigned int irq;
        const char *parent_names[MASTER_SOURCE_MAX];
        const char *name = np->name;
@@ -232,11 +231,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
        if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index df2c1afa52b4acaa6204d5595a76c65f7dc0cb70..e4d7b574f1ea33a198a454e0223818c9e539ebb9 100644 (file)
@@ -134,7 +134,7 @@ at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name,
 
 static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
 {
-       struct clk *parent;
+       struct clk_hw *parent;
        unsigned long parent_rate;
        int shift = 0;
 
@@ -142,8 +142,8 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
                return;
 
        if (periph->range.max) {
-               parent = clk_get_parent_by_index(periph->hw.clk, 0);
-               parent_rate = __clk_get_rate(parent);
+               parent = clk_hw_get_parent_by_index(&periph->hw, 0);
+               parent_rate = clk_hw_get_rate(parent);
                if (!parent_rate)
                        return;
 
index 8c86c0f7847a55a0cdc257289c49c67777216d73..14b270b85fec277a6fdea1ad0df260eeee95f27b 100644 (file)
@@ -54,46 +54,47 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
        return parent_rate >> pres;
 }
 
-static long clk_programmable_determine_rate(struct clk_hw *hw,
-                                           unsigned long rate,
-                                           unsigned long min_rate,
-                                           unsigned long max_rate,
-                                           unsigned long *best_parent_rate,
-                                           struct clk_hw **best_parent_hw)
+static int clk_programmable_determine_rate(struct clk_hw *hw,
+                                          struct clk_rate_request *req)
 {
-       struct clk *parent = NULL;
+       struct clk_hw *parent;
        long best_rate = -EINVAL;
        unsigned long parent_rate;
        unsigned long tmp_rate;
        int shift;
        int i;
 
-       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
-               parent = clk_get_parent_by_index(hw->clk, i);
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
 
-               parent_rate = __clk_get_rate(parent);
+               parent_rate = clk_hw_get_rate(parent);
                for (shift = 0; shift < PROG_PRES_MASK; shift++) {
                        tmp_rate = parent_rate >> shift;
-                       if (tmp_rate <= rate)
+                       if (tmp_rate <= req->rate)
                                break;
                }
 
-               if (tmp_rate > rate)
+               if (tmp_rate > req->rate)
                        continue;
 
-               if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
+               if (best_rate < 0 ||
+                   (req->rate - tmp_rate) < (req->rate - best_rate)) {
                        best_rate = tmp_rate;
-                       *best_parent_rate = parent_rate;
-                       *best_parent_hw = __clk_get_hw(parent);
+                       req->best_parent_rate = parent_rate;
+                       req->best_parent_hw = parent;
                }
 
                if (!best_rate)
                        break;
        }
 
-       return best_rate;
+       if (best_rate < 0)
+               return best_rate;
+
+       req->rate = best_rate;
+       return 0;
 }
 
 static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
@@ -230,7 +231,6 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
 {
        int num;
        u32 id;
-       int i;
        struct clk *clk;
        int num_parents;
        const char *parent_names[PROG_SOURCE_MAX];
@@ -241,11 +241,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
        if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        num = of_get_child_count(np);
        if (!num || num > (PROG_ID_MAX + 1))
index 98a84a865fe1cf1b13a437741631b83804e32bf6..d0d5076a9b94b078f1d78a0c8c4d598c56e8c00a 100644 (file)
  *
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk/at91_pmc.h>
 #include <linux/delay.h>
 #include <linux/of.h>
@@ -371,17 +373,12 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
        const char *parent_names[2];
        int num_parents;
        const char *name = np->name;
-       int i;
 
        num_parents = of_clk_get_parent_count(np);
        if (num_parents <= 0 || num_parents > 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
@@ -449,17 +446,12 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
        const char *parent_names[2];
        int num_parents;
        const char *name = np->name;
-       int i;
 
        num_parents = of_clk_get_parent_count(np);
        if (num_parents != 2)
                return;
 
-       for (i = 0; i < num_parents; ++i) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index 3817ea865ca258ecb8675f6e35c39be4f53fd424..a7f8501cfa056222a103c1e0f05a442521f68eae 100644 (file)
@@ -145,7 +145,6 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
                                        struct at91_pmc *pmc)
 {
        struct clk *clk;
-       int i;
        int num_parents;
        const char *parent_names[SMD_SOURCE_MAX];
        const char *name = np->name;
@@ -154,11 +153,7 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
        if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; i++) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index b0cbd2b1ff5957027a5643963d45038435e8b1ce..8ab8502778a282bac38b56ce9ecb7cd92c8962e2 100644 (file)
@@ -56,47 +56,43 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
        return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
 }
 
-static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
-                                             unsigned long rate,
-                                             unsigned long min_rate,
-                                             unsigned long max_rate,
-                                             unsigned long *best_parent_rate,
-                                             struct clk_hw **best_parent_hw)
+static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
+                                            struct clk_rate_request *req)
 {
-       struct clk *parent = NULL;
+       struct clk_hw *parent;
        long best_rate = -EINVAL;
        unsigned long tmp_rate;
        int best_diff = -1;
        int tmp_diff;
        int i;
 
-       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
                int div;
 
-               parent = clk_get_parent_by_index(hw->clk, i);
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
 
                for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
                        unsigned long tmp_parent_rate;
 
-                       tmp_parent_rate = rate * div;
-                       tmp_parent_rate = __clk_round_rate(parent,
+                       tmp_parent_rate = req->rate * div;
+                       tmp_parent_rate = clk_hw_round_rate(parent,
                                                           tmp_parent_rate);
                        tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
-                       if (tmp_rate < rate)
-                               tmp_diff = rate - tmp_rate;
+                       if (tmp_rate < req->rate)
+                               tmp_diff = req->rate - tmp_rate;
                        else
-                               tmp_diff = tmp_rate - rate;
+                               tmp_diff = tmp_rate - req->rate;
 
                        if (best_diff < 0 || best_diff > tmp_diff) {
                                best_rate = tmp_rate;
                                best_diff = tmp_diff;
-                               *best_parent_rate = tmp_parent_rate;
-                               *best_parent_hw = __clk_get_hw(parent);
+                               req->best_parent_rate = tmp_parent_rate;
+                               req->best_parent_hw = parent;
                        }
 
-                       if (!best_diff || tmp_rate < rate)
+                       if (!best_diff || tmp_rate < req->rate)
                                break;
                }
 
@@ -104,7 +100,11 @@ static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
                        break;
        }
 
-       return best_rate;
+       if (best_rate < 0)
+               return best_rate;
+
+       req->rate = best_rate;
+       return 0;
 }
 
 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
@@ -273,7 +273,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
                                          unsigned long *parent_rate)
 {
        struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
-       struct clk *parent = __clk_get_parent(hw->clk);
+       struct clk_hw *parent = clk_hw_get_parent(hw);
        unsigned long bestrate = 0;
        int bestdiff = -1;
        unsigned long tmprate;
@@ -287,7 +287,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
                        continue;
 
                tmp_parent_rate = rate * usb->divisors[i];
-               tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
+               tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
                tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
                if (tmprate < rate)
                        tmpdiff = rate - tmprate;
@@ -373,7 +373,6 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
                                        struct at91_pmc *pmc)
 {
        struct clk *clk;
-       int i;
        int num_parents;
        const char *parent_names[USB_SOURCE_MAX];
        const char *name = np->name;
@@ -382,11 +381,7 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
        if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
                return;
 
-       for (i = 0; i < num_parents; i++) {
-               parent_names[i] = of_clk_get_parent_name(np, i);
-               if (!parent_names[i])
-                       return;
-       }
+       of_clk_parent_fill(np, parent_names, num_parents);
 
        of_property_read_string(np, "clock-output-names", &name);
 
index 39be2be82b0a04b730258b4a7154aa5be103cc73..d1844f1f37292a79bac681d9037141586b4ba203 100644 (file)
@@ -125,7 +125,6 @@ static int pmc_irq_map(struct irq_domain *h, unsigned int virq,
 
        irq_set_chip_and_handler(virq, &pmc_irq,
                                 handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID);
        irq_set_chip_data(virq, pmc);
 
        return 0;
index eb8e5dc9076d46f07901a98db214fbeec0b0a3dc..8b87771c69b2c4211597c879e01c6256655c4bc0 100644 (file)
@@ -59,71 +59,63 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
 int of_at91_get_clk_range(struct device_node *np, const char *propname,
                          struct clk_range *range);
 
-extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
-                                                struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
-                                                   struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
-                                                      struct at91_pmc *pmc);
-extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np,
-                                                struct at91_pmc *pmc);
-extern void __init of_sama5d3_clk_pll_setup(struct device_node *np,
-                                           struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_master_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np,
-                                                 struct at91_pmc *pmc);
-
-extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np,
-                                                struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-
-#if defined(CONFIG_HAVE_AT91_UTMI)
-extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-#endif
-
-#if defined(CONFIG_HAVE_AT91_USB_CLK)
-extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np,
-                                               struct at91_pmc *pmc);
-#endif
-
-#if defined(CONFIG_HAVE_AT91_SMD)
-extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
-                                              struct at91_pmc *pmc);
-#endif
-
-#if defined(CONFIG_HAVE_AT91_H32MX)
-extern void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
-                                             struct at91_pmc *pmc);
-#endif
+void of_at91sam9260_clk_slow_setup(struct device_node *np,
+                                  struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_main_osc_setup(struct device_node *np,
+                                     struct at91_pmc *pmc);
+void of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
+                                        struct at91_pmc *pmc);
+void of_at91rm9200_clk_main_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+void of_at91sam9x5_clk_main_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_pll_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+void of_at91sam9g45_clk_pll_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+void of_at91sam9g20_clk_pllb_setup(struct device_node *np,
+                                  struct at91_pmc *pmc);
+void of_sama5d3_clk_pll_setup(struct device_node *np,
+                             struct at91_pmc *pmc);
+void of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_master_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+void of_at91sam9x5_clk_master_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_sys_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_periph_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+void of_at91sam9x5_clk_periph_setup(struct device_node *np,
+                                   struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_prog_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+void of_at91sam9g45_clk_prog_setup(struct device_node *np,
+                                  struct at91_pmc *pmc);
+void of_at91sam9x5_clk_prog_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91sam9x5_clk_utmi_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91rm9200_clk_usb_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+void of_at91sam9x5_clk_usb_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+void of_at91sam9n12_clk_usb_setup(struct device_node *np,
+                                 struct at91_pmc *pmc);
+
+void of_at91sam9x5_clk_smd_setup(struct device_node *np,
+                                struct at91_pmc *pmc);
+
+void of_sama5d4_clk_h32mx_setup(struct device_node *np,
+                               struct at91_pmc *pmc);
 
 #endif /* __PMC_H_ */
index 79a98506c433bbbbc12bd50d0f7cf82a029d3b8b..3a15347b423348b83a70613ad5e6b880d05f8875 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/clk.h>
 
 /*
  * "Policies" affect the frequencies of bus clocks provided by a
@@ -1010,25 +1011,23 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
        struct bcm_clk_div *div = &bcm_clk->u.peri->div;
 
        if (!divider_exists(div))
-               return __clk_get_rate(hw->clk);
+               return clk_hw_get_rate(hw);
 
        /* Quietly avoid a zero rate */
        return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
                                rate ? rate : 1, *parent_rate, NULL);
 }
 
-static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate,
-               unsigned long max_rate,
-               unsigned long *best_parent_rate, struct clk_hw **best_parent)
+static int kona_peri_clk_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct clk *clk = hw->clk;
-       struct clk *current_parent;
+       struct clk_hw *current_parent;
        unsigned long parent_rate;
        unsigned long best_delta;
        unsigned long best_rate;
        u32 parent_count;
+       long rate;
        u32 which;
 
        /*
@@ -1037,18 +1036,25 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
         */
        WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
        parent_count = (u32)bcm_clk->init_data.num_parents;
-       if (parent_count < 2)
-               return kona_peri_clk_round_rate(hw, rate, best_parent_rate);
+       if (parent_count < 2) {
+               rate = kona_peri_clk_round_rate(hw, req->rate,
+                                               &req->best_parent_rate);
+               if (rate < 0)
+                       return rate;
+
+               req->rate = rate;
+               return 0;
+       }
 
        /* Unless we can do better, stick with current parent */
-       current_parent = clk_get_parent(clk);
-       parent_rate = __clk_get_rate(current_parent);
-       best_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
-       best_delta = abs(best_rate - rate);
+       current_parent = clk_hw_get_parent(hw);
+       parent_rate = clk_hw_get_rate(current_parent);
+       best_rate = kona_peri_clk_round_rate(hw, req->rate, &parent_rate);
+       best_delta = abs(best_rate - req->rate);
 
        /* Check whether any other parent clock can produce a better result */
        for (which = 0; which < parent_count; which++) {
-               struct clk *parent = clk_get_parent_by_index(clk, which);
+               struct clk_hw *parent = clk_hw_get_parent_by_index(hw, which);
                unsigned long delta;
                unsigned long other_rate;
 
@@ -1057,18 +1063,20 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
                        continue;
 
                /* We don't support CLK_SET_RATE_PARENT */
-               parent_rate = __clk_get_rate(parent);
-               other_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
-               delta = abs(other_rate - rate);
+               parent_rate = clk_hw_get_rate(parent);
+               other_rate = kona_peri_clk_round_rate(hw, req->rate,
+                                                     &parent_rate);
+               delta = abs(other_rate - req->rate);
                if (delta < best_delta) {
                        best_delta = delta;
                        best_rate = other_rate;
-                       *best_parent = __clk_get_hw(parent);
-                       *best_parent_rate = parent_rate;
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = parent_rate;
                }
        }
 
-       return best_rate;
+       req->rate = best_rate;
+       return 0;
 }
 
 static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
@@ -1130,7 +1138,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        if (parent_rate > (unsigned long)LONG_MAX)
                return -EINVAL;
 
-       if (rate == __clk_get_rate(hw->clk))
+       if (rate == clk_hw_get_rate(hw))
                return 0;
 
        if (!divider_exists(div))
@@ -1249,6 +1257,7 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
        unsigned long flags;
        unsigned int which;
        struct clk **clks = ccu->clk_data.clks;
+       struct kona_clk *kona_clks = ccu->kona_clks;
        bool success = true;
 
        flags = ccu_lock(ccu);
@@ -1259,7 +1268,7 @@ bool __init kona_ccu_init(struct ccu_data *ccu)
 
                if (!clks[which])
                        continue;
-               bcm_clk = to_kona_clk(__clk_get_hw(clks[which]));
+               bcm_clk = &kona_clks[which];
                success &= __kona_clk_init(bcm_clk);
        }
 
index f4b8d324b083dfda89d3766cc6958b533b7802d4..1c2294d3ba85a449a7415c034a287045d703dc83 100644 (file)
@@ -61,7 +61,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        fbdiv = (val >> map->fbdiv_shift) & FBDIV_MASK;
        rfdiv = (val >> map->rfdiv_shift) & RFDIV_MASK;
        if (rfdiv == 0) {
-               pr_warn("%s has zero rfdiv\n", __clk_get_name(hw->clk));
+               pr_warn("%s has zero rfdiv\n", clk_hw_get_name(hw));
                rfdiv = 1;
        }
 
@@ -70,7 +70,7 @@ berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        vcodiv = map->vcodiv[vcodivsel];
        if (vcodiv == 0) {
                pr_warn("%s has zero vcodiv (index %d)\n",
-                       __clk_get_name(hw->clk), vcodivsel);
+                       clk_hw_get_name(hw), vcodivsel);
                vcodiv = 1;
        }
 
index e619285c6defddc731ce4eac34c3b5527bf5e47b..3bcd42fbb55e3fbbcdb401f707aef3879fe5d001 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 6b950ca8b71108fdf3f32dd5ea6503eb1e5dc7ed..dd295e498309b9e60f2903910a67563626a883f7 100644 (file)
@@ -32,11 +32,6 @@ void __init bcm2835_init_clocks(void)
        struct clk *clk;
        int ret;
 
-       clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
-                                       250000000);
-       if (IS_ERR(clk))
-               pr_err("sys_pclk not registered\n");
-
        clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
                                        126000000);
        if (IS_ERR(clk))
index f01164fada5dafd4e80d0eac8f5f0242847399dd..01877f64eff6a764ec2fcc2e5e3ff1f88d8f3514 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -309,7 +310,7 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
        if (!mul)
                div = CDCE706_DIVIDER_DIVIDER_MAX;
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                unsigned long best_diff = rate;
                unsigned long best_div = 0;
                struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
index 85fafb41e6ca3a8edbab5f1a1d8adc88c4ec7f4d..089bf88ffa8d677547b1a6f18c6ace50322793c6 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright (C) 2014, Topic Embedded Products
  * Licenced under GPL
  */
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index 715eec1a99022cc0461fa6a26f81e53c0a8dd33f..ff4ef4f1df622a5529402acf3127ada88941491c 100644 (file)
@@ -9,7 +9,6 @@
  * (at your option) any later version.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/io.h>
index 616f5aef3c26c7ad24334b1291d7d8178ef76ede..4735de0660cc912f1bafea1e31388bcf9843543d 100644 (file)
@@ -55,78 +55,77 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
        return rate_ops->recalc_rate(rate_hw, parent_rate);
 }
 
-static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_p)
+static int clk_composite_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req)
 {
        struct clk_composite *composite = to_clk_composite(hw);
        const struct clk_ops *rate_ops = composite->rate_ops;
        const struct clk_ops *mux_ops = composite->mux_ops;
        struct clk_hw *rate_hw = composite->rate_hw;
        struct clk_hw *mux_hw = composite->mux_hw;
-       struct clk *parent;
+       struct clk_hw *parent;
        unsigned long parent_rate;
        long tmp_rate, best_rate = 0;
        unsigned long rate_diff;
        unsigned long best_rate_diff = ULONG_MAX;
+       long rate;
        int i;
 
        if (rate_hw && rate_ops && rate_ops->determine_rate) {
                __clk_hw_set_clk(rate_hw, hw);
-               return rate_ops->determine_rate(rate_hw, rate, min_rate,
-                                               max_rate,
-                                               best_parent_rate,
-                                               best_parent_p);
+               return rate_ops->determine_rate(rate_hw, req);
        } else if (rate_hw && rate_ops && rate_ops->round_rate &&
                   mux_hw && mux_ops && mux_ops->set_parent) {
-               *best_parent_p = NULL;
+               req->best_parent_hw = NULL;
 
-               if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
-                       parent = clk_get_parent(mux_hw->clk);
-                       *best_parent_p = __clk_get_hw(parent);
-                       *best_parent_rate = __clk_get_rate(parent);
+               if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
+                       parent = clk_hw_get_parent(mux_hw);
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = clk_hw_get_rate(parent);
 
-                       return rate_ops->round_rate(rate_hw, rate,
-                                                   best_parent_rate);
+                       rate = rate_ops->round_rate(rate_hw, req->rate,
+                                                   &req->best_parent_rate);
+                       if (rate < 0)
+                               return rate;
+
+                       req->rate = rate;
+                       return 0;
                }
 
-               for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
-                       parent = clk_get_parent_by_index(mux_hw->clk, i);
+               for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) {
+                       parent = clk_hw_get_parent_by_index(mux_hw, i);
                        if (!parent)
                                continue;
 
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
 
-                       tmp_rate = rate_ops->round_rate(rate_hw, rate,
+                       tmp_rate = rate_ops->round_rate(rate_hw, req->rate,
                                                        &parent_rate);
                        if (tmp_rate < 0)
                                continue;
 
-                       rate_diff = abs(rate - tmp_rate);
+                       rate_diff = abs(req->rate - tmp_rate);
 
-                       if (!rate_diff || !*best_parent_p
+                       if (!rate_diff || !req->best_parent_hw
                                       || best_rate_diff > rate_diff) {
-                               *best_parent_p = __clk_get_hw(parent);
-                               *best_parent_rate = parent_rate;
+                               req->best_parent_hw = parent;
+                               req->best_parent_rate = parent_rate;
                                best_rate_diff = rate_diff;
                                best_rate = tmp_rate;
                        }
 
                        if (!rate_diff)
-                               return rate;
+                               return 0;
                }
 
-               return best_rate;
+               req->rate = best_rate;
+               return 0;
        } else if (mux_hw && mux_ops && mux_ops->determine_rate) {
                __clk_hw_set_clk(mux_hw, hw);
-               return mux_ops->determine_rate(mux_hw, rate, min_rate,
-                                              max_rate, best_parent_rate,
-                                              best_parent_p);
+               return mux_ops->determine_rate(mux_hw, req);
        } else {
                pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
-               return 0;
+               return -EINVAL;
        }
 }
 
index 706b5783c360dfc5ba60c6f7054374f5f06ff4f8..f24d0a19ae70aa8cc2a1210ab03da617d048aff0 100644 (file)
@@ -78,12 +78,14 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
 }
 
 static unsigned int _get_div(const struct clk_div_table *table,
-                            unsigned int val, unsigned long flags)
+                            unsigned int val, unsigned long flags, u8 width)
 {
        if (flags & CLK_DIVIDER_ONE_BASED)
                return val;
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
                return 1 << val;
+       if (flags & CLK_DIVIDER_MAX_AT_ZERO)
+               return val ? val : div_mask(width) + 1;
        if (table)
                return _get_table_div(table, val);
        return val + 1;
@@ -101,12 +103,14 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
 }
 
 static unsigned int _get_val(const struct clk_div_table *table,
-                            unsigned int div, unsigned long flags)
+                            unsigned int div, unsigned long flags, u8 width)
 {
        if (flags & CLK_DIVIDER_ONE_BASED)
                return div;
        if (flags & CLK_DIVIDER_POWER_OF_TWO)
                return __ffs(div);
+       if (flags & CLK_DIVIDER_MAX_AT_ZERO)
+               return (div == div_mask(width) + 1) ? 0 : div;
        if (table)
                return  _get_table_val(table, div);
        return div - 1;
@@ -117,13 +121,14 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
                                  const struct clk_div_table *table,
                                  unsigned long flags)
 {
+       struct clk_divider *divider = to_clk_divider(hw);
        unsigned int div;
 
-       div = _get_div(table, val, flags);
+       div = _get_div(table, val, flags, divider->width);
        if (!div) {
                WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
                        "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return parent_rate;
        }
 
@@ -285,7 +290,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        maxdiv = _get_maxdiv(table, width, flags);
 
-       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
                parent_rate = *best_parent_rate;
                bestdiv = _div_round(table, parent_rate, rate, flags);
                bestdiv = bestdiv == 0 ? 1 : bestdiv;
@@ -311,7 +316,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
                        *best_parent_rate = parent_rate_saved;
                        return i;
                }
-               parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+               parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
                                               rate * i);
                now = DIV_ROUND_UP(parent_rate, i);
                if (_is_best_div(rate, now, best, flags)) {
@@ -323,7 +328,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        if (!bestdiv) {
                bestdiv = _get_maxdiv(table, width, flags);
-               *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
+               *best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
        }
 
        return bestdiv;
@@ -351,7 +356,8 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
        if (divider->flags & CLK_DIVIDER_READ_ONLY) {
                bestdiv = readl(divider->reg) >> divider->shift;
                bestdiv &= div_mask(divider->width);
-               bestdiv = _get_div(divider->table, bestdiv, divider->flags);
+               bestdiv = _get_div(divider->table, bestdiv, divider->flags,
+                       divider->width);
                return DIV_ROUND_UP(*prate, bestdiv);
        }
 
@@ -370,7 +376,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
        if (!_is_valid_div(table, div, flags))
                return -EINVAL;
 
-       value = _get_val(table, div, flags);
+       value = _get_val(table, div, flags, width);
 
        return min_t(unsigned int, value, div_mask(width));
 }
@@ -389,6 +395,8 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (divider->lock)
                spin_lock_irqsave(divider->lock, flags);
+       else
+               __acquire(divider->lock);
 
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
                val = div_mask(divider->width) << (divider->shift + 16);
@@ -401,6 +409,8 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (divider->lock)
                spin_unlock_irqrestore(divider->lock, flags);
+       else
+               __release(divider->lock);
 
        return 0;
 }
index 73a8d0ff530c022b3ccdbe0fc96fe3f4a1fc2f67..bac4553f04b854d96f3269a5b624a3723e2e9259 100644 (file)
@@ -6,7 +6,6 @@
  * the terms of the GNU General Public License version 2 as published by the
  * Free Software Foundation.
  */
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
index fccabe497f6e5db42f6585acd9ecb1c4440bcb4e..83de57aeceea514dfaf53fc5a0271b1ca7d3b13d 100644 (file)
@@ -41,12 +41,11 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                unsigned long best_parent;
 
                best_parent = (rate / fix->mult) * fix->div;
-               *prate = __clk_round_rate(__clk_get_parent(hw->clk),
-                               best_parent);
+               *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
        }
 
        return (*prate / fix->div) * fix->mult;
index 140eb5844dc4b86d1fb6b7034b5c375117dee0f8..e85f856b859219b1987dda9a403e07f4ded45769 100644 (file)
@@ -27,11 +27,15 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
 
        if (fd->lock)
                spin_lock_irqsave(fd->lock, flags);
+       else
+               __acquire(fd->lock);
 
        val = clk_readl(fd->reg);
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
+       else
+               __release(fd->lock);
 
        m = (val & fd->mmask) >> fd->mshift;
        n = (val & fd->nmask) >> fd->nshift;
@@ -80,6 +84,8 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (fd->lock)
                spin_lock_irqsave(fd->lock, flags);
+       else
+               __acquire(fd->lock);
 
        val = clk_readl(fd->reg);
        val &= ~(fd->mmask | fd->nmask);
@@ -88,6 +94,8 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (fd->lock)
                spin_unlock_irqrestore(fd->lock, flags);
+       else
+               __release(fd->lock);
 
        return 0;
 }
index 551dd067279402abbd45685315ee9df1c5f7c5d5..de0b322f5f58d4a57677455e6a5a2a78dcf0687d 100644 (file)
@@ -52,6 +52,8 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 
        if (gate->lock)
                spin_lock_irqsave(gate->lock, flags);
+       else
+               __acquire(gate->lock);
 
        if (gate->flags & CLK_GATE_HIWORD_MASK) {
                reg = BIT(gate->bit_idx + 16);
@@ -70,6 +72,8 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
 
        if (gate->lock)
                spin_unlock_irqrestore(gate->lock, flags);
+       else
+               __release(gate->lock);
 }
 
 static int clk_gate_enable(struct clk_hw *hw)
diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
deleted file mode 100644 (file)
index f564e62..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
- * Author: Jyri Sarha <jsarha@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.
- *
- * Gpio gated clock implementation
- */
-
-#include <linux/clk-provider.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of_gpio.h>
-#include <linux/err.h>
-#include <linux/device.h>
-
-/**
- * DOC: basic gpio gated clock which can be enabled and disabled
- *      with gpio output
- * Traits of this clock:
- * prepare - clk_(un)prepare only ensures parent is (un)prepared
- * enable - clk_enable and clk_disable are functional & control gpio
- * rate - inherits rate from parent.  No clk_set_rate support
- * parent - fixed parent.  No clk_set_parent support
- */
-
-#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
-
-static int clk_gpio_gate_enable(struct clk_hw *hw)
-{
-       struct clk_gpio *clk = to_clk_gpio(hw);
-
-       gpiod_set_value(clk->gpiod, 1);
-
-       return 0;
-}
-
-static void clk_gpio_gate_disable(struct clk_hw *hw)
-{
-       struct clk_gpio *clk = to_clk_gpio(hw);
-
-       gpiod_set_value(clk->gpiod, 0);
-}
-
-static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
-{
-       struct clk_gpio *clk = to_clk_gpio(hw);
-
-       return gpiod_get_value(clk->gpiod);
-}
-
-const struct clk_ops clk_gpio_gate_ops = {
-       .enable = clk_gpio_gate_enable,
-       .disable = clk_gpio_gate_disable,
-       .is_enabled = clk_gpio_gate_is_enabled,
-};
-EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
-
-/**
- * clk_register_gpio - register a gpip clock with the clock framework
- * @dev: device that is registering this clock
- * @name: name of this clock
- * @parent_name: name of this clock's parent
- * @gpio: gpio number to gate this clock
- * @active_low: true if gpio should be set to 0 to enable clock
- * @flags: clock flags
- */
-struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, unsigned gpio, bool active_low,
-               unsigned long flags)
-{
-       struct clk_gpio *clk_gpio = NULL;
-       struct clk *clk = ERR_PTR(-EINVAL);
-       struct clk_init_data init = { NULL };
-       unsigned long gpio_flags;
-       int err;
-
-       if (active_low)
-               gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
-       else
-               gpio_flags = GPIOF_OUT_INIT_LOW;
-
-       if (dev)
-               err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
-       else
-               err = gpio_request_one(gpio, gpio_flags, name);
-
-       if (err) {
-               pr_err("%s: %s: Error requesting clock control gpio %u\n",
-                      __func__, name, gpio);
-               return ERR_PTR(err);
-       }
-
-       if (dev)
-               clk_gpio = devm_kzalloc(dev, sizeof(struct clk_gpio),
-                                       GFP_KERNEL);
-       else
-               clk_gpio = kzalloc(sizeof(struct clk_gpio), GFP_KERNEL);
-
-       if (!clk_gpio) {
-               clk = ERR_PTR(-ENOMEM);
-               goto clk_register_gpio_gate_err;
-       }
-
-       init.name = name;
-       init.ops = &clk_gpio_gate_ops;
-       init.flags = flags | CLK_IS_BASIC;
-       init.parent_names = (parent_name ? &parent_name : NULL);
-       init.num_parents = (parent_name ? 1 : 0);
-
-       clk_gpio->gpiod = gpio_to_desc(gpio);
-       clk_gpio->hw.init = &init;
-
-       clk = clk_register(dev, &clk_gpio->hw);
-
-       if (!IS_ERR(clk))
-               return clk;
-
-       if (!dev)
-               kfree(clk_gpio);
-
-clk_register_gpio_gate_err:
-       if (!dev)
-               gpio_free(gpio);
-
-       return clk;
-}
-EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
-
-#ifdef CONFIG_OF
-/**
- * The clk_register_gpio_gate has to be delayed, because the EPROBE_DEFER
- * can not be handled properly at of_clk_init() call time.
- */
-
-struct clk_gpio_gate_delayed_register_data {
-       struct device_node *node;
-       struct mutex lock;
-       struct clk *clk;
-};
-
-static struct clk *of_clk_gpio_gate_delayed_register_get(
-               struct of_phandle_args *clkspec,
-               void *_data)
-{
-       struct clk_gpio_gate_delayed_register_data *data = _data;
-       struct clk *clk;
-       const char *clk_name = data->node->name;
-       const char *parent_name;
-       int gpio;
-       enum of_gpio_flags of_flags;
-
-       mutex_lock(&data->lock);
-
-       if (data->clk) {
-               mutex_unlock(&data->lock);
-               return data->clk;
-       }
-
-       gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0,
-                                               &of_flags);
-       if (gpio < 0) {
-               mutex_unlock(&data->lock);
-               if (gpio != -EPROBE_DEFER)
-                       pr_err("%s: %s: Can't get 'enable-gpios' DT property\n",
-                              __func__, clk_name);
-               return ERR_PTR(gpio);
-       }
-
-       parent_name = of_clk_get_parent_name(data->node, 0);
-
-       clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpio,
-                                       of_flags & OF_GPIO_ACTIVE_LOW, 0);
-       if (IS_ERR(clk)) {
-               mutex_unlock(&data->lock);
-               return clk;
-       }
-
-       data->clk = clk;
-       mutex_unlock(&data->lock);
-
-       return clk;
-}
-
-/**
- * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
- */
-static void __init of_gpio_gate_clk_setup(struct device_node *node)
-{
-       struct clk_gpio_gate_delayed_register_data *data;
-
-       data = kzalloc(sizeof(struct clk_gpio_gate_delayed_register_data),
-                      GFP_KERNEL);
-       if (!data)
-               return;
-
-       data->node = node;
-       mutex_init(&data->lock);
-
-       of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
-}
-CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
-#endif
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
new file mode 100644 (file)
index 0000000..10819e2
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Authors:
+ *    Jyri Sarha <jsarha@ti.com>
+ *    Sergej Sawazki <ce3a@gmx.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.
+ *
+ * Gpio controlled clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_gpio.h>
+#include <linux/err.h>
+#include <linux/device.h>
+
+/**
+ * DOC: basic gpio gated clock which can be enabled and disabled
+ *      with gpio output
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gpio
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
+
+static int clk_gpio_gate_enable(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value(clk->gpiod, 1);
+
+       return 0;
+}
+
+static void clk_gpio_gate_disable(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value(clk->gpiod, 0);
+}
+
+static int clk_gpio_gate_is_enabled(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       return gpiod_get_value(clk->gpiod);
+}
+
+const struct clk_ops clk_gpio_gate_ops = {
+       .enable = clk_gpio_gate_enable,
+       .disable = clk_gpio_gate_disable,
+       .is_enabled = clk_gpio_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
+
+/**
+ * DOC: basic clock multiplexer which can be controlled with a gpio output
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * rate - rate is only affected by parent switching.  No clk_set_rate support
+ * parent - parent is adjustable through clk_set_parent
+ */
+
+static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       return gpiod_get_value(clk->gpiod);
+}
+
+static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value(clk->gpiod, index);
+
+       return 0;
+}
+
+const struct clk_ops clk_gpio_mux_ops = {
+       .get_parent = clk_gpio_mux_get_parent,
+       .set_parent = clk_gpio_mux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
+
+static struct clk *clk_register_gpio(struct device *dev, const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low, unsigned long flags,
+               const struct clk_ops *clk_gpio_ops)
+{
+       struct clk_gpio *clk_gpio;
+       struct clk *clk;
+       struct clk_init_data init = {};
+       unsigned long gpio_flags;
+       int err;
+
+       if (dev)
+               clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio), GFP_KERNEL);
+       else
+               clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL);
+
+       if (!clk_gpio)
+               return ERR_PTR(-ENOMEM);
+
+       if (active_low)
+               gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
+       else
+               gpio_flags = GPIOF_OUT_INIT_LOW;
+
+       if (dev)
+               err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
+       else
+               err = gpio_request_one(gpio, gpio_flags, name);
+       if (err) {
+               if (err != -EPROBE_DEFER)
+                       pr_err("%s: %s: Error requesting clock control gpio %u\n",
+                                       __func__, name, gpio);
+               if (!dev)
+                       kfree(clk_gpio);
+
+               return ERR_PTR(err);
+       }
+
+       init.name = name;
+       init.ops = clk_gpio_ops;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+
+       clk_gpio->gpiod = gpio_to_desc(gpio);
+       clk_gpio->hw.init = &init;
+
+       if (dev)
+               clk = devm_clk_register(dev, &clk_gpio->hw);
+       else
+               clk = clk_register(NULL, &clk_gpio->hw);
+
+       if (!IS_ERR(clk))
+               return clk;
+
+       if (!dev) {
+               gpiod_put(clk_gpio->gpiod);
+               kfree(clk_gpio);
+       }
+
+       return clk;
+}
+
+/**
+ * clk_register_gpio_gate - register a gpio clock gate with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of this clock's parent
+ * @gpio: gpio number to gate this clock
+ * @active_low: true if gpio should be set to 0 to enable clock
+ * @flags: clock flags
+ */
+struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
+               const char *parent_name, unsigned gpio, bool active_low,
+               unsigned long flags)
+{
+       return clk_register_gpio(dev, name,
+                       (parent_name ? &parent_name : NULL),
+                       (parent_name ? 1 : 0), gpio, active_low, flags,
+                       &clk_gpio_gate_ops);
+}
+EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
+
+/**
+ * clk_register_gpio_mux - register a gpio clock mux with the clock framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_names: names of this clock's parents
+ * @num_parents: number of parents listed in @parent_names
+ * @gpio: gpio number to gate this clock
+ * @active_low: true if gpio should be set to 0 to enable clock
+ * @flags: clock flags
+ */
+struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low, unsigned long flags)
+{
+       if (num_parents != 2) {
+               pr_err("mux-clock %s must have 2 parents\n", name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return clk_register_gpio(dev, name, parent_names, num_parents,
+                       gpio, active_low, flags, &clk_gpio_mux_ops);
+}
+EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
+
+#ifdef CONFIG_OF
+/**
+ * clk_register_get() has to be delayed, because -EPROBE_DEFER
+ * can not be handled properly at of_clk_init() call time.
+ */
+
+struct clk_gpio_delayed_register_data {
+       const char *gpio_name;
+       struct device_node *node;
+       struct mutex lock;
+       struct clk *clk;
+       struct clk *(*clk_register_get)(const char *name,
+                       const char * const *parent_names, u8 num_parents,
+                       unsigned gpio, bool active_low);
+};
+
+static struct clk *of_clk_gpio_delayed_register_get(
+               struct of_phandle_args *clkspec, void *_data)
+{
+       struct clk_gpio_delayed_register_data *data = _data;
+       struct clk *clk;
+       const char **parent_names;
+       int i, num_parents;
+       int gpio;
+       enum of_gpio_flags of_flags;
+
+       mutex_lock(&data->lock);
+
+       if (data->clk) {
+               mutex_unlock(&data->lock);
+               return data->clk;
+       }
+
+       gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0,
+                       &of_flags);
+       if (gpio < 0) {
+               mutex_unlock(&data->lock);
+               if (gpio == -EPROBE_DEFER)
+                       pr_debug("%s: %s: GPIOs not yet available, retry later\n",
+                                       data->node->name, __func__);
+               else
+                       pr_err("%s: %s: Can't get '%s' DT property\n",
+                                       data->node->name, __func__,
+                                       data->gpio_name);
+               return ERR_PTR(gpio);
+       }
+
+       num_parents = of_clk_get_parent_count(data->node);
+
+       parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+       if (!parent_names) {
+               clk = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
+       for (i = 0; i < num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(data->node, i);
+
+       clk = data->clk_register_get(data->node->name, parent_names,
+                       num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
+       if (IS_ERR(clk))
+               goto out;
+
+       data->clk = clk;
+out:
+       mutex_unlock(&data->lock);
+       kfree(parent_names);
+
+       return clk;
+}
+
+static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name,
+               const char * const *parent_names, u8 num_parents,
+               unsigned gpio, bool active_low)
+{
+       return clk_register_gpio_gate(NULL, name, parent_names[0],
+                       gpio, active_low, 0);
+}
+
+static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low)
+{
+       return clk_register_gpio_mux(NULL, name, parent_names, num_parents,
+                       gpio, active_low, 0);
+}
+
+static void __init of_gpio_clk_setup(struct device_node *node,
+               const char *gpio_name,
+               struct clk *(*clk_register_get)(const char *name,
+                               const char * const *parent_names,
+                               u8 num_parents,
+                               unsigned gpio, bool active_low))
+{
+       struct clk_gpio_delayed_register_data *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return;
+
+       data->node = node;
+       data->gpio_name = gpio_name;
+       data->clk_register_get = clk_register_get;
+       mutex_init(&data->lock);
+
+       of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data);
+}
+
+static void __init of_gpio_gate_clk_setup(struct device_node *node)
+{
+       of_gpio_clk_setup(node, "enable-gpios",
+               of_clk_gpio_gate_delayed_register_get);
+}
+CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
+
+void __init of_gpio_mux_clk_setup(struct device_node *node)
+{
+       of_gpio_clk_setup(node, "select-gpios",
+               of_clk_gpio_mux_delayed_register_get);
+}
+CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup);
+#endif
index 2e7e9d9798cb20901cc2dd234c33ef6d306dc966..be3a21abb185a188e207d8dd35cb8146293779a0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 5181b89c3cb2f18de2047a70a0bc43c562be4326..f37f719643ec0633552c16f310be264fae97c124 100644 (file)
@@ -10,6 +10,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
index 6066a01b20ea8d0e304dca2ff27bc34da9e0bf1c..7129c86a79dbfa679fa6dd707dab70aad9821324 100644 (file)
@@ -10,7 +10,6 @@
  * Simple multiplexer clock implementation
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -32,7 +31,7 @@
 static u8 clk_mux_get_parent(struct clk_hw *hw)
 {
        struct clk_mux *mux = to_clk_mux(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
        /*
@@ -85,6 +84,8 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 
        if (mux->lock)
                spin_lock_irqsave(mux->lock, flags);
+       else
+               __acquire(mux->lock);
 
        if (mux->flags & CLK_MUX_HIWORD_MASK) {
                val = mux->mask << (mux->shift + 16);
@@ -97,6 +98,8 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
 
        if (mux->lock)
                spin_unlock_irqrestore(mux->lock, flags);
+       else
+               __release(mux->lock);
 
        return 0;
 }
index c9487179f25f46d79e511ace153e3a3e7078e49e..e4d8a991c58fa3972d414810e634ec5c72fb0c9a 100644 (file)
@@ -8,8 +8,7 @@
 #define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
 
 #include <linux/bitops.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk-provider.h>
index 45a535ab48aaa1cf443d4467f42734b7949b1b47..8e3039f0c3f9544de39bc8c06be41a2337b8492a 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/palmas.h>
 #include <linux/module.h>
index 83902b9cd49ef0a5772e807806999a1d16786195..0fee2f4ca258365bfa48a183c5712e7696e3b306 100644 (file)
@@ -15,7 +15,6 @@
  * more details.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 9b13a303d3f81e432f6ddac4ffe85dd27d4c8f82..d266299dfdb1a26e22477f78a2c389d5dc858f4f 100644 (file)
@@ -58,21 +58,17 @@ static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
 static int s2mps11_clk_prepare(struct clk_hw *hw)
 {
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
-       int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
+       return regmap_update_bits(s2mps11->iodev->regmap_pmic,
                                 s2mps11->reg,
                                 s2mps11->mask, s2mps11->mask);
-
-       return ret;
 }
 
 static void s2mps11_clk_unprepare(struct clk_hw *hw)
 {
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
-       int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
+       regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
                           s2mps11->mask, ~s2mps11->mask);
 }
 
@@ -186,15 +182,15 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
        struct clk_init_data *clks_init;
        int i, ret = 0;
 
-       s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
-                                       S2MPS11_CLKS_NUM, GFP_KERNEL);
+       s2mps11_clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
+                               sizeof(*s2mps11_clk), GFP_KERNEL);
        if (!s2mps11_clks)
                return -ENOMEM;
 
        s2mps11_clk = s2mps11_clks;
 
-       clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
-                                S2MPS11_CLKS_NUM, GFP_KERNEL);
+       clk_table = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM,
+                               sizeof(struct clk *), GFP_KERNEL);
        if (!clk_table)
                return -ENOMEM;
 
@@ -246,7 +242,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                                        s2mps11_name(s2mps11_clk), NULL);
                if (!s2mps11_clk->lookup) {
                        ret = -ENOMEM;
-                       goto err_lup;
+                       goto err_reg;
                }
        }
 
@@ -265,16 +261,10 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, s2mps11_clks);
 
        return ret;
-err_lup:
-       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
+
 err_reg:
-       while (s2mps11_clk > s2mps11_clks) {
-               if (s2mps11_clk->lookup) {
-                       clkdev_drop(s2mps11_clk->lookup);
-                       devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
-               }
-               s2mps11_clk--;
-       }
+       while (--i >= 0)
+               clkdev_drop(s2mps11_clks[i].lookup);
 
        return ret;
 }
@@ -322,7 +312,7 @@ static int __init s2mps11_clk_init(void)
 }
 subsys_initcall(s2mps11_clk_init);
 
-static void __init s2mps11_clk_cleanup(void)
+static void __exit s2mps11_clk_cleanup(void)
 {
        platform_driver_unregister(&s2mps11_clk_driver);
 }
index e39e1e680b3c6c09b117e7a32a35b7d1a808bf37..5596c0aac22f8f4f1a639d6e3cf01ad92c7e0df4 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/clkdev.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -439,7 +439,7 @@ static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                parent_rate, (unsigned long)rate);
 
@@ -497,7 +497,7 @@ static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), a, b, c,
+               __func__, clk_hw_get_name(hw), a, b, c,
                *parent_rate, rate);
 
        return rate;
@@ -521,7 +521,7 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                parent_rate, rate);
 
@@ -632,7 +632,7 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, m = %lu, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                m, parent_rate, (unsigned long)rate);
 
@@ -663,7 +663,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
                divby4 = 1;
 
        /* multisync can set pll */
-       if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                /*
                 * find largest integer divider for max
                 * vco frequency and given target rate
@@ -745,7 +745,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), a, b, c, divby4,
+               __func__, clk_hw_get_name(hw), a, b, c, divby4,
                *parent_rate, rate);
 
        return rate;
@@ -777,7 +777,7 @@ static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk),
+               __func__, clk_hw_get_name(hw),
                hwdata->params.p1, hwdata->params.p2, hwdata->params.p3,
                divby4, parent_rate, rate);
 
@@ -1013,7 +1013,7 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
                rate = SI5351_CLKOUT_MIN_FREQ;
 
        /* request frequency if multisync master */
-       if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                /* use r divider for frequencies below 1MHz */
                rdiv = SI5351_OUTPUT_CLK_DIV_1;
                while (rate < SI5351_MULTISYNTH_MIN_FREQ &&
@@ -1042,7 +1042,7 @@ static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
+               __func__, clk_hw_get_name(hw), (1 << rdiv),
                *parent_rate, rate);
 
        return rate;
@@ -1093,7 +1093,7 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
-               __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
+               __func__, clk_hw_get_name(hw), (1 << rdiv),
                parent_rate, rate);
 
        return 0;
index 20a5aec98b1a2ca1b88560ccd0336d75073c4bed..cf478aa9fa5d9e9b791d6fc9cd32ffaa1864d10a 100644 (file)
@@ -19,6 +19,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index 3f6f7ad39490458a6e9cdcf4d944665abd34df86..fd89e771107eadfcb3b319f67f65eb16773bb654 100644 (file)
@@ -175,11 +175,10 @@ static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
        if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
                mult = 2;
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                unsigned long best_parent = rate / mult;
 
-               *prate =
-                   __clk_round_rate(__clk_get_parent(hw->clk), best_parent);
+               *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
        }
 
        return *prate * mult;
index 4a755135bcd388433696ee4c651a5bbb03302f5b..8e5ed649a0986721a1fcad1a9038ccb5b0c1e73d 100644 (file)
@@ -20,7 +20,6 @@
 *
 */
 
-#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
@@ -91,7 +90,7 @@ static int twl6040_clk_probe(struct platform_device *pdev)
        clkdata->twl6040 = twl6040;
 
        clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
-       clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+       clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
        if (IS_ERR(clkdata->clk))
                return PTR_ERR(clkdata->clk);
 
@@ -100,21 +99,11 @@ static int twl6040_clk_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int twl6040_clk_remove(struct platform_device *pdev)
-{
-       struct twl6040_clk *clkdata = platform_get_drvdata(pdev);
-
-       clk_unregister(clkdata->clk);
-
-       return 0;
-}
-
 static struct platform_driver twl6040_clk_driver = {
        .driver = {
                .name = "twl6040-clk",
        },
        .probe = twl6040_clk_probe,
-       .remove = twl6040_clk_remove,
 };
 
 module_platform_driver(twl6040_clk_driver);
index 18bf5e576b9390c680b4e9a08637104cb07cdde4..95d1742dac309fe43036b0d926e3b516a23a7822 100644 (file)
@@ -5,8 +5,8 @@
  * Author: Linus Walleij <linus.walleij@stericsson.com>
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  */
-#include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk-provider.h>
index ef67719f4e52c23cd977844662e3a202be4963bc..43f9d15255f4fd3a902b9ead2ccdc67d6e61fac4 100644 (file)
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/module.h>
index f26b3ac36b27a1aa06fd7db2b3352420f96c7768..96a6190acac230844d7c3588754d4280dc6d8f0e 100644 (file)
@@ -60,7 +60,6 @@ enum xgene_pll_type {
 
 struct xgene_clk_pll {
        struct clk_hw   hw;
-       const char      *name;
        void __iomem    *reg;
        spinlock_t      *lock;
        u32             pll_offset;
@@ -75,7 +74,7 @@ static int xgene_clk_pll_is_enabled(struct clk_hw *hw)
        u32 data;
 
        data = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
-       pr_debug("%s pll %s\n", pllclk->name,
+       pr_debug("%s pll %s\n", clk_hw_get_name(hw),
                data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled");
 
        return data & REGSPEC_RESET_F1_MASK ? 0 : 1;
@@ -113,7 +112,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
                fref = parent_rate / nref;
                fvco = fref * nfb;
        }
-       pr_debug("%s pll recalc rate %ld parent %ld\n", pllclk->name,
+       pr_debug("%s pll recalc rate %ld parent %ld\n", clk_hw_get_name(hw),
                fvco / nout, parent_rate);
 
        return fvco / nout;
@@ -146,7 +145,6 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
 
-       apmclk->name = name;
        apmclk->reg = reg;
        apmclk->lock = lock;
        apmclk->pll_offset = pll_offset;
@@ -210,7 +208,6 @@ struct xgene_dev_parameters {
 
 struct xgene_clk {
        struct clk_hw   hw;
-       const char      *name;
        spinlock_t      *lock;
        struct xgene_dev_parameters     param;
 };
@@ -228,7 +225,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
                spin_lock_irqsave(pclk->lock, flags);
 
        if (pclk->param.csr_reg != NULL) {
-               pr_debug("%s clock enabled\n", pclk->name);
+               pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
                reg = __pa(pclk->param.csr_reg);
                /* First enable the clock */
                data = xgene_clk_read(pclk->param.csr_reg +
@@ -237,7 +234,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
                xgene_clk_write(data, pclk->param.csr_reg +
                                        pclk->param.reg_clk_offset);
                pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
-                       pclk->name, &reg,
+                       clk_hw_get_name(hw), &reg,
                        pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
                        data);
 
@@ -248,7 +245,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
                xgene_clk_write(data, pclk->param.csr_reg +
                                        pclk->param.reg_csr_offset);
                pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
-                       pclk->name, &reg,
+                       clk_hw_get_name(hw), &reg,
                        pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
                        data);
        }
@@ -269,7 +266,7 @@ static void xgene_clk_disable(struct clk_hw *hw)
                spin_lock_irqsave(pclk->lock, flags);
 
        if (pclk->param.csr_reg != NULL) {
-               pr_debug("%s clock disabled\n", pclk->name);
+               pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
                /* First put the CSR in reset */
                data = xgene_clk_read(pclk->param.csr_reg +
                                        pclk->param.reg_csr_offset);
@@ -295,10 +292,10 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
        u32 data = 0;
 
        if (pclk->param.csr_reg != NULL) {
-               pr_debug("%s clock checking\n", pclk->name);
+               pr_debug("%s clock checking\n", clk_hw_get_name(hw));
                data = xgene_clk_read(pclk->param.csr_reg +
                                        pclk->param.reg_clk_offset);
-               pr_debug("%s clock is %s\n", pclk->name,
+               pr_debug("%s clock is %s\n", clk_hw_get_name(hw),
                        data & pclk->param.reg_clk_mask ? "enabled" :
                                                        "disabled");
        }
@@ -321,11 +318,13 @@ static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw,
                data &= (1 << pclk->param.reg_divider_width) - 1;
 
                pr_debug("%s clock recalc rate %ld parent %ld\n",
-                       pclk->name, parent_rate / data, parent_rate);
+                       clk_hw_get_name(hw),
+                       parent_rate / data, parent_rate);
+
                return parent_rate / data;
        } else {
                pr_debug("%s clock recalc rate %ld parent %ld\n",
-                       pclk->name, parent_rate, parent_rate);
+                       clk_hw_get_name(hw), parent_rate, parent_rate);
                return parent_rate;
        }
 }
@@ -357,7 +356,7 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
                data |= divider;
                xgene_clk_write(data, pclk->param.divider_reg +
                                        pclk->param.reg_divider_offset);
-               pr_debug("%s clock set rate %ld\n", pclk->name,
+               pr_debug("%s clock set rate %ld\n", clk_hw_get_name(hw),
                        parent_rate / divider_save);
        } else {
                divider_save = 1;
@@ -419,7 +418,6 @@ static struct clk *xgene_register_clk(struct device *dev,
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
 
-       apmclk->name = name;
        apmclk->lock = lock;
        apmclk->hw.init = &init;
        apmclk->param = *parameters;
index ddb4b541016fe986860a95a4a482d2f6c6713a3e..43e2c3ad6c3111ae6d0a83f027b75344c087f5f2 100644 (file)
@@ -9,6 +9,7 @@
  * Standard functionality for the common clock API.  See Documentation/clk.txt
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/module.h>
@@ -56,8 +57,11 @@ struct clk_core {
        struct clk_core         *new_parent;
        struct clk_core         *new_child;
        unsigned long           flags;
+       bool                    orphan;
        unsigned int            enable_count;
        unsigned int            prepare_count;
+       unsigned long           min_rate;
+       unsigned long           max_rate;
        unsigned long           accuracy;
        int                     phase;
        struct hlist_head       children;
@@ -111,12 +115,14 @@ static void clk_prepare_unlock(void)
 }
 
 static unsigned long clk_enable_lock(void)
+       __acquires(enable_lock)
 {
        unsigned long flags;
 
        if (!spin_trylock_irqsave(&enable_lock, flags)) {
                if (enable_owner == current) {
                        enable_refcnt++;
+                       __acquire(enable_lock);
                        return flags;
                }
                spin_lock_irqsave(&enable_lock, flags);
@@ -129,12 +135,15 @@ static unsigned long clk_enable_lock(void)
 }
 
 static void clk_enable_unlock(unsigned long flags)
+       __releases(enable_lock)
 {
        WARN_ON_ONCE(enable_owner != current);
        WARN_ON_ONCE(enable_refcnt == 0);
 
-       if (--enable_refcnt)
+       if (--enable_refcnt) {
+               __release(enable_lock);
                return;
+       }
        enable_owner = NULL;
        spin_unlock_irqrestore(&enable_lock, flags);
 }
@@ -269,27 +278,29 @@ const char *__clk_get_name(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_name);
 
+const char *clk_hw_get_name(const struct clk_hw *hw)
+{
+       return hw->core->name;
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_name);
+
 struct clk_hw *__clk_get_hw(struct clk *clk)
 {
        return !clk ? NULL : clk->core->hw;
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
-u8 __clk_get_num_parents(struct clk *clk)
+unsigned int clk_hw_get_num_parents(const struct clk_hw *hw)
 {
-       return !clk ? 0 : clk->core->num_parents;
+       return hw->core->num_parents;
 }
-EXPORT_SYMBOL_GPL(__clk_get_num_parents);
+EXPORT_SYMBOL_GPL(clk_hw_get_num_parents);
 
-struct clk *__clk_get_parent(struct clk *clk)
+struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw)
 {
-       if (!clk)
-               return NULL;
-
-       /* TODO: Create a per-user clk and change callers to call clk_put */
-       return !clk->core->parent ? NULL : clk->core->parent->hw->clk;
+       return hw->core->parent ? hw->core->parent->hw : NULL;
 }
-EXPORT_SYMBOL_GPL(__clk_get_parent);
+EXPORT_SYMBOL_GPL(clk_hw_get_parent);
 
 static struct clk_core *__clk_lookup_subtree(const char *name,
                                             struct clk_core *core)
@@ -348,18 +359,16 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
                return core->parents[index];
 }
 
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+struct clk_hw *
+clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
 {
        struct clk_core *parent;
 
-       if (!clk)
-               return NULL;
-
-       parent = clk_core_get_parent_by_index(clk->core, index);
+       parent = clk_core_get_parent_by_index(hw->core, index);
 
-       return !parent ? NULL : parent->hw->clk;
+       return !parent ? NULL : parent->hw;
 }
-EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
+EXPORT_SYMBOL_GPL(clk_hw_get_parent_by_index);
 
 unsigned int __clk_get_enable_count(struct clk *clk)
 {
@@ -387,14 +396,11 @@ out:
        return ret;
 }
 
-unsigned long __clk_get_rate(struct clk *clk)
+unsigned long clk_hw_get_rate(const struct clk_hw *hw)
 {
-       if (!clk)
-               return 0;
-
-       return clk_core_get_rate_nolock(clk->core);
+       return clk_core_get_rate_nolock(hw->core);
 }
-EXPORT_SYMBOL_GPL(__clk_get_rate);
+EXPORT_SYMBOL_GPL(clk_hw_get_rate);
 
 static unsigned long __clk_get_accuracy(struct clk_core *core)
 {
@@ -410,12 +416,15 @@ unsigned long __clk_get_flags(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-bool __clk_is_prepared(struct clk *clk)
+unsigned long clk_hw_get_flags(const struct clk_hw *hw)
 {
-       if (!clk)
-               return false;
+       return hw->core->flags;
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_flags);
 
-       return clk_core_is_prepared(clk->core);
+bool clk_hw_is_prepared(const struct clk_hw *hw)
+{
+       return clk_core_is_prepared(hw->core);
 }
 
 bool __clk_is_enabled(struct clk *clk)
@@ -436,28 +445,31 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
        return now <= rate && now > best;
 }
 
-static long
-clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
-                            unsigned long min_rate,
-                            unsigned long max_rate,
-                            unsigned long *best_parent_rate,
-                            struct clk_hw **best_parent_p,
+static int
+clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req,
                             unsigned long flags)
 {
        struct clk_core *core = hw->core, *parent, *best_parent = NULL;
-       int i, num_parents;
-       unsigned long parent_rate, best = 0;
+       int i, num_parents, ret;
+       unsigned long best = 0;
+       struct clk_rate_request parent_req = *req;
 
        /* if NO_REPARENT flag set, pass through to current parent */
        if (core->flags & CLK_SET_RATE_NO_REPARENT) {
                parent = core->parent;
-               if (core->flags & CLK_SET_RATE_PARENT)
-                       best = __clk_determine_rate(parent ? parent->hw : NULL,
-                                                   rate, min_rate, max_rate);
-               else if (parent)
+               if (core->flags & CLK_SET_RATE_PARENT) {
+                       ret = __clk_determine_rate(parent ? parent->hw : NULL,
+                                                  &parent_req);
+                       if (ret)
+                               return ret;
+
+                       best = parent_req.rate;
+               } else if (parent) {
                        best = clk_core_get_rate_nolock(parent);
-               else
+               } else {
                        best = clk_core_get_rate_nolock(core);
+               }
+
                goto out;
        }
 
@@ -467,24 +479,33 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
                parent = clk_core_get_parent_by_index(core, i);
                if (!parent)
                        continue;
-               if (core->flags & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_determine_rate(parent->hw, rate,
-                                                          min_rate,
-                                                          max_rate);
-               else
-                       parent_rate = clk_core_get_rate_nolock(parent);
-               if (mux_is_better_rate(rate, parent_rate, best, flags)) {
+
+               if (core->flags & CLK_SET_RATE_PARENT) {
+                       parent_req = *req;
+                       ret = __clk_determine_rate(parent->hw, &parent_req);
+                       if (ret)
+                               continue;
+               } else {
+                       parent_req.rate = clk_core_get_rate_nolock(parent);
+               }
+
+               if (mux_is_better_rate(req->rate, parent_req.rate,
+                                      best, flags)) {
                        best_parent = parent;
-                       best = parent_rate;
+                       best = parent_req.rate;
                }
        }
 
+       if (!best_parent)
+               return -EINVAL;
+
 out:
        if (best_parent)
-               *best_parent_p = best_parent->hw;
-       *best_parent_rate = best;
+               req->best_parent_hw = best_parent->hw;
+       req->best_parent_rate = best;
+       req->rate = best;
 
-       return best;
+       return 0;
 }
 
 struct clk *__clk_lookup(const char *name)
@@ -500,8 +521,8 @@ static void clk_core_get_boundaries(struct clk_core *core,
 {
        struct clk *clk_user;
 
-       *min_rate = 0;
-       *max_rate = ULONG_MAX;
+       *min_rate = core->min_rate;
+       *max_rate = core->max_rate;
 
        hlist_for_each_entry(clk_user, &core->clks, clks_node)
                *min_rate = max(*min_rate, clk_user->min_rate);
@@ -510,33 +531,30 @@ static void clk_core_get_boundaries(struct clk_core *core,
                *max_rate = min(*max_rate, clk_user->max_rate);
 }
 
+void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
+                          unsigned long max_rate)
+{
+       hw->core->min_rate = min_rate;
+       hw->core->max_rate = max_rate;
+}
+EXPORT_SYMBOL_GPL(clk_hw_set_rate_range);
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
  * complex clock that may combine a mux with other operations.
  */
-long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p)
+int __clk_mux_determine_rate(struct clk_hw *hw,
+                            struct clk_rate_request *req)
 {
-       return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
-                                           best_parent_rate,
-                                           best_parent_p, 0);
+       return clk_mux_determine_rate_flags(hw, req, 0);
 }
 EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
 
-long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p)
+int __clk_mux_determine_rate_closest(struct clk_hw *hw,
+                                    struct clk_rate_request *req)
 {
-       return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
-                                           best_parent_rate,
-                                           best_parent_p,
-                                           CLK_MUX_ROUND_CLOSEST);
+       return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
 }
 EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
 
@@ -759,14 +777,11 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
-static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
-                                               unsigned long rate,
-                                               unsigned long min_rate,
-                                               unsigned long max_rate)
+static int clk_core_round_rate_nolock(struct clk_core *core,
+                                     struct clk_rate_request *req)
 {
-       unsigned long parent_rate = 0;
        struct clk_core *parent;
-       struct clk_hw *parent_hw;
+       long rate;
 
        lockdep_assert_held(&prepare_lock);
 
@@ -774,21 +789,30 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
                return 0;
 
        parent = core->parent;
-       if (parent)
-               parent_rate = parent->rate;
+       if (parent) {
+               req->best_parent_hw = parent->hw;
+               req->best_parent_rate = parent->rate;
+       } else {
+               req->best_parent_hw = NULL;
+               req->best_parent_rate = 0;
+       }
 
        if (core->ops->determine_rate) {
-               parent_hw = parent ? parent->hw : NULL;
-               return core->ops->determine_rate(core->hw, rate,
-                                               min_rate, max_rate,
-                                               &parent_rate, &parent_hw);
-       } else if (core->ops->round_rate)
-               return core->ops->round_rate(core->hw, rate, &parent_rate);
-       else if (core->flags & CLK_SET_RATE_PARENT)
-               return clk_core_round_rate_nolock(core->parent, rate, min_rate,
-                                                 max_rate);
-       else
-               return core->rate;
+               return core->ops->determine_rate(core->hw, req);
+       } else if (core->ops->round_rate) {
+               rate = core->ops->round_rate(core->hw, req->rate,
+                                            &req->best_parent_rate);
+               if (rate < 0)
+                       return rate;
+
+               req->rate = rate;
+       } else if (core->flags & CLK_SET_RATE_PARENT) {
+               return clk_core_round_rate_nolock(parent, req);
+       } else {
+               req->rate = core->rate;
+       }
+
+       return 0;
 }
 
 /**
@@ -800,38 +824,32 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
  *
  * Useful for clk_ops such as .set_rate and .determine_rate.
  */
-unsigned long __clk_determine_rate(struct clk_hw *hw,
-                                  unsigned long rate,
-                                  unsigned long min_rate,
-                                  unsigned long max_rate)
+int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
-       if (!hw)
+       if (!hw) {
+               req->rate = 0;
                return 0;
+       }
 
-       return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+       return clk_core_round_rate_nolock(hw->core, req);
 }
 EXPORT_SYMBOL_GPL(__clk_determine_rate);
 
-/**
- * __clk_round_rate - round the given rate for a clk
- * @clk: round the rate of this clock
- * @rate: the rate which is to be rounded
- *
- * Useful for clk_ops such as .set_rate
- */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
 {
-       unsigned long min_rate;
-       unsigned long max_rate;
+       int ret;
+       struct clk_rate_request req;
 
-       if (!clk)
-               return 0;
+       clk_core_get_boundaries(hw->core, &req.min_rate, &req.max_rate);
+       req.rate = rate;
 
-       clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+       ret = clk_core_round_rate_nolock(hw->core, &req);
+       if (ret)
+               return 0;
 
-       return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
+       return req.rate;
 }
-EXPORT_SYMBOL_GPL(__clk_round_rate);
+EXPORT_SYMBOL_GPL(clk_hw_round_rate);
 
 /**
  * clk_round_rate - round the given rate for a clk
@@ -844,16 +862,24 @@ EXPORT_SYMBOL_GPL(__clk_round_rate);
  */
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       unsigned long ret;
+       struct clk_rate_request req;
+       int ret;
 
        if (!clk)
                return 0;
 
        clk_prepare_lock();
-       ret = __clk_round_rate(clk, rate);
+
+       clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
+       req.rate = rate;
+
+       ret = clk_core_round_rate_nolock(clk->core, &req);
        clk_prepare_unlock();
 
-       return ret;
+       if (ret)
+               return ret;
+
+       return req.rate;
 }
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
@@ -1064,18 +1090,40 @@ static int clk_fetch_parent_index(struct clk_core *core,
        return -EINVAL;
 }
 
+/*
+ * Update the orphan status of @core and all its children.
+ */
+static void clk_core_update_orphan_status(struct clk_core *core, bool is_orphan)
+{
+       struct clk_core *child;
+
+       core->orphan = is_orphan;
+
+       hlist_for_each_entry(child, &core->children, child_node)
+               clk_core_update_orphan_status(child, is_orphan);
+}
+
 static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
 {
+       bool was_orphan = core->orphan;
+
        hlist_del(&core->child_node);
 
        if (new_parent) {
+               bool becomes_orphan = new_parent->orphan;
+
                /* avoid duplicate POST_RATE_CHANGE notifications */
                if (new_parent->new_child == core)
                        new_parent->new_child = NULL;
 
                hlist_add_head(&core->child_node, &new_parent->children);
+
+               if (was_orphan != becomes_orphan)
+                       clk_core_update_orphan_status(core, becomes_orphan);
        } else {
                hlist_add_head(&core->child_node, &clk_orphan_list);
+               if (!was_orphan)
+                       clk_core_update_orphan_status(core, true);
        }
 
        core->parent = new_parent;
@@ -1160,14 +1208,8 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
                flags = clk_enable_lock();
                clk_reparent(core, old_parent);
                clk_enable_unlock(flags);
+               __clk_set_parent_after(core, old_parent, parent);
 
-               if (core->prepare_count) {
-                       flags = clk_enable_lock();
-                       clk_core_disable(core);
-                       clk_core_disable(parent);
-                       clk_enable_unlock(flags);
-                       clk_core_unprepare(parent);
-               }
                return ret;
        }
 
@@ -1249,7 +1291,6 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 {
        struct clk_core *top = core;
        struct clk_core *old_parent, *parent;
-       struct clk_hw *parent_hw;
        unsigned long best_parent_rate = 0;
        unsigned long new_rate;
        unsigned long min_rate;
@@ -1270,20 +1311,29 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 
        /* find the closest rate and parent clk/rate */
        if (core->ops->determine_rate) {
-               parent_hw = parent ? parent->hw : NULL;
-               ret = core->ops->determine_rate(core->hw, rate,
-                                              min_rate,
-                                              max_rate,
-                                              &best_parent_rate,
-                                              &parent_hw);
+               struct clk_rate_request req;
+
+               req.rate = rate;
+               req.min_rate = min_rate;
+               req.max_rate = max_rate;
+               if (parent) {
+                       req.best_parent_hw = parent->hw;
+                       req.best_parent_rate = parent->rate;
+               } else {
+                       req.best_parent_hw = NULL;
+                       req.best_parent_rate = 0;
+               }
+
+               ret = core->ops->determine_rate(core->hw, &req);
                if (ret < 0)
                        return NULL;
 
-               new_rate = ret;
-               parent = parent_hw ? parent_hw->core : NULL;
+               best_parent_rate = req.best_parent_rate;
+               new_rate = req.rate;
+               parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;
        } else if (core->ops->round_rate) {
                ret = core->ops->round_rate(core->hw, rate,
-                                          &best_parent_rate);
+                                           &best_parent_rate);
                if (ret < 0)
                        return NULL;
 
@@ -1592,8 +1642,12 @@ struct clk *clk_get_parent(struct clk *clk)
 {
        struct clk *parent;
 
+       if (!clk)
+               return NULL;
+
        clk_prepare_lock();
-       parent = __clk_get_parent(clk);
+       /* TODO: Create a per-user clk and change callers to call clk_put */
+       parent = !clk->core->parent ? NULL : clk->core->parent->hw->clk;
        clk_prepare_unlock();
 
        return parent;
@@ -2324,13 +2378,17 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
         * clocks and re-parent any that are children of the clock currently
         * being clk_init'd.
         */
-       if (core->parent)
+       if (core->parent) {
                hlist_add_head(&core->child_node,
                                &core->parent->children);
-       else if (core->flags & CLK_IS_ROOT)
+               core->orphan = core->parent->orphan;
+       } else if (core->flags & CLK_IS_ROOT) {
                hlist_add_head(&core->child_node, &clk_root_list);
-       else
+               core->orphan = false;
+       } else {
                hlist_add_head(&core->child_node, &clk_orphan_list);
+               core->orphan = true;
+       }
 
        /*
         * Set clk's accuracy.  The preferred method is to use
@@ -2479,6 +2537,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
        core->hw = hw;
        core->flags = hw->init->flags;
        core->num_parents = hw->init->num_parents;
+       core->min_rate = 0;
+       core->max_rate = ULONG_MAX;
        hw->core = core;
 
        /* allocate local copy in case parent_names is __initdata */
@@ -3054,8 +3114,6 @@ struct clock_provider {
        struct list_head node;
 };
 
-static LIST_HEAD(clk_provider_list);
-
 /*
  * This function looks for a parent clock. If there is one, then it
  * checks that the provider for this parent clock was initialized, in
@@ -3106,14 +3164,24 @@ void __init of_clk_init(const struct of_device_id *matches)
        struct clock_provider *clk_provider, *next;
        bool is_init_done;
        bool force = false;
+       LIST_HEAD(clk_provider_list);
 
        if (!matches)
                matches = &__clk_of_table;
 
        /* First prepare the list of the clocks providers */
        for_each_matching_node_and_match(np, matches, &match) {
-               struct clock_provider *parent =
-                       kzalloc(sizeof(struct clock_provider),  GFP_KERNEL);
+               struct clock_provider *parent;
+
+               parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+               if (!parent) {
+                       list_for_each_entry_safe(clk_provider, next,
+                                                &clk_provider_list, node) {
+                               list_del(&clk_provider->node);
+                               kfree(clk_provider);
+                       }
+                       return;
+               }
 
                parent->clk_init_cb = match->data;
                parent->np = np;
index 56f9eba91b838d3b855678f70e6a2249cd8d67c6..1dd5d14d5dbe0f4cc6092ba535ef950440d323be 100644 (file)
@@ -4,8 +4,6 @@
  * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/of.h>
@@ -15,7 +13,7 @@ static DEFINE_SPINLOCK(clklock);
 
 static void __init h8300_div_clk_setup(struct device_node *node)
 {
-       unsigned int num_parents;
+       int num_parents;
        struct clk *clk;
        const char *clk_name = node->name;
        const char *parent_name;
index 4701b093e497f6dac1c718674423ded21b40caee..2a38eb4a25527604ec0cbd867ab5d6fbfbc4b648 100644 (file)
@@ -4,8 +4,6 @@
  * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/device.h>
@@ -28,7 +26,7 @@ static unsigned long pll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
        struct pll_clock *pll_clock = to_pll_clock(hw);
-       int mul = 1 << (ctrl_inb((unsigned long)pll_clock->pllcr) & 3);
+       int mul = 1 << (readb(pll_clock->pllcr) & 3);
 
        return parent_rate * mul;
 }
@@ -65,13 +63,13 @@ static int pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        pll = ((rate / parent_rate) / 2) & 0x03;
        spin_lock_irqsave(&clklock, flags);
-       val = ctrl_inb((unsigned long)pll_clock->sckcr);
+       val = readb(pll_clock->sckcr);
        val |= 0x08;
-       ctrl_outb(val, (unsigned long)pll_clock->sckcr);
-       val = ctrl_inb((unsigned long)pll_clock->pllcr);
+       writeb(val, pll_clock->sckcr);
+       val = readb(pll_clock->pllcr);
        val &= ~0x03;
        val |= pll;
-       ctrl_outb(val, (unsigned long)pll_clock->pllcr);
+       writeb(val, pll_clock->pllcr);
        spin_unlock_irqrestore(&clklock, flags);
        return 0;
 }
@@ -84,7 +82,7 @@ static const struct clk_ops pll_ops = {
 
 static void __init h8s2678_pll_clk_setup(struct device_node *node)
 {
-       unsigned int num_parents;
+       int num_parents;
        struct clk *clk;
        const char *clk_name = node->name;
        const char *parent_name;
@@ -98,11 +96,9 @@ static void __init h8s2678_pll_clk_setup(struct device_node *node)
        }
 
 
-       pll_clock = kzalloc(sizeof(struct pll_clock), GFP_KERNEL);
-       if (!pll_clock) {
-               pr_err("%s: failed to alloc memory", clk_name);
+       pll_clock = kzalloc(sizeof(*pll_clock), GFP_KERNEL);
+       if (!pll_clock)
                return;
-       }
 
        pll_clock->sckcr = of_iomap(node, 0);
        if (pll_clock->sckcr == NULL) {
index b4165ba75d9f8b57157647aeca04ab04cfbb3678..2c16807341dce86b386cb662aa1a52418d311665 100644 (file)
@@ -1,6 +1,6 @@
 config COMMON_CLK_HI6220
        bool "Hi6220 Clock Driver"
-       depends on ARCH_HISI || COMPILE_TEST
+       depends on (ARCH_HISI || COMPILE_TEST) && MAILBOX
        default ARCH_HISI
        help
          Build the Hisilicon Hi6220 clock driver based on the common clock framework.
index 48f0116a032a4e0b9606107e4dec92c90ff11bd0..4a1001a11f04502d1b0b003ec5a7b3785946f313 100644 (file)
@@ -7,4 +7,4 @@ obj-y   += clk.o clkgate-separated.o clkdivider-hi6220.o
 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
-obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
+obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o clk-hi6220-stub.o
index 715d34a5ef9bc766b330726493445ffb02cfbb4d..7d03fe17d66f567cae3b69ec11b9e93279ca9dc5 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include <dt-bindings/clock/hi3620-clock.h>
 
@@ -294,34 +292,29 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
        }
 }
 
-static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p)
+static int mmc_clk_determine_rate(struct clk_hw *hw,
+                                 struct clk_rate_request *req)
 {
        struct clk_mmc *mclk = to_mmc(hw);
-       unsigned long best = 0;
 
-       if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
-               rate = 13000000;
-               best = 26000000;
-       } else if (rate <= 26000000) {
-               rate = 25000000;
-               best = 180000000;
-       } else if (rate <= 52000000) {
-               rate = 50000000;
-               best = 360000000;
-       } else if (rate <= 100000000) {
-               rate = 100000000;
-               best = 720000000;
+       if ((req->rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+               req->rate = 13000000;
+               req->best_parent_rate = 26000000;
+       } else if (req->rate <= 26000000) {
+               req->rate = 25000000;
+               req->best_parent_rate = 180000000;
+       } else if (req->rate <= 52000000) {
+               req->rate = 50000000;
+               req->best_parent_rate = 360000000;
+       } else if (req->rate <= 100000000) {
+               req->rate = 100000000;
+               req->best_parent_rate = 720000000;
        } else {
                /* max is 180M */
-               rate = 180000000;
-               best = 1440000000;
+               req->rate = 180000000;
+               req->best_parent_rate = 1440000000;
        }
-       *best_parent_rate = best;
-       return rate;
+       return -EINVAL;
 }
 
 static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
diff --git a/drivers/clk/hisilicon/clk-hi6220-stub.c b/drivers/clk/hisilicon/clk-hi6220-stub.c
new file mode 100644 (file)
index 0000000..2c4add1
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * Hi6220 stub clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Author: Leo Yan <leo.yan@linaro.org>
+ *
+ * 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/clk-provider.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mailbox_client.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+/* Stub clocks id */
+#define HI6220_STUB_ACPU0              0
+#define HI6220_STUB_ACPU1              1
+#define HI6220_STUB_GPU                        2
+#define HI6220_STUB_DDR                        5
+
+/* Mailbox message */
+#define HI6220_MBOX_MSG_LEN            8
+
+#define HI6220_MBOX_FREQ               0xA
+#define HI6220_MBOX_CMD_SET            0x3
+#define HI6220_MBOX_OBJ_AP             0x0
+
+/* CPU dynamic frequency scaling */
+#define ACPU_DFS_FREQ_MAX              0x1724
+#define ACPU_DFS_CUR_FREQ              0x17CC
+#define ACPU_DFS_FLAG                  0x1B30
+#define ACPU_DFS_FREQ_REQ              0x1B34
+#define ACPU_DFS_FREQ_LMT              0x1B38
+#define ACPU_DFS_LOCK_FLAG             0xAEAEAEAE
+
+#define to_stub_clk(hw) container_of(hw, struct hi6220_stub_clk, hw)
+
+struct hi6220_stub_clk {
+       u32 id;
+
+       struct device *dev;
+       struct clk_hw hw;
+
+       struct regmap *dfs_map;
+       struct mbox_client cl;
+       struct mbox_chan *mbox;
+};
+
+struct hi6220_mbox_msg {
+       unsigned char type;
+       unsigned char cmd;
+       unsigned char obj;
+       unsigned char src;
+       unsigned char para[4];
+};
+
+union hi6220_mbox_data {
+       unsigned int data[HI6220_MBOX_MSG_LEN];
+       struct hi6220_mbox_msg msg;
+};
+
+static unsigned int hi6220_acpu_get_freq(struct hi6220_stub_clk *stub_clk)
+{
+       unsigned int freq;
+
+       regmap_read(stub_clk->dfs_map, ACPU_DFS_CUR_FREQ, &freq);
+       return freq;
+}
+
+static int hi6220_acpu_set_freq(struct hi6220_stub_clk *stub_clk,
+                               unsigned int freq)
+{
+       union hi6220_mbox_data data;
+
+       /* set the frequency in sram */
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FREQ_REQ, freq);
+
+       /* compound mailbox message */
+       data.msg.type = HI6220_MBOX_FREQ;
+       data.msg.cmd  = HI6220_MBOX_CMD_SET;
+       data.msg.obj  = HI6220_MBOX_OBJ_AP;
+       data.msg.src  = HI6220_MBOX_OBJ_AP;
+
+       mbox_send_message(stub_clk->mbox, &data);
+       return 0;
+}
+
+static int hi6220_acpu_round_freq(struct hi6220_stub_clk *stub_clk,
+                                 unsigned int freq)
+{
+       unsigned int limit_flag, limit_freq = UINT_MAX;
+       unsigned int max_freq;
+
+       /* check the constrained frequency */
+       regmap_read(stub_clk->dfs_map, ACPU_DFS_FLAG, &limit_flag);
+       if (limit_flag == ACPU_DFS_LOCK_FLAG)
+               regmap_read(stub_clk->dfs_map, ACPU_DFS_FREQ_LMT, &limit_freq);
+
+       /* check the supported maximum frequency */
+       regmap_read(stub_clk->dfs_map, ACPU_DFS_FREQ_MAX, &max_freq);
+
+       /* calculate the real maximum frequency */
+       max_freq = min(max_freq, limit_freq);
+
+       if (WARN_ON(freq > max_freq))
+               freq = max_freq;
+
+       return freq;
+}
+
+static unsigned long hi6220_stub_clk_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       u32 rate = 0;
+       struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
+
+       switch (stub_clk->id) {
+       case HI6220_STUB_ACPU0:
+               rate = hi6220_acpu_get_freq(stub_clk);
+
+               /* convert from kHz to Hz */
+               rate *= 1000;
+               break;
+
+       default:
+               dev_err(stub_clk->dev, "%s: un-supported clock id %d\n",
+                       __func__, stub_clk->id);
+               break;
+       }
+
+       return rate;
+}
+
+static int hi6220_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
+       unsigned long new_rate = rate / 1000;  /* kHz */
+       int ret = 0;
+
+       switch (stub_clk->id) {
+       case HI6220_STUB_ACPU0:
+               ret = hi6220_acpu_set_freq(stub_clk, new_rate);
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       default:
+               dev_err(stub_clk->dev, "%s: un-supported clock id %d\n",
+                       __func__, stub_clk->id);
+               break;
+       }
+
+       pr_debug("%s: set rate=%ldkHz\n", __func__, new_rate);
+       return ret;
+}
+
+static long hi6220_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *parent_rate)
+{
+       struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
+       unsigned long new_rate = rate / 1000;  /* kHz */
+
+       switch (stub_clk->id) {
+       case HI6220_STUB_ACPU0:
+               new_rate = hi6220_acpu_round_freq(stub_clk, new_rate);
+
+               /* convert from kHz to Hz */
+               new_rate *= 1000;
+               break;
+
+       default:
+               dev_err(stub_clk->dev, "%s: un-supported clock id %d\n",
+                       __func__, stub_clk->id);
+               break;
+       }
+
+       return new_rate;
+}
+
+static const struct clk_ops hi6220_stub_clk_ops = {
+       .recalc_rate    = hi6220_stub_clk_recalc_rate,
+       .round_rate     = hi6220_stub_clk_round_rate,
+       .set_rate       = hi6220_stub_clk_set_rate,
+};
+
+static int hi6220_stub_clk_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct clk_init_data init;
+       struct hi6220_stub_clk *stub_clk;
+       struct clk *clk;
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+
+       stub_clk = devm_kzalloc(dev, sizeof(*stub_clk), GFP_KERNEL);
+       if (!stub_clk)
+               return -ENOMEM;
+
+       stub_clk->dfs_map = syscon_regmap_lookup_by_phandle(np,
+                               "hisilicon,hi6220-clk-sram");
+       if (IS_ERR(stub_clk->dfs_map)) {
+               dev_err(dev, "failed to get sram regmap\n");
+               return PTR_ERR(stub_clk->dfs_map);
+       }
+
+       stub_clk->hw.init = &init;
+       stub_clk->dev = dev;
+       stub_clk->id = HI6220_STUB_ACPU0;
+
+       /* Use mailbox client with blocking mode */
+       stub_clk->cl.dev = dev;
+       stub_clk->cl.tx_done = NULL;
+       stub_clk->cl.tx_block = true;
+       stub_clk->cl.tx_tout = 500;
+       stub_clk->cl.knows_txdone = false;
+
+       /* Allocate mailbox channel */
+       stub_clk->mbox = mbox_request_channel(&stub_clk->cl, 0);
+       if (IS_ERR(stub_clk->mbox)) {
+               dev_err(dev, "failed get mailbox channel\n");
+               return PTR_ERR(stub_clk->mbox);
+       };
+
+       init.name = "acpu0";
+       init.ops = &hi6220_stub_clk_ops;
+       init.num_parents = 0;
+       init.flags = CLK_IS_ROOT;
+
+       clk = devm_clk_register(dev, &stub_clk->hw);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       if (ret) {
+               dev_err(dev, "failed to register OF clock provider\n");
+               return ret;
+       }
+
+       /* initialize buffer to zero */
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FLAG, 0x0);
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FREQ_REQ, 0x0);
+       regmap_write(stub_clk->dfs_map, ACPU_DFS_FREQ_LMT, 0x0);
+
+       dev_dbg(dev, "Registered clock '%s'\n", init.name);
+       return 0;
+}
+
+static const struct of_device_id hi6220_stub_clk_of_match[] = {
+       { .compatible = "hisilicon,hi6220-stub-clk", },
+       {}
+};
+
+static struct platform_driver hi6220_stub_clk_driver = {
+       .driver = {
+               .name = "hi6220-stub-clk",
+               .of_match_table = hi6220_stub_clk_of_match,
+       },
+       .probe = hi6220_stub_clk_probe,
+};
+
+static int __init hi6220_stub_clk_init(void)
+{
+       return platform_driver_register(&hi6220_stub_clk_driver);
+}
+subsys_initcall(hi6220_stub_clk_init);
index 132b57a0ce09473d124e4ded7c20b3626640b3a0..8ca9673083431e5229844749f4131dd8b2008c5e 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include <dt-bindings/clock/hip04-clock.h>
 
index c90a89739b033480253641db138c99afde08be6c..9f8e76676553894ee08f4718b039c6dcaac4cfc5 100644 (file)
  */
 
 #include <linux/kernel.h>
-#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
@@ -45,14 +44,9 @@ struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
        struct clk **clk_table;
        void __iomem *base;
 
-       if (np) {
-               base = of_iomap(np, 0);
-               if (!base) {
-                       pr_err("failed to map Hisilicon clock registers\n");
-                       goto err;
-               }
-       } else {
-               pr_err("failed to find Hisilicon clock node in DTS\n");
+       base = of_iomap(np, 0);
+       if (!base) {
+               pr_err("%s: failed to map clock registers\n", __func__);
                goto err;
        }
 
index b03d5a7246f9f0806b370703a8335f816915bdff..a47812f56a17bb97d5a98521b67f1ace784ad9a4 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 75fae169ce8fa6ae9e91cf0b8b0c69d14e02cc67..1ada68abb158a08a4769d31919a83f84265ef655 100644 (file)
@@ -22,5 +22,6 @@ obj-$(CONFIG_SOC_IMX5)   += clk-imx51-imx53.o
 obj-$(CONFIG_SOC_IMX6Q)  += clk-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
+obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
index c2647fa19f281eb74f65d08553bcbe823aa59979..99cf802fa51fa28d6dba3a20a7aaf48836c75da4 100644 (file)
@@ -15,7 +15,6 @@
  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
index dba987e3b89f687c6b48488b385dd781e4122b37..e63188eb08ac9d1a0794850d8766d01fd7285f2a 100644 (file)
@@ -9,7 +9,6 @@
  * of the License, or (at your option) any later version.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index fe66c40b7be2d205af090bc42cc0346ca7c5d667..1f8383475bb369cebaf431772781fb2baf692524 100644 (file)
@@ -147,7 +147,8 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
        clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[rtc_gate], NULL, "imx21-rtc");
+       clk_register_clkdev(clk[ckil], "ref", "imx21-rtc");
+       clk_register_clkdev(clk[rtc_gate], "ipg", "imx21-rtc");
        clk_register_clkdev(clk[epit1_gate], "epit", NULL);
        clk_register_clkdev(clk[epit2_gate], "epit", NULL);
        clk_register_clkdev(clk[nfc], NULL, "imx27-nand.0");
index 69138ba3dec7056cbba6e32156fa99df1b3e2690..8623cd4e49fd5b444e2be3aff9e88fe2ade83432 100644 (file)
@@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll", "arm"};
 static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"};
 
 enum mx35_clks {
-       ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
+       ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
        arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel,
        esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre,
        spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre,
@@ -107,6 +107,7 @@ int __init mx35_clocks_init(void)
        }
 
        clk[ckih] = imx_clk_fixed("ckih", 24000000);
+       clk[ckil] = imx_clk_fixed("ckih", 32768);
        clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "mpll", "ckih", base + MX35_CCM_MPCTL);
        clk[ppll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "ppll", "ckih", base + MX35_CCM_PPCTL);
 
@@ -258,6 +259,9 @@ int __init mx35_clocks_init(void)
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.1");
        clk_register_clkdev(clk[uart3_gate], "per", "imx21-uart.2");
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.2");
+       /* i.mx35 has the i.mx21 type rtc */
+       clk_register_clkdev(clk[ckil], "ref", "imx21-rtc");
+       clk_register_clkdev(clk[rtc_gate], "ipg", "imx21-rtc");
        clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
        clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
        clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.0");
index d046f8e43de8d056d1af2cb1ae4bd790019d2d9a..b2c1c047dc94586710f9dc0858846225318fac6f 100644 (file)
@@ -381,6 +381,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_ASRC]         = imx_clk_gate2_shared("asrc",         "asrc_podf",   base + 0x68, 6, &share_count_asrc);
        clk[IMX6QDL_CLK_ASRC_IPG]     = imx_clk_gate2_shared("asrc_ipg",     "ahb",         base + 0x68, 6, &share_count_asrc);
        clk[IMX6QDL_CLK_ASRC_MEM]     = imx_clk_gate2_shared("asrc_mem",     "ahb",         base + 0x68, 6, &share_count_asrc);
+       clk[IMX6QDL_CLK_CAAM_MEM]     = imx_clk_gate2("caam_mem",      "ahb",               base + 0x68, 8);
+       clk[IMX6QDL_CLK_CAAM_ACLK]    = imx_clk_gate2("caam_aclk",     "ahb",               base + 0x68, 10);
+       clk[IMX6QDL_CLK_CAAM_IPG]     = imx_clk_gate2("caam_ipg",      "ipg",               base + 0x68, 12);
        clk[IMX6QDL_CLK_CAN1_IPG]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
        clk[IMX6QDL_CLK_CAN1_SERIAL]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
        clk[IMX6QDL_CLK_CAN2_IPG]     = imx_clk_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
@@ -494,6 +497,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
        }
 
+       clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
+       if (clk_on_imx6dl())
+               clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
+
        clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
        clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
        clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
new file mode 100644 (file)
index 0000000..aaa3665
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * 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 <dt-bindings/clock/imx6ul-clock.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+#define BM_CCM_CCDR_MMDC_CH0_MASK      (0x2 << 16)
+#define CCDR   0x4
+
+static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *ca7_secondary_sels[] = { "pll2_pfd2_396m", "pll2_bus", };
+static const char *step_sels[] = { "osc", "ca7_secondary_sel", };
+static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = {"periph", "axi_alt_sel", };
+static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
+static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", };
+static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
+static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
+static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
+static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *bch_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *gpmi_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *eim_slow_sels[] =  { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd0_720m", };
+static const char *spdif_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *sai_sels[] = { "pll3_pfd2_508m", "pll5_video_div", "pll4_audio_div", };
+static const char *lcdif_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", };
+static const char *sim_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
+static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd3_454m", "dummy", "dummy", "dummy", };
+static const char *can_sels[] = { "pll3_60m", "osc", "pll3_80m", "dummy", };
+static const char *ecspi_sels[] = { "pll3_60m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "osc", };
+static const char *perclk_sels[] = { "ipg", "osc", };
+static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
+static const char *sim_sels[] = { "sim_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static struct clk *clks[IMX6UL_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int const clks_init_on[] __initconst = {
+       IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AIPSTZ3,
+       IMX6UL_CLK_AXI, IMX6UL_CLK_ARM, IMX6UL_CLK_ROM,
+       IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG,
+};
+
+static struct clk_div_table clk_enet_ref_table[] = {
+       { .val = 0, .div = 20, },
+       { .val = 1, .div = 10, },
+       { .val = 2, .div = 5, },
+       { .val = 3, .div = 4, },
+       { }
+};
+
+static struct clk_div_table post_div_table[] = {
+       { .val = 2, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 0, .div = 4, },
+       { }
+};
+
+static struct clk_div_table video_div_table[] = {
+       { .val = 0, .div = 1, },
+       { .val = 1, .div = 2, },
+       { .val = 2, .div = 1, },
+       { .val = 3, .div = 4, },
+       { }
+};
+
+static u32 share_count_asrc;
+static u32 share_count_audio;
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+
+static void __init imx6ul_clocks_init(struct device_node *ccm_node)
+{
+       struct device_node *np;
+       void __iomem *base;
+       int i;
+
+       clks[IMX6UL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+
+       clks[IMX6UL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+       clks[IMX6UL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+
+       /* ipp_di clock is external input */
+       clks[IMX6UL_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0");
+       clks[IMX6UL_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1");
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop");
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+       clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS,     "pll1", "pll1_bypass_src", base + 0x00, 0x7f);
+       clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1);
+       clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", base + 0x10, 0x3);
+       clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", base + 0x70, 0x7f);
+       clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll5", "pll5_bypass_src", base + 0xa0, 0x7f);
+       clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll6", "pll6_bypass_src", base + 0xe0, 0x3);
+       clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", base + 0x20, 0x3);
+
+       clks[IMX6UL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX6UL_CLK_CSI_SEL] = imx_clk_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
+
+       /* Do not bypass PLLs initially */
+       clk_set_parent(clks[IMX6UL_PLL1_BYPASS], clks[IMX6UL_CLK_PLL1]);
+       clk_set_parent(clks[IMX6UL_PLL2_BYPASS], clks[IMX6UL_CLK_PLL2]);
+       clk_set_parent(clks[IMX6UL_PLL3_BYPASS], clks[IMX6UL_CLK_PLL3]);
+       clk_set_parent(clks[IMX6UL_PLL4_BYPASS], clks[IMX6UL_CLK_PLL4]);
+       clk_set_parent(clks[IMX6UL_PLL5_BYPASS], clks[IMX6UL_CLK_PLL5]);
+       clk_set_parent(clks[IMX6UL_PLL6_BYPASS], clks[IMX6UL_CLK_PLL6]);
+       clk_set_parent(clks[IMX6UL_PLL7_BYPASS], clks[IMX6UL_CLK_PLL7]);
+
+       clks[IMX6UL_CLK_PLL1_SYS]       = imx_clk_fixed_factor("pll1_sys",      "pll1_bypass", 1, 1);
+       clks[IMX6UL_CLK_PLL2_BUS]       = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
+       clks[IMX6UL_CLK_PLL3_USB_OTG]   = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
+       clks[IMX6UL_CLK_PLL4_AUDIO]     = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
+       clks[IMX6UL_CLK_PLL5_VIDEO]     = imx_clk_gate("pll5_video",    "pll5_bypass", base + 0xa0, 13);
+       clks[IMX6UL_CLK_PLL6_ENET]      = imx_clk_gate("pll6_enet",     "pll6_bypass", base + 0xe0, 13);
+       clks[IMX6UL_CLK_PLL7_USB_HOST]  = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+
+       /*
+        * Bit 20 is the reserved and read-only bit, we do this only for:
+        * - Do nothing for usbphy clk_enable/disable
+        * - Keep refcount when do usbphy clk_enable/disable, in that case,
+        * the clk framework many need to enable/disable usbphy's parent
+        */
+       clks[IMX6UL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg",  base + 0x10, 20);
+       clks[IMX6UL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+
+       /*
+        * usbphy*_gate needs to be on after system boots up, and software
+        * never needs to control it anymore.
+        */
+       clks[IMX6UL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+       clks[IMX6UL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+
+       /*                                      name               parent_name     reg          idx */
+       clks[IMX6UL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
+       clks[IMX6UL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
+       clks[IMX6UL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus",     base + 0x100, 2);
+       clks[IMX6UL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus",     base + 0x100, 3);
+       clks[IMX6UL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0,  0);
+       clks[IMX6UL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0,  1);
+       clks[IMX6UL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0,  2);
+       clks[IMX6UL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0,  3);
+
+       clks[IMX6UL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+                       base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
+       clks[IMX6UL_CLK_ENET2_REF] = clk_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0,
+                       base + 0xe0, 2, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
+
+       clks[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_gate("enet_ref_125m", "enet2_ref", base + 0xe0, 20);
+       clks[IMX6UL_CLK_ENET_PTP_REF]   = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
+       clks[IMX6UL_CLK_ENET_PTP]       = imx_clk_gate("enet_ptp", "enet_ptp_ref", base + 0xe0, 21);
+
+       clks[IMX6UL_CLK_PLL4_POST_DIV]  = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX6UL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+       clks[IMX6UL_CLK_PLL5_POST_DIV]  = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+       clks[IMX6UL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
+                CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+
+       /*                                                 name         parent_name      mult  div */
+       clks[IMX6UL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1,     2);
+       clks[IMX6UL_CLK_PLL3_80M]  = imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1,     6);
+       clks[IMX6UL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1,     8);
+       clks[IMX6UL_CLK_GPT_3M]    = imx_clk_fixed_factor("gpt_3m",     "osc",           1,     8);
+
+       np = ccm_node;
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+
+       clks[IMX6UL_CA7_SECONDARY_SEL]    = imx_clk_mux("ca7_secondary_sel", base + 0xc, 3, 1, ca7_secondary_sels, ARRAY_SIZE(ca7_secondary_sels));
+       clks[IMX6UL_CLK_STEP]             = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+       clks[IMX6UL_CLK_PLL1_SW]          = imx_clk_mux_flags("pll1_sw",   base + 0x0c, 2,  1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels), 0);
+       clks[IMX6UL_CLK_AXI_ALT_SEL]      = imx_clk_mux("axi_alt_sel",          base + 0x14, 7,  1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+       clks[IMX6UL_CLK_AXI_SEL]          = imx_clk_mux_flags("axi_sel",        base + 0x14, 6,  1, axi_sels, ARRAY_SIZE(axi_sels), 0);
+       clks[IMX6UL_CLK_PERIPH_PRE]       = imx_clk_mux("periph_pre",       base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+       clks[IMX6UL_CLK_PERIPH2_PRE]      = imx_clk_mux("periph2_pre",      base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+       clks[IMX6UL_CLK_PERIPH_CLK2_SEL]  = imx_clk_mux("periph_clk2_sel",  base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+       clks[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+       clks[IMX6UL_CLK_EIM_SLOW_SEL]     = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels));
+       clks[IMX6UL_CLK_GPMI_SEL]         = imx_clk_mux("gpmi_sel",     base + 0x1c, 19, 1, gpmi_sels, ARRAY_SIZE(gpmi_sels));
+       clks[IMX6UL_CLK_BCH_SEL]          = imx_clk_mux("bch_sel",      base + 0x1c, 18, 1, bch_sels, ARRAY_SIZE(bch_sels));
+       clks[IMX6UL_CLK_USDHC2_SEL]       = imx_clk_mux("usdhc2_sel",   base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6UL_CLK_USDHC1_SEL]       = imx_clk_mux("usdhc1_sel",   base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+       clks[IMX6UL_CLK_SAI3_SEL]         = imx_clk_mux("sai3_sel",     base + 0x1c, 14, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       clks[IMX6UL_CLK_SAI2_SEL]         = imx_clk_mux("sai2_sel",     base + 0x1c, 12, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       clks[IMX6UL_CLK_SAI1_SEL]         = imx_clk_mux("sai1_sel",     base + 0x1c, 10, 2, sai_sels, ARRAY_SIZE(sai_sels));
+       clks[IMX6UL_CLK_QSPI1_SEL]        = imx_clk_mux("qspi1_sel",    base + 0x1c, 7,  3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
+       clks[IMX6UL_CLK_PERCLK_SEL]       = imx_clk_mux("perclk_sel",   base + 0x1c, 6,  1, perclk_sels, ARRAY_SIZE(perclk_sels));
+       clks[IMX6UL_CLK_CAN_SEL]          = imx_clk_mux("can_sel",      base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
+       clks[IMX6UL_CLK_UART_SEL]         = imx_clk_mux("uart_sel",     base + 0x24, 6,  1, uart_sels, ARRAY_SIZE(uart_sels));
+       clks[IMX6UL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",     base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
+       clks[IMX6UL_CLK_LDB_DI0_SEL]      = imx_clk_mux("ldb_di0_sel",  base + 0x2c, 9,  3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
+       clks[IMX6UL_CLK_SPDIF_SEL]        = imx_clk_mux("spdif_sel",    base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+       clks[IMX6UL_CLK_SIM_PRE_SEL]      = imx_clk_mux("sim_pre_sel",  base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+       clks[IMX6UL_CLK_SIM_SEL]          = imx_clk_mux("sim_sel",      base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+       clks[IMX6UL_CLK_ECSPI_SEL]        = imx_clk_mux("ecspi_sel",    base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
+       clks[IMX6UL_CLK_LCDIF_PRE_SEL]    = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
+       clks[IMX6UL_CLK_LCDIF_SEL]        = imx_clk_mux("lcdif_sel",    base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+
+       clks[IMX6UL_CLK_LDB_DI0_DIV_SEL]  = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+       clks[IMX6UL_CLK_LDB_DI1_DIV_SEL]  = imx_clk_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+
+       clks[IMX6UL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       clks[IMX6UL_CLK_LDB_DI0_DIV_7]   = imx_clk_fixed_factor("ldb_di0_div_7",   "ldb_di0_sel", 1, 7);
+       clks[IMX6UL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "qspi1_sel", 2, 7);
+       clks[IMX6UL_CLK_LDB_DI1_DIV_7]   = imx_clk_fixed_factor("ldb_di1_div_7",   "qspi1_sel", 1, 7);
+
+       clks[IMX6UL_CLK_PERIPH]  = imx_clk_busy_mux("periph",  base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+       clks[IMX6UL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+       clks[IMX6UL_CLK_PERIPH_CLK2]    = imx_clk_divider("periph_clk2",   "periph_clk2_sel",   base + 0x14, 27, 3);
+       clks[IMX6UL_CLK_PERIPH2_CLK2]   = imx_clk_divider("periph2_clk2",  "periph2_clk2_sel",  base + 0x14, 0,  3);
+       clks[IMX6UL_CLK_IPG]            = imx_clk_divider("ipg",           "ahb",               base + 0x14, 8,  2);
+       clks[IMX6UL_CLK_LCDIF_PODF]     = imx_clk_divider("lcdif_podf",    "lcdif_pred",        base + 0x18, 23, 3);
+       clks[IMX6UL_CLK_QSPI1_PDOF]     = imx_clk_divider("qspi1_podf",    "qspi1_sel",         base + 0x1c, 26, 3);
+       clks[IMX6UL_CLK_EIM_SLOW_PODF]  = imx_clk_divider("eim_slow_podf", "eim_slow_sel",      base + 0x1c, 23, 3);
+       clks[IMX6UL_CLK_PERCLK]         = imx_clk_divider("perclk",        "perclk_sel",        base + 0x1c, 0,  6);
+       clks[IMX6UL_CLK_CAN_PODF]       = imx_clk_divider("can_podf",      "can_sel",           base + 0x20, 2,  6);
+       clks[IMX6UL_CLK_GPMI_PODF]      = imx_clk_divider("gpmi_podf",     "gpmi_sel",          base + 0x24, 22, 3);
+       clks[IMX6UL_CLK_BCH_PODF]       = imx_clk_divider("bch_podf",      "bch_sel",           base + 0x24, 19, 3);
+       clks[IMX6UL_CLK_USDHC2_PODF]    = imx_clk_divider("usdhc2_podf",   "usdhc2_sel",        base + 0x24, 16, 3);
+       clks[IMX6UL_CLK_USDHC1_PODF]    = imx_clk_divider("usdhc1_podf",   "usdhc1_sel",        base + 0x24, 11, 3);
+       clks[IMX6UL_CLK_UART_PODF]      = imx_clk_divider("uart_podf",     "uart_sel",          base + 0x24, 0,  6);
+       clks[IMX6UL_CLK_SAI3_PRED]      = imx_clk_divider("sai3_pred",     "sai3_sel",          base + 0x28, 22, 3);
+       clks[IMX6UL_CLK_SAI3_PODF]      = imx_clk_divider("sai3_podf",     "sai3_pred",         base + 0x28, 16, 6);
+       clks[IMX6UL_CLK_SAI1_PRED]      = imx_clk_divider("sai1_pred",     "sai1_sel",          base + 0x28, 6,  3);
+       clks[IMX6UL_CLK_SAI1_PODF]      = imx_clk_divider("sai1_podf",     "sai1_pred",         base + 0x28, 0,  6);
+       clks[IMX6UL_CLK_ENFC_PRED]      = imx_clk_divider("enfc_pred",     "enfc_sel",          base + 0x2c, 18, 3);
+       clks[IMX6UL_CLK_ENFC_PODF]      = imx_clk_divider("enfc_podf",     "enfc_pred",         base + 0x2c, 21, 6);
+       clks[IMX6UL_CLK_SAI2_PRED]      = imx_clk_divider("sai2_pred",     "sai2_sel",          base + 0x2c, 6,  3);
+       clks[IMX6UL_CLK_SAI2_PODF]      = imx_clk_divider("sai2_podf",     "sai2_pred",         base + 0x2c, 0,  6);
+       clks[IMX6UL_CLK_SPDIF_PRED]     = imx_clk_divider("spdif_pred",    "spdif_sel",         base + 0x30, 25, 3);
+       clks[IMX6UL_CLK_SPDIF_PODF]     = imx_clk_divider("spdif_podf",    "spdif_pred",        base + 0x30, 22, 3);
+       clks[IMX6UL_CLK_SIM_PODF]       = imx_clk_divider("sim_podf",      "sim_pre_sel",       base + 0x34, 12, 3);
+       clks[IMX6UL_CLK_ECSPI_PODF]     = imx_clk_divider("ecspi_podf",    "ecspi_sel",         base + 0x38, 19, 6);
+       clks[IMX6UL_CLK_LCDIF_PRED]     = imx_clk_divider("lcdif_pred",    "lcdif_pre_sel",     base + 0x38, 12, 3);
+       clks[IMX6UL_CLK_CSI_PODF]       = imx_clk_divider("csi_podf",      "csi_sel",           base + 0x3c, 11, 3);
+
+       clks[IMX6UL_CLK_ARM]            = imx_clk_busy_divider("arm",       "pll1_sw",  base +  0x10, 0,  3,  base + 0x48, 16);
+       clks[IMX6UL_CLK_MMDC_PODF]      = imx_clk_busy_divider("mmdc_podf", "periph2",  base +  0x14, 3,  3,  base + 0x48, 2);
+       clks[IMX6UL_CLK_AXI_PODF]       = imx_clk_busy_divider("axi_podf",  "axi_sel",  base +  0x14, 16, 3,  base + 0x48, 0);
+       clks[IMX6UL_CLK_AHB]            = imx_clk_busy_divider("ahb",       "periph",   base +  0x14, 10, 3,  base + 0x48, 1);
+
+       /* CCGR0 */
+       clks[IMX6UL_CLK_AIPSTZ1]        = imx_clk_gate2("aips_tz1",     "ahb",          base + 0x68,    0);
+       clks[IMX6UL_CLK_AIPSTZ2]        = imx_clk_gate2("aips_tz2",     "ahb",          base + 0x68,    2);
+       clks[IMX6UL_CLK_APBHDMA]        = imx_clk_gate2("apbh_dma",     "bch_podf",     base + 0x68,    4);
+       clks[IMX6UL_CLK_ASRC_IPG]       = imx_clk_gate2_shared("asrc_ipg",      "ahb",  base + 0x68,    6, &share_count_asrc);
+       clks[IMX6UL_CLK_ASRC_MEM]       = imx_clk_gate2_shared("asrc_mem",      "ahb",  base + 0x68,    6, &share_count_asrc);
+       clks[IMX6UL_CLK_CAAM_MEM]       = imx_clk_gate2("caam_mem",     "ahb",          base + 0x68,    8);
+       clks[IMX6UL_CLK_CAAM_ACLK]      = imx_clk_gate2("caam_aclk",    "ahb",          base + 0x68,    10);
+       clks[IMX6UL_CLK_CAAM_IPG]       = imx_clk_gate2("caam_ipg",     "ipg",          base + 0x68,    12);
+       clks[IMX6UL_CLK_CAN1_IPG]       = imx_clk_gate2("can1_ipg",     "ipg",          base + 0x68,    14);
+       clks[IMX6UL_CLK_CAN1_SERIAL]    = imx_clk_gate2("can1_serial",  "can_podf",     base + 0x68,    16);
+       clks[IMX6UL_CLK_CAN2_IPG]       = imx_clk_gate2("can2_ipg",     "ipg",          base + 0x68,    18);
+       clks[IMX6UL_CLK_CAN2_SERIAL]    = imx_clk_gate2("can2_serial",  "can_podf",     base + 0x68,    20);
+       clks[IMX6UL_CLK_GPT2_BUS]       = imx_clk_gate2("gpt_bus",      "perclk",       base + 0x68,    24);
+       clks[IMX6UL_CLK_GPT2_SERIAL]    = imx_clk_gate2("gpt_serial",   "perclk",       base + 0x68,    26);
+       clks[IMX6UL_CLK_UART2_IPG]      = imx_clk_gate2("uart2_ipg",    "ipg",          base + 0x68,    28);
+       clks[IMX6UL_CLK_UART2_SERIAL]   = imx_clk_gate2("uart2_serial", "uart_podf",    base + 0x68,    28);
+       clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",          base + 0x68,    30);
+
+       /* CCGR1 */
+       clks[IMX6UL_CLK_ECSPI1]         = imx_clk_gate2("ecspi1",       "ecspi_podf",   base + 0x6c,    0);
+       clks[IMX6UL_CLK_ECSPI2]         = imx_clk_gate2("ecspi2",       "ecspi_podf",   base + 0x6c,    2);
+       clks[IMX6UL_CLK_ECSPI3]         = imx_clk_gate2("ecspi3",       "ecspi_podf",   base + 0x6c,    4);
+       clks[IMX6UL_CLK_ECSPI4]         = imx_clk_gate2("ecspi4",       "ecspi_podf",   base + 0x6c,    6);
+       clks[IMX6UL_CLK_ADC2]           = imx_clk_gate2("adc2",         "ipg",          base + 0x6c,    8);
+       clks[IMX6UL_CLK_UART3_IPG]      = imx_clk_gate2("uart3_ipg",    "ipg",          base + 0x6c,    10);
+       clks[IMX6UL_CLK_UART3_SERIAL]   = imx_clk_gate2("uart3_serial", "uart_podf",    base + 0x6c,    10);
+       clks[IMX6UL_CLK_EPIT1]          = imx_clk_gate2("epit1",        "perclk",       base + 0x6c,    12);
+       clks[IMX6UL_CLK_EPIT2]          = imx_clk_gate2("epit2",        "perclk",       base + 0x6c,    14);
+       clks[IMX6UL_CLK_ADC1]           = imx_clk_gate2("adc1",         "ipg",          base + 0x6c,    16);
+       clks[IMX6UL_CLK_GPT1_BUS]       = imx_clk_gate2("gpt1_bus",     "perclk",       base + 0x6c,    20);
+       clks[IMX6UL_CLK_GPT1_SERIAL]    = imx_clk_gate2("gpt1_serial",  "perclk",       base + 0x6c,    22);
+       clks[IMX6UL_CLK_UART4_IPG]      = imx_clk_gate2("uart4_ipg",    "ipg",          base + 0x6c,    24);
+       clks[IMX6UL_CLK_UART4_SERIAL]   = imx_clk_gate2("uart4_serail", "uart_podf",    base + 0x6c,    24);
+
+       /* CCGR2 */
+       clks[IMX6UL_CLK_CSI]            = imx_clk_gate2("csi",          "csi_podf",             base + 0x70,    2);
+       clks[IMX6UL_CLK_I2C1]           = imx_clk_gate2("i2c1",         "perclk",       base + 0x70,    6);
+       clks[IMX6UL_CLK_I2C2]           = imx_clk_gate2("i2c2",         "perclk",       base + 0x70,    8);
+       clks[IMX6UL_CLK_I2C3]           = imx_clk_gate2("i2c3",         "perclk",       base + 0x70,    10);
+       clks[IMX6UL_CLK_OCOTP]          = imx_clk_gate2("ocotp",        "ipg",          base + 0x70,    12);
+       clks[IMX6UL_CLK_IOMUXC]         = imx_clk_gate2("iomuxc",       "lcdif_podf",   base + 0x70,    14);
+       clks[IMX6UL_CLK_LCDIF_APB]      = imx_clk_gate2("lcdif_apb",    "axi",          base + 0x70,    28);
+       clks[IMX6UL_CLK_PXP]            = imx_clk_gate2("pxp",          "axi",          base + 0x70,    30);
+
+       /* CCGR3 */
+       clks[IMX6UL_CLK_UART5_IPG]      = imx_clk_gate2("uart5_ipg",    "ipg",          base + 0x74,    2);
+       clks[IMX6UL_CLK_UART5_SERIAL]   = imx_clk_gate2("uart5_serial", "uart_podf",    base + 0x74,    2);
+       clks[IMX6UL_CLK_ENET]           = imx_clk_gate2("enet",         "ipg",          base + 0x74,    4);
+       clks[IMX6UL_CLK_ENET_AHB]       = imx_clk_gate2("enet_ahb",     "ahb",          base + 0x74,    4);
+       clks[IMX6UL_CLK_UART6_IPG]      = imx_clk_gate2("uart6_ipg",    "ipg",          base + 0x74,    6);
+       clks[IMX6UL_CLK_UART6_SERIAL]   = imx_clk_gate2("uart6_serial", "uart_podf",    base + 0x74,    6);
+       clks[IMX6UL_CLK_LCDIF_PIX]      = imx_clk_gate2("lcdif_pix",    "lcdif_podf",   base + 0x74,    10);
+       clks[IMX6UL_CLK_QSPI]           = imx_clk_gate2("qspi1",        "qspi1_podf",   base + 0x74,    14);
+       clks[IMX6UL_CLK_WDOG1]          = imx_clk_gate2("wdog1",        "ipg",          base + 0x74,    16);
+       clks[IMX6UL_CLK_MMDC_P0_FAST]   = imx_clk_gate("mmdc_p0_fast", "mmdc_podf", base + 0x74,        20);
+       clks[IMX6UL_CLK_MMDC_P0_IPG]    = imx_clk_gate2("mmdc_p0_ipg",  "ipg",          base + 0x74,    24);
+       clks[IMX6UL_CLK_AXI]            = imx_clk_gate("axi",   "axi_podf",     base + 0x74,    28);
+
+       /* CCGR4 */
+       clks[IMX6UL_CLK_PER_BCH]        = imx_clk_gate2("per_bch",      "bch_podf",     base + 0x78,    12);
+       clks[IMX6UL_CLK_PWM1]           = imx_clk_gate2("pwm1",         "perclk",       base + 0x78,    16);
+       clks[IMX6UL_CLK_PWM2]           = imx_clk_gate2("pwm2",         "perclk",       base + 0x78,    18);
+       clks[IMX6UL_CLK_PWM3]           = imx_clk_gate2("pwm3",         "perclk",       base + 0x78,    20);
+       clks[IMX6UL_CLK_PWM4]           = imx_clk_gate2("pwm4",         "perclk",       base + 0x78,    22);
+       clks[IMX6UL_CLK_GPMI_BCH_APB]   = imx_clk_gate2("gpmi_bch_apb", "bch_podf",     base + 0x78,    24);
+       clks[IMX6UL_CLK_GPMI_BCH]       = imx_clk_gate2("gpmi_bch",     "gpmi_podf",    base + 0x78,    26);
+       clks[IMX6UL_CLK_GPMI_IO]        = imx_clk_gate2("gpmi_io",      "enfc_podf",    base + 0x78,    28);
+       clks[IMX6UL_CLK_GPMI_APB]       = imx_clk_gate2("gpmi_apb",     "bch_podf",     base + 0x78,    30);
+
+       /* CCGR5 */
+       clks[IMX6UL_CLK_ROM]            = imx_clk_gate2("rom",          "ahb",          base + 0x7c,    0);
+       clks[IMX6UL_CLK_SDMA]           = imx_clk_gate2("sdma",         "ahb",          base + 0x7c,    6);
+       clks[IMX6UL_CLK_WDOG2]          = imx_clk_gate2("wdog2",        "ipg",          base + 0x7c,    10);
+       clks[IMX6UL_CLK_SPBA]           = imx_clk_gate2("spba",         "ipg",          base + 0x7c,    12);
+       clks[IMX6UL_CLK_SPDIF]          = imx_clk_gate2_shared("spdif",         "spdif_podf",   base + 0x7c,    14, &share_count_audio);
+       clks[IMX6UL_CLK_SPDIF_GCLK]     = imx_clk_gate2_shared("spdif_gclk",    "ipg",          base + 0x7c,    14, &share_count_audio);
+       clks[IMX6UL_CLK_SAI3]           = imx_clk_gate2_shared("sai3",          "sai3_podf",    base + 0x7c,    22, &share_count_sai3);
+       clks[IMX6UL_CLK_SAI3_IPG]       = imx_clk_gate2_shared("sai3_ipg",      "ipg",          base + 0x7c,    22, &share_count_sai3);
+       clks[IMX6UL_CLK_UART1_IPG]      = imx_clk_gate2("uart1_ipg",    "ipg",          base + 0x7c,    24);
+       clks[IMX6UL_CLK_UART1_SERIAL]   = imx_clk_gate2("uart1_serial", "uart_podf",    base + 0x7c,    24);
+       clks[IMX6UL_CLK_UART7_IPG]      = imx_clk_gate2("uart7_ipg",    "ipg",          base + 0x7c,    26);
+       clks[IMX6UL_CLK_UART7_SERIAL]   = imx_clk_gate2("uart7_serial", "uart_podf",    base + 0x7c,    26);
+       clks[IMX6UL_CLK_SAI1]           = imx_clk_gate2_shared("sai1",          "sai1_podf",    base + 0x7c,    28, &share_count_sai1);
+       clks[IMX6UL_CLK_SAI1_IPG]       = imx_clk_gate2_shared("sai1_ipg",      "ipg",          base + 0x7c,    28, &share_count_sai1);
+       clks[IMX6UL_CLK_SAI2]           = imx_clk_gate2_shared("sai2",          "sai2_podf",    base + 0x7c,    30, &share_count_sai2);
+       clks[IMX6UL_CLK_SAI2_IPG]       = imx_clk_gate2_shared("sai2_ipg",      "ipg",          base + 0x7c,    30, &share_count_sai2);
+
+       /* CCGR6 */
+       clks[IMX6UL_CLK_USBOH3]         = imx_clk_gate2("usboh3",       "ipg",           base + 0x80,   0);
+       clks[IMX6UL_CLK_USDHC1]         = imx_clk_gate2("usdhc1",       "usdhc1_podf",   base + 0x80,   2);
+       clks[IMX6UL_CLK_USDHC2]         = imx_clk_gate2("usdhc2",       "usdhc2_podf",   base + 0x80,   4);
+       clks[IMX6UL_CLK_SIM1]           = imx_clk_gate2("sim1",         "sim_sel",       base + 0x80,   6);
+       clks[IMX6UL_CLK_SIM2]           = imx_clk_gate2("sim2",         "sim_sel",       base + 0x80,   8);
+       clks[IMX6UL_CLK_EIM]            = imx_clk_gate2("eim",          "eim_slow_podf", base + 0x80,   10);
+       clks[IMX6UL_CLK_PWM8]           = imx_clk_gate2("pwm8",         "perclk",        base + 0x80,   16);
+       clks[IMX6UL_CLK_UART8_IPG]      = imx_clk_gate2("uart8_ipg",    "ipg",           base + 0x80,   14);
+       clks[IMX6UL_CLK_UART8_SERIAL]   = imx_clk_gate2("uart8_serial", "uart_podf",     base + 0x80,   14);
+       clks[IMX6UL_CLK_WDOG3]          = imx_clk_gate2("wdog3",        "ipg",           base + 0x80,   20);
+       clks[IMX6UL_CLK_I2C4]           = imx_clk_gate2("i2c4",         "perclk",        base + 0x80,   24);
+       clks[IMX6UL_CLK_PWM5]           = imx_clk_gate2("pwm5",         "perclk",        base + 0x80,   26);
+       clks[IMX6UL_CLK_PWM6]           = imx_clk_gate2("pwm6",         "perclk",        base + 0x80,   28);
+       clks[IMX6UL_CLK_PWM7]           = imx_clk_gate2("Pwm7",         "perclk",        base + 0x80,   30);
+
+       /* mask handshake of mmdc */
+       writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               if (IS_ERR(clks[i]))
+                       pr_err("i.MX6UL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+
+       clk_data.clks = clks;
+       clk_data.clk_num = ARRAY_SIZE(clks);
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+       /* set perclk to from OSC */
+       clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
+
+       clk_set_rate(clks[IMX6UL_CLK_ENET_REF], 50000000);
+       clk_set_rate(clks[IMX6UL_CLK_ENET2_REF], 50000000);
+       clk_set_rate(clks[IMX6UL_CLK_CSI], 24000000);
+
+       /* keep all the clks on just for bringup */
+       for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+               clk_prepare_enable(clks[clks_init_on[i]]);
+
+       if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+               clk_prepare_enable(clks[IMX6UL_CLK_USBPHY1_GATE]);
+               clk_prepare_enable(clks[IMX6UL_CLK_USBPHY2_GATE]);
+       }
+
+       clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
+       clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+
+       clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
+}
+
+CLK_OF_DECLARE(imx6ul, "fsl,imx6ul-ccm", imx6ul_clocks_init);
index 0b0f6f66ec56b680219bdcad3e550670e7130131..04a3e78ea1bc3254b6cd00ef429c00d234f50fd2 100644 (file)
@@ -10,7 +10,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/slab.h>
index c34ad8a611dd53e6f1465a82e8ad1c1f783b93f7..8564e4342c7d1fa115c1b5f9043bf6bbb8d6e70d 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/slab.h>
index f0d15fb9d7836d7de34338d31b1edb4fe69923cd..6addf8f58b975d9696f91e003b4775afa0da4397 100644 (file)
@@ -10,7 +10,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/io.h>
index b936cdd1a13c2d0254a6f5ef166caa49fe687113..7cfb7b2a2ed65bc9bb0e40abab245e12d3398ba1 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/delay.h>
index 86f1e362eafb8e29c02fae393620d39d32278529..aed5af23895be786db801a2d11360fa3e4a63f2b 100644 (file)
@@ -10,7 +10,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 4a375ead70e9f2c58c1eb6aaced07ea39e579b7b..3f553d0ae0b5f885d3cee60c9f673870684f83fc 100644 (file)
@@ -10,7 +10,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -309,8 +308,7 @@ static void __init of_pll_mux_clk_init(struct device_node *node)
                return;
        }
 
-       parents[0] = of_clk_get_parent_name(node, 0);
-       parents[1] = of_clk_get_parent_name(node, 1);
+       of_clk_parent_fill(node, parents, 2);
        if (!parents[0] || !parents[1]) {
                pr_err("%s: missing parent clocks\n", __func__);
                return;
index 6b6780b1e9c5b55a15524a720eb2af57af225792..11e25c992948fdcc7ea00c5cfa31f0274e6dfb53 100644 (file)
 #define __DRV_CLK_GATE_H
 
 #include <linux/regmap.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
+struct clk;
+
 struct mtk_clk_gate {
        struct clk_hw   hw;
        struct regmap   *regmap;
index 08b4b849b49197973ad5f4d0c491fc0540ac5a62..07c21e44b4b3e6811753525dde3b1ba1f127bacd 100644 (file)
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
index 8b6523d15fb85984f5fb73304fa21803c40b730f..90eff85f4285ec10415509ba8013b63d623f94cb 100644 (file)
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
@@ -795,8 +796,9 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
 
 #define CON0_MT8173_RST_BAR    BIT(24)
 
-#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
-                       _tuner_reg, _pcw_reg, _pcw_shift) { \
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,  \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift, _div_table) {                       \
                .id = _id,                                              \
                .name = _name,                                          \
                .reg = _reg,                                            \
@@ -811,14 +813,31 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
                .tuner_reg = _tuner_reg,                                \
                .pcw_reg = _pcw_reg,                                    \
                .pcw_shift = _pcw_shift,                                \
+               .div_table = _div_table,                                \
        }
 
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,    \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift)                                     \
+               PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
+                       NULL)
+
+static const struct mtk_pll_div_table mmpll_div_table[] = {
+       { .div = 0, .freq = MT8173_PLL_FMAX },
+       { .div = 1, .freq = 1000000000 },
+       { .div = 2, .freq = 702000000 },
+       { .div = 3, .freq = 253500000 },
+       { .div = 4, .freq = 126750000 },
+       { } /* sentinel */
+};
+
 static const struct mtk_pll_data plls[] = {
        PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
        PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
        PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
        PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
-       PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+       PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0, mmpll_div_table),
        PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
        PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
        PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
index 9dda9d8ad10b0164bc5e15611659f6eda6f06ab8..c5cbecb3d218c3d33e116db2d814819987067e8d 100644 (file)
 
 #include <linux/regmap.h>
 #include <linux/bitops.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
+struct clk;
+
 #define MAX_MUX_GATE_BIT       31
 #define INVALID_MUX_GATE_BIT   (MAX_MUX_GATE_BIT + 1)
 
@@ -134,6 +135,11 @@ struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
 
 #define HAVE_RST_BAR   BIT(0)
 
+struct mtk_pll_div_table {
+       u32 div;
+       unsigned long freq;
+};
+
 struct mtk_pll_data {
        int id;
        const char *name;
@@ -150,6 +156,7 @@ struct mtk_pll_data {
        int pcwbits;
        uint32_t pcw_reg;
        int pcw_shift;
+       const struct mtk_pll_div_table *div_table;
 };
 
 void __init mtk_clk_register_plls(struct device_node *node,
index 44409e98c52f5b112889a6458189cad87a5f2898..622e7b6c62b42893f1c4c98574a492eed361130e 100644 (file)
@@ -90,20 +90,23 @@ static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
 static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
                int postdiv)
 {
-       u32 con1, pd, val;
+       u32 con1, val;
        int pll_en;
 
-       /* set postdiv */
-       pd = readl(pll->pd_addr);
-       pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
-       pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
-       writel(pd, pll->pd_addr);
-
        pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
 
-       /* set pcw */
-       val = readl(pll->pcw_addr);
+       /* set postdiv */
+       val = readl(pll->pd_addr);
+       val &= ~(POSTDIV_MASK << pll->data->pd_shift);
+       val |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+
+       /* postdiv and pcw need to set at the same time if on same register */
+       if (pll->pd_addr != pll->pcw_addr) {
+               writel(val, pll->pd_addr);
+               val = readl(pll->pcw_addr);
+       }
 
+       /* set pcw */
        val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
                        pll->data->pcw_shift);
        val |= pcw << pll->data->pcw_shift;
@@ -135,16 +138,28 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
                u32 freq, u32 fin)
 {
        unsigned long fmin = 1000 * MHZ;
+       const struct mtk_pll_div_table *div_table = pll->data->div_table;
        u64 _pcw;
        u32 val;
 
        if (freq > pll->data->fmax)
                freq = pll->data->fmax;
 
-       for (val = 0; val < 4; val++) {
+       if (div_table) {
+               if (freq > div_table[0].freq)
+                       freq = div_table[0].freq;
+
+               for (val = 0; div_table[val + 1].freq != 0; val++) {
+                       if (freq > div_table[val + 1].freq)
+                               break;
+               }
                *postdiv = 1 << val;
-               if (freq * *postdiv >= fmin)
-                       break;
+       } else {
+               for (val = 0; val < 5; val++) {
+                       *postdiv = 1 << val;
+                       if ((u64)freq * *postdiv >= fmin)
+                               break;
+               }
        }
 
        /* _pcw = freq * postdiv / fin * 2^pcwfbits */
index 71ad493b94df0cbb344b9e259c0c77304074f143..f7c30ea54ca8d85625b8bc33c5c772dd2700e0dd 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #define MESON_CPU_CLK_CNTL1            0x00
index b8c511c5e7a7e4c4aa2d04b94777ec907dd49b2a..c83ae1367abc1791618b858fe3544211c12dfaaf 100644 (file)
@@ -15,7 +15,6 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/syscon.h>
 #include <linux/slab.h>
index 09d41c717c52830efd22849100deb01e9f9252fb..4c717db05f2deb61a4519c7b112d3c75199371fe 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
index cdcf2d7f321e0d5becfaa90b199d9839bcc9d81a..47b5542ce50f3ec8c356eeb4bdbf9c580f207bfd 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
index adbd9d64ded2b149f5b7411cf788de0459ed6542..d20cd3431ac27547121d8bc6412c460a45b1ff10 100644 (file)
@@ -27,7 +27,6 @@
 static int mmp_clk_gate_enable(struct clk_hw *hw)
 {
        struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
-       struct clk *clk = hw->clk;
        unsigned long flags = 0;
        unsigned long rate;
        u32 tmp;
@@ -44,7 +43,7 @@ static int mmp_clk_gate_enable(struct clk_hw *hw)
                spin_unlock_irqrestore(gate->lock, flags);
 
        if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
-               rate = __clk_get_rate(clk);
+               rate = clk_hw_get_rate(hw);
                /* Need delay 2 cycles. */
                udelay(2000000/rate);
        }
index de6a873175d2b833f64d95f8e2bf5729da6fd1b4..c554833cffc509a8d2e120c4af5873b8100e3018 100644 (file)
@@ -63,7 +63,7 @@ static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
 
 static unsigned int _get_mux(struct mmp_clk_mix *mix, unsigned int val)
 {
-       int num_parents = __clk_get_num_parents(mix->hw.clk);
+       int num_parents = clk_hw_get_num_parents(&mix->hw);
        int i;
 
        if (mix->mux_flags & CLK_MUX_INDEX_BIT)
@@ -113,15 +113,15 @@ static void _filter_clk_table(struct mmp_clk_mix *mix,
 {
        int i;
        struct mmp_clk_mix_clk_table *item;
-       struct clk *parent, *clk;
+       struct clk_hw *parent, *hw;
        unsigned long parent_rate;
 
-       clk = mix->hw.clk;
+       hw = &mix->hw;
 
        for (i = 0; i < table_size; i++) {
                item = &table[i];
-               parent = clk_get_parent_by_index(clk, item->parent_index);
-               parent_rate = __clk_get_rate(parent);
+               parent = clk_hw_get_parent_by_index(hw, item->parent_index);
+               parent_rate = clk_hw_get_rate(parent);
                if (parent_rate % item->rate) {
                        item->valid = 0;
                } else {
@@ -181,7 +181,7 @@ static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val,
 
                if (timeout == 0) {
                        pr_err("%s:%s cannot do frequency change\n",
-                               __func__, __clk_get_name(mix->hw.clk));
+                               __func__, clk_hw_get_name(&mix->hw));
                        ret = -EBUSY;
                        goto error;
                }
@@ -201,27 +201,22 @@ error:
        return ret;
 }
 
-static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
        struct mmp_clk_mix *mix = to_clk_mix(hw);
        struct mmp_clk_mix_clk_table *item;
-       struct clk *parent, *parent_best, *mix_clk;
+       struct clk_hw *parent, *parent_best;
        unsigned long parent_rate, mix_rate, mix_rate_best, parent_rate_best;
        unsigned long gap, gap_best;
        u32 div_val_max;
        unsigned int div;
        int i, j;
 
-       mix_clk = hw->clk;
 
-       parent = NULL;
        mix_rate_best = 0;
        parent_rate_best = 0;
-       gap_best = rate;
+       gap_best = ULONG_MAX;
        parent_best = NULL;
 
        if (mix->table) {
@@ -229,11 +224,11 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
                        item = &mix->table[i];
                        if (item->valid == 0)
                                continue;
-                       parent = clk_get_parent_by_index(mix_clk,
+                       parent = clk_hw_get_parent_by_index(hw,
                                                        item->parent_index);
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
                        mix_rate = parent_rate / item->divisor;
-                       gap = abs(mix_rate - rate);
+                       gap = abs(mix_rate - req->rate);
                        if (parent_best == NULL || gap < gap_best) {
                                parent_best = parent;
                                parent_rate_best = parent_rate;
@@ -244,14 +239,14 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
                        }
                }
        } else {
-               for (i = 0; i < __clk_get_num_parents(mix_clk); i++) {
-                       parent = clk_get_parent_by_index(mix_clk, i);
-                       parent_rate = __clk_get_rate(parent);
+               for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+                       parent = clk_hw_get_parent_by_index(hw, i);
+                       parent_rate = clk_hw_get_rate(parent);
                        div_val_max = _get_maxdiv(mix);
                        for (j = 0; j < div_val_max; j++) {
                                div = _get_div(mix, j);
                                mix_rate = parent_rate / div;
-                               gap = abs(mix_rate - rate);
+                               gap = abs(mix_rate - req->rate);
                                if (parent_best == NULL || gap < gap_best) {
                                        parent_best = parent;
                                        parent_rate_best = parent_rate;
@@ -265,10 +260,14 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
        }
 
 found:
-       *best_parent_rate = parent_rate_best;
-       *best_parent_clk = __clk_get_hw(parent_best);
+       if (!parent_best)
+               return -EINVAL;
+
+       req->best_parent_rate = parent_rate_best;
+       req->best_parent_hw = parent_best;
+       req->rate = mix_rate_best;
 
-       return mix_rate_best;
+       return 0;
 }
 
 static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
@@ -381,20 +380,19 @@ static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        struct mmp_clk_mix_clk_table *item;
        unsigned long parent_rate;
        unsigned int best_divisor;
-       struct clk *mix_clk, *parent;
+       struct clk_hw *parent;
        int i;
 
        best_divisor = best_parent_rate / rate;
 
-       mix_clk = hw->clk;
        if (mix->table) {
                for (i = 0; i < mix->table_size; i++) {
                        item = &mix->table[i];
                        if (item->valid == 0)
                                continue;
-                       parent = clk_get_parent_by_index(mix_clk,
+                       parent = clk_hw_get_parent_by_index(hw,
                                                        item->parent_index);
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
                        if (parent_rate == best_parent_rate
                                && item->divisor == best_divisor)
                                break;
@@ -407,13 +405,13 @@ static int mmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
                else
                        return -EINVAL;
        } else {
-               for (i = 0; i < __clk_get_num_parents(mix_clk); i++) {
-                       parent = clk_get_parent_by_index(mix_clk, i);
-                       parent_rate = __clk_get_rate(parent);
+               for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+                       parent = clk_hw_get_parent_by_index(hw, i);
+                       parent_rate = clk_hw_get_rate(parent);
                        if (parent_rate == best_parent_rate)
                                break;
                }
-               if (i < __clk_get_num_parents(mix_clk))
+               if (i < clk_hw_get_num_parents(hw))
                        return _set_rate(mix, _get_mux_val(mix, i),
                                        _get_div_val(mix, best_divisor), 1, 1);
                else
@@ -468,20 +466,20 @@ struct clk *mmp_clk_register_mix(struct device *dev,
        memcpy(&mix->reg_info, &config->reg_info, sizeof(config->reg_info));
        if (config->table) {
                table_bytes = sizeof(*config->table) * config->table_size;
-               mix->table = kzalloc(table_bytes, GFP_KERNEL);
+               mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL);
                if (!mix->table) {
                        pr_err("%s:%s: could not allocate mmp mix table\n",
                                __func__, name);
                        kfree(mix);
                        return ERR_PTR(-ENOMEM);
                }
-               memcpy(mix->table, config->table, table_bytes);
                mix->table_size = config->table_size;
        }
 
        if (config->mux_table) {
                table_bytes = sizeof(u32) * num_parents;
-               mix->mux_table = kzalloc(table_bytes, GFP_KERNEL);
+               mix->mux_table = kmemdup(config->mux_table, table_bytes,
+                                        GFP_KERNEL);
                if (!mix->mux_table) {
                        pr_err("%s:%s: could not allocate mmp mix mux-table\n",
                                __func__, name);
@@ -489,7 +487,6 @@ struct clk *mmp_clk_register_mix(struct device *dev,
                        kfree(mix);
                        return ERR_PTR(-ENOMEM);
                }
-               memcpy(mix->mux_table, config->mux_table, table_bytes);
        }
 
        mix->div_flags = config->div_flags;
index cf038ef54c5961f9764f1540eca0f717c14a172a..61893fe73251b41048ed1aebee177ca605c91cdc 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 3821a88077eaf5489f4d6e3be3d293fd6f0ca5f8..5837eb8a212fbdcd8446ff9da77f393cc05c128a 100644 (file)
@@ -10,7 +10,8 @@
  * warranty of any kind, whether express or implied.
  */
 #include <linux/kernel.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/io.h>
@@ -120,7 +121,7 @@ static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
        if (!cpuclk->pmu_dfs)
                return -ENODEV;
 
-       cur_rate = __clk_get_rate(hwclk->clk);
+       cur_rate = clk_hw_get_rate(hwclk);
 
        reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET);
        fabric_div = (reg >> SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT) &
@@ -196,7 +197,6 @@ static void __init of_cpu_clk_setup(struct device_node *node)
        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;
 
@@ -208,9 +208,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
                        goto bail_out;
 
                sprintf(clk_name, "cpu%d", cpu);
-               parent_clk = of_clk_get(node, 0);
 
-               cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
+               cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0);
                cpuclk[cpu].clk_name = clk_name;
                cpuclk[cpu].cpu = cpu;
                cpuclk[cpu].reg_base = clock_complex_base;
index 15b370ff37481a61e4351377793d5619e14a6cd8..4a22429cd7a23b4171f825062ac96abc0f34d311 100644 (file)
@@ -13,8 +13,8 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 90e1da93877e6286fca36ab99ac5959ca6b0e75c..049ee27d5a22e680fad65c689a69813086d157e8 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/slab.h>
index e6aa6b567d6803295976a6d9f6a5206898a2189a..73f0240569ac0733d0312a3627d891d454f98ec5 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 32216f9b7f03e9b5540106d29c842cd68cf9b60a..f01876af6bb8b317bfcbcf53e3aef39d81bb0876 100644 (file)
@@ -9,9 +9,8 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk/mxs.h>
-#include <linux/clkdev.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/init.h>
index a68670868baacd42686b4ce61471838b02ee4905..6b572b759f9a38c71469faf1e09da19c9a964ac1 100644 (file)
@@ -9,9 +9,9 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/init.h>
index fadae41833ec0acef838ce55e671f7675c42f586..d4ca79a868e060da71c19a7e89d8531ac47b1990 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
index 4adeed6c2f9461a7012742fef335370d11322bd1..495f99b7965ea3a589eb7c2b3103cdb2f39d9ed4 100644 (file)
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
index f07d821dd75d5d4a9318d5976c6c84938e3420f9..a4590956d2a28863565549b7e4b4ed0a40d7a66e 100644 (file)
@@ -12,7 +12,8 @@
 #ifndef __MXS_CLK_H
 #define __MXS_CLK_H
 
-#include <linux/clk.h>
+struct clk;
+
 #include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 
index 81e9e1c788f41f70fbd5b99bbbbf8489bd59d8a4..e0a3cb8970ab5b68e24dbb2fbcbb45f13d0ae0b3 100644 (file)
@@ -8,7 +8,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
index 8c0fe8828f9938d8e6491e430c33154cdcda3565..c4ceb5eaf46c16d281f8ce1c3e6334262a2db083 100644 (file)
@@ -159,9 +159,15 @@ PNAME(mux_debug) = { "mips_pll_mux", "rpu_v_pll_mux",
                     "wifi_pll_mux", "bt_pll_mux" };
 static u32 mux_debug_idx[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10 };
 
-static unsigned int pistachio_critical_clks[] __initdata = {
-       CLK_MIPS,
-       CLK_PERIPH_SYS,
+static unsigned int pistachio_critical_clks_core[] __initdata = {
+       CLK_MIPS
+};
+
+static unsigned int pistachio_critical_clks_sys[] __initdata = {
+       PERIPH_CLK_SYS,
+       PERIPH_CLK_SYS_BUS,
+       PERIPH_CLK_DDR,
+       PERIPH_CLK_ROM,
 };
 
 static void __init pistachio_clk_init(struct device_node *np)
@@ -193,8 +199,8 @@ static void __init pistachio_clk_init(struct device_node *np)
 
        pistachio_clk_register_provider(p);
 
-       pistachio_clk_force_enable(p, pistachio_critical_clks,
-                                  ARRAY_SIZE(pistachio_critical_clks));
+       pistachio_clk_force_enable(p, pistachio_critical_clks_core,
+                                  ARRAY_SIZE(pistachio_critical_clks_core));
 }
 CLK_OF_DECLARE(pistachio_clk, "img,pistachio-clk", pistachio_clk_init);
 
@@ -261,6 +267,9 @@ static void __init pistachio_clk_periph_init(struct device_node *np)
                                    ARRAY_SIZE(pistachio_periph_gates));
 
        pistachio_clk_register_provider(p);
+
+       pistachio_clk_force_enable(p, pistachio_critical_clks_sys,
+                                  ARRAY_SIZE(pistachio_critical_clks_sys));
 }
 CLK_OF_DECLARE(pistachio_clk_periph, "img,pistachio-clk-periph",
               pistachio_clk_periph_init);
index e17dada0dd21ab88fe1282b6dcc662e5e775988a..7e8daab9025bd326cc74d686d5e8f166ac775312 100644 (file)
 #define MIN_OUTPUT_FRAC                        12000000UL
 #define MAX_OUTPUT_FRAC                        1600000000UL
 
+/* Fractional PLL operating modes */
+enum pll_mode {
+       PLL_MODE_FRAC,
+       PLL_MODE_INT,
+};
+
 struct pistachio_clk_pll {
        struct clk_hw hw;
        void __iomem *base;
@@ -88,12 +94,10 @@ static inline void pll_lock(struct pistachio_clk_pll *pll)
                cpu_relax();
 }
 
-static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
+static inline u64 do_div_round_closest(u64 dividend, u64 divisor)
 {
        dividend += divisor / 2;
-       do_div(dividend, divisor);
-
-       return dividend;
+       return div64_u64(dividend, divisor);
 }
 
 static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
@@ -101,6 +105,29 @@ static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw)
        return container_of(hw, struct pistachio_clk_pll, hw);
 }
 
+static inline enum pll_mode pll_frac_get_mode(struct clk_hw *hw)
+{
+       struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
+       u32 val;
+
+       val = pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_DSMPD;
+       return val ? PLL_MODE_INT : PLL_MODE_FRAC;
+}
+
+static inline void pll_frac_set_mode(struct clk_hw *hw, enum pll_mode mode)
+{
+       struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
+       u32 val;
+
+       val = pll_readl(pll, PLL_CTRL3);
+       if (mode == PLL_MODE_INT)
+               val |= PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD;
+       else
+               val &= ~(PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_DACPD);
+
+       pll_writel(pll, val, PLL_CTRL3);
+}
+
 static struct pistachio_pll_rate_table *
 pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
               unsigned long fout)
@@ -136,8 +163,7 @@ static int pll_gf40lp_frac_enable(struct clk_hw *hw)
        u32 val;
 
        val = pll_readl(pll, PLL_CTRL3);
-       val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_DACPD |
-                PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
+       val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD |
                 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD);
        pll_writel(pll, val, PLL_CTRL3);
 
@@ -173,8 +199,8 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
        struct pistachio_pll_rate_table *params;
        int enabled = pll_gf40lp_frac_is_enabled(hw);
-       u32 val, vco, old_postdiv1, old_postdiv2;
-       const char *name = __clk_get_name(hw->clk);
+       u64 val, vco, old_postdiv1, old_postdiv2;
+       const char *name = clk_hw_get_name(hw);
 
        if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
                return -EINVAL;
@@ -183,17 +209,21 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!params || !params->refdiv)
                return -EINVAL;
 
-       vco = params->fref * params->fbdiv / params->refdiv;
+       /* calculate vco */
+       vco = params->fref;
+       vco *= (params->fbdiv << 24) + params->frac;
+       vco = div64_u64(vco, params->refdiv << 24);
+
        if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
-               pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+               pr_warn("%s: VCO %llu is out of range %lu..%lu\n", name, vco,
                        MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
 
-       val = params->fref / params->refdiv;
+       val = div64_u64(params->fref, params->refdiv);
        if (val < MIN_PFD)
-               pr_warn("%s: PFD %u is too low (min %lu)\n",
+               pr_warn("%s: PFD %llu is too low (min %lu)\n",
                        name, val, MIN_PFD);
        if (val > vco / 16)
-               pr_warn("%s: PFD %u is too high (max %u)\n",
+               pr_warn("%s: PFD %llu is too high (max %llu)\n",
                        name, val, vco / 16);
 
        val = pll_readl(pll, PLL_CTRL1);
@@ -227,6 +257,12 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
                (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
        pll_writel(pll, val, PLL_CTRL2);
 
+       /* set operating mode */
+       if (params->frac)
+               pll_frac_set_mode(hw, PLL_MODE_FRAC);
+       else
+               pll_frac_set_mode(hw, PLL_MODE_INT);
+
        if (enabled)
                pll_lock(pll);
 
@@ -237,8 +273,7 @@ static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
                                                 unsigned long parent_rate)
 {
        struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
-       u32 val, prediv, fbdiv, frac, postdiv1, postdiv2;
-       u64 rate = parent_rate;
+       u64 val, prediv, fbdiv, frac, postdiv1, postdiv2, rate;
 
        val = pll_readl(pll, PLL_CTRL1);
        prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK;
@@ -251,7 +286,13 @@ static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw,
                PLL_FRAC_CTRL2_POSTDIV2_MASK;
        frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK;
 
-       rate *= (fbdiv << 24) + frac;
+       /* get operating mode (int/frac) and calculate rate accordingly */
+       rate = parent_rate;
+       if (pll_frac_get_mode(hw) == PLL_MODE_FRAC)
+               rate *= (fbdiv << 24) + frac;
+       else
+               rate *= (fbdiv << 24);
+
        rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24);
 
        return rate;
@@ -279,7 +320,7 @@ static int pll_gf40lp_laint_enable(struct clk_hw *hw)
        u32 val;
 
        val = pll_readl(pll, PLL_CTRL1);
-       val &= ~(PLL_INT_CTRL1_PD | PLL_INT_CTRL1_DSMPD |
+       val &= ~(PLL_INT_CTRL1_PD |
                 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD);
        pll_writel(pll, val, PLL_CTRL1);
 
@@ -316,7 +357,7 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
        struct pistachio_pll_rate_table *params;
        int enabled = pll_gf40lp_laint_is_enabled(hw);
        u32 val, vco, old_postdiv1, old_postdiv2;
-       const char *name = __clk_get_name(hw->clk);
+       const char *name = clk_hw_get_name(hw);
 
        if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
                return -EINVAL;
@@ -325,12 +366,12 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!params || !params->refdiv)
                return -EINVAL;
 
-       vco = params->fref * params->fbdiv / params->refdiv;
+       vco = div_u64(params->fref * params->fbdiv, params->refdiv);
        if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
                pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
                        MIN_VCO_LA, MAX_VCO_LA);
 
-       val = params->fref / params->refdiv;
+       val = div_u64(params->fref, params->refdiv);
        if (val < MIN_PFD)
                pr_warn("%s: PFD %u is too low (min %lu)\n",
                        name, val, MIN_PFD);
index 85faa83e1bd7a94fa8e4f98881a9d4add3ab4f6d..698cad4f509e70303aa17bf337fb8ea51b8a41e6 100644 (file)
@@ -6,6 +6,7 @@
  * version 2, as published by the Free Software Foundation.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
index 52fabbc24624bc5490442b10e381e752eae49887..8d45178dbde3e183e0806594e0fd1800f04076d5 100644 (file)
@@ -95,13 +95,13 @@ struct pistachio_fixed_factor {
        }
 
 struct pistachio_pll_rate_table {
-       unsigned long fref;
-       unsigned long fout;
-       unsigned int refdiv;
-       unsigned int fbdiv;
-       unsigned int postdiv1;
-       unsigned int postdiv2;
-       unsigned int frac;
+       unsigned long long fref;
+       unsigned long long fout;
+       unsigned long long refdiv;
+       unsigned long long fbdiv;
+       unsigned long long postdiv1;
+       unsigned long long postdiv2;
+       unsigned long long frac;
 };
 
 enum pistachio_pll_type {
index 6cd88d963a7ffbaa531b84f0a919b5aeef8f989d..542e45ef5087b5736e2111cfca08eb42ed7b24a3 100644 (file)
@@ -79,7 +79,7 @@ unsigned int pxa25x_get_clk_frequency_khz(int info)
                        clks[3] / 1000000, (clks[3] % 1000000) / 10000);
        }
 
-       return (unsigned int)clks[0];
+       return (unsigned int)clks[0] / KHz;
 }
 
 static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw,
index 9a31b77eed23511545f453022d9263db08b7add8..5b82d30baf9f36e9506544e554f1e79cf2b1b511 100644 (file)
@@ -80,7 +80,7 @@ unsigned int pxa27x_get_clk_frequency_khz(int info)
                pr_info("System bus clock: %ld.%02ldMHz\n",
                        clks[4] / 1000000, (clks[4] % 1000000) / 10000);
        }
-       return (unsigned int)clks[0];
+       return (unsigned int)clks[0] / KHz;
 }
 
 bool pxa27x_is_ppll_disabled(void)
index 4b93a1efb36d11fa7171735d29bac283e4bb6d97..4af4eed5f89f03bb8affd1104de702b677326249 100644 (file)
@@ -78,7 +78,7 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info)
                pr_info("System bus clock: %ld.%02ldMHz\n",
                        clks[4] / 1000000, (clks[4] % 1000000) / 10000);
        }
-       return (unsigned int)clks[0];
+       return (unsigned int)clks[0] / KHz;
 }
 
 static unsigned long clk_pxa3xx_ac97_get_rate(struct clk_hw *hw,
@@ -126,7 +126,7 @@ PARENTS(pxa3xx_ac97_bus) = { "ring_osc_60mhz", "ac97" };
 PARENTS(pxa3xx_sbus) = { "ring_osc_60mhz", "system_bus" };
 PARENTS(pxa3xx_smemcbus) = { "ring_osc_60mhz", "smemc" };
 
-#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? &CKENA : &CKENB)
+#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? &CKENB : &CKENA)
 #define PXA3XX_CKEN(dev_id, con_id, parents, mult_lp, div_lp, mult_hp, \
                    div_hp, bit, is_lp, flags)                          \
        PXA_CKEN(dev_id, con_id, bit, parents, mult_lp, div_lp,         \
index 6b4d2bcb1a53e9830cd3059abc7dcee04f2d6e58..26f7af315066f2381d10396d6d8e5b350f370032 100644 (file)
@@ -75,7 +75,7 @@ static int clk_branch_wait(const struct clk_branch *br, bool enabling,
                bool (check_halt)(const struct clk_branch *, bool))
 {
        bool voted = br->halt_check & BRANCH_VOTED;
-       const char *name = __clk_get_name(br->clkr.hw.clk);
+       const char *name = clk_hw_get_name(&br->clkr.hw);
 
        /* Skip checking halt bit if the clock is in hardware gated mode */
        if (clk_branch_in_hwcg_mode(br))
index 245d5063a385968a5081050b7ef679f86a71b124..5b940d629045fe706707f1d6a8c92a3ef12098b5 100644 (file)
@@ -135,19 +135,19 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
        return NULL;
 }
 
-static long
-clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
-                      unsigned long min_rate, unsigned long max_rate,
-                      unsigned long *p_rate, struct clk_hw **p)
+static int
+clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
        struct clk_pll *pll = to_clk_pll(hw);
        const struct pll_freq_tbl *f;
 
-       f = find_freq(pll->freq_tbl, rate);
+       f = find_freq(pll->freq_tbl, req->rate);
        if (!f)
-               return clk_pll_recalc_rate(hw, *p_rate);
+               req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate);
+       else
+               req->rate = f->freq;
 
-       return f->freq;
+       return 0;
 }
 
 static int
@@ -194,7 +194,7 @@ static int wait_for_pll(struct clk_pll *pll)
        u32 val;
        int count;
        int ret;
-       const char *name = __clk_get_name(pll->clkr.hw.clk);
+       const char *name = clk_hw_get_name(&pll->clkr.hw);
 
        /* Wait for pll to enable. */
        for (count = 200; count > 0; count--) {
@@ -213,7 +213,7 @@ static int wait_for_pll(struct clk_pll *pll)
 static int clk_pll_vote_enable(struct clk_hw *hw)
 {
        int ret;
-       struct clk_pll *p = to_clk_pll(__clk_get_hw(__clk_get_parent(hw->clk)));
+       struct clk_pll *p = to_clk_pll(clk_hw_get_parent(hw));
 
        ret = clk_enable_regmap(hw);
        if (ret)
@@ -292,3 +292,78 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
                clk_pll_set_fsm_mode(pll, regmap, 0);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
+
+static int clk_pll_sr2_enable(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       int ret;
+       u32 mode;
+
+       ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
+       if (ret)
+               return ret;
+
+       /* Disable PLL bypass mode. */
+       ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
+                                PLL_BYPASSNL);
+       if (ret)
+               return ret;
+
+       /*
+        * H/W requires a 5us delay between disabling the bypass and
+        * de-asserting the reset. Delay 10us just to be safe.
+        */
+       udelay(10);
+
+       /* De-assert active-low PLL reset. */
+       ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
+                                PLL_RESET_N);
+       if (ret)
+               return ret;
+
+       ret = wait_for_pll(pll);
+       if (ret)
+               return ret;
+
+       /* Enable PLL output. */
+       return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
+                                PLL_OUTCTRL);
+}
+
+static int
+clk_pll_sr2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       const struct pll_freq_tbl *f;
+       bool enabled;
+       u32 mode;
+       u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
+
+       f = find_freq(pll->freq_tbl, rate);
+       if (!f)
+               return -EINVAL;
+
+       regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
+       enabled = (mode & enable_mask) == enable_mask;
+
+       if (enabled)
+               clk_pll_disable(hw);
+
+       regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
+       regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
+       regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
+
+       if (enabled)
+               clk_pll_sr2_enable(hw);
+
+       return 0;
+}
+
+const struct clk_ops clk_pll_sr2_ops = {
+       .enable = clk_pll_sr2_enable,
+       .disable = clk_pll_disable,
+       .set_rate = clk_pll_sr2_set_rate,
+       .recalc_rate = clk_pll_recalc_rate,
+       .determine_rate = clk_pll_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);
index c9c0cda306d04e45548daa0d5b50f802ab2c04a9..ffd0c63bddbc41d78e65509bd4091826a3ab5408 100644 (file)
@@ -62,6 +62,7 @@ struct clk_pll {
 
 extern const struct clk_ops clk_pll_ops;
 extern const struct clk_ops clk_pll_vote_ops;
+extern const struct clk_ops clk_pll_sr2_ops;
 
 #define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr)
 
index 7b3d62674203e4238cba23ff2eb6530f9bdac23b..bccedc4b57568bda6edafa516933fc45f8cfa439 100644 (file)
@@ -45,7 +45,7 @@ static u32 src_to_ns(struct src_sel *s, u8 src, u32 ns)
 static u8 clk_rcg_get_parent(struct clk_hw *hw)
 {
        struct clk_rcg *rcg = to_clk_rcg(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 ns;
        int i, ret;
 
@@ -59,7 +59,7 @@ static u8 clk_rcg_get_parent(struct clk_hw *hw)
 
 err:
        pr_debug("%s: Clock %s has invalid parent, using default.\n",
-                __func__, __clk_get_name(hw->clk));
+                __func__, clk_hw_get_name(hw));
        return 0;
 }
 
@@ -72,7 +72,7 @@ static int reg_to_bank(struct clk_dyn_rcg *rcg, u32 bank)
 static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
 {
        struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 ns, reg;
        int bank;
        int i, ret;
@@ -95,7 +95,7 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
 
 err:
        pr_debug("%s: Clock %s has invalid parent, using default.\n",
-                __func__, __clk_get_name(hw->clk));
+                __func__, clk_hw_get_name(hw));
        return 0;
 }
 
@@ -404,14 +404,12 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        return calc_rate(parent_rate, m, n, mode, pre_div);
 }
 
-static long _freq_tbl_determine_rate(struct clk_hw *hw,
-               const struct freq_tbl *f, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p_hw,
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+               struct clk_rate_request *req,
                const struct parent_map *parent_map)
 {
-       unsigned long clk_flags;
-       struct clk *p;
+       unsigned long clk_flags, rate = req->rate;
+       struct clk_hw *p;
        int index;
 
        f = qcom_find_freq(f, rate);
@@ -422,8 +420,8 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
        if (index < 0)
                return index;
 
-       clk_flags = __clk_get_flags(hw->clk);
-       p = clk_get_parent_by_index(hw->clk, index);
+       clk_flags = clk_hw_get_flags(hw);
+       p = clk_hw_get_parent_by_index(hw, index);
        if (clk_flags & CLK_SET_RATE_PARENT) {
                rate = rate * f->pre_div;
                if (f->n) {
@@ -433,27 +431,26 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
                        rate = tmp;
                }
        } else {
-               rate =  __clk_get_rate(p);
+               rate =  clk_hw_get_rate(p);
        }
-       *p_hw = __clk_get_hw(p);
-       *p_rate = rate;
+       req->best_parent_hw = p;
+       req->best_parent_rate = rate;
+       req->rate = f->freq;
 
-       return f->freq;
+       return 0;
 }
 
-static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p)
+static int clk_rcg_determine_rate(struct clk_hw *hw,
+                                 struct clk_rate_request *req)
 {
        struct clk_rcg *rcg = to_clk_rcg(hw);
 
-       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
-                       max_rate, p_rate, p, rcg->s.parent_map);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req,
+                                       rcg->s.parent_map);
 }
 
-static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p)
+static int clk_dyn_rcg_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
        struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
        u32 reg;
@@ -464,24 +461,22 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
        bank = reg_to_bank(rcg, reg);
        s = &rcg->s[bank];
 
-       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
-                       max_rate, p_rate, p, s->parent_map);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, s->parent_map);
 }
 
-static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p_hw)
+static int clk_rcg_bypass_determine_rate(struct clk_hw *hw,
+                                        struct clk_rate_request *req)
 {
        struct clk_rcg *rcg = to_clk_rcg(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
-       struct clk *p;
+       struct clk_hw *p;
        int index = qcom_find_src_index(hw, rcg->s.parent_map, f->src);
 
-       p = clk_get_parent_by_index(hw->clk, index);
-       *p_hw = __clk_get_hw(p);
-       *p_rate = __clk_round_rate(p, rate);
+       req->best_parent_hw = p = clk_hw_get_parent_by_index(hw, index);
+       req->best_parent_rate = clk_hw_round_rate(p, req->rate);
+       req->rate = req->best_parent_rate;
 
-       return *p_rate;
+       return 0;
 }
 
 static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
index 92936f0912d2f86622d5ae1372cf03a046b83979..9aec1761fd29e26c4c2ad0fbd7979e609c880db3 100644 (file)
@@ -63,7 +63,7 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw)
 static u8 clk_rcg2_get_parent(struct clk_hw *hw)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 cfg;
        int i, ret;
 
@@ -80,7 +80,7 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw)
 
 err:
        pr_debug("%s: Clock %s has invalid parent, using default.\n",
-                __func__, __clk_get_name(hw->clk));
+                __func__, clk_hw_get_name(hw));
        return 0;
 }
 
@@ -89,7 +89,7 @@ static int update_config(struct clk_rcg2 *rcg)
        int count, ret;
        u32 cmd;
        struct clk_hw *hw = &rcg->clkr.hw;
-       const char *name = __clk_get_name(hw->clk);
+       const char *name = clk_hw_get_name(hw);
 
        ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
                                 CMD_UPDATE, CMD_UPDATE);
@@ -176,12 +176,11 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        return calc_rate(parent_rate, m, n, mode, hid_div);
 }
 
-static long _freq_tbl_determine_rate(struct clk_hw *hw,
-               const struct freq_tbl *f, unsigned long rate,
-               unsigned long *p_rate, struct clk_hw **p_hw)
+static int _freq_tbl_determine_rate(struct clk_hw *hw,
+               const struct freq_tbl *f, struct clk_rate_request *req)
 {
-       unsigned long clk_flags;
-       struct clk *p;
+       unsigned long clk_flags, rate = req->rate;
+       struct clk_hw *p;
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        int index;
 
@@ -193,8 +192,8 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
        if (index < 0)
                return index;
 
-       clk_flags = __clk_get_flags(hw->clk);
-       p = clk_get_parent_by_index(hw->clk, index);
+       clk_flags = clk_hw_get_flags(hw);
+       p = clk_hw_get_parent_by_index(hw, index);
        if (clk_flags & CLK_SET_RATE_PARENT) {
                if (f->pre_div) {
                        rate /= 2;
@@ -208,21 +207,21 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
                        rate = tmp;
                }
        } else {
-               rate =  __clk_get_rate(p);
+               rate =  clk_hw_get_rate(p);
        }
-       *p_hw = __clk_get_hw(p);
-       *p_rate = rate;
+       req->best_parent_hw = p;
+       req->best_parent_rate = rate;
+       req->rate = f->freq;
 
-       return f->freq;
+       return 0;
 }
 
-static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p)
+static int clk_rcg2_determine_rate(struct clk_hw *hw,
+                                  struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 
-       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+       return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
 }
 
 static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
@@ -374,35 +373,33 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
        return clk_edp_pixel_set_rate(hw, rate, parent_rate);
 }
 
-static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long min_rate,
-                                unsigned long max_rate,
-                                unsigned long *p_rate, struct clk_hw **p)
+static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
        const struct frac_entry *frac;
        int delta = 100000;
-       s64 src_rate = *p_rate;
        s64 request;
        u32 mask = BIT(rcg->hid_width) - 1;
        u32 hid_div;
        int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
        /* Force the correct parent */
-       *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, index));
+       req->best_parent_hw = clk_hw_get_parent_by_index(hw, index);
+       req->best_parent_rate = clk_hw_get_rate(req->best_parent_hw);
 
-       if (src_rate == 810000000)
+       if (req->best_parent_rate == 810000000)
                frac = frac_table_810m;
        else
                frac = frac_table_675m;
 
        for (; frac->num; frac++) {
-               request = rate;
+               request = req->rate;
                request *= frac->den;
                request = div_s64(request, frac->num);
-               if ((src_rate < (request - delta)) ||
-                   (src_rate > (request + delta)))
+               if ((req->best_parent_rate < (request - delta)) ||
+                   (req->best_parent_rate > (request + delta)))
                        continue;
 
                regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
@@ -410,8 +407,10 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
                hid_div >>= CFG_SRC_DIV_SHIFT;
                hid_div &= mask;
 
-               return calc_rate(src_rate, frac->num, frac->den, !!frac->den,
-                                hid_div);
+               req->rate = calc_rate(req->best_parent_rate,
+                                     frac->num, frac->den,
+                                     !!frac->den, hid_div);
+               return 0;
        }
 
        return -EINVAL;
@@ -428,28 +427,28 @@ const struct clk_ops clk_edp_pixel_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
 
-static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
-                        unsigned long min_rate, unsigned long max_rate,
-                        unsigned long *p_rate, struct clk_hw **p_hw)
+static int clk_byte_determine_rate(struct clk_hw *hw,
+                                  struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
        int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
        unsigned long parent_rate, div;
        u32 mask = BIT(rcg->hid_width) - 1;
-       struct clk *p;
+       struct clk_hw *p;
 
-       if (rate == 0)
+       if (req->rate == 0)
                return -EINVAL;
 
-       p = clk_get_parent_by_index(hw->clk, index);
-       *p_hw = __clk_get_hw(p);
-       *p_rate = parent_rate = __clk_round_rate(p, rate);
+       req->best_parent_hw = p = clk_hw_get_parent_by_index(hw, index);
+       req->best_parent_rate = parent_rate = clk_hw_round_rate(p, req->rate);
 
-       div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
+       div = DIV_ROUND_UP((2 * parent_rate), req->rate) - 1;
        div = min_t(u32, div, mask);
 
-       return calc_rate(parent_rate, 0, 0, 0, div);
+       req->rate = calc_rate(parent_rate, 0, 0, 0, div);
+
+       return 0;
 }
 
 static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -494,10 +493,8 @@ static const struct frac_entry frac_table_pixel[] = {
        { }
 };
 
-static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long min_rate,
-                                unsigned long max_rate,
-                                unsigned long *p_rate, struct clk_hw **p)
+static int clk_pixel_determine_rate(struct clk_hw *hw,
+                                   struct clk_rate_request *req)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        unsigned long request, src_rate;
@@ -505,20 +502,20 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
        const struct freq_tbl *f = rcg->freq_tbl;
        const struct frac_entry *frac = frac_table_pixel;
        int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
-       struct clk *parent = clk_get_parent_by_index(hw->clk, index);
 
-       *p = __clk_get_hw(parent);
+       req->best_parent_hw = clk_hw_get_parent_by_index(hw, index);
 
        for (; frac->num; frac++) {
-               request = (rate * frac->den) / frac->num;
+               request = (req->rate * frac->den) / frac->num;
 
-               src_rate = __clk_round_rate(parent, request);
+               src_rate = clk_hw_round_rate(req->best_parent_hw, request);
                if ((src_rate < (request - delta)) ||
                        (src_rate > (request + delta)))
                        continue;
 
-               *p_rate = src_rate;
-               return (src_rate * frac->num) / frac->den;
+               req->best_parent_rate = src_rate;
+               req->rate = (src_rate * frac->num) / frac->den;
+               return 0;
        }
 
        return -EINVAL;
index f7101e330b1dd5d1ef182155282275abc1b51405..2dedceefd21d84464f4733bdfa36fda1f3489a2b 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/export.h>
+#include <linux/module.h>
 #include <linux/regmap.h>
 #include <linux/platform_device.h>
 #include <linux/clk-provider.h>
@@ -45,7 +46,7 @@ EXPORT_SYMBOL_GPL(qcom_find_freq);
 
 int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
 {
-       int i, num_parents = __clk_get_num_parents(hw->clk);
+       int i, num_parents = clk_hw_get_num_parents(hw);
 
        for (i = 0; i < num_parents; i++)
                if (src == map[i].src)
@@ -144,3 +145,5 @@ void qcom_cc_remove(struct platform_device *pdev)
        reset_controller_unregister(platform_get_drvdata(pdev));
 }
 EXPORT_SYMBOL_GPL(qcom_cc_remove);
+
+MODULE_LICENSE("GPL v2");
index 54a756b90a3742342b5babcd5f38a26dfc4df48c..3563019b8e3cefe1ac8347464297a2183ce69c34 100644 (file)
@@ -48,7 +48,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
        { P_GPLL0, 1 }
 };
 
-static const char *gcc_xo_gpll0[] = {
+static const char * const gcc_xo_gpll0[] = {
        "xo",
        "gpll0_vote",
 };
@@ -59,7 +59,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
        { P_GPLL4, 5 }
 };
 
-static const char *gcc_xo_gpll0_gpll4[] = {
+static const char * const gcc_xo_gpll0_gpll4[] = {
        "xo",
        "gpll0_vote",
        "gpll4_vote",
@@ -70,7 +70,7 @@ static const struct parent_map gcc_xo_sata_asic0_map[] = {
        { P_SATA_ASIC0_CLK, 2 }
 };
 
-static const char *gcc_xo_sata_asic0[] = {
+static const char * const gcc_xo_sata_asic0[] = {
        "xo",
        "sata_asic0_clk",
 };
@@ -80,7 +80,7 @@ static const struct parent_map gcc_xo_sata_rx_map[] = {
        { P_SATA_RX_CLK, 2}
 };
 
-static const char *gcc_xo_sata_rx[] = {
+static const char * const gcc_xo_sata_rx[] = {
        "xo",
        "sata_rx_clk",
 };
@@ -90,7 +90,7 @@ static const struct parent_map gcc_xo_pcie_map[] = {
        { P_PCIE_0_1_PIPE_CLK, 2 }
 };
 
-static const char *gcc_xo_pcie[] = {
+static const char * const gcc_xo_pcie[] = {
        "xo",
        "pcie_pipe",
 };
@@ -100,7 +100,7 @@ static const struct parent_map gcc_xo_pcie_sleep_map[] = {
        { P_SLEEP_CLK, 6 }
 };
 
-static const char *gcc_xo_pcie_sleep[] = {
+static const char * const gcc_xo_pcie_sleep[] = {
        "xo",
        "sleep_clk_src",
 };
@@ -2105,6 +2105,7 @@ static struct clk_branch gcc_ce1_clk = {
                                "ce1_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
index 563969942a1df2bee95ef9164b7f4fce509a2229..40e480220cd3fb60206a5d8f5bbbf5aba10c3ac9 100644 (file)
@@ -188,7 +188,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = {
        { P_PLL8, 3 }
 };
 
-static const char *gcc_pxo_pll8[] = {
+static const char * const gcc_pxo_pll8[] = {
        "pxo",
        "pll8_vote",
 };
@@ -199,7 +199,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
        { P_CXO, 5 }
 };
 
-static const char *gcc_pxo_pll8_cxo[] = {
+static const char * const gcc_pxo_pll8_cxo[] = {
        "pxo",
        "pll8_vote",
        "cxo",
@@ -215,7 +215,7 @@ static const struct parent_map gcc_pxo_pll3_sata_map[] = {
        { P_PLL3, 6 }
 };
 
-static const char *gcc_pxo_pll3[] = {
+static const char * const gcc_pxo_pll3[] = {
        "pxo",
        "pll3",
 };
@@ -226,7 +226,7 @@ static const struct parent_map gcc_pxo_pll8_pll0[] = {
        { P_PLL0, 2 }
 };
 
-static const char *gcc_pxo_pll8_pll0_map[] = {
+static const char * const gcc_pxo_pll8_pll0_map[] = {
        "pxo",
        "pll8_vote",
        "pll0_vote",
@@ -240,7 +240,7 @@ static const struct parent_map gcc_pxo_pll8_pll14_pll18_pll0_map[] = {
        { P_PLL18, 1 }
 };
 
-static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = {
+static const char * const gcc_pxo_pll8_pll14_pll18_pll0[] = {
        "pxo",
        "pll8_vote",
        "pll0_vote",
index fc6b12da5b306916b771583334ebaf39b9a0336c..b02826ed770a25f474e37922133c7e0ead56c8d0 100644 (file)
@@ -70,7 +70,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = {
        { P_PLL8, 3 }
 };
 
-static const char *gcc_pxo_pll8[] = {
+static const char * const gcc_pxo_pll8[] = {
        "pxo",
        "pll8_vote",
 };
@@ -81,7 +81,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
        { P_CXO, 5 }
 };
 
-static const char *gcc_pxo_pll8_cxo[] = {
+static const char * const gcc_pxo_pll8_cxo[] = {
        "pxo",
        "pll8_vote",
        "cxo",
@@ -1917,7 +1917,7 @@ static struct clk_rcg usb_fs1_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
+static const char * const usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
 
 static struct clk_branch usb_fs1_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
@@ -1984,7 +1984,7 @@ static struct clk_rcg usb_fs2_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
+static const char * const usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
 
 static struct clk_branch usb_fs2_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
index c66f7bc2ae87cde429121af226970c2c7fd973c4..22a4e1e732c0a3cddc38bb20f1beeb97052ce733 100644 (file)
@@ -51,7 +51,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
        { P_GPLL0, 1 },
 };
 
-static const char *gcc_xo_gpll0[] = {
+static const char * const gcc_xo_gpll0[] = {
        "xo",
        "gpll0_vote",
 };
@@ -62,7 +62,7 @@ static const struct parent_map gcc_xo_gpll0_bimc_map[] = {
        { P_BIMC, 2 },
 };
 
-static const char *gcc_xo_gpll0_bimc[] = {
+static const char * const gcc_xo_gpll0_bimc[] = {
        "xo",
        "gpll0_vote",
        "bimc_pll_vote",
@@ -75,7 +75,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2a_map[] = {
        { P_GPLL2_AUX, 2 },
 };
 
-static const char *gcc_xo_gpll0a_gpll1_gpll2a[] = {
+static const char * const gcc_xo_gpll0a_gpll1_gpll2a[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -88,7 +88,7 @@ static const struct parent_map gcc_xo_gpll0_gpll2_map[] = {
        { P_GPLL2, 2 },
 };
 
-static const char *gcc_xo_gpll0_gpll2[] = {
+static const char * const gcc_xo_gpll0_gpll2[] = {
        "xo",
        "gpll0_vote",
        "gpll2_vote",
@@ -99,7 +99,7 @@ static const struct parent_map gcc_xo_gpll0a_map[] = {
        { P_GPLL0_AUX, 2 },
 };
 
-static const char *gcc_xo_gpll0a[] = {
+static const char * const gcc_xo_gpll0a[] = {
        "xo",
        "gpll0_vote",
 };
@@ -111,7 +111,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_sleep_map[] = {
        { P_SLEEP_CLK, 6 },
 };
 
-static const char *gcc_xo_gpll0_gpll1a_sleep[] = {
+static const char * const gcc_xo_gpll0_gpll1a_sleep[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -124,7 +124,7 @@ static const struct parent_map gcc_xo_gpll0_gpll1a_map[] = {
        { P_GPLL1_AUX, 2 },
 };
 
-static const char *gcc_xo_gpll0_gpll1a[] = {
+static const char * const gcc_xo_gpll0_gpll1a[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -135,7 +135,7 @@ static const struct parent_map gcc_xo_dsibyte_map[] = {
        { P_DSI0_PHYPLL_BYTE, 2 },
 };
 
-static const char *gcc_xo_dsibyte[] = {
+static const char * const gcc_xo_dsibyte[] = {
        "xo",
        "dsi0pllbyte",
 };
@@ -146,7 +146,7 @@ static const struct parent_map gcc_xo_gpll0a_dsibyte_map[] = {
        { P_DSI0_PHYPLL_BYTE, 1 },
 };
 
-static const char *gcc_xo_gpll0a_dsibyte[] = {
+static const char * const gcc_xo_gpll0a_dsibyte[] = {
        "xo",
        "gpll0_vote",
        "dsi0pllbyte",
@@ -158,7 +158,7 @@ static const struct parent_map gcc_xo_gpll0_dsiphy_map[] = {
        { P_DSI0_PHYPLL_DSI, 2 },
 };
 
-static const char *gcc_xo_gpll0_dsiphy[] = {
+static const char * const gcc_xo_gpll0_dsiphy[] = {
        "xo",
        "gpll0_vote",
        "dsi0pll",
@@ -170,7 +170,7 @@ static const struct parent_map gcc_xo_gpll0a_dsiphy_map[] = {
        { P_DSI0_PHYPLL_DSI, 1 },
 };
 
-static const char *gcc_xo_gpll0a_dsiphy[] = {
+static const char * const gcc_xo_gpll0a_dsiphy[] = {
        "xo",
        "gpll0_vote",
        "dsi0pll",
@@ -183,7 +183,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2_map[] = {
        { P_GPLL2, 2 },
 };
 
-static const char *gcc_xo_gpll0a_gpll1_gpll2[] = {
+static const char * const gcc_xo_gpll0a_gpll1_gpll2[] = {
        "xo",
        "gpll0_vote",
        "gpll1_vote",
@@ -2278,7 +2278,7 @@ static struct clk_branch gcc_prng_ahb_clk = {
        .halt_check = BRANCH_HALT_VOTED,
        .clkr = {
                .enable_reg = 0x45004,
-               .enable_mask = BIT(0),
+               .enable_mask = BIT(8),
                .hw.init = &(struct clk_init_data){
                        .name = "gcc_prng_ahb_clk",
                        .parent_names = (const char *[]){
index eb6a4f9fa107e9af98ab1991f50e22d4c8b503c5..aa294b1bad343ccbef5b4daef38cda33fd6513f1 100644 (file)
@@ -125,7 +125,7 @@ static const struct parent_map gcc_pxo_pll8_map[] = {
        { P_PLL8, 3 }
 };
 
-static const char *gcc_pxo_pll8[] = {
+static const char * const gcc_pxo_pll8[] = {
        "pxo",
        "pll8_vote",
 };
@@ -136,7 +136,7 @@ static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
        { P_CXO, 5 }
 };
 
-static const char *gcc_pxo_pll8_cxo[] = {
+static const char * const gcc_pxo_pll8_cxo[] = {
        "pxo",
        "pll8_vote",
        "cxo",
@@ -148,7 +148,7 @@ static const struct parent_map gcc_pxo_pll8_pll3_map[] = {
        { P_PLL3, 6 }
 };
 
-static const char *gcc_pxo_pll8_pll3[] = {
+static const char * const gcc_pxo_pll8_pll3[] = {
        "pxo",
        "pll8_vote",
        "pll3",
@@ -2085,7 +2085,7 @@ static struct clk_rcg usb_hsic_xcvr_fs_src = {
        }
 };
 
-static const char *usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" };
+static const char * const usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" };
 
 static struct clk_branch usb_hsic_xcvr_fs_clk = {
        .halt_reg = 0x2fc8,
@@ -2181,7 +2181,7 @@ static struct clk_rcg usb_fs1_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
+static const char * const usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
 
 static struct clk_branch usb_fs1_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
@@ -2248,7 +2248,7 @@ static struct clk_rcg usb_fs2_xcvr_fs_src = {
        }
 };
 
-static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
+static const char * const usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
 
 static struct clk_branch usb_fs2_xcvr_fs_clk = {
        .halt_reg = 0x2fcc,
index c39d09874e74d5d05a7f59e437ce5bb1f0ef8199..2bcf87538f9d7e34700d1a2e21b366e1618d4a5e 100644 (file)
@@ -44,7 +44,7 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
        { P_GPLL0, 1 }
 };
 
-static const char *gcc_xo_gpll0[] = {
+static const char * const gcc_xo_gpll0[] = {
        "xo",
        "gpll0_vote",
 };
@@ -55,7 +55,7 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
        { P_GPLL4, 5 }
 };
 
-static const char *gcc_xo_gpll0_gpll4[] = {
+static const char * const gcc_xo_gpll0_gpll4[] = {
        "xo",
        "gpll0_vote",
        "gpll4_vote",
@@ -1783,6 +1783,7 @@ static struct clk_branch gcc_ce1_clk = {
                                "ce1_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
index 47f0ac16d149c811d9f9ceca241e0d0468d09935..93ad42b1436604be66fcbb8081932879929fd823 100644 (file)
@@ -71,7 +71,7 @@ static const struct parent_map lcc_pxo_pll4_map[] = {
        { P_PLL4, 2 }
 };
 
-static const char *lcc_pxo_pll4[] = {
+static const char * const lcc_pxo_pll4[] = {
        "pxo",
        "pll4_vote",
 };
@@ -146,7 +146,7 @@ static struct clk_rcg mi2s_osr_src = {
        },
 };
 
-static const char *lcc_mi2s_parents[] = {
+static const char * const lcc_mi2s_parents[] = {
        "mi2s_osr_src",
 };
 
@@ -340,7 +340,7 @@ static struct clk_rcg spdif_src = {
        },
 };
 
-static const char *lcc_spdif_parents[] = {
+static const char * const lcc_spdif_parents[] = {
        "spdif_src",
 };
 
index d0df9d5fc3af0a8eda7349bff0a6179a841bfa09..ecb96c2846756e78185ad9b3be6b9d8d75218edc 100644 (file)
@@ -57,7 +57,7 @@ static const struct parent_map lcc_pxo_pll4_map[] = {
        { P_PLL4, 2 }
 };
 
-static const char *lcc_pxo_pll4[] = {
+static const char * const lcc_pxo_pll4[] = {
        "pxo",
        "pll4_vote",
 };
@@ -127,7 +127,7 @@ static struct clk_rcg mi2s_osr_src = {
        },
 };
 
-static const char *lcc_mi2s_parents[] = {
+static const char * const lcc_mi2s_parents[] = {
        "mi2s_osr_src",
 };
 
@@ -233,7 +233,7 @@ static struct clk_rcg prefix##_osr_src = {                  \
        },                                                      \
 };                                                             \
                                                                \
-static const char *lcc_##prefix##_parents[] = {                        \
+static const char * const lcc_##prefix##_parents[] = {         \
        #prefix "_osr_src",                                     \
 };                                                             \
                                                                \
@@ -445,7 +445,7 @@ static struct clk_rcg slimbus_src = {
        },
 };
 
-static const char *lcc_slimbus_parents[] = {
+static const char * const lcc_slimbus_parents[] = {
        "slimbus_src",
 };
 
index 1b17df2cb0afdd9350283fddbce43f048fb8acf3..f0ee6bde11af3b4e31d4566329c07004657414c1 100644 (file)
@@ -53,7 +53,7 @@ static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
        { P_GPLL0, 5 }
 };
 
-static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -69,7 +69,7 @@ static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
        { P_DSI1PLL, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "hdmipll",
@@ -86,7 +86,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = {
        { P_MMPLL2, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_2_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -102,7 +102,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
        { P_MMPLL3, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -119,7 +119,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -137,7 +137,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -155,7 +155,7 @@ static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL_BYTE, 2 }
 };
 
-static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -172,7 +172,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll0_map[] = {
        { P_MMPLL4, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_4_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_4_gpll0[] = {
        "xo",
        "mmpll0",
        "mmpll1",
@@ -189,7 +189,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_map[] = {
        { P_GPLL1, 4 }
 };
 
-static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = {
+static const char * const mmcc_xo_mmpll0_1_4_gpll1_0[] = {
        "xo",
        "mmpll0",
        "mmpll1",
@@ -208,7 +208,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = {
        { P_MMSLEEP, 6 }
 };
 
-static const char *mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
+static const char * const mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
        "xo",
        "mmpll0",
        "mmpll1",
index 9711bca9cc06aaf270ed2fb1c4195fa23eade8c2..bad02aebf959b6caed9b1941d8b9decf4152f7dd 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 #include <linux/reset-controller.h>
@@ -50,7 +51,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_map[] = {
        { P_PLL2, 1 }
 };
 
-static const char *mmcc_pxo_pll8_pll2[] = {
+static const char * const mmcc_pxo_pll8_pll2[] = {
        "pxo",
        "pll8_vote",
        "pll2",
@@ -63,7 +64,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_pll3_map[] = {
        { P_PLL3, 3 }
 };
 
-static const char *mmcc_pxo_pll8_pll2_pll15[] = {
+static const char * const mmcc_pxo_pll8_pll2_pll15[] = {
        "pxo",
        "pll8_vote",
        "pll2",
@@ -77,7 +78,7 @@ static const struct parent_map mmcc_pxo_pll8_pll2_pll15_map[] = {
        { P_PLL15, 3 }
 };
 
-static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+static const char * const mmcc_pxo_pll8_pll2_pll3[] = {
        "pxo",
        "pll8_vote",
        "pll2",
@@ -508,8 +509,7 @@ static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
        int ret = 0;
        u32 val;
        struct clk_pix_rdi *rdi = to_clk_pix_rdi(hw);
-       struct clk *clk = hw->clk;
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
 
        /*
         * These clocks select three inputs via two muxes. One mux selects
@@ -520,7 +520,8 @@ static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
         * needs to be on at what time.
         */
        for (i = 0; i < num_parents; i++) {
-               ret = clk_prepare_enable(clk_get_parent_by_index(clk, i));
+               struct clk_hw *p = clk_hw_get_parent_by_index(hw, i);
+               ret = clk_prepare_enable(p->clk);
                if (ret)
                        goto err;
        }
@@ -548,8 +549,10 @@ static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
        udelay(1);
 
 err:
-       for (i--; i >= 0; i--)
-               clk_disable_unprepare(clk_get_parent_by_index(clk, i));
+       for (i--; i >= 0; i--) {
+               struct clk_hw *p = clk_hw_get_parent_by_index(hw, i);
+               clk_disable_unprepare(p->clk);
+       }
 
        return ret;
 }
@@ -579,7 +582,7 @@ static const struct clk_ops clk_ops_pix_rdi = {
        .determine_rate = __clk_mux_determine_rate,
 };
 
-static const char *pix_rdi_parents[] = {
+static const char * const pix_rdi_parents[] = {
        "csi0_clk",
        "csi1_clk",
        "csi2_clk",
@@ -709,7 +712,7 @@ static struct clk_rcg csiphytimer_src = {
        },
 };
 
-static const char *csixphy_timer_src[] = { "csiphytimer_src" };
+static const char * const csixphy_timer_src[] = { "csiphytimer_src" };
 
 static struct clk_branch csiphy0_timer_clk = {
        .halt_reg = 0x01e8,
@@ -1385,7 +1388,7 @@ static const struct parent_map mmcc_pxo_hdmi_map[] = {
        { P_HDMI_PLL, 3 }
 };
 
-static const char *mmcc_pxo_hdmi[] = {
+static const char * const mmcc_pxo_hdmi[] = {
        "pxo",
        "hdmi_pll",
 };
@@ -1428,7 +1431,7 @@ static struct clk_rcg tv_src = {
        },
 };
 
-static const char *tv_src_name[] = { "tv_src" };
+static const char * const tv_src_name[] = { "tv_src" };
 
 static struct clk_branch tv_enc_clk = {
        .halt_reg = 0x01d4,
index 07f4cc159ad3103e79a955d26e085b596e34756c..0987bf443e1f3f57d6a0c36ff0702505abe10041 100644 (file)
@@ -56,7 +56,7 @@ static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
        { P_GPLL0, 5 }
 };
 
-static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -72,7 +72,7 @@ static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
        { P_DSI1PLL, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "hdmipll",
@@ -89,7 +89,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = {
        { P_MMPLL2, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_2_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -105,7 +105,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
        { P_MMPLL3, 3 }
 };
 
-static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -121,7 +121,7 @@ static const struct parent_map mmcc_xo_mmpll0_1_gpll1_0_map[] = {
        { P_GPLL1, 4 }
 };
 
-static const char *mmcc_xo_mmpll0_1_gpll1_0[] = {
+static const char * const mmcc_xo_mmpll0_1_gpll1_0[] = {
        "xo",
        "mmpll0_vote",
        "mmpll1_vote",
@@ -138,7 +138,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -156,7 +156,7 @@ static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL, 2 }
 };
 
-static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
@@ -174,7 +174,7 @@ static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
        { P_DSI1PLL_BYTE, 2 }
 };
 
-static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
        "xo",
        "edp_link_clk",
        "hdmipll",
index 2714097f90db1138b1f71771461b15932b826cce..b27edd6c8183378c8899d2dee22e42c913c4a46f 100644 (file)
@@ -6,8 +6,10 @@ obj-y  += clk-rockchip.o
 obj-y  += clk.o
 obj-y  += clk-pll.o
 obj-y  += clk-cpu.o
+obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
 
 obj-y  += clk-rk3188.o
 obj-y  += clk-rk3288.o
+obj-y  += clk-rk3368.o
index fb7721bd37e6a9595f70cbd8125fdab52fd2265e..330870a6d8bfa9163405398ff3de7e1eb0d8a864 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include "clk.h"
 
diff --git a/drivers/clk/rockchip/clk-inverter.c b/drivers/clk/rockchip/clk-inverter.c
new file mode 100644 (file)
index 0000000..7cbf43b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2015 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include "clk.h"
+
+struct rockchip_inv_clock {
+       struct clk_hw   hw;
+       void __iomem    *reg;
+       int             shift;
+       int             flags;
+       spinlock_t      *lock;
+};
+
+#define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
+
+#define INVERTER_MASK 0x1
+
+static int rockchip_inv_get_phase(struct clk_hw *hw)
+{
+       struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+       u32 val;
+
+       val = readl(inv_clock->reg) >> inv_clock->shift;
+       val &= INVERTER_MASK;
+       return val ? 180 : 0;
+}
+
+static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
+{
+       struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+       u32 val;
+
+       if (degrees % 180 == 0) {
+               val = !!degrees;
+       } else {
+               pr_err("%s: unsupported phase %d for %s\n",
+                      __func__, degrees, clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
+               writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
+                      inv_clock->reg);
+       } else {
+               unsigned long flags;
+               u32 reg;
+
+               spin_lock_irqsave(inv_clock->lock, flags);
+
+               reg = readl(inv_clock->reg);
+               reg &= ~BIT(inv_clock->shift);
+               reg |= val;
+               writel(reg, inv_clock->reg);
+
+               spin_unlock_irqrestore(inv_clock->lock, flags);
+       }
+
+       return 0;
+}
+
+static const struct clk_ops rockchip_inv_clk_ops = {
+       .get_phase      = rockchip_inv_get_phase,
+       .set_phase      = rockchip_inv_set_phase,
+};
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+                               const char *const *parent_names, u8 num_parents,
+                               void __iomem *reg, int shift, int flags,
+                               spinlock_t *lock)
+{
+       struct clk_init_data init;
+       struct rockchip_inv_clock *inv_clock;
+       struct clk *clk;
+
+       inv_clock = kmalloc(sizeof(*inv_clock), GFP_KERNEL);
+       if (!inv_clock)
+               return NULL;
+
+       init.name = name;
+       init.num_parents = num_parents;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.parent_names = parent_names;
+       init.ops = &rockchip_inv_clk_ops;
+
+       inv_clock->hw.init = &init;
+       inv_clock->reg = reg;
+       inv_clock->shift = shift;
+       inv_clock->flags = flags;
+       inv_clock->lock = lock;
+
+       clk = clk_register(NULL, &inv_clock->hw);
+       if (IS_ERR(clk))
+               goto err_free;
+
+       return clk;
+
+err_free:
+       kfree(inv_clock);
+       return NULL;
+}
index e9f8df324e7ccecad7730998d8210c8ea11a2276..9b613426e968ab6a0e36fdcb52b7c87ac076253b 100644 (file)
  */
 
 #include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include "clk.h"
 
 struct rockchip_mmc_clock {
@@ -105,7 +108,7 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
        writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg);
 
        pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
-               __clk_get_name(hw->clk), degrees, delay_num,
+               clk_hw_get_name(hw), degrees, delay_num,
                mmc_clock->reg, raw_value>>(mmc_clock->shift),
                rockchip_mmc_get_phase(hw)
        );
@@ -131,6 +134,7 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        if (!mmc_clock)
                return NULL;
 
+       init.name = name;
        init.num_parents = num_parents;
        init.parent_names = parent_names;
        init.ops = &rockchip_mmc_clk_ops;
@@ -139,9 +143,6 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        mmc_clock->reg = reg;
        mmc_clock->shift = shift;
 
-       if (name)
-               init.name = name;
-
        clk = clk_register(NULL, &mmc_clock->hw);
        if (IS_ERR(clk))
                goto err_free;
index 76027261f7ed999971f0b46ca10a4b4774d55bc3..7737a1df1e4ba09e9d0fb0ccf420be7219d780b4 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 #include "clk.h"
@@ -121,8 +120,8 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
 #define RK3066_PLLCON0_NR_SHIFT                8
 #define RK3066_PLLCON1_NF_MASK         0x1fff
 #define RK3066_PLLCON1_NF_SHIFT                0
-#define RK3066_PLLCON2_BWADJ_MASK      0xfff
-#define RK3066_PLLCON2_BWADJ_SHIFT     0
+#define RK3066_PLLCON2_NB_MASK         0xfff
+#define RK3066_PLLCON2_NB_SHIFT                0
 #define RK3066_PLLCON3_RESET           (1 << 5)
 #define RK3066_PLLCON3_PWRDOWN         (1 << 1)
 #define RK3066_PLLCON3_BYPASS          (1 << 0)
@@ -137,7 +136,7 @@ static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
        pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
        if (pllcon & RK3066_PLLCON3_BYPASS) {
                pr_debug("%s: pll %s is bypassed\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return prate;
        }
 
@@ -175,13 +174,13 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        }
 
        pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
-                __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+                __func__, clk_hw_get_name(hw), old_rate, drate, prate);
 
        /* Get required rate settings from table */
        rate = rockchip_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -208,8 +207,8 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,
                                                   RK3066_PLLCON1_NF_SHIFT),
                       pll->reg_base + RK3066_PLLCON(1));
-       writel_relaxed(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK,
-                                                 RK3066_PLLCON2_BWADJ_SHIFT),
+       writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK,
+                                                  RK3066_PLLCON2_NB_SHIFT),
                       pll->reg_base + RK3066_PLLCON(2));
 
        /* leave reset and wait the reset_delay */
@@ -262,14 +261,14 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
 {
        struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
        const struct rockchip_pll_rate_table *rate;
-       unsigned int nf, nr, no, bwadj;
+       unsigned int nf, nr, no, nb;
        unsigned long drate;
        u32 pllcon;
 
        if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
                return;
 
-       drate = __clk_get_rate(hw->clk);
+       drate = clk_hw_get_rate(hw);
        rate = rockchip_get_pll_settings(pll, drate);
 
        /* when no rate setting for the current rate, rely on clk_set_rate */
@@ -284,25 +283,25 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
        nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
 
        pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
-       bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK;
+       nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1;
 
-       pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n",
-                __func__, __clk_get_name(hw->clk), drate, rate->nr, nr,
-               rate->no, no, rate->nf, nf, rate->bwadj, bwadj);
+       pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
+                __func__, clk_hw_get_name(hw), drate, rate->nr, nr,
+               rate->no, no, rate->nf, nf, rate->nb, nb);
        if (rate->nr != nr || rate->no != no || rate->nf != nf
-                                            || rate->bwadj != bwadj) {
-               struct clk *parent = __clk_get_parent(hw->clk);
+                                            || rate->nb != nb) {
+               struct clk_hw *parent = clk_hw_get_parent(hw);
                unsigned long prate;
 
                if (!parent) {
                        pr_warn("%s: parent of %s not available\n",
-                               __func__, __clk_get_name(hw->clk));
+                               __func__, clk_hw_get_name(hw));
                        return;
                }
 
                pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
-                        __func__, __clk_get_name(hw->clk));
-               prate = __clk_get_rate(parent);
+                        __func__, clk_hw_get_name(hw));
+               prate = clk_hw_get_rate(parent);
                rockchip_rk3066_pll_set_rate(hw, drate, prate);
        }
 }
@@ -354,6 +353,35 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
        if (!pll)
                return ERR_PTR(-ENOMEM);
 
+       /* create the mux on top of the real pll */
+       pll->pll_mux_ops = &clk_mux_ops;
+       pll_mux = &pll->pll_mux;
+       pll_mux->reg = base + mode_offset;
+       pll_mux->shift = mode_shift;
+       pll_mux->mask = PLL_MODE_MASK;
+       pll_mux->flags = 0;
+       pll_mux->lock = lock;
+       pll_mux->hw.init = &init;
+
+       if (pll_type == pll_rk3066)
+               pll_mux->flags |= CLK_MUX_HIWORD_MASK;
+
+       /* the actual muxing is xin24m, pll-output, xin32k */
+       pll_parents[0] = parent_names[0];
+       pll_parents[1] = pll_name;
+       pll_parents[2] = parent_names[1];
+
+       init.name = name;
+       init.flags = CLK_SET_RATE_PARENT;
+       init.ops = pll->pll_mux_ops;
+       init.parent_names = pll_parents;
+       init.num_parents = ARRAY_SIZE(pll_parents);
+
+       mux_clk = clk_register(NULL, &pll_mux->hw);
+       if (IS_ERR(mux_clk))
+               goto err_mux;
+
+       /* now create the actual pll */
        init.name = pll_name;
 
        /* keep all plls untouched for now */
@@ -399,47 +427,19 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
        pll->flags = clk_pll_flags;
        pll->lock = lock;
 
-       /* create the mux on top of the real pll */
-       pll->pll_mux_ops = &clk_mux_ops;
-       pll_mux = &pll->pll_mux;
-       pll_mux->reg = base + mode_offset;
-       pll_mux->shift = mode_shift;
-       pll_mux->mask = PLL_MODE_MASK;
-       pll_mux->flags = 0;
-       pll_mux->lock = lock;
-       pll_mux->hw.init = &init;
-
-       if (pll_type == pll_rk3066)
-               pll_mux->flags |= CLK_MUX_HIWORD_MASK;
-
        pll_clk = clk_register(NULL, &pll->hw);
        if (IS_ERR(pll_clk)) {
                pr_err("%s: failed to register pll clock %s : %ld\n",
                        __func__, name, PTR_ERR(pll_clk));
-               mux_clk = pll_clk;
                goto err_pll;
        }
 
-       /* the actual muxing is xin24m, pll-output, xin32k */
-       pll_parents[0] = parent_names[0];
-       pll_parents[1] = pll_name;
-       pll_parents[2] = parent_names[1];
-
-       init.name = name;
-       init.flags = CLK_SET_RATE_PARENT;
-       init.ops = pll->pll_mux_ops;
-       init.parent_names = pll_parents;
-       init.num_parents = ARRAY_SIZE(pll_parents);
-
-       mux_clk = clk_register(NULL, &pll_mux->hw);
-       if (IS_ERR(mux_clk))
-               goto err_mux;
-
        return mux_clk;
 
-err_mux:
-       clk_unregister(pll_clk);
 err_pll:
+       clk_unregister(mux_clk);
+       mux_clk = pll_clk;
+err_mux:
        kfree(pll);
        return mux_clk;
 }
index e4f9d472f1ffb52f7ffb5f5061b39d56d519fb89..ed02bbc7b11f303a3d265003074ef022e545ddcf 100644 (file)
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -201,7 +202,7 @@ PNAME(mux_pll_src_cpll_gpll_p)      = { "cpll", "gpll" };
 PNAME(mux_aclk_cpu_p)          = { "apll", "gpll" };
 PNAME(mux_sclk_cif0_p)         = { "cif0_pre", "xin24m" };
 PNAME(mux_sclk_i2s0_p)         = { "i2s0_pre", "i2s0_frac", "xin12m" };
-PNAME(mux_sclk_spdif_p)                = { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_sclk_spdif_p)                = { "spdif_pre", "spdif_frac", "xin12m" };
 PNAME(mux_sclk_uart0_p)                = { "uart0_pre", "uart0_frac", "xin24m" };
 PNAME(mux_sclk_uart1_p)                = { "uart1_pre", "uart1_frac", "xin24m" };
 PNAME(mux_sclk_uart2_p)                = { "uart2_pre", "uart2_frac", "xin24m" };
@@ -235,6 +236,7 @@ static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
 #define MFLAGS CLK_MUX_HIWORD_MASK
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
 /* 2 ^ (val + 1) */
 static struct clk_div_table div_core_peri_t[] = {
@@ -310,6 +312,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 
        GATE(0, "pclkin_cif0", "ext_cif0", 0,
                        RK2928_CLKGATE_CON(3), 3, GFLAGS),
+       INVERTER(0, "pclk_cif0", "pclkin_cif0",
+                       RK2928_CLKSEL_CON(30), 8, IFLAGS),
 
        /*
         * the 480m are generated inside the usb block from these clocks,
@@ -334,8 +338,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
                        RK2928_CLKSEL_CON(23), 0,
                        RK2928_CLKGATE_CON(2), 7, GFLAGS),
-       MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
+       MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
                        RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+       INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+                       RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
        COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
                        RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
@@ -344,10 +350,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
                        RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
                        RK2928_CLKGATE_CON(0), 13, GFLAGS),
-       COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+       COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(9), 0,
                        RK2928_CLKGATE_CON(0), 14, GFLAGS),
-       MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+       MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
 
        /*
@@ -557,6 +563,8 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 
        GATE(0, "pclkin_cif1", "ext_cif1", 0,
                        RK2928_CLKGATE_CON(3), 4, GFLAGS),
+       INVERTER(0, "pclk_cif1", "pclkin_cif1",
+                       RK2928_CLKSEL_CON(30), 12, IFLAGS),
 
        COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
                        RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
@@ -809,7 +817,7 @@ static void __init rk3188_clk_init(struct device_node *np)
 
                rate = pll->rate_table;
                while (rate->rate > 0) {
-                       rate->bwadj = 0;
+                       rate->nb = 1;
                        rate++;
                }
        }
index 4f817ed9e6eedc432d0e6fd05adcb365e03e0f6b..0df5bae9ddbf062a0b3199ba7173eaedb2ab3fa1 100644 (file)
@@ -84,7 +84,7 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
        RK3066_PLL_RATE( 742500000, 8, 495, 2),
        RK3066_PLL_RATE( 696000000, 1, 58, 2),
        RK3066_PLL_RATE( 600000000, 1, 50, 2),
-       RK3066_PLL_RATE_BWADJ(594000000, 1, 198, 8, 1),
+       RK3066_PLL_RATE_NB(594000000, 1, 198, 8, 1),
        RK3066_PLL_RATE( 552000000, 1, 46, 2),
        RK3066_PLL_RATE( 504000000, 1, 84, 4),
        RK3066_PLL_RATE( 500000000, 3, 125, 2),
@@ -189,7 +189,7 @@ PNAME(mux_uart1_p)  = { "uart1_src", "uart1_frac", "xin24m" };
 PNAME(mux_uart2_p)     = { "uart2_src", "uart2_frac", "xin24m" };
 PNAME(mux_uart3_p)     = { "uart3_src", "uart3_frac", "xin24m" };
 PNAME(mux_uart4_p)     = { "uart4_src", "uart4_frac", "xin24m" };
-PNAME(mux_cif_out_p)   = { "cif_src", "xin24m" };
+PNAME(mux_vip_out_p)   = { "vip_src", "xin24m" };
 PNAME(mux_mac_p)       = { "mac_pll_src", "ext_gmac" };
 PNAME(mux_hsadcout_p)  = { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)   = { "ext_edp_24m", "xin24m" };
@@ -223,6 +223,7 @@ static struct clk_div_table div_hclk_cpu_t[] = {
 #define MFLAGS CLK_MUX_HIWORD_MASK
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
 static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        /*
@@ -434,7 +435,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
                        RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
                        RK3288_CLKGATE_CON(3), 7, GFLAGS),
-       COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0,
+       COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
                        RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
 
        DIV(0, "pclk_pd_alive", "gpll", 0,
@@ -578,7 +579,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
                        RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
                        RK3288_CLKGATE_CON(2), 5, GFLAGS),
-       MUX(SCLK_MAC, "mac_clk", mux_mac_p, 0,
+       MUX(SCLK_MAC, "mac_clk", mux_mac_p, CLK_SET_RATE_PARENT,
                        RK3288_CLKSEL_CON(21), 4, 1, MFLAGS),
        GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
                        RK3288_CLKGATE_CON(5), 3, GFLAGS),
@@ -592,8 +593,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0,
                        RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
                        RK3288_CLKGATE_CON(2), 6, GFLAGS),
-       MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0,
+       MUX(0, "sclk_hsadc_out", mux_hsadcout_p, 0,
                        RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+       INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+                       RK3288_CLKSEL_CON(22), 7, IFLAGS),
 
        GATE(0, "jtag", "ext_jtag", 0,
                        RK3288_CLKGATE_CON(4), 14, GFLAGS),
@@ -768,7 +771,9 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
         */
 
        GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
+       INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS),
        GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+       INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
 };
 
 static const char *const rk3288_critical_clocks[] __initconst = {
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
new file mode 100644 (file)
index 0000000..9c5d61e
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/rk3368-cru.h>
+#include "clk.h"
+
+#define RK3368_GRF_SOC_STATUS0 0x480
+
+enum rk3368_plls {
+       apllb, aplll, dpll, cpll, gpll, npll,
+};
+
+static struct rockchip_pll_rate_table rk3368_pll_rates[] = {
+       RK3066_PLL_RATE(2208000000, 1, 92, 1),
+       RK3066_PLL_RATE(2184000000, 1, 91, 1),
+       RK3066_PLL_RATE(2160000000, 1, 90, 1),
+       RK3066_PLL_RATE(2136000000, 1, 89, 1),
+       RK3066_PLL_RATE(2112000000, 1, 88, 1),
+       RK3066_PLL_RATE(2088000000, 1, 87, 1),
+       RK3066_PLL_RATE(2064000000, 1, 86, 1),
+       RK3066_PLL_RATE(2040000000, 1, 85, 1),
+       RK3066_PLL_RATE(2016000000, 1, 84, 1),
+       RK3066_PLL_RATE(1992000000, 1, 83, 1),
+       RK3066_PLL_RATE(1968000000, 1, 82, 1),
+       RK3066_PLL_RATE(1944000000, 1, 81, 1),
+       RK3066_PLL_RATE(1920000000, 1, 80, 1),
+       RK3066_PLL_RATE(1896000000, 1, 79, 1),
+       RK3066_PLL_RATE(1872000000, 1, 78, 1),
+       RK3066_PLL_RATE(1848000000, 1, 77, 1),
+       RK3066_PLL_RATE(1824000000, 1, 76, 1),
+       RK3066_PLL_RATE(1800000000, 1, 75, 1),
+       RK3066_PLL_RATE(1776000000, 1, 74, 1),
+       RK3066_PLL_RATE(1752000000, 1, 73, 1),
+       RK3066_PLL_RATE(1728000000, 1, 72, 1),
+       RK3066_PLL_RATE(1704000000, 1, 71, 1),
+       RK3066_PLL_RATE(1680000000, 1, 70, 1),
+       RK3066_PLL_RATE(1656000000, 1, 69, 1),
+       RK3066_PLL_RATE(1632000000, 1, 68, 1),
+       RK3066_PLL_RATE(1608000000, 1, 67, 1),
+       RK3066_PLL_RATE(1560000000, 1, 65, 1),
+       RK3066_PLL_RATE(1512000000, 1, 63, 1),
+       RK3066_PLL_RATE(1488000000, 1, 62, 1),
+       RK3066_PLL_RATE(1464000000, 1, 61, 1),
+       RK3066_PLL_RATE(1440000000, 1, 60, 1),
+       RK3066_PLL_RATE(1416000000, 1, 59, 1),
+       RK3066_PLL_RATE(1392000000, 1, 58, 1),
+       RK3066_PLL_RATE(1368000000, 1, 57, 1),
+       RK3066_PLL_RATE(1344000000, 1, 56, 1),
+       RK3066_PLL_RATE(1320000000, 1, 55, 1),
+       RK3066_PLL_RATE(1296000000, 1, 54, 1),
+       RK3066_PLL_RATE(1272000000, 1, 53, 1),
+       RK3066_PLL_RATE(1248000000, 1, 52, 1),
+       RK3066_PLL_RATE(1224000000, 1, 51, 1),
+       RK3066_PLL_RATE(1200000000, 1, 50, 1),
+       RK3066_PLL_RATE(1176000000, 1, 49, 1),
+       RK3066_PLL_RATE(1128000000, 1, 47, 1),
+       RK3066_PLL_RATE(1104000000, 1, 46, 1),
+       RK3066_PLL_RATE(1008000000, 1, 84, 2),
+       RK3066_PLL_RATE( 912000000, 1, 76, 2),
+       RK3066_PLL_RATE( 888000000, 1, 74, 2),
+       RK3066_PLL_RATE( 816000000, 1, 68, 2),
+       RK3066_PLL_RATE( 792000000, 1, 66, 2),
+       RK3066_PLL_RATE( 696000000, 1, 58, 2),
+       RK3066_PLL_RATE( 672000000, 1, 56, 2),
+       RK3066_PLL_RATE( 648000000, 1, 54, 2),
+       RK3066_PLL_RATE( 624000000, 1, 52, 2),
+       RK3066_PLL_RATE( 600000000, 1, 50, 2),
+       RK3066_PLL_RATE( 576000000, 1, 48, 2),
+       RK3066_PLL_RATE( 552000000, 1, 46, 2),
+       RK3066_PLL_RATE( 528000000, 1, 88, 4),
+       RK3066_PLL_RATE( 504000000, 1, 84, 4),
+       RK3066_PLL_RATE( 480000000, 1, 80, 4),
+       RK3066_PLL_RATE( 456000000, 1, 76, 4),
+       RK3066_PLL_RATE( 408000000, 1, 68, 4),
+       RK3066_PLL_RATE( 312000000, 1, 52, 4),
+       RK3066_PLL_RATE( 252000000, 1, 84, 8),
+       RK3066_PLL_RATE( 216000000, 1, 72, 8),
+       RK3066_PLL_RATE( 126000000, 2, 84, 8),
+       RK3066_PLL_RATE(  48000000, 2, 32, 8),
+       { /* sentinel */ },
+};
+
+PNAME(mux_pll_p)               = { "xin24m", "xin32k" };
+PNAME(mux_armclkb_p)           = { "apllb_core", "gpllb_core" };
+PNAME(mux_armclkl_p)           = { "aplll_core", "gplll_core" };
+PNAME(mux_ddrphy_p)            = { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_cs_src_p)            = { "apllb_cs", "aplll_cs", "gpll_cs"};
+PNAME(mux_aclk_bus_src_p)      = { "cpll_aclk_bus", "gpll_aclk_bus" };
+
+PNAME(mux_pll_src_cpll_gpll_p)         = { "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p)    = { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p)    = { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_usb_p)     = { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_usb_p) = { "cpll", "gpll", "usbphy_480m",
+                                           "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_npll_p)        = { "cpll", "gpll", "usbphy_480m",
+                                           "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_npll_p) = { "cpll", "gpll", "npll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_usb_p) = { "cpll", "gpll", "npll",
+                                           "usbphy_480m" };
+
+PNAME(mux_i2s_8ch_pre_p)       = { "i2s_8ch_src", "i2s_8ch_frac",
+                                   "ext_i2s", "xin12m" };
+PNAME(mux_i2s_8ch_clkout_p)    = { "i2s_8ch_pre", "xin12m" };
+PNAME(mux_i2s_2ch_p)           = { "i2s_2ch_src", "i2s_2ch_frac",
+                                   "dummy", "xin12m" };
+PNAME(mux_spdif_8ch_p)         = { "spdif_8ch_pre", "spdif_8ch_frac",
+                                   "ext_i2s", "xin12m" };
+PNAME(mux_edp_24m_p)           = { "dummy", "xin24m" };
+PNAME(mux_vip_out_p)           = { "vip_src", "xin24m" };
+PNAME(mux_usbphy480m_p)                = { "usbotg_out", "xin24m" };
+PNAME(mux_hsic_usbphy480m_p)   = { "usbotg_out", "dummy" };
+PNAME(mux_hsicphy480m_p)       = { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_uart0_p)             = { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)             = { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)             = { "uart2_src", "xin24m" };
+PNAME(mux_uart3_p)             = { "uart3_src", "uart3_frac", "xin24m" };
+PNAME(mux_uart4_p)             = { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_mac_p)               = { "mac_pll_src", "ext_gmac" };
+PNAME(mux_mmc_src_p)           = { "cpll", "gpll", "usbphy_480m", "xin24m" };
+
+static struct rockchip_pll_clock rk3368_pll_clks[] __initdata = {
+       [apllb] = PLL(pll_rk3066, PLL_APLLB, "apllb", mux_pll_p, 0, RK3368_PLL_CON(0),
+                    RK3368_PLL_CON(3), 8, 1, 0, rk3368_pll_rates),
+       [aplll] = PLL(pll_rk3066, PLL_APLLL, "aplll", mux_pll_p, 0, RK3368_PLL_CON(4),
+                    RK3368_PLL_CON(7), 8, 0, 0, rk3368_pll_rates),
+       [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3368_PLL_CON(8),
+                    RK3368_PLL_CON(11), 8, 2, 0, NULL),
+       [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3368_PLL_CON(12),
+                    RK3368_PLL_CON(15), 8, 3, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+       [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3368_PLL_CON(16),
+                    RK3368_PLL_CON(19), 8, 4, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+       [npll] = PLL(pll_rk3066, PLL_NPLL, "npll",  mux_pll_p, 0, RK3368_PLL_CON(20),
+                    RK3368_PLL_CON(23), 8, 5, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+};
+
+static struct clk_div_table div_ddrphy_t[] = {
+       { .val = 0, .div = 1 },
+       { .val = 1, .div = 2 },
+       { .val = 3, .div = 4 },
+       { /* sentinel */ },
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
+       .core_reg = RK3368_CLKSEL_CON(0),
+       .div_core_shift = 0,
+       .div_core_mask = 0x1f,
+       .mux_core_shift = 15,
+};
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
+       .core_reg = RK3368_CLKSEL_CON(2),
+       .div_core_shift = 0,
+       .div_core_mask = 0x1f,
+       .mux_core_shift = 7,
+};
+
+#define RK3368_DIV_ACLKM_MASK          0x1f
+#define RK3368_DIV_ACLKM_SHIFT         8
+#define RK3368_DIV_ATCLK_MASK          0x1f
+#define RK3368_DIV_ATCLK_SHIFT         0
+#define RK3368_DIV_PCLK_DBG_MASK       0x1f
+#define RK3368_DIV_PCLK_DBG_SHIFT      8
+
+#define RK3368_CLKSEL0(_offs, _aclkm)                                  \
+       {                                                               \
+               .reg = RK3288_CLKSEL_CON(0 + _offs),                    \
+               .val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK,     \
+                               RK3368_DIV_ACLKM_SHIFT),                \
+       }
+#define RK3368_CLKSEL1(_offs, _atclk, _pdbg)                           \
+       {                                                               \
+               .reg = RK3288_CLKSEL_CON(1 + _offs),                    \
+               .val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK,     \
+                               RK3368_DIV_ATCLK_SHIFT) |               \
+                      HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK,   \
+                               RK3368_DIV_PCLK_DBG_SHIFT),             \
+       }
+
+/* cluster_b: aclkm in clksel0, rest in clksel1 */
+#define RK3368_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg)             \
+       {                                                               \
+               .prate = _prate,                                        \
+               .divs = {                                               \
+                       RK3368_CLKSEL0(0, _aclkm),                      \
+                       RK3368_CLKSEL1(0, _atclk, _pdbg),               \
+               },                                                      \
+       }
+
+/* cluster_l: aclkm in clksel2, rest in clksel3 */
+#define RK3368_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg)             \
+       {                                                               \
+               .prate = _prate,                                        \
+               .divs = {                                               \
+                       RK3368_CLKSEL0(2, _aclkm),                      \
+                       RK3368_CLKSEL1(2, _atclk, _pdbg),               \
+               },                                                      \
+       }
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
+       RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
+       RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
+       RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
+       RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
+       RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
+       RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
+       RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
+       RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
+       RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
+       RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
+       RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
+       RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
+       RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
+       RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
+       RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
+       RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
+       RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
+       RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
+       RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
+       RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
+       /*
+        * Clock-Architecture Diagram 2
+        */
+
+       MUX(SCLK_USBPHY480M, "usbphy_480m", mux_usbphy480m_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(13), 8, 1, MFLAGS),
+
+       GATE(0, "apllb_core", "apllb", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 0, GFLAGS),
+       GATE(0, "gpllb_core", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 1, GFLAGS),
+
+       GATE(0, "aplll_core", "aplll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 4, GFLAGS),
+       GATE(0, "gplll_core", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 5, GFLAGS),
+
+       DIV(0, "aclkm_core_b", "armclkb", 0,
+                       RK3368_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "atclk_core_b", "armclkb", 0,
+                       RK3368_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "pclk_dbg_b", "armclkb", 0,
+                       RK3368_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+       DIV(0, "aclkm_core_l", "armclkl", 0,
+                       RK3368_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "atclk_core_l", "armclkl", 0,
+                       RK3368_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+       DIV(0, "pclk_dbg_l", "armclkl", 0,
+                       RK3368_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+       GATE(0, "apllb_cs", "apllb", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 9, GFLAGS),
+       GATE(0, "aplll_cs", "aplll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 10, GFLAGS),
+       GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(0), 8, GFLAGS),
+       COMPOSITE_NOGATE(0, "sclk_cs_pre", mux_cs_src_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS),
+       COMPOSITE_NOMUX(0, "clkin_trace", "sclk_cs_pre", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(4), 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(0), 13, GFLAGS),
+
+       COMPOSITE(0, "aclk_cci_pre", mux_pll_src_cpll_gpll_usb_npll_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(0), 12, GFLAGS),
+       GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3368_CLKGATE_CON(7), 10, GFLAGS),
+
+       GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 8, GFLAGS),
+       GATE(0, "gpll_ddr", "gpll", 0,
+                       RK3368_CLKGATE_CON(1), 9, GFLAGS),
+       COMPOSITE_NOGATE_DIVTBL(0, "ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(13), 4, 1, MFLAGS, 0, 2, DFLAGS, div_ddrphy_t),
+
+       GATE(0, "sclk_ddr", "ddrphy_div4", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(6), 14, GFLAGS),
+       GATE(0, "sclk_ddr4x", "ddrphy_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(6), 15, GFLAGS),
+
+       GATE(0, "gpll_aclk_bus", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 10, GFLAGS),
+       GATE(0, "cpll_aclk_bus", "cpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 11, GFLAGS),
+       COMPOSITE_NOGATE(0, "aclk_bus_src", mux_aclk_bus_src_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(8), 7, 1, MFLAGS, 0, 5, DFLAGS),
+
+       GATE(ACLK_BUS, "aclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(1), 0, GFLAGS),
+       COMPOSITE_NOMUX(PCLK_BUS, "pclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(8), 12, 3, DFLAGS,
+                       RK3368_CLKGATE_CON(1), 2, GFLAGS),
+       COMPOSITE_NOMUX(HCLK_BUS, "hclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(8), 8, 2, DFLAGS,
+                       RK3368_CLKGATE_CON(1), 1, GFLAGS),
+       COMPOSITE_NOMUX(0, "sclk_crypto", "aclk_bus_src", 0,
+                       RK3368_CLKSEL_CON(10), 14, 2, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 2, GFLAGS),
+
+       COMPOSITE(0, "fclk_mcu_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(1), 3, GFLAGS),
+       /*
+        * stclk_mcu is listed as child of fclk_mcu_src in diagram 5,
+        * but stclk_mcu has an additional own divider in diagram 2
+        */
+       COMPOSITE_NOMUX(0, "stclk_mcu", "fclk_mcu_src", 0,
+                       RK3368_CLKSEL_CON(12), 8, 3, DFLAGS,
+                       RK3368_CLKGATE_CON(13), 13, GFLAGS),
+
+       COMPOSITE(0, "i2s_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(27), 12, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 1, GFLAGS),
+       COMPOSITE_FRAC(0, "i2s_8ch_frac", "i2s_8ch_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(28), 0,
+                       RK3368_CLKGATE_CON(6), 2, GFLAGS),
+       MUX(0, "i2s_8ch_pre", mux_i2s_8ch_pre_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(27), 8, 2, MFLAGS),
+       COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "i2s_8ch_clkout", mux_i2s_8ch_clkout_p, 0,
+                       RK3368_CLKSEL_CON(27), 15, 1, MFLAGS,
+                       RK3368_CLKGATE_CON(6), 0, GFLAGS),
+       GATE(SCLK_I2S_8CH, "sclk_i2s_8ch", "i2s_8ch_pre", CLK_SET_RATE_PARENT,
+                       RK3368_CLKGATE_CON(6), 3, GFLAGS),
+       COMPOSITE(0, "spdif_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(31), 12, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 4, GFLAGS),
+       COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(32), 0,
+                       RK3368_CLKGATE_CON(6), 5, GFLAGS),
+       COMPOSITE_NODIV(SCLK_SPDIF_8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+                       RK3368_CLKSEL_CON(31), 8, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(6), 6, GFLAGS),
+       COMPOSITE(0, "i2s_2ch_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(53), 12, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 13, GFLAGS),
+       COMPOSITE_FRAC(0, "i2s_2ch_frac", "i2s_2ch_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(54), 0,
+                       RK3368_CLKGATE_CON(5), 14, GFLAGS),
+       COMPOSITE_NODIV(SCLK_I2S_2CH, "sclk_i2s_2ch", mux_i2s_2ch_p, 0,
+                       RK3368_CLKSEL_CON(53), 8, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(5), 15, GFLAGS),
+
+       COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0,
+                       RK3368_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 12, GFLAGS),
+       GATE(0, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0,
+                       RK3368_CLKGATE_CON(13), 7, GFLAGS),
+
+       MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(35), 12, 1, MFLAGS),
+       COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(37), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 4, GFLAGS),
+       MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(37), 8, 1, MFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 3
+        */
+
+       COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 6, GFLAGS),
+       COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 7, GFLAGS),
+
+       /*
+        * We introduce a virtual node of hclk_vodec_pre_v to split one clock
+        * struct with a gate and a fix divider into two node in software.
+        */
+       GATE(0, "hclk_video_pre_v", "aclk_vdpu", 0,
+               RK3368_CLKGATE_CON(4), 8, GFLAGS),
+
+       COMPOSITE(0, "sclk_hevc_cabac_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+                       RK3368_CLKSEL_CON(17), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 1, GFLAGS),
+       COMPOSITE(0, "sclk_hevc_core_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+                       RK3368_CLKSEL_CON(17), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 2, GFLAGS),
+
+       COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(19), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 0, GFLAGS),
+       DIV(0, "hclk_vio", "aclk_vio0", 0,
+                       RK3368_CLKSEL_CON(21), 0, 5, DFLAGS),
+
+       COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(18), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 3, GFLAGS),
+       COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_cpll_gpll_usb_p, 0,
+                       RK3368_CLKSEL_CON(18), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 4, GFLAGS),
+
+       COMPOSITE(DCLK_VOP, "dclk_vop", mux_pll_src_cpll_gpll_npll_p, 0,
+                       RK3368_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 1, GFLAGS),
+
+       GATE(SCLK_VOP0_PWM, "sclk_vop0_pwm", "xin24m", 0,
+                       RK3368_CLKGATE_CON(4), 2, GFLAGS),
+
+       COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+                       RK3368_CLKSEL_CON(22), 6, 2, MFLAGS, 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 9, GFLAGS),
+
+       GATE(0, "pclk_isp_in", "ext_isp", 0,
+                       RK3368_CLKGATE_CON(17), 2, GFLAGS),
+       INVERTER(PCLK_ISP, "pclk_isp", "pclk_isp_in",
+                       RK3368_CLKSEL_CON(21), 6, IFLAGS),
+
+       GATE(0, "pclk_vip_in", "ext_vip", 0,
+                       RK3368_CLKGATE_CON(16), 13, GFLAGS),
+       INVERTER(PCLK_VIP, "pclk_vip", "pclk_vip_in",
+                       RK3368_CLKSEL_CON(21), 13, IFLAGS),
+
+       GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
+                       RK3368_CLKGATE_CON(4), 13, GFLAGS),
+       GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
+                       RK3368_CLKGATE_CON(5), 12, GFLAGS),
+
+       COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
+                       RK3368_CLKGATE_CON(4), 5, GFLAGS),
+       COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
+                       RK3368_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS),
+
+       COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0,
+                       RK3368_CLKSEL_CON(23), 8, 1, MFLAGS,
+                       RK3368_CLKGATE_CON(5), 4, GFLAGS),
+       COMPOSITE(SCLK_EDP, "sclk_edp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+                       RK3368_CLKSEL_CON(23), 6, 2, MFLAGS, 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 3, GFLAGS),
+
+       COMPOSITE(SCLK_HDCP, "sclk_hdcp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+                       RK3368_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 5, GFLAGS),
+
+       DIV(0, "pclk_pd_alive", "gpll", 0,
+                       RK3368_CLKSEL_CON(10), 8, 5, DFLAGS),
+
+       /* sclk_timer has a gate in the sgrf */
+
+       COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(10), 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 9, GFLAGS),
+       GATE(SCLK_PVTM_PMU, "sclk_pvtm_pmu", "xin24m", 0,
+                       RK3368_CLKGATE_CON(7), 3, GFLAGS),
+       COMPOSITE(0, "sclk_gpu_core_src", mux_pll_src_cpll_gpll_usb_npll_p, 0,
+                       RK3368_CLKSEL_CON(14), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(4), 11, GFLAGS),
+       MUX(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(14), 14, 1, MFLAGS),
+       COMPOSITE_NOMUX(0, "aclk_gpu_mem_pre", "aclk_gpu_src", 0,
+                       RK3368_CLKSEL_CON(14), 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 8, GFLAGS),
+       COMPOSITE_NOMUX(0, "aclk_gpu_cfg_pre", "aclk_gpu_src", 0,
+                       RK3368_CLKSEL_CON(16), 8, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(5), 9, GFLAGS),
+       GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0,
+                       RK3368_CLKGATE_CON(7), 11, GFLAGS),
+
+       COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(9), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 0, GFLAGS),
+       COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+                       RK3368_CLKSEL_CON(9), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+                       RK3368_CLKGATE_CON(3), 3, GFLAGS),
+       COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKSEL_CON(9), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+                       RK3368_CLKGATE_CON(3), 2, GFLAGS),
+       GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(3), 1, GFLAGS),
+
+       GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3368_CLKGATE_CON(4), 14, GFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 4
+        */
+
+       COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(45), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 7, GFLAGS),
+       COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(45), 15, 1, MFLAGS, 8, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 8, GFLAGS),
+       COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(46), 15, 1, MFLAGS, 8, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 9, GFLAGS),
+
+
+       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
+                       RK3368_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 12, GFLAGS),
+       COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0,
+                       RK3368_CLKSEL_CON(48), 8, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 13, GFLAGS),
+       COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+                       RK3368_CLKSEL_CON(51), 8, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 15, GFLAGS),
+
+       MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3368_SDMMC_CON0, 1),
+       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3368_SDMMC_CON1, 0),
+
+       MMC(SCLK_SDIO0_DRV,    "sdio0_drv",    "sclk_sdio0", RK3368_SDIO0_CON0, 1),
+       MMC(SCLK_SDIO0_SAMPLE, "sdio0_sample", "sclk_sdio0", RK3368_SDIO0_CON1, 0),
+
+       MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3368_EMMC_CON0,  1),
+       MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3368_EMMC_CON1,  0),
+
+       GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(8), 1, GFLAGS),
+
+       /* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+       GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
+                       RK3368_CLKGATE_CON(8), 4, GFLAGS),
+
+       /* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+       COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0,
+                       RK3368_CLKSEL_CON(25), 0, 6, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 5, GFLAGS),
+
+       COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+                       RK3368_CLKSEL_CON(25), 8, 8, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 6, GFLAGS),
+
+       COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(47), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(7), 8, GFLAGS),
+
+       COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(52), 7, 1, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(6), 7, GFLAGS),
+
+       COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb_usb_p, 0,
+                       RK3368_CLKSEL_CON(33), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 0, GFLAGS),
+       COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(34), 0,
+                       RK3368_CLKGATE_CON(2), 1, GFLAGS),
+       MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(33), 8, 2, MFLAGS),
+
+       COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(35), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 2, GFLAGS),
+       COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(36), 0,
+                       RK3368_CLKGATE_CON(2), 3, GFLAGS),
+       MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(35), 8, 2, MFLAGS),
+
+       COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(39), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 6, GFLAGS),
+       COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(40), 0,
+                       RK3368_CLKGATE_CON(2), 7, GFLAGS),
+       MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(39), 8, 2, MFLAGS),
+
+       COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
+                       RK3368_CLKSEL_CON(41), 0, 7, DFLAGS,
+                       RK3368_CLKGATE_CON(2), 8, GFLAGS),
+       COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(42), 0,
+                       RK3368_CLKGATE_CON(2), 9, GFLAGS),
+       MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(41), 8, 2, MFLAGS),
+
+       COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
+                       RK3368_CLKSEL_CON(43), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3368_CLKGATE_CON(3), 4, GFLAGS),
+       MUX(SCLK_MAC, "mac_clk", mux_mac_p, CLK_SET_RATE_PARENT,
+                       RK3368_CLKSEL_CON(43), 8, 1, MFLAGS),
+       GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 7, GFLAGS),
+       GATE(SCLK_MACREF, "sclk_macref", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 6, GFLAGS),
+       GATE(SCLK_MAC_RX, "sclk_mac_rx", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 4, GFLAGS),
+       GATE(SCLK_MAC_TX, "sclk_mac_tx", "mac_clk", 0,
+                       RK3368_CLKGATE_CON(7), 5, GFLAGS),
+
+       GATE(0, "jtag", "ext_jtag", 0,
+                       RK3368_CLKGATE_CON(7), 0, GFLAGS),
+
+       COMPOSITE_NODIV(0, "hsic_usbphy_480m", mux_hsic_usbphy480m_p, 0,
+                       RK3368_CLKSEL_CON(26), 8, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(8), 0, GFLAGS),
+       COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
+                       RK3368_CLKSEL_CON(26), 12, 2, MFLAGS,
+                       RK3368_CLKGATE_CON(8), 7, GFLAGS),
+       GATE(SCLK_HSICPHY12M, "sclk_hsicphy12m", "xin12m", 0,
+                       RK3368_CLKGATE_CON(8), 6, GFLAGS),
+
+       /*
+        * Clock-Architecture Diagram 5
+        */
+
+       /* aclk_cci_pre gates */
+       GATE(0, "aclk_core_niu_cpup", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 4, GFLAGS),
+       GATE(0, "aclk_core_niu_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 3, GFLAGS),
+       GATE(0, "aclk_cci400", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 2, GFLAGS),
+       GATE(0, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 1, GFLAGS),
+       GATE(0, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 0, GFLAGS),
+
+       /* aclkm_core_* gates */
+       GATE(0, "aclk_adb400s_pd_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 0, GFLAGS),
+       GATE(0, "aclk_adb400s_pd_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 0, GFLAGS),
+
+       /* armclk* gates */
+       GATE(0, "sclk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 1, GFLAGS),
+       GATE(0, "sclk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 1, GFLAGS),
+
+       /* sclk_cs_pre gates */
+       GATE(0, "sclk_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 7, GFLAGS),
+       GATE(0, "pclk_core_niu_sdbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 6, GFLAGS),
+       GATE(0, "hclk_core_niu_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 5, GFLAGS),
+
+       /* aclk_bus gates */
+       GATE(0, "aclk_strc_sys", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 12, GFLAGS),
+       GATE(ACLK_DMAC_BUS, "aclk_dmac_bus", "aclk_bus", 0, RK3368_CLKGATE_CON(12), 11, GFLAGS),
+       GATE(0, "sclk_intmem1", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 6, GFLAGS),
+       GATE(0, "sclk_intmem0", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 5, GFLAGS),
+       GATE(0, "aclk_intmem", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 4, GFLAGS),
+       GATE(0, "aclk_gic400", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 9, GFLAGS),
+
+       /* sclk_ddr gates */
+       GATE(0, "nclk_ddrupctl", "sclk_ddr", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 2, GFLAGS),
+
+       /* clk_hsadc_tsp is part of diagram2 */
+
+       /* fclk_mcu_src gates */
+       GATE(0, "hclk_noc_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 14, GFLAGS),
+       GATE(0, "fclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 12, GFLAGS),
+       GATE(0, "hclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+       /* hclk_cpu gates */
+       GATE(HCLK_SPDIF, "hclk_spdif", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 10, GFLAGS),
+       GATE(HCLK_ROM, "hclk_rom", "hclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 9, GFLAGS),
+       GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 8, GFLAGS),
+       GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 7, GFLAGS),
+       GATE(HCLK_TSP, "hclk_tsp", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 10, GFLAGS),
+       GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 4, GFLAGS),
+       GATE(MCLK_CRYPTO, "mclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 3, GFLAGS),
+
+       /* pclk_cpu gates */
+       GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 14, GFLAGS),
+       GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 13, GFLAGS),
+       GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 3, GFLAGS),
+       GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 2, GFLAGS),
+       GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 1, GFLAGS),
+       GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 0, GFLAGS),
+       GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS),
+       GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS),
+       GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS),
+       GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS),
+       GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS),
+
+       /*
+        * video clk gates
+        * aclk_video(_pre) can actually select between parents of aclk_vdpu
+        * and aclk_vepu by setting bit GRF_SOC_CON0[7].
+        */
+       GATE(ACLK_VIDEO, "aclk_video", "aclk_vdpu", 0, RK3368_CLKGATE_CON(15), 0, GFLAGS),
+       GATE(SCLK_HEVC_CABAC, "sclk_hevc_cabac", "sclk_hevc_cabac_src", 0, RK3368_CLKGATE_CON(15), 3, GFLAGS),
+       GATE(SCLK_HEVC_CORE, "sclk_hevc_core", "sclk_hevc_core_src", 0, RK3368_CLKGATE_CON(15), 2, GFLAGS),
+       GATE(HCLK_VIDEO, "hclk_video", "hclk_video_pre", 0, RK3368_CLKGATE_CON(15), 1, GFLAGS),
+
+       /* aclk_rga_pre gates */
+       GATE(ACLK_VIO1_NOC, "aclk_vio1_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 10, GFLAGS),
+       GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(16), 0, GFLAGS),
+       GATE(ACLK_HDCP, "aclk_hdcp", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(17), 10, GFLAGS),
+
+       /* aclk_vio0 gates */
+       GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 11, GFLAGS),
+       GATE(ACLK_VIO0_NOC, "aclk_vio0_noc", "aclk_vio0", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 9, GFLAGS),
+       GATE(ACLK_VOP, "aclk_vop", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 5, GFLAGS),
+       GATE(ACLK_VOP_IEP, "aclk_vop_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 4, GFLAGS),
+       GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 2, GFLAGS),
+
+       /* sclk_isp gates */
+       GATE(HCLK_ISP, "hclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(16), 14, GFLAGS),
+       GATE(ACLK_ISP, "aclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+
+       /* hclk_vio gates */
+       GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 12, GFLAGS),
+       GATE(HCLK_VIO_NOC, "hclk_vio_noc", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 8, GFLAGS),
+       GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 7, GFLAGS),
+       GATE(HCLK_VOP, "hclk_vop", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 6, GFLAGS),
+       GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 3, GFLAGS),
+       GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 1, GFLAGS),
+       GATE(HCLK_VIO_HDCPMMU, "hclk_hdcpmmu", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 12, GFLAGS),
+       GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 7, GFLAGS),
+
+       /*
+        * pclk_vio gates
+        * pclk_vio comes from the exactly same source as hclk_vio
+        */
+       GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 11, GFLAGS),
+       GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 9, GFLAGS),
+       GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 8, GFLAGS),
+       GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 6, GFLAGS),
+       GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+       GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+
+       /* ext_vip gates in diagram3 */
+
+       /* gpu gates */
+       GATE(SCLK_GPU_CORE, "sclk_gpu_core", "sclk_gpu_core_src", 0, RK3368_CLKGATE_CON(18), 2, GFLAGS),
+       GATE(ACLK_GPU_MEM, "aclk_gpu_mem", "aclk_gpu_mem_pre", 0, RK3368_CLKGATE_CON(18), 1, GFLAGS),
+       GATE(ACLK_GPU_CFG, "aclk_gpu_cfg", "aclk_gpu_cfg_pre", 0, RK3368_CLKGATE_CON(18), 0, GFLAGS),
+
+       /* aclk_peri gates */
+       GATE(ACLK_DMAC_PERI, "aclk_dmac_peri", "aclk_peri", 0, RK3368_CLKGATE_CON(19), 3, GFLAGS),
+       GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 2, GFLAGS),
+       GATE(HCLK_SFC, "hclk_sfc", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 15, GFLAGS),
+       GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 13, GFLAGS),
+       GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 8, GFLAGS),
+       GATE(ACLK_PERI_MMU, "aclk_peri_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(21), 4, GFLAGS),
+
+       /* hclk_peri gates */
+       GATE(0, "hclk_peri_axi_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 0, GFLAGS),
+       GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 11, GFLAGS),
+       GATE(0, "hclk_mmc_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 10, GFLAGS),
+       GATE(0, "hclk_emem_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 9, GFLAGS),
+       GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 7, GFLAGS),
+       GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 6, GFLAGS),
+       GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 5, GFLAGS),
+       GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 4, GFLAGS),
+       GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 3, GFLAGS),
+       GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 2, GFLAGS),
+       GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 1, GFLAGS),
+       GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 3, GFLAGS),
+       GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 2, GFLAGS),
+       GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 1, GFLAGS),
+       GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 0, GFLAGS),
+
+       /* pclk_peri gates */
+       GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 15, GFLAGS),
+       GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 14, GFLAGS),
+       GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 13, GFLAGS),
+       GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 12, GFLAGS),
+       GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 11, GFLAGS),
+       GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 10, GFLAGS),
+       GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 9, GFLAGS),
+       GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 8, GFLAGS),
+       GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 7, GFLAGS),
+       GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 6, GFLAGS),
+       GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 5, GFLAGS),
+       GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 4, GFLAGS),
+       GATE(0, "pclk_peri_axi_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 1, GFLAGS),
+       GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 14, GFLAGS),
+       GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS),
+
+       /* pclk_pd_alive gates */
+       GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+       GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS),
+       GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS),
+       GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS),
+       GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS),
+       GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS),
+       GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS),
+
+       /*
+        * pclk_vio gates
+        * pclk_vio comes from the exactly same source as hclk_vio
+        */
+       GATE(0, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+       GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+
+       /* pclk_pd_pmu gates */
+       GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+       GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+       GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+       GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+       GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS),
+       GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+
+       /* timer gates */
+       GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
+       GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
+       GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
+       GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
+       GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
+       GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
+       GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
+       GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
+       GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
+       GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
+       GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
+       GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
+};
+
+static void __init rk3368_clk_init(struct device_node *np)
+{
+       void __iomem *reg_base;
+       struct clk *clk;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("%s: could not map cru region\n", __func__);
+               return;
+       }
+
+       rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+       /* xin12m is created by a cru-internal divider */
+       clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock xin12m: %ld\n",
+                       __func__, PTR_ERR(clk));
+
+       /* ddrphy_div4 is created by a cru-internal divider */
+       clk = clk_register_fixed_factor(NULL, "ddrphy_div4", "ddrphy_src", 0, 1, 4);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock xin12m: %ld\n",
+                       __func__, PTR_ERR(clk));
+
+       clk = clk_register_fixed_factor(NULL, "hclk_video_pre",
+                                       "hclk_video_pre_v", 0, 1, 4);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
+                       __func__, PTR_ERR(clk));
+
+       /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
+       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
+       if (IS_ERR(clk))
+               pr_warn("%s: could not register clock pclk_wdt: %ld\n",
+                       __func__, PTR_ERR(clk));
+       else
+               rockchip_clk_add_lookup(clk, PCLK_WDT);
+
+       rockchip_clk_register_plls(rk3368_pll_clks,
+                                  ARRAY_SIZE(rk3368_pll_clks),
+                                  RK3368_GRF_SOC_STATUS0);
+       rockchip_clk_register_branches(rk3368_clk_branches,
+                                 ARRAY_SIZE(rk3368_clk_branches));
+
+       rockchip_clk_register_armclk(ARMCLKB, "armclkb",
+                       mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
+                       &rk3368_cpuclkb_data, rk3368_cpuclkb_rates,
+                       ARRAY_SIZE(rk3368_cpuclkb_rates));
+
+       rockchip_clk_register_armclk(ARMCLKL, "armclkl",
+                       mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+                       &rk3368_cpuclkl_data, rk3368_cpuclkl_rates,
+                       ARRAY_SIZE(rk3368_cpuclkl_rates));
+
+       rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
+                                 ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+       rockchip_register_restart_notifier(RK3368_GLB_SRST_FST);
+}
+CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
index 052b94db0ff93a690dda50339b81ad673c00fadd..24938815655fa847512bf2e970589e112a7d35f7 100644 (file)
@@ -277,6 +277,13 @@ void __init rockchip_clk_register_branches(
                                list->div_shift
                        );
                        break;
+               case branch_inverter:
+                       clk = rockchip_clk_register_inverter(
+                               list->name, list->parent_names,
+                               list->num_parents,
+                               reg_base + list->muxdiv_offset,
+                               list->div_shift, list->div_flags, &clk_lock);
+                       break;
                }
 
                /* none of the cases above matched */
index 6b092673048a2514399bd07cf156aefb081fb56a..dc8ecb2673b7b2a249befe3de93a4b39493f3134 100644 (file)
 #define CLK_ROCKCHIP_CLK_H
 
 #include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
+
+struct clk;
 
 #define HIWORD_UPDATE(val, mask, shift) \
                ((val) << (shift) | (mask) << ((shift) + 16))
 
 /* register positions shared by RK2928, RK3066 and RK3188 */
-#define RK2928_PLL_CON(x)              (x * 0x4)
+#define RK2928_PLL_CON(x)              ((x) * 0x4)
 #define RK2928_MODE_CON                0x40
-#define RK2928_CLKSEL_CON(x)   (x * 0x4 + 0x44)
-#define RK2928_CLKGATE_CON(x)  (x * 0x4 + 0xd0)
+#define RK2928_CLKSEL_CON(x)   ((x) * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x)  ((x) * 0x4 + 0xd0)
 #define RK2928_GLB_SRST_FST            0x100
 #define RK2928_GLB_SRST_SND            0x104
-#define RK2928_SOFTRST_CON(x)  (x * 0x4 + 0x110)
+#define RK2928_SOFTRST_CON(x)  ((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON                0x134
 
 #define RK3288_PLL_CON(x)              RK2928_PLL_CON(x)
 #define RK3288_MODE_CON                        0x50
-#define RK3288_CLKSEL_CON(x)           (x * 0x4 + 0x60)
-#define RK3288_CLKGATE_CON(x)          (x * 0x4 + 0x160)
+#define RK3288_CLKSEL_CON(x)           ((x) * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x)          ((x) * 0x4 + 0x160)
 #define RK3288_GLB_SRST_FST            0x1b0
 #define RK3288_GLB_SRST_SND            0x1b4
-#define RK3288_SOFTRST_CON(x)          (x * 0x4 + 0x1b8)
+#define RK3288_SOFTRST_CON(x)          ((x) * 0x4 + 0x1b8)
 #define RK3288_MISC_CON                        0x1e8
 #define RK3288_SDMMC_CON0              0x200
 #define RK3288_SDMMC_CON1              0x204
 #define RK3288_EMMC_CON0               0x218
 #define RK3288_EMMC_CON1               0x21c
 
+#define RK3368_PLL_CON(x)              RK2928_PLL_CON(x)
+#define RK3368_CLKSEL_CON(x)           ((x) * 0x4 + 0x100)
+#define RK3368_CLKGATE_CON(x)          ((x) * 0x4 + 0x200)
+#define RK3368_GLB_SRST_FST            0x280
+#define RK3368_GLB_SRST_SND            0x284
+#define RK3368_SOFTRST_CON(x)          ((x) * 0x4 + 0x300)
+#define RK3368_MISC_CON                        0x380
+#define RK3368_SDMMC_CON0              0x400
+#define RK3368_SDMMC_CON1              0x404
+#define RK3368_SDIO0_CON0              0x408
+#define RK3368_SDIO0_CON1              0x40c
+#define RK3368_SDIO1_CON0              0x410
+#define RK3368_SDIO1_CON1              0x414
+#define RK3368_EMMC_CON0               0x418
+#define RK3368_EMMC_CON1               0x41c
+
 enum rockchip_pll_type {
        pll_rk3066,
 };
@@ -67,16 +83,16 @@ enum rockchip_pll_type {
        .nr = _nr,                              \
        .nf = _nf,                              \
        .no = _no,                              \
-       .bwadj = (_nf >> 1),                    \
+       .nb = ((_nf) < 2) ? 1 : (_nf) >> 1,     \
 }
 
-#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw)       \
+#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb)          \
 {                                                              \
        .rate   = _rate##U,                                     \
        .nr = _nr,                                              \
        .nf = _nf,                                              \
        .no = _no,                                              \
-       .bwadj = _bw,                                           \
+       .nb = _nb,                                              \
 }
 
 struct rockchip_pll_rate_table {
@@ -84,7 +100,7 @@ struct rockchip_pll_rate_table {
        unsigned int nr;
        unsigned int nf;
        unsigned int no;
-       unsigned int bwadj;
+       unsigned int nb;
 };
 
 /**
@@ -182,6 +198,13 @@ struct clk *rockchip_clk_register_mmc(const char *name,
                                const char *const *parent_names, u8 num_parents,
                                void __iomem *reg, int shift);
 
+#define ROCKCHIP_INVERTER_HIWORD_MASK  BIT(0)
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+                               const char *const *parent_names, u8 num_parents,
+                               void __iomem *reg, int shift, int flags,
+                               spinlock_t *lock);
+
 #define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
@@ -191,6 +214,7 @@ enum rockchip_clk_branch_type {
        branch_fraction_divider,
        branch_gate,
        branch_mmc,
+       branch_inverter,
 };
 
 struct rockchip_clk_branch {
@@ -308,6 +332,26 @@ struct rockchip_clk_branch {
                .gate_offset    = -1,                           \
        }
 
+#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \
+                               mw, mf, ds, dw, df, dt)         \
+       {                                                       \
+               .id             = _id,                          \
+               .branch_type    = branch_composite,             \
+               .name           = cname,                        \
+               .parent_names   = pnames,                       \
+               .num_parents    = ARRAY_SIZE(pnames),           \
+               .flags          = f,                            \
+               .muxdiv_offset  = mo,                           \
+               .mux_shift      = ms,                           \
+               .mux_width      = mw,                           \
+               .mux_flags      = mf,                           \
+               .div_shift      = ds,                           \
+               .div_width      = dw,                           \
+               .div_flags      = df,                           \
+               .div_table      = dt,                           \
+               .gate_offset    = -1,                           \
+       }
+
 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
        {                                                       \
                .id             = _id,                          \
@@ -394,6 +438,18 @@ struct rockchip_clk_branch {
                .div_shift      = shift,                        \
        }
 
+#define INVERTER(_id, cname, pname, io, is, if)                        \
+       {                                                       \
+               .id             = _id,                          \
+               .branch_type    = branch_inverter,              \
+               .name           = cname,                        \
+               .parent_names   = (const char *[]){ pname },    \
+               .num_parents    = 1,                            \
+               .muxdiv_offset  = io,                           \
+               .div_shift      = is,                           \
+               .div_flags      = if,                           \
+       }
+
 void rockchip_clk_init(struct device_node *np, void __iomem *base,
                       unsigned long nr_clks);
 struct regmap *rockchip_clk_get_grf(void);
index 3a1fe07cfe9e7b306ddd2eebd22531f81492a512..7c1e1f58e2da2e7dc7909fce407bc477651add3a 100644 (file)
@@ -33,6 +33,9 @@
 */
 
 #include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include "clk-cpu.h"
 
 #define E4210_SRC_CPU          0x0
@@ -97,8 +100,8 @@ static void wait_until_mux_stable(void __iomem *mux_reg, u32 mux_pos,
 static long exynos_cpuclk_round_rate(struct clk_hw *hw,
                        unsigned long drate, unsigned long *prate)
 {
-       struct clk *parent = __clk_get_parent(hw->clk);
-       *prate = __clk_round_rate(parent, drate);
+       struct clk_hw *parent = clk_hw_get_parent(hw);
+       *prate = clk_hw_round_rate(parent, drate);
        return *prate;
 }
 
index 454b02ae486a86917f31614c2c4b016841deefaa..4e9584d79089d355fcc67b4154724f4d6cc2ed62 100644 (file)
@@ -9,8 +9,9 @@
  * Common Clock Framework support for Audio Subsystem Clock Controller.
 */
 
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index 03a52228b6d1f1a4a280fcca7862b2aea2b79c0d..7cd02ff37a1f6919fea89e6c1a6306fd3695dc28 100644 (file)
@@ -9,8 +9,8 @@
  * Clock driver for Exynos clock output
  */
 
+#include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 538de66a759e12092e70b385e579bbc112133ca3..fdd41b17a24fc590254768e346f10d7e0b253321 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for Exynos3250 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -19,6 +17,7 @@
 #include <dt-bindings/clock/exynos3250.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 #include "clk-pll.h"
 
 #define SRC_LEFTBUS            0x4200
@@ -319,8 +318,10 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
        MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p,
            SRC_CPU, 24, 1),
        MUX(CLK_MOUT_HPM, "mout_hpm", mout_hpm_p, SRC_CPU, 20, 1),
-       MUX(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1),
-       MUX(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
+       MUX_F(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+                       CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock div_clks[] __initdata = {
@@ -772,6 +773,26 @@ static struct samsung_cmu_info cmu_info __initdata = {
        .nr_clk_regs            = ARRAY_SIZE(exynos3250_cmu_clk_regs),
 };
 
+#define E3250_CPU_DIV0(apll, pclk_dbg, atb, corem)                     \
+               (((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) |  \
+               ((corem) << 4))
+#define E3250_CPU_DIV1(hpm, copy)                                      \
+               (((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data e3250_armclk_d[] __initconst = {
+       { 1000000, E3250_CPU_DIV0(1, 7, 4, 1), E3250_CPU_DIV1(7, 7), },
+       {  900000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  800000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  700000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  600000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  500000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  400000, E3250_CPU_DIV0(1, 7, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  300000, E3250_CPU_DIV0(1, 5, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  200000, E3250_CPU_DIV0(1, 3, 3, 1), E3250_CPU_DIV1(7, 7), },
+       {  100000, E3250_CPU_DIV0(1, 1, 1, 1), E3250_CPU_DIV1(7, 7), },
+       {  0 },
+};
+
 static void __init exynos3250_cmu_init(struct device_node *np)
 {
        struct samsung_clk_provider *ctx;
@@ -780,6 +801,11 @@ static void __init exynos3250_cmu_init(struct device_node *np)
        if (!ctx)
                return;
 
+       exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+                       mout_core_p[0], mout_core_p[1], 0x14200,
+                       e3250_armclk_d, ARRAY_SIZE(e3250_armclk_d),
+                       CLK_CPU_HAS_DIV1);
+
        exynos3_core_down_clock(ctx->reg_base);
 }
 CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
index cae2c048488db3e7a4c3545c81faa50f450797d7..251f48dcd12d5fa344a80d370bd6177c7f705091 100644 (file)
@@ -11,8 +11,8 @@
 */
 
 #include <dt-bindings/clock/exynos4.h>
+#include <linux/slab.h>
 #include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -86,6 +86,7 @@
 #define DIV_PERIL4             0xc560
 #define DIV_PERIL5             0xc564
 #define E4X12_DIV_CAM1         0xc568
+#define E4X12_GATE_BUS_FSYS1   0xc744
 #define GATE_SCLK_CAM          0xc820
 #define GATE_IP_CAM            0xc920
 #define GATE_IP_TV             0xc924
@@ -1097,6 +1098,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
                0),
        GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4X12_GATE_IP_IMAGE, 9, 0,
                0),
+       GATE(CLK_TSADC, "tsadc", "aclk133", E4X12_GATE_BUS_FSYS1, 16, 0, 0),
        GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
        GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
        GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
index 6c78b09c829f9148453f56d4f05981452f91487c..92c39f6efec82a1617881e2dd75d3261dcc4d007 100644 (file)
@@ -9,8 +9,6 @@
  * Common Clock Framework support for Exynos4415 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 70ec3d2608a17e2f282e65dc198cd6af9c3fbbb9..55b83c7ef878bfa8c3fbb683fc6ba329db4a58c3 100644 (file)
 */
 
 #include <dt-bindings/clock/exynos5250.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 
 #define APLL_LOCK              0x0
 #define APLL_CON0              0x100
@@ -748,6 +747,32 @@ static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
                VPLL_LOCK, VPLL_CON0, NULL),
 };
 
+#define E5250_CPU_DIV0(apll, pclk_dbg, atb, periph, acp, cpud)         \
+               ((((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
+                ((periph) << 12) | ((acp) << 8) | ((cpud) << 4)))
+#define E5250_CPU_DIV1(hpm, copy)                                      \
+               (((hpm) << 4) | (copy))
+
+static const struct exynos_cpuclk_cfg_data exynos5250_armclk_d[] __initconst = {
+       { 1700000, E5250_CPU_DIV0(5, 3, 7, 7, 7, 3), E5250_CPU_DIV1(2, 0), },
+       { 1600000, E5250_CPU_DIV0(4, 1, 7, 7, 7, 3), E5250_CPU_DIV1(2, 0), },
+       { 1500000, E5250_CPU_DIV0(4, 1, 7, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1400000, E5250_CPU_DIV0(4, 1, 6, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1300000, E5250_CPU_DIV0(3, 1, 6, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1200000, E5250_CPU_DIV0(3, 1, 5, 7, 7, 2), E5250_CPU_DIV1(2, 0), },
+       { 1100000, E5250_CPU_DIV0(3, 1, 5, 7, 7, 3), E5250_CPU_DIV1(2, 0), },
+       { 1000000, E5250_CPU_DIV0(2, 1, 4, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  900000, E5250_CPU_DIV0(2, 1, 4, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  800000, E5250_CPU_DIV0(2, 1, 4, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  700000, E5250_CPU_DIV0(1, 1, 3, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  600000, E5250_CPU_DIV0(1, 1, 3, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  500000, E5250_CPU_DIV0(1, 1, 2, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  400000, E5250_CPU_DIV0(1, 1, 2, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  300000, E5250_CPU_DIV0(1, 1, 1, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  200000, E5250_CPU_DIV0(1, 1, 1, 7, 7, 1), E5250_CPU_DIV1(2, 0), },
+       {  0 },
+};
+
 static const struct of_device_id ext_clk_match[] __initconst = {
        { .compatible = "samsung,clock-xxti", .data = (void *)0, },
        { },
@@ -797,6 +822,10 @@ static void __init exynos5250_clk_init(struct device_node *np)
                        ARRAY_SIZE(exynos5250_div_clks));
        samsung_clk_register_gate(ctx, exynos5250_gate_clks,
                        ARRAY_SIZE(exynos5250_gate_clks));
+       exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+                       mout_cpu_p[0], mout_cpu_p[1], 0x200,
+                       exynos5250_armclk_d, ARRAY_SIZE(exynos5250_armclk_d),
+                       CLK_CPU_HAS_DIV1);
 
        /*
         * Enable arm clock down (in idle) and set arm divider
index 06f96eb7cf93c5b4c7d946d41b57b30078042db2..d1a29f6c10849f0a0023c7a040a9b55248c81e9a 100644 (file)
@@ -9,8 +9,6 @@
  * Common Clock Framework support for Exynos5260 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
index 231475bc2b99604ef16351ba49a3874c61d974b3..d5d5dcabc4a968c490a768634f28d8cd04327c93 100644 (file)
@@ -11,8 +11,6 @@
 
 #include <dt-bindings/clock/exynos5410.h>
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index a1d731ca8f48587870753182a1ef76db82072686..389af3c15ec450bf9bf8e8526dca3cf00c958a57 100644 (file)
@@ -11,8 +11,7 @@
 */
 
 #include <dt-bindings/clock/exynos5420.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 39c95649d3d016d14da7500e5b5ea188860252c9..cee062c588dec2c2471b55c4c2b60a44d20ec42f 100644 (file)
@@ -9,8 +9,6 @@
  * Common Clock Framework support for Exynos5443 SoC.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 
index 979e81389cdd04bf668f6982ea2ceee5ebb17f82..590813871ffe2bf80ab33be555ce036ea131d6b5 100644 (file)
@@ -10,8 +10,6 @@
 */
 
 #include <dt-bindings/clock/exynos5440.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 03d36e847b78e067d16bdfe1758df10560c4a2b4..8524e667097e062cf426a1e4b18cd1eb0c90e708 100644 (file)
@@ -8,8 +8,6 @@
  *
 */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 
index bebc61b5fce1f3741200bf146e6dd059a222f5b9..b7dd396100d8118381caebffade2ff7e3acf831d 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/errno.h>
 #include <linux/hrtimer.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
 #include "clk.h"
 #include "clk-pll.h"
 
@@ -180,7 +182,7 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -288,7 +290,7 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -403,7 +405,7 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -455,7 +457,7 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
 
                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
                        pr_err("%s: could not lock PLL %s\n",
-                                       __func__, __clk_get_name(hw->clk));
+                                       __func__, clk_hw_get_name(hw));
                        return -EFAULT;
                }
 
@@ -554,7 +556,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -614,7 +616,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
 
                if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
                        pr_err("%s: could not lock PLL %s\n",
-                                       __func__, __clk_get_name(hw->clk));
+                                       __func__, clk_hw_get_name(hw));
                        return -EFAULT;
                }
 
@@ -772,7 +774,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -1013,7 +1015,7 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
@@ -1111,7 +1113,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
        rate = samsung_get_pll_settings(pll, drate);
        if (!rate) {
                pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
-                       drate, __clk_get_name(hw->clk));
+                       drate, clk_hw_get_name(hw));
                return -EINVAL;
        }
 
index e56df5064889e00530ddf8c531e29539debecc76..e9eb935d7616b370717deb858e7196310ab7b5fe 100644 (file)
@@ -8,6 +8,10 @@
  * Common Clock Framework support for s3c24xx external clock output.
  */
 
+#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include "clk.h"
@@ -57,7 +61,7 @@ struct s3c24xx_clkout {
 static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
 {
        struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
        val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift;
index 5d2f03461bc5d2fe6cf4acd6ef11b379ef25e0bd..0945a8852299d5f779bcaba6827efae37cb6653b 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for S3C2410 and following SoCs.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 2ceedaf8ce18a6e411cc3e229f311805939535cd..44d6a9f4f5b2f7d1d203f7257d708f6dc42d7590 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for S3C2412 and S3C2413.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 0c3c182b902af709313d69f72477b9f46f187e89..2c0a1ea3c80c7eda87d73b2d0aeb6375009c9e8a 100644 (file)
@@ -8,8 +8,6 @@
  * Common Clock Framework support for S3C2443 and following SoCs.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 0f590e5550cb237ed1e73c836205ef501d723a78..d325ed1e196bf4f536938edb12dce790666fa3db 100644 (file)
@@ -8,8 +8,7 @@
  * Common Clock Framework support for all S3C64xx SoCs.
 */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index de4455b75e8a3be51c22d4064b83a066a7bc4fc6..eefb84b2256650294618b168a23b60d4ca170f74 100644 (file)
@@ -13,8 +13,8 @@
  * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
 */
 
-#include <linux/clkdev.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
index cf7e8fa7b624c701511d7cefadb4c721221ec1bd..759aaf342bea986db7414374e6805df2bf24aa5e 100644 (file)
@@ -11,8 +11,6 @@
  * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -828,6 +826,8 @@ static void __init __s5pv210_clk_init(struct device_node *np,
 
        s5pv210_clk_sleep_init();
 
+       samsung_clk_of_add_provider(np, ctx);
+
        pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
                "\tmout_epll = %ld, mout_vpll = %ld\n",
                is_s5p6442 ? "S5P6442" : "S5PV210",
index 0117238391d6532b5b332a0ba09d319b693c03aa..f38a6c49f7449cc1293910ec5c9eacf8df8544aa 100644 (file)
  * clock framework for Samsung platforms.
 */
 
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
 
index b775fc29caa507dcaccfa1e54d78fef2f7d4a45b..aa872d2c51052a7f81181aabd57b249c55ea0afc 100644 (file)
 #ifndef __SAMSUNG_CLK_H
 #define __SAMSUNG_CLK_H
 
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include "clk-pll.h"
 
+struct clk;
+
 /**
  * struct samsung_clk_provider: information about clock provider
  * @reg_base: virtual address for the register base.
index 036a692c72195db93760e40dc1fcb1928b1ecded..b4c8d6746f68a7b843efef38de7f6941483690e2 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 
 #define CPG_DIV6_CKSTP         BIT(8)
 #define CPG_DIV6_DIV(d)                ((d) & 0x3f)
@@ -133,13 +133,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
 
        hw_index = (clk_readl(clock->reg) >> clock->src_shift) &
                   (BIT(clock->src_width) - 1);
-       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
+       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
                if (clock->parents[i] == hw_index)
                        return i;
        }
 
        pr_err("%s: %s DIV6 clock set to invalid parent %u\n",
-              __func__, __clk_get_name(hw->clk), hw_index);
+              __func__, clk_hw_get_name(hw), hw_index);
        return 0;
 }
 
@@ -149,7 +149,7 @@ static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
        u8 hw_index;
        u32 mask;
 
-       if (index >= __clk_get_num_parents(hw->clk))
+       if (index >= clk_hw_get_num_parents(hw))
                return -EINVAL;
 
        mask = ~((BIT(clock->src_width) - 1) << clock->src_shift);
index 29b9a0b0012ad3260d882be6d5dbb40f3fabaf0d..9326204bed9d6cb7734cfb7b84b80252abcaba7a 100644 (file)
@@ -9,10 +9,10 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/spinlock.h>
index 1e2eaae21e01947b1d2998fd80c3184d32020de3..1e6b1da580658f46e6fc31f42c054760e52e0af6 100644 (file)
@@ -9,10 +9,10 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/spinlock.h>
index cb33b57274bf9f55c016637bddd410610fc6dd26..e97e28fcfc13d102d5ea75566dd4eb97a59a83d4 100644 (file)
@@ -9,9 +9,9 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 
 struct r8a7778_cpg {
        struct clk_onecell_data data;
index 652ecacb6daf79222644252c4886e4df1c5938f1..af297963489f473d82ced3db8237135ddd47d99d 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #include <dt-bindings/clock/r8a7779-clock.h>
index acfb6d7dbd6bc049fe39213d675d5a2602e65d9e..9233ebf8cc49f933d0343cccf8c11a2a4f11ae58 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 struct rcar_gen2_cpg {
index cd529cfe412f1d186bb07e2936b7e1e512cfd9a1..8966f8bbfd726e62f19cc997d2e2c1046aec0b09 100644 (file)
@@ -9,12 +9,12 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/clk/shmobile.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 struct sh73a0_cpg {
index d63b76ca60c311edd1dcb66ef35d364e0cb27247..c5eaa9d1624760f6db1347cdbeaf44c7b97a2049 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
index db8ab691dbf6245d1f1ffee966a92a167c39e33d..a98e21fe773a364739f299aac651ccc4d2e18656 100644 (file)
@@ -358,6 +358,7 @@ static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
        if (regctrl0 & SIRFSOC_ABPLL_CTRL0_SSEN) {
                rate = fin;
                rate *= 1 << 24;
+               do_div(rate, nr);
                do_div(rate, (256 * ((ssdiv >> ssdepth) << ssdepth)
                        + (ssmod << ssdepth)));
        } else {
@@ -465,6 +466,9 @@ static struct clk_pll clk_sys3pll = {
  *  double resolution mode:fout = fin * finc / 2^29
  *  normal mode:fout = fin * finc / 2^28
  */
+#define DTO_RESL_DOUBLE        (1ULL << 29)
+#define DTO_RESL_NORMAL        (1ULL << 28)
+
 static int dto_clk_is_enabled(struct clk_hw *hw)
 {
        struct clk_dto *clk = to_dtoclk(hw);
@@ -509,9 +513,9 @@ static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
        rate *= finc;
        if (droff & BIT(0))
                /* Double resolution off */
-               do_div(rate, 1 << 28);
+               do_div(rate, DTO_RESL_NORMAL);
        else
-               do_div(rate, 1 << 29);
+               do_div(rate, DTO_RESL_DOUBLE);
 
        return rate;
 }
@@ -519,11 +523,11 @@ static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
 static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long *parent_rate)
 {
-       u64 dividend = rate * (1 << 29);
+       u64 dividend = rate * DTO_RESL_DOUBLE;
 
        do_div(dividend, *parent_rate);
        dividend *= *parent_rate;
-       do_div(dividend, 1 << 29);
+       do_div(dividend, DTO_RESL_DOUBLE);
 
        return dividend;
 }
@@ -531,7 +535,7 @@ static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 static int dto_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long parent_rate)
 {
-       u64 dividend = rate * (1 << 29);
+       u64 dividend = rate * DTO_RESL_DOUBLE;
        struct clk_dto *clk = to_dtoclk(hw);
 
        do_div(dividend, parent_rate);
@@ -1161,7 +1165,7 @@ static struct atlas7_unit_init_data unit_list[] __initdata = {
        { 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
        { 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
        { 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
-       { 125, "thcpum_cpudiv4", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
+       { 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
        { 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
        { 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
        { 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
@@ -1174,9 +1178,13 @@ static struct atlas7_unit_init_data unit_list[] __initdata = {
        { 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
        { 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
        { 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
+       { 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, &leaf0_gate_lock },
+       { 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, &leaf0_gate_lock },
+       { 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, &leaf0_gate_lock },
+       { 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, &leaf0_gate_lock },
 };
 
-static struct clk *atlas7_clks[ARRAY_SIZE(unit_list)];
+static struct clk *atlas7_clks[ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list)];
 
 static int unit_clk_is_enabled(struct clk_hw *hw)
 {
@@ -1609,6 +1617,7 @@ static void __init atlas7_clk_init(struct device_node *np)
                               sirfsoc_clk_vbase + mux->mux_offset,
                               mux->shift, mux->width,
                               mux->mux_flags, NULL);
+               atlas7_clks[ARRAY_SIZE(unit_list) + i] = clk;
                BUG_ON(!clk);
        }
 
@@ -1620,7 +1629,7 @@ static void __init atlas7_clk_init(struct device_node *np)
        }
 
        clk_data.clks = atlas7_clks;
-       clk_data.clk_num = ARRAY_SIZE(unit_list);
+       clk_data.clk_num = ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list);
 
        ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
        BUG_ON(ret);
index 9fc285d784d3faa4b78eac774cc466b989b8d667..77e1e2491689b9c37e943c43e8fabf5778a561aa 100644 (file)
@@ -7,6 +7,8 @@
  * Licensed under GPLv2 or later.
  */
 
+#include <linux/clk.h>
+
 #define KHZ     1000
 #define MHZ     (KHZ * KHZ)
 
@@ -165,10 +167,10 @@ static long cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
         * SiRF SoC has not cpu clock control,
         * So bypass to it's parent pll.
         */
-       struct clk *parent_clk = clk_get_parent(hw->clk);
-       struct clk *pll_parent_clk = clk_get_parent(parent_clk);
-       unsigned long pll_parent_rate = clk_get_rate(pll_parent_clk);
-       return pll_clk_round_rate(__clk_get_hw(parent_clk), rate, &pll_parent_rate);
+       struct clk_hw *parent_clk = clk_hw_get_parent(hw);
+       struct clk_hw *pll_parent_clk = clk_hw_get_parent(parent_clk);
+       unsigned long pll_parent_rate = clk_hw_get_rate(pll_parent_clk);
+       return pll_clk_round_rate(parent_clk, rate, &pll_parent_rate);
 }
 
 static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw,
@@ -178,8 +180,8 @@ static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw,
         * SiRF SoC has not cpu clock control,
         * So return the parent pll rate.
         */
-       struct clk *parent_clk = clk_get_parent(hw->clk);
-       return __clk_get_rate(parent_clk);
+       struct clk_hw *parent_clk = clk_hw_get_parent(hw);
+       return clk_hw_get_rate(parent_clk);
 }
 
 static struct clk_ops std_pll_ops = {
index 6968e2ebcd8a4d09959d02b2edbf5ffe19e7b9da..f92c40264342574af6fbf2af02de0e3db4236602 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
index 83c6780ff4b2e47dea9db1674fbffadb2bcfcd3a..1cebf253e8fd44dbe22e37e1eb6a18ed63cd2f14 100644 (file)
@@ -13,6 +13,7 @@
  * 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/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
@@ -38,7 +39,7 @@ static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
                div = socfpgaclk->fixed_div;
        else if (socfpgaclk->div_reg) {
                val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-               val &= div_mask(socfpgaclk->width);
+               val &= GENMASK(socfpgaclk->width - 1, 0);
                div = (1 << val);
        }
 
index 82449cd76fd7e3ebb9b98b39ce81682eb1105173..aa7a6e6a15b656808d3cc9f92229125cb2baea81 100644 (file)
@@ -15,8 +15,7 @@
  * Based from clk-highbank.c
  *
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
@@ -106,7 +105,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
                div = socfpgaclk->fixed_div;
        else if (socfpgaclk->div_reg) {
                val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-               val &= div_mask(socfpgaclk->width);
+               val &= GENMASK(socfpgaclk->width - 1, 0);
                /* Check for GPIO_DB_CLK by its offset */
                if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET)
                        div = val + 1;
index 9d0181b5a6a48d4990b1d2844b194e94cb851a81..1f397cb72e89a8ff421edfaf92cddf2fee1e16a8 100644 (file)
@@ -13,6 +13,7 @@
  * 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/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -37,7 +38,7 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
                div = socfpgaclk->fixed_div;
        } else if (socfpgaclk->div_reg) {
                div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-               div &= div_mask(socfpgaclk->width);
+               div &= GENMASK(socfpgaclk->width - 1, 0);
                div += 1;
        } else {
                div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
index 83aeaa219d14e82800976e476fc24a72a0f032a9..52c883ea7706715d18b9ec8dc676fbc98060acd7 100644 (file)
@@ -15,8 +15,7 @@
  * Based from clk-highbank.c
  *
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -36,7 +35,7 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
        } else {
                if (socfpgaclk->div_reg) {
                        val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
-                       val &= div_mask(socfpgaclk->width);
+                       val &= GENMASK(socfpgaclk->width - 1, 0);
                        parent_rate /= (val + 1);
                }
                div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
@@ -45,8 +44,17 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
        return parent_rate / div;
 }
 
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+       u32 clk_src;
+
+       clk_src = readl(clk_mgr_base_addr + CLKMGR_DBCTRL);
+       return clk_src & 0x1;
+}
+
 static const struct clk_ops periclk_ops = {
        .recalc_rate = clk_periclk_recalc_rate,
+       .get_parent = clk_periclk_get_parent,
 };
 
 static __init void __socfpga_periph_init(struct device_node *node,
@@ -56,7 +64,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
        struct clk *clk;
        struct socfpga_periph_clk *periph_clk;
        const char *clk_name = node->name;
-       const char *parent_name;
+       const char *parent_name[SOCFPGA_MAX_PARENTS];
        struct clk_init_data init;
        int rc;
        u32 fixed_div;
@@ -90,9 +98,10 @@ static __init void __socfpga_periph_init(struct device_node *node,
        init.name = clk_name;
        init.ops = ops;
        init.flags = 0;
-       parent_name = of_clk_get_parent_name(node, 0);
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
+
+       init.num_parents = of_clk_parent_fill(node, parent_name,
+                                             SOCFPGA_MAX_PARENTS);
+       init.parent_names = parent_name;
 
        periph_clk->hw.hw.init = &init;
 
index 1178b11babca028ff6ba7c11a7408d11d65d4f08..402d630bd531ecf65ee15ba3f70966afe33cb8e7 100644 (file)
@@ -13,6 +13,7 @@
  * 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/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 8f26b5234947eafca2649fdbce3262db4351f8bd..c7f463172e4b93d0cec4b46e45558a301aa16234 100644 (file)
@@ -15,8 +15,7 @@
  * Based from clk-highbank.c
  *
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
index 603973ab7e2914d0da3c39e56d7613dd8263ee19..814c7247bf73b071fcc2f19770a005425b404294 100644 (file)
 #define __SOCFPGA_CLK_H
 
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 
 /* Clock Manager offsets */
 #define CLKMGR_CTRL            0x0
 #define CLKMGR_BYPASS          0x4
+#define CLKMGR_DBCTRL          0x10
 #define CLKMGR_L4SRC           0x70
 #define CLKMGR_PERPLL_SRC      0xAC
 
 #define SOCFPGA_MAX_PARENTS            5
-#define div_mask(width) ((1 << (width)) - 1)
 
 #define streq(a, b) (strcmp((a), (b)) == 0)
 #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
index 5ebddc528145bb82827c2a6895b5467fb6dfaeca..dc21ca4601aab28ce2eba866e2d00e0e33f9dbe1 100644 (file)
@@ -87,7 +87,7 @@ static long clk_pll_round_rate_index(struct clk_hw *hw, unsigned long drate,
        struct clk_pll *pll = to_clk_pll(hw);
        unsigned long prev_rate, vco_prev_rate, rate = 0;
        unsigned long vco_parent_rate =
-               __clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk)));
+               clk_hw_get_rate(clk_hw_get_parent(clk_hw_get_parent(hw)));
 
        if (!prate) {
                pr_err("%s: prate is must for pll clk\n", __func__);
index 222ce108b41a0e48afd4bf2d370a535d24511774..009bd1410cfa87759d6aa3c224dbd3a1c64e832f 100644 (file)
@@ -11,7 +11,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 973c9d3fbcf82285e2a6bf6412cb15fe602a892e..9c7abfd951baa2fa91950dd0e4b0a2a76f8fecb5 100644 (file)
@@ -11,7 +11,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
index 231061fa73a4309b0744d2a8dda0d68bddeda5e0..e24f85cd4300f39845f8bd8dd065ee5fceb1940b 100644 (file)
@@ -9,7 +9,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/spinlock_types.h>
index 8dd8cce273617e1db85c8af512a431cef14cf328..bd355ee33766b807556c848fcabeeb0c9293a187 100644 (file)
@@ -5,6 +5,7 @@
  * Author:  Maxime Coquelin <maxime.coquelin@st.com> for ST-Microelectronics.
  * License terms:  GNU General Public License (GPL), version 2  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -44,7 +45,7 @@ static int flexgen_enable(struct clk_hw *hw)
 
        clk_gate_ops.enable(fgate_hw);
 
-       pr_debug("%s: flexgen output enabled\n", __clk_get_name(hw->clk));
+       pr_debug("%s: flexgen output enabled\n", clk_hw_get_name(hw));
        return 0;
 }
 
@@ -58,7 +59,7 @@ static void flexgen_disable(struct clk_hw *hw)
 
        clk_gate_ops.disable(fgate_hw);
 
-       pr_debug("%s: flexgen output disabled\n", __clk_get_name(hw->clk));
+       pr_debug("%s: flexgen output disabled\n", clk_hw_get_name(hw));
 }
 
 static int flexgen_is_enabled(struct clk_hw *hw)
@@ -108,7 +109,7 @@ static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
        /* Round div according to exact prate and wished rate */
        div = clk_best_div(*prate, rate);
 
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
                *prate = rate * div;
                return rate;
        }
@@ -243,7 +244,7 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
                                                       int *num_parents)
 {
        const char **parents;
-       int nparents, i;
+       int nparents;
 
        nparents = of_clk_get_parent_count(np);
        if (WARN_ON(nparents <= 0))
@@ -253,10 +254,8 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
        if (!parents)
                return NULL;
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
+       *num_parents = of_clk_parent_fill(np, parents, nparents);
 
-       *num_parents = nparents;
        return parents;
 }
 
index d9eb2e1d84710c34abe8b656b4dd5e89a1ac7f9a..83ccf142ff2acaea7b5d4f3cf9d8f6475d1f6093 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #include "clkgen.h"
@@ -512,7 +513,7 @@ static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
        params.ndiv = CLKGEN_READ(pll, ndiv);
        if (clk_fs660c32_vco_get_rate(parent_rate, &params, &rate))
                pr_err("%s:%s error calculating rate\n",
-                      __clk_get_name(hw->clk), __func__);
+                      clk_hw_get_name(hw), __func__);
 
        pll->ndiv = params.ndiv;
 
@@ -557,7 +558,7 @@ static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate
                clk_fs660c32_vco_get_rate(*prate, &params, &rate);
 
        pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
-                __func__, __clk_get_name(hw->clk),
+                __func__, clk_hw_get_name(hw),
                 rate, (unsigned int)params.sdiv,
                 (unsigned int)params.mdiv,
                 (unsigned int)params.pe, (unsigned int)params.nsdiv);
@@ -580,7 +581,7 @@ static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
                clk_fs660c32_vco_get_rate(parent_rate, &params, &hwrate);
 
        pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n",
-                __func__, __clk_get_name(hw->clk),
+                __func__, clk_hw_get_name(hw),
                 hwrate, (unsigned int)params.ndiv);
 
        if (!hwrate)
@@ -744,7 +745,7 @@ static int quadfs_fsynth_enable(struct clk_hw *hw)
        struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
        unsigned long flags = 0;
 
-       pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+       pr_debug("%s: %s\n", __func__, clk_hw_get_name(hw));
 
        quadfs_fsynth_program_rate(fs);
 
@@ -769,7 +770,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw)
        struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
        unsigned long flags = 0;
 
-       pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+       pr_debug("%s: %s\n", __func__, clk_hw_get_name(hw));
 
        if (fs->lock)
                spin_lock_irqsave(fs->lock, flags);
@@ -786,7 +787,7 @@ static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
        u32 nsb = CLKGEN_READ(fs, nsb[fs->chan]);
 
        pr_debug("%s: %s enable bit = 0x%x\n",
-                __func__, __clk_get_name(hw->clk), nsb);
+                __func__, clk_hw_get_name(hw), nsb);
 
        return fs->data->standby_polarity ? !nsb : !!nsb;
 }
@@ -945,10 +946,10 @@ static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
 
        if (clk_fs_get_rate(parent_rate, &params, &rate)) {
                pr_err("%s:%s error calculating rate\n",
-                      __clk_get_name(hw->clk), __func__);
+                      clk_hw_get_name(hw), __func__);
        }
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
@@ -961,7 +962,7 @@ static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
        rate = quadfs_find_best_rate(hw, rate, *prate, &params);
 
        pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
-                __func__, __clk_get_name(hw->clk),
+                __func__, clk_hw_get_name(hw),
                 rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
                         (unsigned int)params.pe, (unsigned int)params.nsdiv);
 
index 717c4a91a17b12643146eb028ed02dd0727eac50..4f7f6c00b219dc005e98e5fc68733742c93efdcf 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
@@ -24,20 +25,17 @@ static const char ** __init clkgen_mux_get_parents(struct device_node *np,
                                                       int *num_parents)
 {
        const char **parents;
-       int nparents, i;
+       int nparents;
 
        nparents = of_clk_get_parent_count(np);
        if (WARN_ON(nparents <= 0))
                return ERR_PTR(-EINVAL);
 
-       parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL);
+       parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL);
        if (!parents)
                return ERR_PTR(-ENOMEM);
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
-
-       *num_parents = nparents;
+       *num_parents = of_clk_parent_fill(np, parents, nparents);
        return parents;
 }
 
@@ -141,7 +139,7 @@ static u8 clkgena_divmux_get_parent(struct clk_hw *hw)
        genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
        if ((s8)genamux->muxsel < 0) {
                pr_debug("%s: %s: Invalid parent, setting to default.\n",
-                     __func__, __clk_get_name(hw->clk));
+                     __func__, clk_hw_get_name(hw));
                genamux->muxsel = 0;
        }
 
@@ -215,7 +213,7 @@ static const struct clk_ops clkgena_divmux_ops = {
 /**
  * clk_register_genamux - register a genamux clock with the clock framework
  */
-static struct clk *clk_register_genamux(const char *name,
+static struct clk * __init clk_register_genamux(const char *name,
                                const char **parent_names, u8 num_parents,
                                void __iomem *reg,
                                const struct clkgena_divmux_data *muxdata,
@@ -369,11 +367,10 @@ static const struct of_device_id clkgena_divmux_of_match[] = {
        {}
 };
 
-static void __iomem * __init clkgen_get_register_base(
-                               struct device_node *np)
+static void __iomem * __init clkgen_get_register_base(struct device_node *np)
 {
        struct device_node *pnode;
-       void __iomem *reg = NULL;
+       void __iomem *reg;
 
        pnode = of_get_parent(np);
        if (!pnode)
@@ -398,7 +395,7 @@ static void __init st_of_clkgena_divmux_setup(struct device_node *np)
        if (WARN_ON(!match))
                return;
 
-       data = (struct clkgena_divmux_data *)match->data;
+       data = match->data;
 
        reg = clkgen_get_register_base(np);
        if (!reg)
@@ -406,18 +403,18 @@ static void __init st_of_clkgena_divmux_setup(struct device_node *np)
 
        parents = clkgen_mux_get_parents(np, &num_parents);
        if (IS_ERR(parents))
-               return;
+               goto err_parents;
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
-               goto err;
+               goto err_alloc;
 
        clk_data->clk_num = data->num_outputs;
-       clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+       clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
                                 GFP_KERNEL);
 
        if (!clk_data->clks)
-               goto err;
+               goto err_alloc_clks;
 
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
@@ -447,11 +444,13 @@ static void __init st_of_clkgena_divmux_setup(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
        return;
 err:
-       if (clk_data)
-               kfree(clk_data->clks);
-
+       kfree(clk_data->clks);
+err_alloc_clks:
        kfree(clk_data);
+err_alloc:
        kfree(parents);
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup);
 
@@ -491,7 +490,7 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
        void __iomem *reg;
        const char *parent_name, *clk_name;
        struct clk *clk;
-       struct clkgena_prediv_data *data;
+       const struct clkgena_prediv_data *data;
 
        match = of_match_node(clkgena_prediv_of_match, np);
        if (!match) {
@@ -499,7 +498,7 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
                return;
        }
 
-       data = (struct clkgena_prediv_data *)match->data;
+       data = match->data;
 
        reg = clkgen_get_register_base(np);
        if (!reg)
@@ -507,18 +506,18 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
 
        parent_name = of_clk_get_parent_name(np, 0);
        if (!parent_name)
-               return;
+               goto err;
 
        if (of_property_read_string_index(np, "clock-output-names",
                                          0, &clk_name))
-               return;
+               goto err;
 
        clk = clk_register_divider_table(NULL, clk_name, parent_name,
                                         CLK_GET_RATE_NOCACHE,
                                         reg + data->offset, data->shift, 1,
                                         0, data->table, NULL);
        if (IS_ERR(clk))
-               return;
+               goto err;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
        pr_debug("%s: parent %s rate %u\n",
@@ -527,6 +526,8 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np)
                (unsigned int)clk_get_rate(clk));
 
        return;
+err:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
 
@@ -630,7 +631,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
        void __iomem *reg;
        const char **parents;
        int num_parents;
-       struct clkgen_mux_data *data;
+       const struct clkgen_mux_data *data;
 
        match = of_match_node(mux_of_match, np);
        if (!match) {
@@ -638,7 +639,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
                return;
        }
 
-       data = (struct clkgen_mux_data *)match->data;
+       data = match->data;
 
        reg = of_iomap(np, 0);
        if (!reg) {
@@ -650,7 +651,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
        if (IS_ERR(parents)) {
                pr_err("%s: Failed to get parents (%ld)\n",
                                __func__, PTR_ERR(parents));
-               return;
+               goto err_parents;
        }
 
        clk = clk_register_mux(NULL, np->name, parents, num_parents,
@@ -666,12 +667,14 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np)
                        __clk_get_name(clk_get_parent(clk)),
                        (unsigned int)clk_get_rate(clk));
 
+       kfree(parents);
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
 
 err:
        kfree(parents);
-
-       return;
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup);
 
@@ -707,12 +710,12 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
        const char **parents;
        int num_parents, i;
        struct clk_onecell_data *clk_data;
-       struct clkgen_vcc_data *data;
+       const struct clkgen_vcc_data *data;
 
        match = of_match_node(vcc_of_match, np);
        if (WARN_ON(!match))
                return;
-       data = (struct clkgen_vcc_data *)match->data;
+       data = match->data;
 
        reg = of_iomap(np, 0);
        if (!reg)
@@ -720,18 +723,18 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
 
        parents = clkgen_mux_get_parents(np, &num_parents);
        if (IS_ERR(parents))
-               return;
+               goto err_parents;
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
-               goto err;
+               goto err_alloc;
 
        clk_data->clk_num = VCC_MAX_CHANNELS;
-       clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+       clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
                                 GFP_KERNEL);
 
        if (!clk_data->clks)
-               goto err;
+               goto err_alloc_clks;
 
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
@@ -750,21 +753,21 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np)
                if (*clk_name == '\0')
                        continue;
 
-               gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+               gate = kzalloc(sizeof(*gate), GFP_KERNEL);
                if (!gate)
-                       break;
+                       goto err;
 
-               div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+               div = kzalloc(sizeof(*div), GFP_KERNEL);
                if (!div) {
                        kfree(gate);
-                       break;
+                       goto err;
                }
 
-               mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+               mux = kzalloc(sizeof(*mux), GFP_KERNEL);
                if (!mux) {
                        kfree(gate);
                        kfree(div);
-                       break;
+                       goto err;
                }
 
                gate->reg = reg + VCC_GATE_OFFSET;
@@ -823,10 +826,12 @@ err:
                kfree(container_of(composite->mux_hw, struct clk_mux, hw));
        }
 
-       if (clk_data)
-               kfree(clk_data->clks);
-
+       kfree(clk_data->clks);
+err_alloc_clks:
        kfree(clk_data);
+err_alloc:
        kfree(parents);
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup);
index 72d1c27eaffa8247a0e49d029c21d2481caa83a7..47a38a994cac7a29113c086cb928e7957180e1fd 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #include "clkgen.h"
@@ -291,7 +292,7 @@ static unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
        res = (uint64_t)2 * (uint64_t)parent_rate * (uint64_t)ndiv;
        rate = (unsigned long)div64_u64(res, mdiv * (1 << pdiv));
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 
@@ -316,7 +317,7 @@ static unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
        /* Note: input is divided by 1000 to avoid overflow */
        rate = ((2 * (parent_rate / 1000) * ndiv) / mdiv) * 1000;
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
@@ -338,7 +339,7 @@ static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
                /* Note: input is divided to avoid overflow */
                rate = ((2 * (parent_rate/1000) * ndiv) / idf) * 1000;
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
@@ -365,7 +366,7 @@ static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
        /* Note: input is divided by 1000 to avoid overflow */
        rate = (((parent_rate / 1000) * ldf) / (odf * idf)) * 1000;
 
-       pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate);
+       pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
 
        return rate;
 }
index 058f273d6154745d0fc4173677ee533cbd04a243..f5a35b82cc1a8b5bcce5edabf4b3e46479b8e846 100644 (file)
@@ -6,6 +6,7 @@ obj-y += clk-sunxi.o clk-factors.o
 obj-y += clk-a10-hosc.o
 obj-y += clk-a20-gmac.o
 obj-y += clk-mod0.o
+obj-y += clk-simple-gates.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
 obj-y += clk-sun9i-mmc.o
index 0dcf4f205fb86f1510dfa8b74f20311e301613ce..1611b036421c20e76f438e13fb326111b24e5cda 100644 (file)
@@ -80,9 +80,7 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
                goto free_mux;
 
        /* gmac clock requires exactly 2 parents */
-       parents[0] = of_clk_get_parent_name(node, 0);
-       parents[1] = of_clk_get_parent_name(node, 1);
-       if (!parents[0] || !parents[1])
+       if (of_clk_parent_fill(node, parents, 2) != 2)
                goto free_gate;
 
        reg = of_iomap(node, 0);
index 8c20190a3e9f4e134824449c10a72e9e13b5b957..59428dbd607a85d3ff15e3b648f529e1a575abf9 100644 (file)
@@ -79,41 +79,42 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
        return rate;
 }
 
-static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long min_rate,
-                                      unsigned long max_rate,
-                                      unsigned long *best_parent_rate,
-                                      struct clk_hw **best_parent_p)
+static int clk_factors_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
-       struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+       struct clk_hw *parent, *best_parent = NULL;
        int i, num_parents;
        unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
 
        /* find the parent that can help provide the fastest rate <= rate */
-       num_parents = __clk_get_num_parents(clk);
+       num_parents = clk_hw_get_num_parents(hw);
        for (i = 0; i < num_parents; i++) {
-               parent = clk_get_parent_by_index(clk, i);
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
-               if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_round_rate(parent, rate);
+               if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
+                       parent_rate = clk_hw_round_rate(parent, req->rate);
                else
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
 
-               child_rate = clk_factors_round_rate(hw, rate, &parent_rate);
+               child_rate = clk_factors_round_rate(hw, req->rate,
+                                                   &parent_rate);
 
-               if (child_rate <= rate && child_rate > best_child_rate) {
+               if (child_rate <= req->rate && child_rate > best_child_rate) {
                        best_parent = parent;
                        best = parent_rate;
                        best_child_rate = child_rate;
                }
        }
 
-       if (best_parent)
-               *best_parent_p = __clk_get_hw(best_parent);
-       *best_parent_rate = best;
+       if (!best_parent)
+               return -EINVAL;
 
-       return best_child_rate;
+       req->best_parent_hw = best_parent;
+       req->best_parent_rate = best;
+       req->rate = best_child_rate;
+
+       return 0;
 }
 
 static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -174,9 +175,7 @@ struct clk *sunxi_factors_register(struct device_node *node,
        int i = 0;
 
        /* if we have a mux, we will have >1 parents */
-       while (i < FACTORS_MAX_PARENTS &&
-              (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-               i++;
+       i = of_clk_parent_fill(node, parents, FACTORS_MAX_PARENTS);
 
        /*
         * some factor clocks, such as pll5 and pll6, may have multiple
index 9d028aec58e5d8addc3a080ced48594db57c1657..d167e1efb92761a0f223a6054787587d58b11152 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 
 #include "clk-factors.h"
 
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
new file mode 100644 (file)
index 0000000..6ce9118
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(gates_lock);
+
+static void __init sunxi_simple_gates_setup(struct device_node *node,
+                                           const int protected[],
+                                           int nprotected)
+{
+       struct clk_onecell_data *clk_data;
+       const char *clk_parent, *clk_name;
+       struct property *prop;
+       struct resource res;
+       void __iomem *clk_reg;
+       void __iomem *reg;
+       const __be32 *p;
+       int number, i = 0, j;
+       u8 clk_bit;
+       u32 index;
+
+       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+       if (IS_ERR(reg))
+               return;
+
+       clk_parent = of_clk_get_parent_name(node, 0);
+
+       clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+       if (!clk_data)
+               goto err_unmap;
+
+       number = of_property_count_u32_elems(node, "clock-indices");
+       of_property_read_u32_index(node, "clock-indices", number - 1, &number);
+
+       clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+       if (!clk_data->clks)
+               goto err_free_data;
+
+       of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+               of_property_read_string_index(node, "clock-output-names",
+                                             i, &clk_name);
+
+               clk_reg = reg + 4 * (index / 32);
+               clk_bit = index % 32;
+
+               clk_data->clks[index] = clk_register_gate(NULL, clk_name,
+                                                         clk_parent, 0,
+                                                         clk_reg,
+                                                         clk_bit,
+                                                         0, &gates_lock);
+               i++;
+
+               if (IS_ERR(clk_data->clks[index])) {
+                       WARN_ON(true);
+                       continue;
+               }
+
+               for (j = 0; j < nprotected; j++)
+                       if (protected[j] == index)
+                               clk_prepare_enable(clk_data->clks[index]);
+
+       }
+
+       clk_data->clk_num = number + 1;
+       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+       return;
+
+err_free_data:
+       kfree(clk_data);
+err_unmap:
+       iounmap(reg);
+       of_address_to_resource(node, 0, &res);
+       release_mem_region(res.start, resource_size(&res));
+}
+
+static void __init sunxi_simple_gates_init(struct device_node *node)
+{
+       sunxi_simple_gates_setup(node, NULL, 0);
+}
+
+CLK_OF_DECLARE(sun4i_a10_apb0, "allwinner,sun4i-a10-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun4i_a10_apb1, "allwinner,sun4i-a10-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun4i_a10_axi, "allwinner,sun4i-a10-axi-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a10s_apb0, "allwinner,sun5i-a10s-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a10s_apb1, "allwinner,sun5i-a10s-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a13_apb0, "allwinner,sun5i-a13-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun5i_a13_apb1, "allwinner,sun5i-a13-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun6i_a31_apb1, "allwinner,sun6i-a31-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun6i_a31_apb2, "allwinner,sun6i-a31-apb2-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun7i_a20_apb0, "allwinner,sun7i-a20-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun7i_a20_apb1, "allwinner,sun7i-a20-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a23_ahb1, "allwinner,sun8i-a23-ahb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a23_apb1, "allwinner,sun8i-a23-apb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_ahb2, "allwinner,sun9i-a80-ahb2-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-gates-clk",
+              sunxi_simple_gates_init);
+CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-gates-clk",
+              sunxi_simple_gates_init);
+
+static const int sun4i_a10_ahb_critical_clocks[] __initconst = {
+       14,     /* ahb_sdram */
+};
+
+static void __init sun4i_a10_ahb_init(struct device_node *node)
+{
+       sunxi_simple_gates_setup(node, sun4i_a10_ahb_critical_clocks,
+                                ARRAY_SIZE(sun4i_a10_ahb_critical_clocks));
+}
+CLK_OF_DECLARE(sun4i_a10_ahb, "allwinner,sun4i-a10-ahb-gates-clk",
+              sun4i_a10_ahb_init);
+CLK_OF_DECLARE(sun5i_a10s_ahb, "allwinner,sun5i-a10s-ahb-gates-clk",
+              sun4i_a10_ahb_init);
+CLK_OF_DECLARE(sun5i_a13_ahb, "allwinner,sun5i-a13-ahb-gates-clk",
+              sun4i_a10_ahb_init);
+CLK_OF_DECLARE(sun7i_a20_ahb, "allwinner,sun7i-a20-ahb-gates-clk",
+              sun4i_a10_ahb_init);
index 63cf149195ae1a40cb61a7b2256878c0f2ccd5ef..806fd019c05dd103c272446ef03e01e3a9def11f 100644 (file)
@@ -44,28 +44,25 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
        return (parent_rate >> shift) / (div + 1);
 }
 
-static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long min_rate,
-                                unsigned long max_rate,
-                                unsigned long *best_parent_rate,
-                                struct clk_hw **best_parent_clk)
+static int ar100_determine_rate(struct clk_hw *hw,
+                               struct clk_rate_request *req)
 {
-       int nparents = __clk_get_num_parents(hw->clk);
+       int nparents = clk_hw_get_num_parents(hw);
        long best_rate = -EINVAL;
        int i;
 
-       *best_parent_clk = NULL;
+       req->best_parent_hw = NULL;
 
        for (i = 0; i < nparents; i++) {
                unsigned long parent_rate;
                unsigned long tmp_rate;
-               struct clk *parent;
+               struct clk_hw *parent;
                unsigned long div;
                int shift;
 
-               parent = clk_get_parent_by_index(hw->clk, i);
-               parent_rate = __clk_get_rate(parent);
-               div = DIV_ROUND_UP(parent_rate, rate);
+               parent = clk_hw_get_parent_by_index(hw, i);
+               parent_rate = clk_hw_get_rate(parent);
+               div = DIV_ROUND_UP(parent_rate, req->rate);
 
                /*
                 * The AR100 clk contains 2 divisors:
@@ -101,14 +98,19 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
                        continue;
 
                tmp_rate = (parent_rate >> shift) / div;
-               if (!*best_parent_clk || tmp_rate > best_rate) {
-                       *best_parent_clk = __clk_get_hw(parent);
-                       *best_parent_rate = parent_rate;
+               if (!req->best_parent_hw || tmp_rate > best_rate) {
+                       req->best_parent_hw = parent;
+                       req->best_parent_rate = parent_rate;
                        best_rate = tmp_rate;
                }
        }
 
-       return best_rate;
+       if (best_rate < 0)
+               return best_rate;
+
+       req->rate = best_rate;
+
+       return 0;
 }
 
 static int ar100_set_parent(struct clk_hw *hw, u8 index)
@@ -180,7 +182,6 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
        struct resource *r;
        struct clk *clk;
        int nparents;
-       int i;
 
        ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL);
        if (!ar100)
@@ -195,8 +196,7 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
        if (nparents > SUN6I_AR100_MAX_PARENTS)
                nparents = SUN6I_AR100_MAX_PARENTS;
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
+       of_clk_parent_fill(np, parents, nparents);
 
        of_property_read_string(np, "clock-output-names", &clk_name);
 
index 14cd026064bf377ed7cbc05bbd84aa608e639fec..bf117a636d2397f6a7059f55962134cade4b3cc0 100644 (file)
@@ -14,8 +14,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of_address.h>
 
 #include "clk-factors.h"
index 887f4ea161bb4eb79700c7778aecbec2c977e2b4..6c4c98324d3cc6800bace1b4a918707e2b4cc53f 100644 (file)
@@ -14,8 +14,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/log2.h>
index 710c273648d709e172b0691acca853c05c658dab..3436a948b796fc42b53181cda67ca89ab731f690 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/reset.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #define SUN9I_MMC_WIDTH                4
index abf7b37faf73f3dd2366024a5bb97affc152cda2..413070d07b3f1f255a8229a259eeb97c5aaf94ae 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/log2.h>
 
@@ -118,42 +120,42 @@ static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
        return (parent_rate / calcm) >> calcp;
 }
 
-static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                         unsigned long min_rate,
-                                         unsigned long max_rate,
-                                         unsigned long *best_parent_rate,
-                                         struct clk_hw **best_parent_clk)
+static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw,
+                                        struct clk_rate_request *req)
 {
-       struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+       struct clk_hw *parent, *best_parent = NULL;
        int i, num_parents;
        unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
 
        /* find the parent that can help provide the fastest rate <= rate */
-       num_parents = __clk_get_num_parents(clk);
+       num_parents = clk_hw_get_num_parents(hw);
        for (i = 0; i < num_parents; i++) {
-               parent = clk_get_parent_by_index(clk, i);
+               parent = clk_hw_get_parent_by_index(hw, i);
                if (!parent)
                        continue;
-               if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
-                       parent_rate = __clk_round_rate(parent, rate);
+               if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
+                       parent_rate = clk_hw_round_rate(parent, req->rate);
                else
-                       parent_rate = __clk_get_rate(parent);
+                       parent_rate = clk_hw_get_rate(parent);
 
-               child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i,
+               child_rate = sun6i_ahb1_clk_round(req->rate, NULL, NULL, i,
                                                  parent_rate);
 
-               if (child_rate <= rate && child_rate > best_child_rate) {
+               if (child_rate <= req->rate && child_rate > best_child_rate) {
                        best_parent = parent;
                        best = parent_rate;
                        best_child_rate = child_rate;
                }
        }
 
-       if (best_parent)
-               *best_parent_clk = __clk_get_hw(best_parent);
-       *best_parent_rate = best;
+       if (!best_parent)
+               return -EINVAL;
 
-       return best_child_rate;
+       req->best_parent_hw = best_parent;
+       req->best_parent_rate = best;
+       req->rate = best_child_rate;
+
+       return 0;
 }
 
 static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -195,17 +197,14 @@ static void __init sun6i_ahb1_clk_setup(struct device_node *node)
        const char *clk_name = node->name;
        const char *parents[SUN6I_AHB1_MAX_PARENTS];
        void __iomem *reg;
-       int i = 0;
+       int i;
 
        reg = of_io_request_and_map(node, 0, of_node_full_name(node));
        if (IS_ERR(reg))
                return;
 
        /* we have a mux, we will have >1 parents */
-       while (i < SUN6I_AHB1_MAX_PARENTS &&
-              (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-               i++;
-
+       i = of_clk_parent_fill(node, parents, SUN6I_AHB1_MAX_PARENTS);
        of_property_read_string(node, "clock-output-names", &clk_name);
 
        ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL);
@@ -786,14 +785,11 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
        const char *clk_name = node->name;
        const char *parents[SUNXI_MAX_PARENTS];
        void __iomem *reg;
-       int i = 0;
+       int i;
 
        reg = of_iomap(node, 0);
 
-       while (i < SUNXI_MAX_PARENTS &&
-              (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-               i++;
-
+       i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS);
        of_property_read_string(node, "clock-output-names", &clk_name);
 
        clk = clk_register_mux(NULL, clk_name, parents, i,
@@ -900,150 +896,6 @@ struct gates_data {
        DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
 };
 
-static const struct gates_data sun4i_axi_gates_data __initconst = {
-       .mask = {1},
-};
-
-static const struct gates_data sun4i_ahb_gates_data __initconst = {
-       .mask = {0x7F77FFF, 0x14FB3F},
-};
-
-static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
-       .mask = {0x147667e7, 0x185915},
-};
-
-static const struct gates_data sun5i_a13_ahb_gates_data __initconst = {
-       .mask = {0x107067e7, 0x185111},
-};
-
-static const struct gates_data sun6i_a31_ahb1_gates_data __initconst = {
-       .mask = {0xEDFE7F62, 0x794F931},
-};
-
-static const struct gates_data sun7i_a20_ahb_gates_data __initconst = {
-       .mask = { 0x12f77fff, 0x16ff3f },
-};
-
-static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = {
-       .mask = {0x25386742, 0x2505111},
-};
-
-static const struct gates_data sun9i_a80_ahb0_gates_data __initconst = {
-       .mask = {0xF5F12B},
-};
-
-static const struct gates_data sun9i_a80_ahb1_gates_data __initconst = {
-       .mask = {0x1E20003},
-};
-
-static const struct gates_data sun9i_a80_ahb2_gates_data __initconst = {
-       .mask = {0x9B7},
-};
-
-static const struct gates_data sun4i_apb0_gates_data __initconst = {
-       .mask = {0x4EF},
-};
-
-static const struct gates_data sun5i_a10s_apb0_gates_data __initconst = {
-       .mask = {0x469},
-};
-
-static const struct gates_data sun5i_a13_apb0_gates_data __initconst = {
-       .mask = {0x61},
-};
-
-static const struct gates_data sun7i_a20_apb0_gates_data __initconst = {
-       .mask = { 0x4ff },
-};
-
-static const struct gates_data sun9i_a80_apb0_gates_data __initconst = {
-       .mask = {0xEB822},
-};
-
-static const struct gates_data sun4i_apb1_gates_data __initconst = {
-       .mask = {0xFF00F7},
-};
-
-static const struct gates_data sun5i_a10s_apb1_gates_data __initconst = {
-       .mask = {0xf0007},
-};
-
-static const struct gates_data sun5i_a13_apb1_gates_data __initconst = {
-       .mask = {0xa0007},
-};
-
-static const struct gates_data sun6i_a31_apb1_gates_data __initconst = {
-       .mask = {0x3031},
-};
-
-static const struct gates_data sun8i_a23_apb1_gates_data __initconst = {
-       .mask = {0x3021},
-};
-
-static const struct gates_data sun6i_a31_apb2_gates_data __initconst = {
-       .mask = {0x3F000F},
-};
-
-static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
-       .mask = { 0xff80ff },
-};
-
-static const struct gates_data sun9i_a80_apb1_gates_data __initconst = {
-       .mask = {0x3F001F},
-};
-
-static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
-       .mask = {0x1F0007},
-};
-
-static void __init sunxi_gates_clk_setup(struct device_node *node,
-                                        struct gates_data *data)
-{
-       struct clk_onecell_data *clk_data;
-       const char *clk_parent;
-       const char *clk_name;
-       void __iomem *reg;
-       int qty;
-       int i = 0;
-       int j = 0;
-
-       reg = of_iomap(node, 0);
-
-       clk_parent = of_clk_get_parent_name(node, 0);
-
-       /* Worst-case size approximation and memory allocation */
-       qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
-       clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
-       if (!clk_data)
-               return;
-       clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
-       if (!clk_data->clks) {
-               kfree(clk_data);
-               return;
-       }
-
-       for_each_set_bit(i, data->mask, SUNXI_GATES_MAX_SIZE) {
-               of_property_read_string_index(node, "clock-output-names",
-                                             j, &clk_name);
-
-               clk_data->clks[i] = clk_register_gate(NULL, clk_name,
-                                                     clk_parent, 0,
-                                                     reg + 4 * (i/32), i % 32,
-                                                     0, &clk_lock);
-               WARN_ON(IS_ERR(clk_data->clks[i]));
-               clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
-
-               j++;
-       }
-
-       /* Adjust to the real max */
-       clk_data->clk_num = i;
-
-       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
-}
-
-
-
 /**
  * sunxi_divs_clk_setup() helper data
  */
@@ -1281,34 +1133,6 @@ static const struct of_device_id clk_mux_match[] __initconst = {
        {}
 };
 
-/* Matches for gate clocks */
-static const struct of_device_id clk_gates_match[] __initconst = {
-       {.compatible = "allwinner,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
-       {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
-       {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
-       {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
-       {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
-       {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
-       {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
-       {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
-       {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,},
-       {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
-       {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
-       {}
-};
 
 static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match,
                                              void *function)
@@ -1340,9 +1164,6 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
        /* Register mux clocks */
        of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
 
-       /* Register gate clocks */
-       of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
-
        /* Protect the clocks that needs to stay on */
        for (i = 0; i < nclocks; i++) {
                struct clk *clk = clk_get(NULL, clocks[i]);
@@ -1354,7 +1175,6 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
 
 static const char *sun4i_a10_critical_clocks[] __initdata = {
        "pll5_ddr",
-       "ahb_sdram",
 };
 
 static void __init sun4i_a10_init_clocks(struct device_node *node)
@@ -1367,7 +1187,6 @@ CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks)
 static const char *sun5i_critical_clocks[] __initdata = {
        "cpu",
        "pll5_ddr",
-       "ahb_sdram",
 };
 
 static void __init sun5i_init_clocks(struct device_node *node)
index 3a25f9588e67b58da122a82056854e5add44fd1c..1a72cd672839e81e63b118b588df75db9de4cf70 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 
index aec862ba7a17547b870a175ef436927b2c7307d3..826c325dc2e8b57bf022fac471f3c028dc1fbbf0 100644 (file)
@@ -1,5 +1,6 @@
 obj-y                                  += clk.o
 obj-y                                  += clk-audio-sync.o
+obj-y                                  += clk-dfll.o
 obj-y                                  += clk-divider.o
 obj-y                                  += clk-periph.o
 obj-y                                  += clk-periph-gate.o
@@ -16,4 +17,6 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += clk-tegra114.o
 obj-$(CONFIG_ARCH_TEGRA_124_SOC)       += clk-tegra124.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)       += clk-tegra124-dfll-fcpu.o
 obj-$(CONFIG_ARCH_TEGRA_132_SOC)       += clk-tegra124.o
+obj-y                                  += cvb.o
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
new file mode 100644 (file)
index 0000000..c2ff859
--- /dev/null
@@ -0,0 +1,1757 @@
+/*
+ * clk-dfll.c - Tegra DFLL clock source common code
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation. All rights reserved.
+ *
+ * Aleksandr Frid <afrid@nvidia.com>
+ * Paul Walmsley <pwalmsley@nvidia.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.
+ *
+ * This library is for the DVCO and DFLL IP blocks on the Tegra124
+ * SoC. These IP blocks together are also known at NVIDIA as
+ * "CL-DVFS". To try to avoid confusion, this code refers to them
+ * collectively as the "DFLL."
+ *
+ * The DFLL is a root clocksource which tolerates some amount of
+ * supply voltage noise. Tegra124 uses it to clock the fast CPU
+ * complex when the target CPU speed is above a particular rate. The
+ * DFLL can be operated in either open-loop mode or closed-loop mode.
+ * In open-loop mode, the DFLL generates an output clock appropriate
+ * to the supply voltage. In closed-loop mode, when configured with a
+ * target frequency, the DFLL minimizes supply voltage while
+ * delivering an average frequency equal to the target.
+ *
+ * Devices clocked by the DFLL must be able to tolerate frequency
+ * variation. In the case of the CPU, it's important to note that the
+ * CPU cycle time will vary. This has implications for
+ * performance-measurement code and any code that relies on the CPU
+ * cycle time to delay for a certain length of time.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/seq_file.h>
+
+#include "clk-dfll.h"
+
+/*
+ * DFLL control registers - access via dfll_{readl,writel}
+ */
+
+/* DFLL_CTRL: DFLL control register */
+#define DFLL_CTRL                      0x00
+#define DFLL_CTRL_MODE_MASK            0x03
+
+/* DFLL_CONFIG: DFLL sample rate control */
+#define DFLL_CONFIG                    0x04
+#define DFLL_CONFIG_DIV_MASK           0xff
+#define DFLL_CONFIG_DIV_PRESCALE       32
+
+/* DFLL_PARAMS: tuning coefficients for closed loop integrator */
+#define DFLL_PARAMS                    0x08
+#define DFLL_PARAMS_CG_SCALE           (0x1 << 24)
+#define DFLL_PARAMS_FORCE_MODE_SHIFT   22
+#define DFLL_PARAMS_FORCE_MODE_MASK    (0x3 << DFLL_PARAMS_FORCE_MODE_SHIFT)
+#define DFLL_PARAMS_CF_PARAM_SHIFT     16
+#define DFLL_PARAMS_CF_PARAM_MASK      (0x3f << DFLL_PARAMS_CF_PARAM_SHIFT)
+#define DFLL_PARAMS_CI_PARAM_SHIFT     8
+#define DFLL_PARAMS_CI_PARAM_MASK      (0x7 << DFLL_PARAMS_CI_PARAM_SHIFT)
+#define DFLL_PARAMS_CG_PARAM_SHIFT     0
+#define DFLL_PARAMS_CG_PARAM_MASK      (0xff << DFLL_PARAMS_CG_PARAM_SHIFT)
+
+/* DFLL_TUNE0: delay line configuration register 0 */
+#define DFLL_TUNE0                     0x0c
+
+/* DFLL_TUNE1: delay line configuration register 1 */
+#define DFLL_TUNE1                     0x10
+
+/* DFLL_FREQ_REQ: target DFLL frequency control */
+#define DFLL_FREQ_REQ                  0x14
+#define DFLL_FREQ_REQ_FORCE_ENABLE     (0x1 << 28)
+#define DFLL_FREQ_REQ_FORCE_SHIFT      16
+#define DFLL_FREQ_REQ_FORCE_MASK       (0xfff << DFLL_FREQ_REQ_FORCE_SHIFT)
+#define FORCE_MAX                      2047
+#define FORCE_MIN                      -2048
+#define DFLL_FREQ_REQ_SCALE_SHIFT      8
+#define DFLL_FREQ_REQ_SCALE_MASK       (0xff << DFLL_FREQ_REQ_SCALE_SHIFT)
+#define DFLL_FREQ_REQ_SCALE_MAX                256
+#define DFLL_FREQ_REQ_FREQ_VALID       (0x1 << 7)
+#define DFLL_FREQ_REQ_MULT_SHIFT       0
+#define DFLL_FREQ_REG_MULT_MASK                (0x7f << DFLL_FREQ_REQ_MULT_SHIFT)
+#define FREQ_MAX                       127
+
+/* DFLL_DROOP_CTRL: droop prevention control */
+#define DFLL_DROOP_CTRL                        0x1c
+
+/* DFLL_OUTPUT_CFG: closed loop mode control registers */
+/* NOTE: access via dfll_i2c_{readl,writel} */
+#define DFLL_OUTPUT_CFG                        0x20
+#define DFLL_OUTPUT_CFG_I2C_ENABLE     (0x1 << 30)
+#define OUT_MASK                       0x3f
+#define DFLL_OUTPUT_CFG_SAFE_SHIFT     24
+#define DFLL_OUTPUT_CFG_SAFE_MASK      \
+               (OUT_MASK << DFLL_OUTPUT_CFG_SAFE_SHIFT)
+#define DFLL_OUTPUT_CFG_MAX_SHIFT      16
+#define DFLL_OUTPUT_CFG_MAX_MASK       \
+               (OUT_MASK << DFLL_OUTPUT_CFG_MAX_SHIFT)
+#define DFLL_OUTPUT_CFG_MIN_SHIFT      8
+#define DFLL_OUTPUT_CFG_MIN_MASK       \
+               (OUT_MASK << DFLL_OUTPUT_CFG_MIN_SHIFT)
+#define DFLL_OUTPUT_CFG_PWM_DELTA      (0x1 << 7)
+#define DFLL_OUTPUT_CFG_PWM_ENABLE     (0x1 << 6)
+#define DFLL_OUTPUT_CFG_PWM_DIV_SHIFT  0
+#define DFLL_OUTPUT_CFG_PWM_DIV_MASK   \
+               (OUT_MASK << DFLL_OUTPUT_CFG_PWM_DIV_SHIFT)
+
+/* DFLL_OUTPUT_FORCE: closed loop mode voltage forcing control */
+#define DFLL_OUTPUT_FORCE              0x24
+#define DFLL_OUTPUT_FORCE_ENABLE       (0x1 << 6)
+#define DFLL_OUTPUT_FORCE_VALUE_SHIFT  0
+#define DFLL_OUTPUT_FORCE_VALUE_MASK   \
+               (OUT_MASK << DFLL_OUTPUT_FORCE_VALUE_SHIFT)
+
+/* DFLL_MONITOR_CTRL: internal monitor data source control */
+#define DFLL_MONITOR_CTRL              0x28
+#define DFLL_MONITOR_CTRL_FREQ         6
+
+/* DFLL_MONITOR_DATA: internal monitor data output */
+#define DFLL_MONITOR_DATA              0x2c
+#define DFLL_MONITOR_DATA_NEW_MASK     (0x1 << 16)
+#define DFLL_MONITOR_DATA_VAL_SHIFT    0
+#define DFLL_MONITOR_DATA_VAL_MASK     (0xFFFF << DFLL_MONITOR_DATA_VAL_SHIFT)
+
+/*
+ * I2C output control registers - access via dfll_i2c_{readl,writel}
+ */
+
+/* DFLL_I2C_CFG: I2C controller configuration register */
+#define DFLL_I2C_CFG                   0x40
+#define DFLL_I2C_CFG_ARB_ENABLE                (0x1 << 20)
+#define DFLL_I2C_CFG_HS_CODE_SHIFT     16
+#define DFLL_I2C_CFG_HS_CODE_MASK      (0x7 << DFLL_I2C_CFG_HS_CODE_SHIFT)
+#define DFLL_I2C_CFG_PACKET_ENABLE     (0x1 << 15)
+#define DFLL_I2C_CFG_SIZE_SHIFT                12
+#define DFLL_I2C_CFG_SIZE_MASK         (0x7 << DFLL_I2C_CFG_SIZE_SHIFT)
+#define DFLL_I2C_CFG_SLAVE_ADDR_10     (0x1 << 10)
+#define DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_7BIT     1
+#define DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_10BIT    0
+
+/* DFLL_I2C_VDD_REG_ADDR: PMIC I2C address for closed loop mode */
+#define DFLL_I2C_VDD_REG_ADDR          0x44
+
+/* DFLL_I2C_STS: I2C controller status */
+#define DFLL_I2C_STS                   0x48
+#define DFLL_I2C_STS_I2C_LAST_SHIFT    1
+#define DFLL_I2C_STS_I2C_REQ_PENDING   0x1
+
+/* DFLL_INTR_STS: DFLL interrupt status register */
+#define DFLL_INTR_STS                  0x5c
+
+/* DFLL_INTR_EN: DFLL interrupt enable register */
+#define DFLL_INTR_EN                   0x60
+#define DFLL_INTR_MIN_MASK             0x1
+#define DFLL_INTR_MAX_MASK             0x2
+
+/*
+ * Integrated I2C controller registers - relative to td->i2c_controller_base
+ */
+
+/* DFLL_I2C_CLK_DIVISOR: I2C controller clock divisor */
+#define DFLL_I2C_CLK_DIVISOR           0x6c
+#define DFLL_I2C_CLK_DIVISOR_MASK      0xffff
+#define DFLL_I2C_CLK_DIVISOR_FS_SHIFT  16
+#define DFLL_I2C_CLK_DIVISOR_HS_SHIFT  0
+#define DFLL_I2C_CLK_DIVISOR_PREDIV    8
+#define DFLL_I2C_CLK_DIVISOR_HSMODE_PREDIV     12
+
+/*
+ * Other constants
+ */
+
+/* MAX_DFLL_VOLTAGES: number of LUT entries in the DFLL IP block */
+#define MAX_DFLL_VOLTAGES              33
+
+/*
+ * REF_CLK_CYC_PER_DVCO_SAMPLE: the number of ref_clk cycles that the hardware
+ *    integrates the DVCO counter over - used for debug rate monitoring and
+ *    droop control
+ */
+#define REF_CLK_CYC_PER_DVCO_SAMPLE    4
+
+/*
+ * REF_CLOCK_RATE: the DFLL reference clock rate currently supported by this
+ * driver, in Hz
+ */
+#define REF_CLOCK_RATE                 51000000UL
+
+#define DVCO_RATE_TO_MULT(rate, ref_rate)      ((rate) / ((ref_rate) / 2))
+#define MULT_TO_DVCO_RATE(mult, ref_rate)      ((mult) * ((ref_rate) / 2))
+
+/**
+ * enum dfll_ctrl_mode - DFLL hardware operating mode
+ * @DFLL_UNINITIALIZED: (uninitialized state - not in hardware bitfield)
+ * @DFLL_DISABLED: DFLL not generating an output clock
+ * @DFLL_OPEN_LOOP: DVCO running, but DFLL not adjusting voltage
+ * @DFLL_CLOSED_LOOP: DVCO running, and DFLL adjusting voltage to match
+ *                   the requested rate
+ *
+ * The integer corresponding to the last two states, minus one, is
+ * written to the DFLL hardware to change operating modes.
+ */
+enum dfll_ctrl_mode {
+       DFLL_UNINITIALIZED = 0,
+       DFLL_DISABLED = 1,
+       DFLL_OPEN_LOOP = 2,
+       DFLL_CLOSED_LOOP = 3,
+};
+
+/**
+ * enum dfll_tune_range - voltage range that the driver believes it's in
+ * @DFLL_TUNE_UNINITIALIZED: DFLL tuning not yet programmed
+ * @DFLL_TUNE_LOW: DFLL in the low-voltage range (or open-loop mode)
+ *
+ * Some DFLL tuning parameters may need to change depending on the
+ * DVCO's voltage; these states represent the ranges that the driver
+ * supports. These are software states; these values are never
+ * written into registers.
+ */
+enum dfll_tune_range {
+       DFLL_TUNE_UNINITIALIZED = 0,
+       DFLL_TUNE_LOW = 1,
+};
+
+/**
+ * struct dfll_rate_req - target DFLL rate request data
+ * @rate: target frequency, after the postscaling
+ * @dvco_target_rate: target frequency, after the postscaling
+ * @lut_index: LUT index at which voltage the dvco_target_rate will be reached
+ * @mult_bits: value to program to the MULT bits of the DFLL_FREQ_REQ register
+ * @scale_bits: value to program to the SCALE bits of the DFLL_FREQ_REQ register
+ */
+struct dfll_rate_req {
+       unsigned long rate;
+       unsigned long dvco_target_rate;
+       int lut_index;
+       u8 mult_bits;
+       u8 scale_bits;
+};
+
+struct tegra_dfll {
+       struct device                   *dev;
+       struct tegra_dfll_soc_data      *soc;
+
+       void __iomem                    *base;
+       void __iomem                    *i2c_base;
+       void __iomem                    *i2c_controller_base;
+       void __iomem                    *lut_base;
+
+       struct regulator                *vdd_reg;
+       struct clk                      *soc_clk;
+       struct clk                      *ref_clk;
+       struct clk                      *i2c_clk;
+       struct clk                      *dfll_clk;
+       struct reset_control            *dvco_rst;
+       unsigned long                   ref_rate;
+       unsigned long                   i2c_clk_rate;
+       unsigned long                   dvco_rate_min;
+
+       enum dfll_ctrl_mode             mode;
+       enum dfll_tune_range            tune_range;
+       struct dentry                   *debugfs_dir;
+       struct clk_hw                   dfll_clk_hw;
+       const char                      *output_clock_name;
+       struct dfll_rate_req            last_req;
+       unsigned long                   last_unrounded_rate;
+
+       /* Parameters from DT */
+       u32                             droop_ctrl;
+       u32                             sample_rate;
+       u32                             force_mode;
+       u32                             cf;
+       u32                             ci;
+       u32                             cg;
+       bool                            cg_scale;
+
+       /* I2C interface parameters */
+       u32                             i2c_fs_rate;
+       u32                             i2c_reg;
+       u32                             i2c_slave_addr;
+
+       /* i2c_lut array entries are regulator framework selectors */
+       unsigned                        i2c_lut[MAX_DFLL_VOLTAGES];
+       int                             i2c_lut_size;
+       u8                              lut_min, lut_max, lut_safe;
+};
+
+#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
+
+/* mode_name: map numeric DFLL modes to names for friendly console messages */
+static const char * const mode_name[] = {
+       [DFLL_UNINITIALIZED] = "uninitialized",
+       [DFLL_DISABLED] = "disabled",
+       [DFLL_OPEN_LOOP] = "open_loop",
+       [DFLL_CLOSED_LOOP] = "closed_loop",
+};
+
+/*
+ * Register accessors
+ */
+
+static inline u32 dfll_readl(struct tegra_dfll *td, u32 offs)
+{
+       return __raw_readl(td->base + offs);
+}
+
+static inline void dfll_writel(struct tegra_dfll *td, u32 val, u32 offs)
+{
+       WARN_ON(offs >= DFLL_I2C_CFG);
+       __raw_writel(val, td->base + offs);
+}
+
+static inline void dfll_wmb(struct tegra_dfll *td)
+{
+       dfll_readl(td, DFLL_CTRL);
+}
+
+/* I2C output control registers - for addresses above DFLL_I2C_CFG */
+
+static inline u32 dfll_i2c_readl(struct tegra_dfll *td, u32 offs)
+{
+       return __raw_readl(td->i2c_base + offs);
+}
+
+static inline void dfll_i2c_writel(struct tegra_dfll *td, u32 val, u32 offs)
+{
+       __raw_writel(val, td->i2c_base + offs);
+}
+
+static inline void dfll_i2c_wmb(struct tegra_dfll *td)
+{
+       dfll_i2c_readl(td, DFLL_I2C_CFG);
+}
+
+/**
+ * dfll_is_running - is the DFLL currently generating a clock?
+ * @td: DFLL instance
+ *
+ * If the DFLL is currently generating an output clock signal, return
+ * true; otherwise return false.
+ */
+static bool dfll_is_running(struct tegra_dfll *td)
+{
+       return td->mode >= DFLL_OPEN_LOOP;
+}
+
+/*
+ * Runtime PM suspend/resume callbacks
+ */
+
+/**
+ * tegra_dfll_runtime_resume - enable all clocks needed by the DFLL
+ * @dev: DFLL device *
+ *
+ * Enable all clocks needed by the DFLL. Assumes that clk_prepare()
+ * has already been called on all the clocks.
+ *
+ * XXX Should also handle context restore when returning from off.
+ */
+int tegra_dfll_runtime_resume(struct device *dev)
+{
+       struct tegra_dfll *td = dev_get_drvdata(dev);
+       int ret;
+
+       ret = clk_enable(td->ref_clk);
+       if (ret) {
+               dev_err(dev, "could not enable ref clock: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_enable(td->soc_clk);
+       if (ret) {
+               dev_err(dev, "could not enable register clock: %d\n", ret);
+               clk_disable(td->ref_clk);
+               return ret;
+       }
+
+       ret = clk_enable(td->i2c_clk);
+       if (ret) {
+               dev_err(dev, "could not enable i2c clock: %d\n", ret);
+               clk_disable(td->soc_clk);
+               clk_disable(td->ref_clk);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_runtime_resume);
+
+/**
+ * tegra_dfll_runtime_suspend - disable all clocks needed by the DFLL
+ * @dev: DFLL device *
+ *
+ * Disable all clocks needed by the DFLL. Assumes that other code
+ * will later call clk_unprepare().
+ */
+int tegra_dfll_runtime_suspend(struct device *dev)
+{
+       struct tegra_dfll *td = dev_get_drvdata(dev);
+
+       clk_disable(td->ref_clk);
+       clk_disable(td->soc_clk);
+       clk_disable(td->i2c_clk);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_runtime_suspend);
+
+/*
+ * DFLL tuning operations (per-voltage-range tuning settings)
+ */
+
+/**
+ * dfll_tune_low - tune to DFLL and CPU settings valid for any voltage
+ * @td: DFLL instance
+ *
+ * Tune the DFLL oscillator parameters and the CPU clock shaper for
+ * the low-voltage range. These settings are valid for any voltage,
+ * but may not be optimal.
+ */
+static void dfll_tune_low(struct tegra_dfll *td)
+{
+       td->tune_range = DFLL_TUNE_LOW;
+
+       dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0);
+       dfll_writel(td, td->soc->tune1, DFLL_TUNE1);
+       dfll_wmb(td);
+
+       if (td->soc->set_clock_trimmers_low)
+               td->soc->set_clock_trimmers_low();
+}
+
+/*
+ * Output clock scaler helpers
+ */
+
+/**
+ * dfll_scale_dvco_rate - calculate scaled rate from the DVCO rate
+ * @scale_bits: clock scaler value (bits in the DFLL_FREQ_REQ_SCALE field)
+ * @dvco_rate: the DVCO rate
+ *
+ * Apply the same scaling formula that the DFLL hardware uses to scale
+ * the DVCO rate.
+ */
+static unsigned long dfll_scale_dvco_rate(int scale_bits,
+                                         unsigned long dvco_rate)
+{
+       return (u64)dvco_rate * (scale_bits + 1) / DFLL_FREQ_REQ_SCALE_MAX;
+}
+
+/*
+ * Monitor control
+ */
+
+/**
+ * dfll_calc_monitored_rate - convert DFLL_MONITOR_DATA_VAL rate into real freq
+ * @monitor_data: value read from the DFLL_MONITOR_DATA_VAL bitfield
+ * @ref_rate: DFLL reference clock rate
+ *
+ * Convert @monitor_data from DFLL_MONITOR_DATA_VAL units into cycles
+ * per second. Returns the converted value.
+ */
+static u64 dfll_calc_monitored_rate(u32 monitor_data,
+                                   unsigned long ref_rate)
+{
+       return monitor_data * (ref_rate / REF_CLK_CYC_PER_DVCO_SAMPLE);
+}
+
+/**
+ * dfll_read_monitor_rate - return the DFLL's output rate from internal monitor
+ * @td: DFLL instance
+ *
+ * If the DFLL is enabled, return the last rate reported by the DFLL's
+ * internal monitoring hardware. This works in both open-loop and
+ * closed-loop mode, and takes the output scaler setting into account.
+ * Assumes that the monitor was programmed to monitor frequency before
+ * the sample period started. If the driver believes that the DFLL is
+ * currently uninitialized or disabled, it will return 0, since
+ * otherwise the DFLL monitor data register will return the last
+ * measured rate from when the DFLL was active.
+ */
+static u64 dfll_read_monitor_rate(struct tegra_dfll *td)
+{
+       u32 v, s;
+       u64 pre_scaler_rate, post_scaler_rate;
+
+       if (!dfll_is_running(td))
+               return 0;
+
+       v = dfll_readl(td, DFLL_MONITOR_DATA);
+       v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
+       pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);
+
+       s = dfll_readl(td, DFLL_FREQ_REQ);
+       s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
+       post_scaler_rate = dfll_scale_dvco_rate(s, pre_scaler_rate);
+
+       return post_scaler_rate;
+}
+
+/*
+ * DFLL mode switching
+ */
+
+/**
+ * dfll_set_mode - change the DFLL control mode
+ * @td: DFLL instance
+ * @mode: DFLL control mode (see enum dfll_ctrl_mode)
+ *
+ * Change the DFLL's operating mode between disabled, open-loop mode,
+ * and closed-loop mode, or vice versa.
+ */
+static void dfll_set_mode(struct tegra_dfll *td,
+                         enum dfll_ctrl_mode mode)
+{
+       td->mode = mode;
+       dfll_writel(td, mode - 1, DFLL_CTRL);
+       dfll_wmb(td);
+}
+
+/*
+ * DFLL-to-I2C controller interface
+ */
+
+/**
+ * dfll_i2c_set_output_enabled - enable/disable I2C PMIC voltage requests
+ * @td: DFLL instance
+ * @enable: whether to enable or disable the I2C voltage requests
+ *
+ * Set the master enable control for I2C control value updates. If disabled,
+ * then I2C control messages are inhibited, regardless of the DFLL mode.
+ */
+static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
+{
+       u32 val;
+
+       val = dfll_i2c_readl(td, DFLL_OUTPUT_CFG);
+
+       if (enable)
+               val |= DFLL_OUTPUT_CFG_I2C_ENABLE;
+       else
+               val &= ~DFLL_OUTPUT_CFG_I2C_ENABLE;
+
+       dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
+       dfll_i2c_wmb(td);
+
+       return 0;
+}
+
+/**
+ * dfll_load_lut - load the voltage lookup table
+ * @td: struct tegra_dfll *
+ *
+ * Load the voltage-to-PMIC register value lookup table into the DFLL
+ * IP block memory. Look-up tables can be loaded at any time.
+ */
+static void dfll_load_i2c_lut(struct tegra_dfll *td)
+{
+       int i, lut_index;
+       u32 val;
+
+       for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
+               if (i < td->lut_min)
+                       lut_index = td->lut_min;
+               else if (i > td->lut_max)
+                       lut_index = td->lut_max;
+               else
+                       lut_index = i;
+
+               val = regulator_list_hardware_vsel(td->vdd_reg,
+                                                    td->i2c_lut[lut_index]);
+               __raw_writel(val, td->lut_base + i * 4);
+       }
+
+       dfll_i2c_wmb(td);
+}
+
+/**
+ * dfll_init_i2c_if - set up the DFLL's DFLL-I2C interface
+ * @td: DFLL instance
+ *
+ * During DFLL driver initialization, program the DFLL-I2C interface
+ * with the PMU slave address, vdd register offset, and transfer mode.
+ * This data is used by the DFLL to automatically construct I2C
+ * voltage-set commands, which are then passed to the DFLL's internal
+ * I2C controller.
+ */
+static void dfll_init_i2c_if(struct tegra_dfll *td)
+{
+       u32 val;
+
+       if (td->i2c_slave_addr > 0x7f) {
+               val = td->i2c_slave_addr << DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_10BIT;
+               val |= DFLL_I2C_CFG_SLAVE_ADDR_10;
+       } else {
+               val = td->i2c_slave_addr << DFLL_I2C_CFG_SLAVE_ADDR_SHIFT_7BIT;
+       }
+       val |= DFLL_I2C_CFG_SIZE_MASK;
+       val |= DFLL_I2C_CFG_ARB_ENABLE;
+       dfll_i2c_writel(td, val, DFLL_I2C_CFG);
+
+       dfll_i2c_writel(td, td->i2c_reg, DFLL_I2C_VDD_REG_ADDR);
+
+       val = DIV_ROUND_UP(td->i2c_clk_rate, td->i2c_fs_rate * 8);
+       BUG_ON(!val || (val > DFLL_I2C_CLK_DIVISOR_MASK));
+       val = (val - 1) << DFLL_I2C_CLK_DIVISOR_FS_SHIFT;
+
+       /* default hs divisor just in case */
+       val |= 1 << DFLL_I2C_CLK_DIVISOR_HS_SHIFT;
+       __raw_writel(val, td->i2c_controller_base + DFLL_I2C_CLK_DIVISOR);
+       dfll_i2c_wmb(td);
+}
+
+/**
+ * dfll_init_out_if - prepare DFLL-to-PMIC interface
+ * @td: DFLL instance
+ *
+ * During DFLL driver initialization or resume from context loss,
+ * disable the I2C command output to the PMIC, set safe voltage and
+ * output limits, and disable and clear limit interrupts.
+ */
+static void dfll_init_out_if(struct tegra_dfll *td)
+{
+       u32 val;
+
+       td->lut_min = 0;
+       td->lut_max = td->i2c_lut_size - 1;
+       td->lut_safe = td->lut_min + 1;
+
+       dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
+       val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
+               (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
+               (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
+       dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
+       dfll_i2c_wmb(td);
+
+       dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
+       dfll_i2c_writel(td, 0, DFLL_INTR_EN);
+       dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
+                       DFLL_INTR_STS);
+
+       dfll_load_i2c_lut(td);
+       dfll_init_i2c_if(td);
+}
+
+/*
+ * Set/get the DFLL's targeted output clock rate
+ */
+
+/**
+ * find_lut_index_for_rate - determine I2C LUT index for given DFLL rate
+ * @td: DFLL instance
+ * @rate: clock rate
+ *
+ * Determines the index of a I2C LUT entry for a voltage that approximately
+ * produces the given DFLL clock rate. This is used when forcing a value
+ * to the integrator during rate changes. Returns -ENOENT if a suitable
+ * LUT index is not found.
+ */
+static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
+{
+       struct dev_pm_opp *opp;
+       int i, uv;
+
+       opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
+       if (IS_ERR(opp))
+               return PTR_ERR(opp);
+       uv = dev_pm_opp_get_voltage(opp);
+
+       for (i = 0; i < td->i2c_lut_size; i++) {
+               if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
+                       return i;
+       }
+
+       return -ENOENT;
+}
+
+/**
+ * dfll_calculate_rate_request - calculate DFLL parameters for a given rate
+ * @td: DFLL instance
+ * @req: DFLL-rate-request structure
+ * @rate: the desired DFLL rate
+ *
+ * Populate the DFLL-rate-request record @req fields with the scale_bits
+ * and mult_bits fields, based on the target input rate. Returns 0 upon
+ * success, or -EINVAL if the requested rate in req->rate is too high
+ * or low for the DFLL to generate.
+ */
+static int dfll_calculate_rate_request(struct tegra_dfll *td,
+                                      struct dfll_rate_req *req,
+                                      unsigned long rate)
+{
+       u32 val;
+
+       /*
+        * If requested rate is below the minimum DVCO rate, active the scaler.
+        * In the future the DVCO minimum voltage should be selected based on
+        * chip temperature and the actual minimum rate should be calibrated
+        * at runtime.
+        */
+       req->scale_bits = DFLL_FREQ_REQ_SCALE_MAX - 1;
+       if (rate < td->dvco_rate_min) {
+               int scale;
+
+               scale = DIV_ROUND_CLOSEST(rate / 1000 * DFLL_FREQ_REQ_SCALE_MAX,
+                                         td->dvco_rate_min / 1000);
+               if (!scale) {
+                       dev_err(td->dev, "%s: Rate %lu is too low\n",
+                               __func__, rate);
+                       return -EINVAL;
+               }
+               req->scale_bits = scale - 1;
+               rate = td->dvco_rate_min;
+       }
+
+       /* Convert requested rate into frequency request and scale settings */
+       val = DVCO_RATE_TO_MULT(rate, td->ref_rate);
+       if (val > FREQ_MAX) {
+               dev_err(td->dev, "%s: Rate %lu is above dfll range\n",
+                       __func__, rate);
+               return -EINVAL;
+       }
+       req->mult_bits = val;
+       req->dvco_target_rate = MULT_TO_DVCO_RATE(req->mult_bits, td->ref_rate);
+       req->rate = dfll_scale_dvco_rate(req->scale_bits,
+                                        req->dvco_target_rate);
+       req->lut_index = find_lut_index_for_rate(td, req->dvco_target_rate);
+       if (req->lut_index < 0)
+               return req->lut_index;
+
+       return 0;
+}
+
+/**
+ * dfll_set_frequency_request - start the frequency change operation
+ * @td: DFLL instance
+ * @req: rate request structure
+ *
+ * Tell the DFLL to try to change its output frequency to the
+ * frequency represented by @req. DFLL must be in closed-loop mode.
+ */
+static void dfll_set_frequency_request(struct tegra_dfll *td,
+                                      struct dfll_rate_req *req)
+{
+       u32 val = 0;
+       int force_val;
+       int coef = 128; /* FIXME: td->cg_scale? */;
+
+       force_val = (req->lut_index - td->lut_safe) * coef / td->cg;
+       force_val = clamp(force_val, FORCE_MIN, FORCE_MAX);
+
+       val |= req->mult_bits << DFLL_FREQ_REQ_MULT_SHIFT;
+       val |= req->scale_bits << DFLL_FREQ_REQ_SCALE_SHIFT;
+       val |= ((u32)force_val << DFLL_FREQ_REQ_FORCE_SHIFT) &
+               DFLL_FREQ_REQ_FORCE_MASK;
+       val |= DFLL_FREQ_REQ_FREQ_VALID | DFLL_FREQ_REQ_FORCE_ENABLE;
+
+       dfll_writel(td, val, DFLL_FREQ_REQ);
+       dfll_wmb(td);
+}
+
+/**
+ * tegra_dfll_request_rate - set the next rate for the DFLL to tune to
+ * @td: DFLL instance
+ * @rate: clock rate to target
+ *
+ * Convert the requested clock rate @rate into the DFLL control logic
+ * settings. In closed-loop mode, update new settings immediately to
+ * adjust DFLL output rate accordingly. Otherwise, just save them
+ * until the next switch to closed loop. Returns 0 upon success,
+ * -EPERM if the DFLL driver has not yet been initialized, or -EINVAL
+ * if @rate is outside the DFLL's tunable range.
+ */
+static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
+{
+       int ret;
+       struct dfll_rate_req req;
+
+       if (td->mode == DFLL_UNINITIALIZED) {
+               dev_err(td->dev, "%s: Cannot set DFLL rate in %s mode\n",
+                       __func__, mode_name[td->mode]);
+               return -EPERM;
+       }
+
+       ret = dfll_calculate_rate_request(td, &req, rate);
+       if (ret)
+               return ret;
+
+       td->last_unrounded_rate = rate;
+       td->last_req = req;
+
+       if (td->mode == DFLL_CLOSED_LOOP)
+               dfll_set_frequency_request(td, &td->last_req);
+
+       return 0;
+}
+
+/*
+ * DFLL enable/disable & open-loop <-> closed-loop transitions
+ */
+
+/**
+ * dfll_disable - switch from open-loop mode to disabled mode
+ * @td: DFLL instance
+ *
+ * Switch from OPEN_LOOP state to DISABLED state. Returns 0 upon success
+ * or -EPERM if the DFLL is not currently in open-loop mode.
+ */
+static int dfll_disable(struct tegra_dfll *td)
+{
+       if (td->mode != DFLL_OPEN_LOOP) {
+               dev_err(td->dev, "cannot disable DFLL in %s mode\n",
+                       mode_name[td->mode]);
+               return -EINVAL;
+       }
+
+       dfll_set_mode(td, DFLL_DISABLED);
+       pm_runtime_put_sync(td->dev);
+
+       return 0;
+}
+
+/**
+ * dfll_enable - switch a disabled DFLL to open-loop mode
+ * @td: DFLL instance
+ *
+ * Switch from DISABLED state to OPEN_LOOP state. Returns 0 upon success
+ * or -EPERM if the DFLL is not currently disabled.
+ */
+static int dfll_enable(struct tegra_dfll *td)
+{
+       if (td->mode != DFLL_DISABLED) {
+               dev_err(td->dev, "cannot enable DFLL in %s mode\n",
+                       mode_name[td->mode]);
+               return -EPERM;
+       }
+
+       pm_runtime_get_sync(td->dev);
+       dfll_set_mode(td, DFLL_OPEN_LOOP);
+
+       return 0;
+}
+
+/**
+ * dfll_set_open_loop_config - prepare to switch to open-loop mode
+ * @td: DFLL instance
+ *
+ * Prepare to switch the DFLL to open-loop mode. This switches the
+ * DFLL to the low-voltage tuning range, ensures that I2C output
+ * forcing is disabled, and disables the output clock rate scaler.
+ * The DFLL's low-voltage tuning range parameters must be
+ * characterized to keep the downstream device stable at any DVCO
+ * input voltage. No return value.
+ */
+static void dfll_set_open_loop_config(struct tegra_dfll *td)
+{
+       u32 val;
+
+       /* always tune low (safe) in open loop */
+       if (td->tune_range != DFLL_TUNE_LOW)
+               dfll_tune_low(td);
+
+       val = dfll_readl(td, DFLL_FREQ_REQ);
+       val |= DFLL_FREQ_REQ_SCALE_MASK;
+       val &= ~DFLL_FREQ_REQ_FORCE_ENABLE;
+       dfll_writel(td, val, DFLL_FREQ_REQ);
+       dfll_wmb(td);
+}
+
+/**
+ * tegra_dfll_lock - switch from open-loop to closed-loop mode
+ * @td: DFLL instance
+ *
+ * Switch from OPEN_LOOP state to CLOSED_LOOP state. Returns 0 upon success,
+ * -EINVAL if the DFLL's target rate hasn't been set yet, or -EPERM if the
+ * DFLL is not currently in open-loop mode.
+ */
+static int dfll_lock(struct tegra_dfll *td)
+{
+       struct dfll_rate_req *req = &td->last_req;
+
+       switch (td->mode) {
+       case DFLL_CLOSED_LOOP:
+               return 0;
+
+       case DFLL_OPEN_LOOP:
+               if (req->rate == 0) {
+                       dev_err(td->dev, "%s: Cannot lock DFLL at rate 0\n",
+                               __func__);
+                       return -EINVAL;
+               }
+
+               dfll_i2c_set_output_enabled(td, true);
+               dfll_set_mode(td, DFLL_CLOSED_LOOP);
+               dfll_set_frequency_request(td, req);
+               return 0;
+
+       default:
+               BUG_ON(td->mode > DFLL_CLOSED_LOOP);
+               dev_err(td->dev, "%s: Cannot lock DFLL in %s mode\n",
+                       __func__, mode_name[td->mode]);
+               return -EPERM;
+       }
+}
+
+/**
+ * tegra_dfll_unlock - switch from closed-loop to open-loop mode
+ * @td: DFLL instance
+ *
+ * Switch from CLOSED_LOOP state to OPEN_LOOP state. Returns 0 upon success,
+ * or -EPERM if the DFLL is not currently in open-loop mode.
+ */
+static int dfll_unlock(struct tegra_dfll *td)
+{
+       switch (td->mode) {
+       case DFLL_CLOSED_LOOP:
+               dfll_set_open_loop_config(td);
+               dfll_set_mode(td, DFLL_OPEN_LOOP);
+               dfll_i2c_set_output_enabled(td, false);
+               return 0;
+
+       case DFLL_OPEN_LOOP:
+               return 0;
+
+       default:
+               BUG_ON(td->mode > DFLL_CLOSED_LOOP);
+               dev_err(td->dev, "%s: Cannot unlock DFLL in %s mode\n",
+                       __func__, mode_name[td->mode]);
+               return -EPERM;
+       }
+}
+
+/*
+ * Clock framework integration
+ *
+ * When the DFLL is being controlled by the CCF, always enter closed loop
+ * mode when the clk is enabled. This requires that a DFLL rate request
+ * has been set beforehand, which implies that a clk_set_rate() call is
+ * always required before a clk_enable().
+ */
+
+static int dfll_clk_is_enabled(struct clk_hw *hw)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+
+       return dfll_is_running(td);
+}
+
+static int dfll_clk_enable(struct clk_hw *hw)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+       int ret;
+
+       ret = dfll_enable(td);
+       if (ret)
+               return ret;
+
+       ret = dfll_lock(td);
+       if (ret)
+               dfll_disable(td);
+
+       return ret;
+}
+
+static void dfll_clk_disable(struct clk_hw *hw)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+       int ret;
+
+       ret = dfll_unlock(td);
+       if (!ret)
+               dfll_disable(td);
+}
+
+static unsigned long dfll_clk_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+
+       return td->last_unrounded_rate;
+}
+
+static long dfll_clk_round_rate(struct clk_hw *hw,
+                               unsigned long rate,
+                               unsigned long *parent_rate)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+       struct dfll_rate_req req;
+       int ret;
+
+       ret = dfll_calculate_rate_request(td, &req, rate);
+       if (ret)
+               return ret;
+
+       /*
+        * Don't return the rounded rate, since it doesn't really matter as
+        * the output rate will be voltage controlled anyway, and cpufreq
+        * freaks out if any rounding happens.
+        */
+       return rate;
+}
+
+static int dfll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       struct tegra_dfll *td = clk_hw_to_dfll(hw);
+
+       return dfll_request_rate(td, rate);
+}
+
+static const struct clk_ops dfll_clk_ops = {
+       .is_enabled     = dfll_clk_is_enabled,
+       .enable         = dfll_clk_enable,
+       .disable        = dfll_clk_disable,
+       .recalc_rate    = dfll_clk_recalc_rate,
+       .round_rate     = dfll_clk_round_rate,
+       .set_rate       = dfll_clk_set_rate,
+};
+
+static struct clk_init_data dfll_clk_init_data = {
+       .flags          = CLK_IS_ROOT,
+       .ops            = &dfll_clk_ops,
+       .num_parents    = 0,
+};
+
+/**
+ * dfll_register_clk - register the DFLL output clock with the clock framework
+ * @td: DFLL instance
+ *
+ * Register the DFLL's output clock with the Linux clock framework and register
+ * the DFLL driver as an OF clock provider. Returns 0 upon success or -EINVAL
+ * or -ENOMEM upon failure.
+ */
+static int dfll_register_clk(struct tegra_dfll *td)
+{
+       int ret;
+
+       dfll_clk_init_data.name = td->output_clock_name;
+       td->dfll_clk_hw.init = &dfll_clk_init_data;
+
+       td->dfll_clk = clk_register(td->dev, &td->dfll_clk_hw);
+       if (IS_ERR(td->dfll_clk)) {
+               dev_err(td->dev, "DFLL clock registration error\n");
+               return -EINVAL;
+       }
+
+       ret = of_clk_add_provider(td->dev->of_node, of_clk_src_simple_get,
+                                 td->dfll_clk);
+       if (ret) {
+               dev_err(td->dev, "of_clk_add_provider() failed\n");
+
+               clk_unregister(td->dfll_clk);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * dfll_unregister_clk - unregister the DFLL output clock
+ * @td: DFLL instance
+ *
+ * Unregister the DFLL's output clock from the Linux clock framework
+ * and from clkdev. No return value.
+ */
+static void dfll_unregister_clk(struct tegra_dfll *td)
+{
+       of_clk_del_provider(td->dev->of_node);
+       clk_unregister(td->dfll_clk);
+       td->dfll_clk = NULL;
+}
+
+/*
+ * Debugfs interface
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+static int attr_enable_get(void *data, u64 *val)
+{
+       struct tegra_dfll *td = data;
+
+       *val = dfll_is_running(td);
+
+       return 0;
+}
+static int attr_enable_set(void *data, u64 val)
+{
+       struct tegra_dfll *td = data;
+
+       return val ? dfll_enable(td) : dfll_disable(td);
+}
+DEFINE_SIMPLE_ATTRIBUTE(enable_fops, attr_enable_get, attr_enable_set,
+                       "%llu\n");
+
+static int attr_lock_get(void *data, u64 *val)
+{
+       struct tegra_dfll *td = data;
+
+       *val = (td->mode == DFLL_CLOSED_LOOP);
+
+       return 0;
+}
+static int attr_lock_set(void *data, u64 val)
+{
+       struct tegra_dfll *td = data;
+
+       return val ? dfll_lock(td) :  dfll_unlock(td);
+}
+DEFINE_SIMPLE_ATTRIBUTE(lock_fops, attr_lock_get, attr_lock_set,
+                       "%llu\n");
+
+static int attr_rate_get(void *data, u64 *val)
+{
+       struct tegra_dfll *td = data;
+
+       *val = dfll_read_monitor_rate(td);
+
+       return 0;
+}
+
+static int attr_rate_set(void *data, u64 val)
+{
+       struct tegra_dfll *td = data;
+
+       return dfll_request_rate(td, val);
+}
+DEFINE_SIMPLE_ATTRIBUTE(rate_fops, attr_rate_get, attr_rate_set, "%llu\n");
+
+static int attr_registers_show(struct seq_file *s, void *data)
+{
+       u32 val, offs;
+       struct tegra_dfll *td = s->private;
+
+       seq_puts(s, "CONTROL REGISTERS:\n");
+       for (offs = 0; offs <= DFLL_MONITOR_DATA; offs += 4) {
+               if (offs == DFLL_OUTPUT_CFG)
+                       val = dfll_i2c_readl(td, offs);
+               else
+                       val = dfll_readl(td, offs);
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs, val);
+       }
+
+       seq_puts(s, "\nI2C and INTR REGISTERS:\n");
+       for (offs = DFLL_I2C_CFG; offs <= DFLL_I2C_STS; offs += 4)
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                          dfll_i2c_readl(td, offs));
+       for (offs = DFLL_INTR_STS; offs <= DFLL_INTR_EN; offs += 4)
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                          dfll_i2c_readl(td, offs));
+
+       seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
+       offs = DFLL_I2C_CLK_DIVISOR;
+       seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                  __raw_readl(td->i2c_controller_base + offs));
+
+       seq_puts(s, "\nLUT:\n");
+       for (offs = 0; offs <  4 * MAX_DFLL_VOLTAGES; offs += 4)
+               seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
+                          __raw_readl(td->lut_base + offs));
+
+       return 0;
+}
+
+static int attr_registers_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, attr_registers_show, inode->i_private);
+}
+
+static const struct file_operations attr_registers_fops = {
+       .open           = attr_registers_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dfll_debug_init(struct tegra_dfll *td)
+{
+       int ret;
+
+       if (!td || (td->mode == DFLL_UNINITIALIZED))
+               return 0;
+
+       td->debugfs_dir = debugfs_create_dir("tegra_dfll_fcpu", NULL);
+       if (!td->debugfs_dir)
+               return -ENOMEM;
+
+       ret = -ENOMEM;
+
+       if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR,
+                                td->debugfs_dir, td, &enable_fops))
+               goto err_out;
+
+       if (!debugfs_create_file("lock", S_IRUGO,
+                                td->debugfs_dir, td, &lock_fops))
+               goto err_out;
+
+       if (!debugfs_create_file("rate", S_IRUGO,
+                                td->debugfs_dir, td, &rate_fops))
+               goto err_out;
+
+       if (!debugfs_create_file("registers", S_IRUGO,
+                                td->debugfs_dir, td, &attr_registers_fops))
+               goto err_out;
+
+       return 0;
+
+err_out:
+       debugfs_remove_recursive(td->debugfs_dir);
+       return ret;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+/*
+ * DFLL initialization
+ */
+
+/**
+ * dfll_set_default_params - program non-output related DFLL parameters
+ * @td: DFLL instance
+ *
+ * During DFLL driver initialization or resume from context loss,
+ * program parameters for the closed loop integrator, DVCO tuning,
+ * voltage droop control and monitor control.
+ */
+static void dfll_set_default_params(struct tegra_dfll *td)
+{
+       u32 val;
+
+       val = DIV_ROUND_UP(td->ref_rate, td->sample_rate * 32);
+       BUG_ON(val > DFLL_CONFIG_DIV_MASK);
+       dfll_writel(td, val, DFLL_CONFIG);
+
+       val = (td->force_mode << DFLL_PARAMS_FORCE_MODE_SHIFT) |
+               (td->cf << DFLL_PARAMS_CF_PARAM_SHIFT) |
+               (td->ci << DFLL_PARAMS_CI_PARAM_SHIFT) |
+               (td->cg << DFLL_PARAMS_CG_PARAM_SHIFT) |
+               (td->cg_scale ? DFLL_PARAMS_CG_SCALE : 0);
+       dfll_writel(td, val, DFLL_PARAMS);
+
+       dfll_tune_low(td);
+       dfll_writel(td, td->droop_ctrl, DFLL_DROOP_CTRL);
+       dfll_writel(td, DFLL_MONITOR_CTRL_FREQ, DFLL_MONITOR_CTRL);
+}
+
+/**
+ * dfll_init_clks - clk_get() the DFLL source clocks
+ * @td: DFLL instance
+ *
+ * Call clk_get() on the DFLL source clocks and save the pointers for later
+ * use. Returns 0 upon success or error (see devm_clk_get) if one or more
+ * of the clocks couldn't be looked up.
+ */
+static int dfll_init_clks(struct tegra_dfll *td)
+{
+       td->ref_clk = devm_clk_get(td->dev, "ref");
+       if (IS_ERR(td->ref_clk)) {
+               dev_err(td->dev, "missing ref clock\n");
+               return PTR_ERR(td->ref_clk);
+       }
+
+       td->soc_clk = devm_clk_get(td->dev, "soc");
+       if (IS_ERR(td->soc_clk)) {
+               dev_err(td->dev, "missing soc clock\n");
+               return PTR_ERR(td->soc_clk);
+       }
+
+       td->i2c_clk = devm_clk_get(td->dev, "i2c");
+       if (IS_ERR(td->i2c_clk)) {
+               dev_err(td->dev, "missing i2c clock\n");
+               return PTR_ERR(td->i2c_clk);
+       }
+       td->i2c_clk_rate = clk_get_rate(td->i2c_clk);
+
+       return 0;
+}
+
+/**
+ * dfll_init - Prepare the DFLL IP block for use
+ * @td: DFLL instance
+ *
+ * Do everything necessary to prepare the DFLL IP block for use. The
+ * DFLL will be left in DISABLED state. Called by dfll_probe().
+ * Returns 0 upon success, or passes along the error from whatever
+ * function returned it.
+ */
+static int dfll_init(struct tegra_dfll *td)
+{
+       int ret;
+
+       td->ref_rate = clk_get_rate(td->ref_clk);
+       if (td->ref_rate != REF_CLOCK_RATE) {
+               dev_err(td->dev, "unexpected ref clk rate %lu, expecting %lu",
+                       td->ref_rate, REF_CLOCK_RATE);
+               return -EINVAL;
+       }
+
+       reset_control_deassert(td->dvco_rst);
+
+       ret = clk_prepare(td->ref_clk);
+       if (ret) {
+               dev_err(td->dev, "failed to prepare ref_clk\n");
+               return ret;
+       }
+
+       ret = clk_prepare(td->soc_clk);
+       if (ret) {
+               dev_err(td->dev, "failed to prepare soc_clk\n");
+               goto di_err1;
+       }
+
+       ret = clk_prepare(td->i2c_clk);
+       if (ret) {
+               dev_err(td->dev, "failed to prepare i2c_clk\n");
+               goto di_err2;
+       }
+
+       td->last_unrounded_rate = 0;
+
+       pm_runtime_enable(td->dev);
+       pm_runtime_get_sync(td->dev);
+
+       dfll_set_mode(td, DFLL_DISABLED);
+       dfll_set_default_params(td);
+
+       if (td->soc->init_clock_trimmers)
+               td->soc->init_clock_trimmers();
+
+       dfll_set_open_loop_config(td);
+
+       dfll_init_out_if(td);
+
+       pm_runtime_put_sync(td->dev);
+
+       return 0;
+
+di_err2:
+       clk_unprepare(td->soc_clk);
+di_err1:
+       clk_unprepare(td->ref_clk);
+
+       reset_control_assert(td->dvco_rst);
+
+       return ret;
+}
+
+/*
+ * DT data fetch
+ */
+
+/*
+ * Find a PMIC voltage register-to-voltage mapping for the given voltage.
+ * An exact voltage match is required.
+ */
+static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
+{
+       int i, n_voltages, reg_uV;
+
+       n_voltages = regulator_count_voltages(td->vdd_reg);
+       for (i = 0; i < n_voltages; i++) {
+               reg_uV = regulator_list_voltage(td->vdd_reg, i);
+               if (reg_uV < 0)
+                       break;
+
+               if (uV == reg_uV)
+                       return i;
+       }
+
+       dev_err(td->dev, "no voltage map entry for %d uV\n", uV);
+       return -EINVAL;
+}
+
+/*
+ * Find a PMIC voltage register-to-voltage mapping for the given voltage,
+ * rounding up to the closest supported voltage.
+ * */
+static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
+{
+       int i, n_voltages, reg_uV;
+
+       n_voltages = regulator_count_voltages(td->vdd_reg);
+       for (i = 0; i < n_voltages; i++) {
+               reg_uV = regulator_list_voltage(td->vdd_reg, i);
+               if (reg_uV < 0)
+                       break;
+
+               if (uV <= reg_uV)
+                       return i;
+       }
+
+       dev_err(td->dev, "no voltage map entry rounding to %d uV\n", uV);
+       return -EINVAL;
+}
+
+/**
+ * dfll_build_i2c_lut - build the I2C voltage register lookup table
+ * @td: DFLL instance
+ *
+ * The DFLL hardware has 33 bytes of look-up table RAM that must be filled with
+ * PMIC voltage register values that span the entire DFLL operating range.
+ * This function builds the look-up table based on the OPP table provided by
+ * the soc-specific platform driver (td->soc->opp_dev) and the PMIC
+ * register-to-voltage mapping queried from the regulator framework.
+ *
+ * On success, fills in td->i2c_lut and returns 0, or -err on failure.
+ */
+static int dfll_build_i2c_lut(struct tegra_dfll *td)
+{
+       int ret = -EINVAL;
+       int j, v, v_max, v_opp;
+       int selector;
+       unsigned long rate;
+       struct dev_pm_opp *opp;
+       int lut;
+
+       rcu_read_lock();
+
+       rate = ULONG_MAX;
+       opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
+       if (IS_ERR(opp)) {
+               dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
+               goto out;
+       }
+       v_max = dev_pm_opp_get_voltage(opp);
+
+       v = td->soc->min_millivolts * 1000;
+       lut = find_vdd_map_entry_exact(td, v);
+       if (lut < 0)
+               goto out;
+       td->i2c_lut[0] = lut;
+
+       for (j = 1, rate = 0; ; rate++) {
+               opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
+               if (IS_ERR(opp))
+                       break;
+               v_opp = dev_pm_opp_get_voltage(opp);
+
+               if (v_opp <= td->soc->min_millivolts * 1000)
+                       td->dvco_rate_min = dev_pm_opp_get_freq(opp);
+
+               for (;;) {
+                       v += max(1, (v_max - v) / (MAX_DFLL_VOLTAGES - j));
+                       if (v >= v_opp)
+                               break;
+
+                       selector = find_vdd_map_entry_min(td, v);
+                       if (selector < 0)
+                               goto out;
+                       if (selector != td->i2c_lut[j - 1])
+                               td->i2c_lut[j++] = selector;
+               }
+
+               v = (j == MAX_DFLL_VOLTAGES - 1) ? v_max : v_opp;
+               selector = find_vdd_map_entry_exact(td, v);
+               if (selector < 0)
+                       goto out;
+               if (selector != td->i2c_lut[j - 1])
+                       td->i2c_lut[j++] = selector;
+
+               if (v >= v_max)
+                       break;
+       }
+       td->i2c_lut_size = j;
+
+       if (!td->dvco_rate_min)
+               dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
+                       td->soc->min_millivolts);
+       else
+               ret = 0;
+
+out:
+       rcu_read_unlock();
+
+       return ret;
+}
+
+/**
+ * read_dt_param - helper function for reading required parameters from the DT
+ * @td: DFLL instance
+ * @param: DT property name
+ * @dest: output pointer for the value read
+ *
+ * Read a required numeric parameter from the DFLL device node, or complain
+ * if the property doesn't exist. Returns a boolean indicating success for
+ * easy chaining of multiple calls to this function.
+ */
+static bool read_dt_param(struct tegra_dfll *td, const char *param, u32 *dest)
+{
+       int err = of_property_read_u32(td->dev->of_node, param, dest);
+
+       if (err < 0) {
+               dev_err(td->dev, "failed to read DT parameter %s: %d\n",
+                       param, err);
+               return false;
+       }
+
+       return true;
+}
+
+/**
+ * dfll_fetch_i2c_params - query PMIC I2C params from DT & regulator subsystem
+ * @td: DFLL instance
+ *
+ * Read all the parameters required for operation in I2C mode. The parameters
+ * can originate from the device tree or the regulator subsystem.
+ * Returns 0 on success or -err on failure.
+ */
+static int dfll_fetch_i2c_params(struct tegra_dfll *td)
+{
+       struct regmap *regmap;
+       struct device *i2c_dev;
+       struct i2c_client *i2c_client;
+       int vsel_reg, vsel_mask;
+       int ret;
+
+       if (!read_dt_param(td, "nvidia,i2c-fs-rate", &td->i2c_fs_rate))
+               return -EINVAL;
+
+       regmap = regulator_get_regmap(td->vdd_reg);
+       i2c_dev = regmap_get_device(regmap);
+       i2c_client = to_i2c_client(i2c_dev);
+
+       td->i2c_slave_addr = i2c_client->addr;
+
+       ret = regulator_get_hardware_vsel_register(td->vdd_reg,
+                                                  &vsel_reg,
+                                                  &vsel_mask);
+       if (ret < 0) {
+               dev_err(td->dev,
+                       "regulator unsuitable for DFLL I2C operation\n");
+               return -EINVAL;
+       }
+       td->i2c_reg = vsel_reg;
+
+       ret = dfll_build_i2c_lut(td);
+       if (ret) {
+               dev_err(td->dev, "couldn't build I2C LUT\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * dfll_fetch_common_params - read DFLL parameters from the device tree
+ * @td: DFLL instance
+ *
+ * Read all the DT parameters that are common to both I2C and PWM operation.
+ * Returns 0 on success or -EINVAL on any failure.
+ */
+static int dfll_fetch_common_params(struct tegra_dfll *td)
+{
+       bool ok = true;
+
+       ok &= read_dt_param(td, "nvidia,droop-ctrl", &td->droop_ctrl);
+       ok &= read_dt_param(td, "nvidia,sample-rate", &td->sample_rate);
+       ok &= read_dt_param(td, "nvidia,force-mode", &td->force_mode);
+       ok &= read_dt_param(td, "nvidia,cf", &td->cf);
+       ok &= read_dt_param(td, "nvidia,ci", &td->ci);
+       ok &= read_dt_param(td, "nvidia,cg", &td->cg);
+       td->cg_scale = of_property_read_bool(td->dev->of_node,
+                                            "nvidia,cg-scale");
+
+       if (of_property_read_string(td->dev->of_node, "clock-output-names",
+                                   &td->output_clock_name)) {
+               dev_err(td->dev, "missing clock-output-names property\n");
+               ok = false;
+       }
+
+       return ok ? 0 : -EINVAL;
+}
+
+/*
+ * API exported to per-SoC platform drivers
+ */
+
+/**
+ * tegra_dfll_register - probe a Tegra DFLL device
+ * @pdev: DFLL platform_device *
+ * @soc: Per-SoC integration and characterization data for this DFLL instance
+ *
+ * Probe and initialize a DFLL device instance. Intended to be called
+ * by a SoC-specific shim driver that passes in per-SoC integration
+ * and configuration data via @soc. Returns 0 on success or -err on failure.
+ */
+int tegra_dfll_register(struct platform_device *pdev,
+                       struct tegra_dfll_soc_data *soc)
+{
+       struct resource *mem;
+       struct tegra_dfll *td;
+       int ret;
+
+       if (!soc) {
+               dev_err(&pdev->dev, "no tegra_dfll_soc_data provided\n");
+               return -EINVAL;
+       }
+
+       td = devm_kzalloc(&pdev->dev, sizeof(*td), GFP_KERNEL);
+       if (!td)
+               return -ENOMEM;
+       td->dev = &pdev->dev;
+       platform_set_drvdata(pdev, td);
+
+       td->soc = soc;
+
+       td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
+       if (IS_ERR(td->vdd_reg)) {
+               dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
+               return PTR_ERR(td->vdd_reg);
+       }
+
+       td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
+       if (IS_ERR(td->dvco_rst)) {
+               dev_err(td->dev, "couldn't get dvco reset\n");
+               return PTR_ERR(td->dvco_rst);
+       }
+
+       ret = dfll_fetch_common_params(td);
+       if (ret) {
+               dev_err(td->dev, "couldn't parse device tree parameters\n");
+               return ret;
+       }
+
+       ret = dfll_fetch_i2c_params(td);
+       if (ret)
+               return ret;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(td->dev, "no control register resource\n");
+               return -ENODEV;
+       }
+
+       td->base = devm_ioremap(td->dev, mem->start, resource_size(mem));
+       if (!td->base) {
+               dev_err(td->dev, "couldn't ioremap DFLL control registers\n");
+               return -ENODEV;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!mem) {
+               dev_err(td->dev, "no i2c_base resource\n");
+               return -ENODEV;
+       }
+
+       td->i2c_base = devm_ioremap(td->dev, mem->start, resource_size(mem));
+       if (!td->i2c_base) {
+               dev_err(td->dev, "couldn't ioremap i2c_base resource\n");
+               return -ENODEV;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       if (!mem) {
+               dev_err(td->dev, "no i2c_controller_base resource\n");
+               return -ENODEV;
+       }
+
+       td->i2c_controller_base = devm_ioremap(td->dev, mem->start,
+                                              resource_size(mem));
+       if (!td->i2c_controller_base) {
+               dev_err(td->dev,
+                       "couldn't ioremap i2c_controller_base resource\n");
+               return -ENODEV;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       if (!mem) {
+               dev_err(td->dev, "no lut_base resource\n");
+               return -ENODEV;
+       }
+
+       td->lut_base = devm_ioremap(td->dev, mem->start, resource_size(mem));
+       if (!td->lut_base) {
+               dev_err(td->dev,
+                       "couldn't ioremap lut_base resource\n");
+               return -ENODEV;
+       }
+
+       ret = dfll_init_clks(td);
+       if (ret) {
+               dev_err(&pdev->dev, "DFLL clock init error\n");
+               return ret;
+       }
+
+       /* Enable the clocks and set the device up */
+       ret = dfll_init(td);
+       if (ret)
+               return ret;
+
+       ret = dfll_register_clk(td);
+       if (ret) {
+               dev_err(&pdev->dev, "DFLL clk registration failed\n");
+               return ret;
+       }
+
+#ifdef CONFIG_DEBUG_FS
+       dfll_debug_init(td);
+#endif
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_register);
+
+/**
+ * tegra_dfll_unregister - release all of the DFLL driver resources for a device
+ * @pdev: DFLL platform_device *
+ *
+ * Unbind this driver from the DFLL hardware device represented by
+ * @pdev. The DFLL must be disabled for this to succeed. Returns 0
+ * upon success or -EBUSY if the DFLL is still active.
+ */
+int tegra_dfll_unregister(struct platform_device *pdev)
+{
+       struct tegra_dfll *td = platform_get_drvdata(pdev);
+
+       /* Try to prevent removal while the DFLL is active */
+       if (td->mode != DFLL_DISABLED) {
+               dev_err(&pdev->dev,
+                       "must disable DFLL before removing driver\n");
+               return -EBUSY;
+       }
+
+       debugfs_remove_recursive(td->debugfs_dir);
+
+       dfll_unregister_clk(td);
+       pm_runtime_disable(&pdev->dev);
+
+       clk_unprepare(td->ref_clk);
+       clk_unprepare(td->soc_clk);
+       clk_unprepare(td->i2c_clk);
+
+       reset_control_assert(td->dvco_rst);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_unregister);
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
new file mode 100644 (file)
index 0000000..2e4c077
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * clk-dfll.h - prototypes and macros for the Tegra DFLL clocksource driver
+ * Copyright (C) 2013 NVIDIA Corporation.  All rights reserved.
+ *
+ * Aleksandr Frid <afrid@nvidia.com>
+ * Paul Walmsley <pwalmsley@nvidia.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.
+ */
+
+#ifndef __DRIVERS_CLK_TEGRA_CLK_DFLL_H
+#define __DRIVERS_CLK_TEGRA_CLK_DFLL_H
+
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/types.h>
+
+/**
+ * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
+ * @opp_dev: struct device * that holds the OPP table for the DFLL
+ * @min_millivolts: minimum voltage (in mV) that the DFLL can operate
+ * @tune0_low: DFLL tuning register 0 (low voltage range)
+ * @tune0_high: DFLL tuning register 0 (high voltage range)
+ * @tune1: DFLL tuning register 1
+ * @assert_dvco_reset: fn ptr to place the DVCO in reset
+ * @deassert_dvco_reset: fn ptr to release the DVCO reset
+ * @set_clock_trimmers_high: fn ptr to tune clock trimmers for high voltage
+ * @set_clock_trimmers_low: fn ptr to tune clock trimmers for low voltage
+ */
+struct tegra_dfll_soc_data {
+       struct device *dev;
+       unsigned int min_millivolts;
+       u32 tune0_low;
+       u32 tune0_high;
+       u32 tune1;
+       void (*init_clock_trimmers)(void);
+       void (*set_clock_trimmers_high)(void);
+       void (*set_clock_trimmers_low)(void);
+};
+
+int tegra_dfll_register(struct platform_device *pdev,
+                       struct tegra_dfll_soc_data *soc);
+int tegra_dfll_unregister(struct platform_device *pdev);
+int tegra_dfll_runtime_suspend(struct device *dev);
+int tegra_dfll_runtime_resume(struct device *dev);
+
+#endif /* __DRIVERS_CLK_TEGRA_CLK_DFLL_H */
index 59a5714dfe18c237323821027ccae5bb59916a38..48c83efda4cff4cb99ab3df0d3c3a26bc7999c26 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 7649685c86bc181dcada918f3bcf181ec9d4c802..138a94b99b5bb5ce0863ef9a0110b4bea928159a 100644 (file)
@@ -103,7 +103,7 @@ static unsigned long emc_recalc_rate(struct clk_hw *hw,
         * CCF wrongly assumes that the parent won't change during set_rate,
         * so get the parent rate explicitly.
         */
-       parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+       parent_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        val = readl(tegra->clk_regs + CLK_SOURCE_EMC);
        div = val & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK;
@@ -116,11 +116,7 @@ static unsigned long emc_recalc_rate(struct clk_hw *hw,
  * safer since things have EMC rate floors. Also don't touch parent_rate
  * since we don't want the CCF to play with our parent clocks.
  */
-static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long min_rate,
-                              unsigned long max_rate,
-                              unsigned long *best_parent_rate,
-                              struct clk_hw **best_parent_hw)
+static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
        struct tegra_clk_emc *tegra;
        u8 ram_code = tegra_read_ram_code();
@@ -135,22 +131,28 @@ static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
 
                timing = tegra->timings + i;
 
-               if (timing->rate > max_rate) {
+               if (timing->rate > req->max_rate) {
                        i = min(i, 1);
-                       return tegra->timings[i - 1].rate;
+                       req->rate = tegra->timings[i - 1].rate;
+                       return 0;
                }
 
-               if (timing->rate < min_rate)
+               if (timing->rate < req->min_rate)
                        continue;
 
-               if (timing->rate >= rate)
-                       return timing->rate;
+               if (timing->rate >= req->rate) {
+                       req->rate = timing->rate;
+                       return 0;
+               }
        }
 
-       if (timing)
-               return timing->rate;
+       if (timing) {
+               req->rate = timing->rate;
+               return 0;
+       }
 
-       return __clk_get_rate(hw->clk);
+       req->rate = clk_hw_get_rate(hw);
+       return 0;
 }
 
 static u8 emc_get_parent(struct clk_hw *hw)
@@ -312,7 +314,7 @@ static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
 
        tegra = container_of(hw, struct tegra_clk_emc, hw);
 
-       if (__clk_get_rate(hw->clk) == rate)
+       if (clk_hw_get_rate(hw) == rate)
                return 0;
 
        /*
@@ -525,8 +527,8 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
        if (IS_ERR(clk))
                return clk;
 
-       tegra->prev_parent = clk_get_parent_by_index(
-               tegra->hw.clk, emc_get_parent(&tegra->hw));
+       tegra->prev_parent = clk_hw_get_parent_by_index(
+               &tegra->hw, emc_get_parent(&tegra->hw))->clk;
        tegra->changing_timing = false;
 
        /* Allow debugging tools to see the EMC clock */
index 0aa8830ae7cc76c5fd1335ce8149a981ec0612d8..d28d6e95020fe3913a0af333ef24680659f6aee4 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
index d84ae49d0e05eead08c6379a0236c339ff88cb5c..ec5b6113b01270f25210216d9093d2bb37c67e4a 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/export.h>
 #include <linux/slab.h>
index 3598987a451d77a33b6d3515a85d9b3d879252f1..257cae0c1488e13f30b12dff93dbe1e2a7d544e1 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 05c6d08a6695861344713919e0474cc05a3c701e..d6d4ecb88e945e6a8c23ecbd12081d3e8616e10a 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/clk-provider.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 
 #include "clk.h"
 
@@ -264,7 +264,7 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
        }
 
        pr_err("%s: Timed out waiting for pll %s lock\n", __func__,
-              __clk_get_name(pll->hw.clk));
+              clk_hw_get_name(&pll->hw));
 
        return -1;
 }
@@ -595,7 +595,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (pll->params->flags & TEGRA_PLL_FIXED) {
                if (rate != pll->params->fixed_rate) {
                        pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
-                               __func__, __clk_get_name(hw->clk),
+                               __func__, clk_hw_get_name(hw),
                                pll->params->fixed_rate, rate);
                        return -EINVAL;
                }
@@ -605,7 +605,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
            _calc_rate(hw, &cfg, rate, parent_rate)) {
                pr_err("%s: Failed to set %s rate %lu\n", __func__,
-                      __clk_get_name(hw->clk), rate);
+                      clk_hw_get_name(hw), rate);
                WARN_ON(1);
                return -EINVAL;
        }
@@ -634,7 +634,7 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 
        /* PLLM is used for memory; we do not change rate */
        if (pll->params->flags & TEGRA_PLLM)
-               return __clk_get_rate(hw->clk);
+               return clk_hw_get_rate(hw);
 
        if (_get_table_rate(hw, &cfg, rate, *prate) &&
            _calc_rate(hw, &cfg, rate, *prate))
@@ -663,7 +663,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
                if (_get_table_rate(hw, &sel, pll->params->fixed_rate,
                                        parent_rate)) {
                        pr_err("Clock %s has unknown fixed frequency\n",
-                              __clk_get_name(hw->clk));
+                              clk_hw_get_name(hw));
                        BUG();
                }
                return pll->params->fixed_rate;
@@ -1577,7 +1577,7 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
        if (!pll_params->pdiv_tohw)
                return ERR_PTR(-EINVAL);
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
@@ -1674,7 +1674,7 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
                return ERR_PTR(-EINVAL);
        }
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
@@ -1715,7 +1715,7 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
                return ERR_PTR(-EINVAL);
        }
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
@@ -1848,7 +1848,7 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
        val &= ~PLLSS_REF_SRC_SEL_MASK;
        pll_writel_base(val, pll);
 
-       parent_rate = __clk_get_rate(parent);
+       parent_rate = clk_get_rate(parent);
 
        pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
 
index 2fd924d38606920ce011cb51edf4adb0ab544720..131d1b5085e287a1f3b72d83f79370cd380a7b9e 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 
 #include "clk.h"
 
index 5c38aab2c5b8273a0b2fddc88d398faacdd12e6d..11e3ad7ad7a381b1f3a0ea7081e497f361b58512 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 605676d368eb49acdb7c57d1740e2af151a81279..da0b5941c89ffae2ee3b7b367f0f0413f0a1959a 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 46af9244ba74576f23e3e27dc9b2380cb0d39686..cb6ab830941d4052625b2218a37370761eff7df7 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index 08b21c1ee867e6d898699b904afa6a93781eff3e..91377abfefa19189f82ba32e12a6e0484ed8f9c9 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index feb3201c85ce5df6d8786eaf2e4a0408e5890ec0..5b1d723932c5e07e4a2dd6efce31cf02f0d12b0f 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -44,7 +43,9 @@ static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
 
 static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
                                        "pll_p", "pll_p_out4", "unused",
-                                       "unused", "pll_x" };
+                                       "unused", "pll_x", "unused", "unused",
+                                       "unused", "unused", "unused", "unused",
+                                       "dfllCPU_out" };
 
 static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
                                         "pll_p", "pll_p_out4", "unused",
index 8237d16b407597dab129c5a277802190898a061f..db5871519bf5d5a17cac3bf06dba8d3f4fef3a31 100644 (file)
@@ -15,9 +15,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/delay.h>
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
new file mode 100644 (file)
index 0000000..6125333
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Tegra124 DFLL FCPU clock source driver
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * Aleksandr Frid <afrid@nvidia.com>
+ * Paul Walmsley <pwalmsley@nvidia.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.
+ *
+ */
+
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <soc/tegra/fuse.h>
+
+#include "clk.h"
+#include "clk-dfll.h"
+#include "cvb.h"
+
+/* Maximum CPU frequency, indexed by CPU speedo id */
+static const unsigned long cpu_max_freq_table[] = {
+       [0] = 2014500000UL,
+       [1] = 2320500000UL,
+       [2] = 2116500000UL,
+       [3] = 2524500000UL,
+};
+
+static const struct cvb_table tegra124_cpu_cvb_tables[] = {
+       {
+               .speedo_id = -1,
+               .process_id = -1,
+               .min_millivolts = 900,
+               .max_millivolts = 1260,
+               .alignment = {
+                       .step_uv = 10000, /* 10mV */
+               },
+               .speedo_scale = 100,
+               .voltage_scale = 1000,
+               .cvb_table = {
+                       {204000000UL,   {1112619, -29295, 402} },
+                       {306000000UL,   {1150460, -30585, 402} },
+                       {408000000UL,   {1190122, -31865, 402} },
+                       {510000000UL,   {1231606, -33155, 402} },
+                       {612000000UL,   {1274912, -34435, 402} },
+                       {714000000UL,   {1320040, -35725, 402} },
+                       {816000000UL,   {1366990, -37005, 402} },
+                       {918000000UL,   {1415762, -38295, 402} },
+                       {1020000000UL,  {1466355, -39575, 402} },
+                       {1122000000UL,  {1518771, -40865, 402} },
+                       {1224000000UL,  {1573009, -42145, 402} },
+                       {1326000000UL,  {1629068, -43435, 402} },
+                       {1428000000UL,  {1686950, -44715, 402} },
+                       {1530000000UL,  {1746653, -46005, 402} },
+                       {1632000000UL,  {1808179, -47285, 402} },
+                       {1734000000UL,  {1871526, -48575, 402} },
+                       {1836000000UL,  {1936696, -49855, 402} },
+                       {1938000000UL,  {2003687, -51145, 402} },
+                       {2014500000UL,  {2054787, -52095, 402} },
+                       {2116500000UL,  {2124957, -53385, 402} },
+                       {2218500000UL,  {2196950, -54665, 402} },
+                       {2320500000UL,  {2270765, -55955, 402} },
+                       {2422500000UL,  {2346401, -57235, 402} },
+                       {2524500000UL,  {2437299, -58535, 402} },
+                       {0,             {      0,      0,   0} },
+               },
+               .cpu_dfll_data = {
+                       .tune0_low = 0x005020ff,
+                       .tune0_high = 0x005040ff,
+                       .tune1 = 0x00000060,
+               }
+       },
+};
+
+static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
+{
+       int process_id, speedo_id, speedo_value;
+       struct tegra_dfll_soc_data *soc;
+       const struct cvb_table *cvb;
+
+       process_id = tegra_sku_info.cpu_process_id;
+       speedo_id = tegra_sku_info.cpu_speedo_id;
+       speedo_value = tegra_sku_info.cpu_speedo_value;
+
+       if (speedo_id >= ARRAY_SIZE(cpu_max_freq_table)) {
+               dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
+                       speedo_id);
+               return -ENODEV;
+       }
+
+       soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL);
+       if (!soc)
+               return -ENOMEM;
+
+       soc->dev = get_cpu_device(0);
+       if (!soc->dev) {
+               dev_err(&pdev->dev, "no CPU0 device\n");
+               return -ENODEV;
+       }
+
+       cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables,
+                                       ARRAY_SIZE(tegra124_cpu_cvb_tables),
+                                       process_id, speedo_id, speedo_value,
+                                       cpu_max_freq_table[speedo_id],
+                                       soc->dev);
+       if (IS_ERR(cvb)) {
+               dev_err(&pdev->dev, "couldn't build OPP table: %ld\n",
+                       PTR_ERR(cvb));
+               return PTR_ERR(cvb);
+       }
+
+       soc->min_millivolts = cvb->min_millivolts;
+       soc->tune0_low = cvb->cpu_dfll_data.tune0_low;
+       soc->tune0_high = cvb->cpu_dfll_data.tune0_high;
+       soc->tune1 = cvb->cpu_dfll_data.tune1;
+
+       return tegra_dfll_register(pdev, soc);
+}
+
+static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
+       { .compatible = "nvidia,tegra124-dfll", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, tegra124_dfll_fcpu_of_match);
+
+static const struct dev_pm_ops tegra124_dfll_pm_ops = {
+       SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
+                          tegra_dfll_runtime_resume, NULL)
+};
+
+static struct platform_driver tegra124_dfll_fcpu_driver = {
+       .probe = tegra124_dfll_fcpu_probe,
+       .remove = tegra_dfll_unregister,
+       .driver = {
+               .name = "tegra124-dfll",
+               .of_match_table = tegra124_dfll_fcpu_of_match,
+               .pm = &tegra124_dfll_pm_ops,
+       },
+};
+
+static int __init tegra124_dfll_fcpu_init(void)
+{
+       return platform_driver_register(&tegra124_dfll_fcpu_driver);
+}
+module_init(tegra124_dfll_fcpu_init);
+
+static void __exit tegra124_dfll_fcpu_exit(void)
+{
+       platform_driver_unregister(&tegra124_dfll_fcpu_driver);
+}
+module_exit(tegra124_dfll_fcpu_exit);
+
+MODULE_DESCRIPTION("Tegra124 DFLL clock source driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Aleksandr Frid <afrid@nvidia.com>");
+MODULE_AUTHOR("Paul Walmsley <pwalmsley@nvidia.com>");
index e8cca3eac00742713cc8fe39f9a63c8fe9b62def..824d75883d2bfbca814f101e1a601387bbce070b 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
@@ -24,6 +23,7 @@
 #include <linux/export.h>
 #include <linux/clk/tegra.h>
 #include <dt-bindings/clock/tegra124-car.h>
+#include <dt-bindings/reset/tegra124-car.h>
 
 #include "clk.h"
 #include "clk-id.h"
@@ -39,6 +39,9 @@
 #define CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 
+#define RST_DFLL_DVCO                  0x2f4
+#define DVFS_DFLL_RESET_SHIFT          0
+
 #define PLLC_BASE 0x80
 #define PLLC_OUT 0x84
 #define PLLC_MISC2 0x88
@@ -94,6 +97,8 @@
 #define PMC_PLLM_WB0_OVERRIDE 0x1dc
 #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
 
+#define CCLKG_BURST_POLICY 0x368
+
 #define UTMIP_PLL_CFG2 0x488
 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
 #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
 #ifdef CONFIG_PM_SLEEP
 static struct cpu_clk_suspend_context {
        u32 clk_csite_src;
+       u32 cclkg_burst;
+       u32 cclkg_divider;
 } tegra124_cpu_clk_sctx;
 #endif
 
@@ -1319,12 +1326,22 @@ static void tegra124_cpu_clock_suspend(void)
        tegra124_cpu_clk_sctx.clk_csite_src =
                                readl(clk_base + CLK_SOURCE_CSITE);
        writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+
+       tegra124_cpu_clk_sctx.cclkg_burst =
+                               readl(clk_base + CCLKG_BURST_POLICY);
+       tegra124_cpu_clk_sctx.cclkg_divider =
+                               readl(clk_base + CCLKG_BURST_POLICY + 4);
 }
 
 static void tegra124_cpu_clock_resume(void)
 {
        writel(tegra124_cpu_clk_sctx.clk_csite_src,
                                clk_base + CLK_SOURCE_CSITE);
+
+       writel(tegra124_cpu_clk_sctx.cclkg_burst,
+                                       clk_base + CCLKG_BURST_POLICY);
+       writel(tegra124_cpu_clk_sctx.cclkg_divider,
+                                       clk_base + CCLKG_BURST_POLICY + 4);
 }
 #endif
 
@@ -1414,6 +1431,68 @@ static void __init tegra124_clock_apply_init_table(void)
        tegra_init_from_table(tegra124_init_table, clks, TEGRA124_CLK_CLK_MAX);
 }
 
+/**
+ * tegra124_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution.  No return value.
+ */
+static void tegra124_car_barrier(void)
+{
+       readl_relaxed(clk_base + RST_DFLL_DVCO);
+}
+
+/**
+ * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO.  No return value.
+ */
+static void tegra124_clock_assert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v |= (1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra124_car_barrier();
+}
+
+/**
+ * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate.  No return value.
+ */
+static void tegra124_clock_deassert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra124_car_barrier();
+}
+
+static int tegra124_reset_assert(unsigned long id)
+{
+       if (id == TEGRA124_RST_DFLL_DVCO)
+               tegra124_clock_assert_dfll_dvco_reset();
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tegra124_reset_deassert(unsigned long id)
+{
+       if (id == TEGRA124_RST_DFLL_DVCO)
+               tegra124_clock_deassert_dfll_dvco_reset();
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
  *
@@ -1499,6 +1578,8 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
 {
        tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
                                  &pll_x_params);
+       tegra_init_special_resets(1, tegra124_reset_assert,
+                                 tegra124_reset_deassert);
        tegra_add_of_provider(np);
 
        clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
index 41272dcc9e225758da291018dc71bf921f85be8f..bf004f0e4f658b39ab38edf4b57e20005922a25e 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index 0af3e834dd24a25d3e3e0cbfa020c596d57bc908..fad561a5896beddbd3ee56efbaa363cc3375964f 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
index 41cd87c67be6a009a8b5a138672e21f6a4c0c003..2a3a4fe803d6d27e16c7de373f0ec1b8f2164264 100644 (file)
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/clkdev.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
@@ -49,7 +50,6 @@
 #define RST_DEVICES_L                  0x004
 #define RST_DEVICES_H                  0x008
 #define RST_DEVICES_U                  0x00C
-#define RST_DFLL_DVCO                  0x2F4
 #define RST_DEVICES_V                  0x358
 #define RST_DEVICES_W                  0x35C
 #define RST_DEVICES_X                  0x28C
@@ -79,6 +79,11 @@ static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
 
+/* Handlers for SoC-specific reset lines */
+static int (*special_reset_assert)(unsigned long);
+static int (*special_reset_deassert)(unsigned long);
+static unsigned int num_special_reset;
+
 static struct tegra_clk_periph_regs periph_regs[] = {
        [0] = {
                .enb_reg = CLK_OUT_ENB_L,
@@ -152,19 +157,29 @@ static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
         */
        tegra_read_chipid();
 
-       writel_relaxed(BIT(id % 32),
-                       clk_base + periph_regs[id / 32].rst_set_reg);
+       if (id < periph_banks * 32) {
+               writel_relaxed(BIT(id % 32),
+                              clk_base + periph_regs[id / 32].rst_set_reg);
+               return 0;
+       } else if (id < periph_banks * 32 + num_special_reset) {
+               return special_reset_assert(id);
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
                unsigned long id)
 {
-       writel_relaxed(BIT(id % 32),
-                       clk_base + periph_regs[id / 32].rst_clr_reg);
+       if (id < periph_banks * 32) {
+               writel_relaxed(BIT(id % 32),
+                              clk_base + periph_regs[id / 32].rst_clr_reg);
+               return 0;
+       } else if (id < periph_banks * 32 + num_special_reset) {
+               return special_reset_deassert(id);
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 struct tegra_clk_periph_regs *get_reg_bank(int clkid)
@@ -286,10 +301,19 @@ void __init tegra_add_of_provider(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
        rst_ctlr.of_node = np;
-       rst_ctlr.nr_resets = periph_banks * 32;
+       rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
        reset_controller_register(&rst_ctlr);
 }
 
+void __init tegra_init_special_resets(unsigned int num,
+                                     int (*assert)(unsigned long),
+                                     int (*deassert)(unsigned long))
+{
+       num_special_reset = num;
+       special_reset_assert = assert;
+       special_reset_deassert = deassert;
+}
+
 void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 {
        int i;
index 75ddc8ff8bd4aff97d61ff9ae27095aa2ba0cf33..0621887e06f71604eb3193f36690fe28d8ff9124 100644 (file)
@@ -591,6 +591,9 @@ struct tegra_devclk {
        char            *con_id;
 };
 
+void tegra_init_special_resets(unsigned int num, int (*assert)(unsigned long),
+                              int (*deassert)(unsigned long));
+
 void tegra_init_from_table(struct tegra_clk_init_table *tbl,
                struct clk *clks[], int clk_max);
 
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
new file mode 100644 (file)
index 0000000..0204e08
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Utility functions for parsing Tegra CVB voltage tables
+ *
+ * Copyright (C) 2012-2014 NVIDIA Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ */
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/pm_opp.h>
+
+#include "cvb.h"
+
+/* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) */
+static inline int get_cvb_voltage(int speedo, int s_scale,
+                                 const struct cvb_coefficients *cvb)
+{
+       int mv;
+
+       /* apply only speedo scale: output mv = cvb_mv * v_scale */
+       mv = DIV_ROUND_CLOSEST(cvb->c2 * speedo, s_scale);
+       mv = DIV_ROUND_CLOSEST((mv + cvb->c1) * speedo, s_scale) + cvb->c0;
+       return mv;
+}
+
+static int round_cvb_voltage(int mv, int v_scale,
+                            const struct rail_alignment *align)
+{
+       /* combined: apply voltage scale and round to cvb alignment step */
+       int uv;
+       int step = (align->step_uv ? : 1000) * v_scale;
+       int offset = align->offset_uv * v_scale;
+
+       uv = max(mv * 1000, offset) - offset;
+       uv = DIV_ROUND_UP(uv, step) * align->step_uv + align->offset_uv;
+       return uv / 1000;
+}
+
+enum {
+       DOWN,
+       UP
+};
+
+static int round_voltage(int mv, const struct rail_alignment *align, int up)
+{
+       if (align->step_uv) {
+               int uv;
+
+               uv = max(mv * 1000, align->offset_uv) - align->offset_uv;
+               uv = (uv + (up ? align->step_uv - 1 : 0)) / align->step_uv;
+               return (uv * align->step_uv + align->offset_uv) / 1000;
+       }
+       return mv;
+}
+
+static int build_opp_table(const struct cvb_table *d,
+                          int speedo_value,
+                          unsigned long max_freq,
+                          struct device *opp_dev)
+{
+       int i, ret, dfll_mv, min_mv, max_mv;
+       const struct cvb_table_freq_entry *table = NULL;
+       const struct rail_alignment *align = &d->alignment;
+
+       min_mv = round_voltage(d->min_millivolts, align, UP);
+       max_mv = round_voltage(d->max_millivolts, align, DOWN);
+
+       for (i = 0; i < MAX_DVFS_FREQS; i++) {
+               table = &d->cvb_table[i];
+               if (!table->freq || (table->freq > max_freq))
+                       break;
+
+               /*
+                * FIXME after clk_round_rate/clk_determine_rate prototypes
+                * have been updated
+                */
+               if (table->freq & (1<<31))
+                       continue;
+
+               dfll_mv = get_cvb_voltage(
+                       speedo_value, d->speedo_scale, &table->coefficients);
+               dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align);
+               dfll_mv = clamp(dfll_mv, min_mv, max_mv);
+
+               ret = dev_pm_opp_add(opp_dev, table->freq, dfll_mv * 1000);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables
+ * @cvb_tables: array of CVB tables
+ * @sz: size of the previously mentioned array
+ * @process_id: process id of the HW module
+ * @speedo_id: speedo id of the HW module
+ * @speedo_value: speedo value of the HW module
+ * @max_rate: highest safe clock rate
+ * @opp_dev: the struct device * for which the OPP table is built
+ *
+ * On Tegra, a CVB table encodes the relationship between operating voltage
+ * and safe maximal frequency for a given module (e.g. GPU or CPU). This
+ * function calculates the optimal voltage-frequency operating points
+ * for the given arguments and exports them via the OPP library for the
+ * given @opp_dev. Returns a pointer to the struct cvb_table that matched
+ * or an ERR_PTR on failure.
+ */
+const struct cvb_table *tegra_cvb_build_opp_table(
+               const struct cvb_table *cvb_tables,
+               size_t sz, int process_id,
+               int speedo_id, int speedo_value,
+               unsigned long max_rate,
+               struct device *opp_dev)
+{
+       int i, ret;
+
+       for (i = 0; i < sz; i++) {
+               const struct cvb_table *d = &cvb_tables[i];
+
+               if (d->speedo_id != -1 && d->speedo_id != speedo_id)
+                       continue;
+               if (d->process_id != -1 && d->process_id != process_id)
+                       continue;
+
+               ret = build_opp_table(d, speedo_value, max_rate, opp_dev);
+               return ret ? ERR_PTR(ret) : d;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
new file mode 100644 (file)
index 0000000..f62cdc4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Utility functions for parsing Tegra CVB voltage tables
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DRIVERS_CLK_TEGRA_CVB_H
+#define __DRIVERS_CLK_TEGRA_CVB_H
+
+#include <linux/types.h>
+
+struct device;
+
+#define MAX_DVFS_FREQS 40
+
+struct rail_alignment {
+       int offset_uv;
+       int step_uv;
+};
+
+struct cvb_coefficients {
+       int c0;
+       int c1;
+       int c2;
+};
+
+struct cvb_table_freq_entry {
+       unsigned long freq;
+       struct cvb_coefficients coefficients;
+};
+
+struct cvb_cpu_dfll_data {
+       u32 tune0_low;
+       u32 tune0_high;
+       u32 tune1;
+};
+
+struct cvb_table {
+       int speedo_id;
+       int process_id;
+
+       int min_millivolts;
+       int max_millivolts;
+       struct rail_alignment alignment;
+
+       int speedo_scale;
+       int voltage_scale;
+       struct cvb_table_freq_entry cvb_table[MAX_DVFS_FREQS];
+       struct cvb_cpu_dfll_data cpu_dfll_data;
+};
+
+const struct cvb_table *tegra_cvb_build_opp_table(
+               const struct cvb_table *cvb_tables,
+               size_t sz, int process_id,
+               int speedo_id, int speedo_value,
+               unsigned long max_rate,
+               struct device *opp_dev);
+
+#endif
index 105ffd0f5e79da04e496b291e4eb3968b834ba64..9b93e6904359ddd465712a291da1f43b9fefc735 100644 (file)
@@ -1,16 +1,19 @@
 obj-y                                  += clk.o autoidle.o clockdomain.o
 clk-common                             = dpll.o composite.o divider.o gate.o \
-                                         fixed-factor.o mux.o apll.o
-obj-$(CONFIG_SOC_AM33XX)               += $(clk-common) clk-33xx.o
+                                         fixed-factor.o mux.o apll.o \
+                                         clkt_dpll.o clkt_iclk.o clkt_dflt.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clk-common) clk-33xx.o dpll3xxx.o
 obj-$(CONFIG_SOC_TI81XX)               += $(clk-common) fapll.o clk-816x.o
 obj-$(CONFIG_ARCH_OMAP2)               += $(clk-common) interface.o clk-2xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += $(clk-common) interface.o \
-                                          clk-3xxx.o
-obj-$(CONFIG_ARCH_OMAP4)               += $(clk-common) clk-44xx.o
-obj-$(CONFIG_SOC_OMAP5)                        += $(clk-common) clk-54xx.o
+                                          clk-3xxx.o dpll3xxx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(clk-common) clk-44xx.o \
+                                          dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clk-common) clk-54xx.o \
+                                          dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_DRA7XX)               += $(clk-common) clk-7xx.o \
-                                          clk-dra7-atl.o
-obj-$(CONFIG_SOC_AM43XX)               += $(clk-common) clk-43xx.o
+                                          clk-dra7-atl.o dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_AM43XX)               += $(clk-common) dpll3xxx.o clk-43xx.o
 
 ifdef CONFIG_ATAGS
 obj-$(CONFIG_ARCH_OMAP3)                += clk-3xxx-legacy.o
index 49baf38315463d9e77cd6b34e3fdbd8cc21cc832..f3eab6e7902707d6f0d11ea01daef8e1f76a8d9b 100644 (file)
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -27,6 +28,8 @@
 #include <linux/clk/ti.h>
 #include <linux/delay.h>
 
+#include "clock.h"
+
 #define APLL_FORCE_LOCK 0x1
 #define APLL_AUTO_IDLE 0x2
 #define MAX_APLL_WAIT_TRIES            1000000
@@ -47,7 +50,7 @@ static int dra7_apll_enable(struct clk_hw *hw)
        if (!ad)
                return -EINVAL;
 
-       clk_name = __clk_get_name(clk->hw.clk);
+       clk_name = clk_hw_get_name(&clk->hw);
 
        state <<= __ffs(ad->idlest_mask);
 
@@ -170,7 +173,6 @@ static void __init of_dra7_apll_setup(struct device_node *node)
        struct clk_hw_omap *clk_hw = NULL;
        struct clk_init_data *init = NULL;
        const char **parent_names = NULL;
-       int i;
 
        ad = kzalloc(sizeof(*ad), GFP_KERNEL);
        clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
@@ -195,8 +197,7 @@ static void __init of_dra7_apll_setup(struct device_node *node)
        if (!parent_names)
                goto cleanup;
 
-       for (i = 0; i < init->num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, init->num_parents);
 
        init->parent_names = parent_names;
 
@@ -272,7 +273,7 @@ static int omap2_apll_enable(struct clk_hw *hw)
 
        if (i == MAX_APLL_WAIT_TRIES) {
                pr_warn("%s failed to transition to locked\n",
-                       __clk_get_name(clk->hw.clk));
+                       clk_hw_get_name(&clk->hw));
                return -EBUSY;
        }
 
index e75c64c9e81c1d1c3dae2b9779e3538426a66e85..345af43465f0f9a27aeedc431b51d0733bc4b896 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 struct clk_ti_autoidle {
        void __iomem            *reg;
        u8                      shift;
@@ -33,8 +35,41 @@ struct clk_ti_autoidle {
 #define AUTOIDLE_LOW           0x1
 
 static LIST_HEAD(autoidle_clks);
+static LIST_HEAD(clk_hw_omap_clocks);
+
+/**
+ * omap2_clk_deny_idle - disable autoidle on an OMAP clock
+ * @clk: struct clk * to disable autoidle for
+ *
+ * Disable autoidle on an OMAP clock.
+ */
+int omap2_clk_deny_idle(struct clk *clk)
+{
+       struct clk_hw_omap *c;
 
-static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
+       c = to_clk_hw_omap(__clk_get_hw(clk));
+       if (c->ops && c->ops->deny_idle)
+               c->ops->deny_idle(c);
+       return 0;
+}
+
+/**
+ * omap2_clk_allow_idle - enable autoidle on an OMAP clock
+ * @clk: struct clk * to enable autoidle for
+ *
+ * Enable autoidle on an OMAP clock.
+ */
+int omap2_clk_allow_idle(struct clk *clk)
+{
+       struct clk_hw_omap *c;
+
+       c = to_clk_hw_omap(__clk_get_hw(clk));
+       if (c->ops && c->ops->allow_idle)
+               c->ops->allow_idle(c);
+       return 0;
+}
+
+static void _allow_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
@@ -48,7 +83,7 @@ static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
        ti_clk_ll_ops->clk_writel(val, clk->reg);
 }
 
-static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+static void _deny_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
@@ -63,31 +98,31 @@ static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
 }
 
 /**
- * of_ti_clk_allow_autoidle_all - enable autoidle for all clocks
+ * _clk_generic_allow_autoidle_all - enable autoidle for all clocks
  *
  * Enables hardware autoidle for all registered DT clocks, which have
  * the feature.
  */
-void of_ti_clk_allow_autoidle_all(void)
+static void _clk_generic_allow_autoidle_all(void)
 {
        struct clk_ti_autoidle *c;
 
        list_for_each_entry(c, &autoidle_clks, node)
-               ti_allow_autoidle(c);
+               _allow_autoidle(c);
 }
 
 /**
- * of_ti_clk_deny_autoidle_all - disable autoidle for all clocks
+ * _clk_generic_deny_autoidle_all - disable autoidle for all clocks
  *
  * Disables hardware autoidle for all registered DT clocks, which have
  * the feature.
  */
-void of_ti_clk_deny_autoidle_all(void)
+static void _clk_generic_deny_autoidle_all(void)
 {
        struct clk_ti_autoidle *c;
 
        list_for_each_entry(c, &autoidle_clks, node)
-               ti_deny_autoidle(c);
+               _deny_autoidle(c);
 }
 
 /**
@@ -131,3 +166,67 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
 
        return 0;
 }
+
+/**
+ * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
+ * @hw: struct clk_hw * to initialize
+ *
+ * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
+ * temporarily for autoidle handling, until this support can be
+ * integrated into the common clock framework code in some way.  No
+ * return value.
+ */
+void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw)
+{
+       struct clk_hw_omap *c;
+
+       if (clk_hw_get_flags(hw) & CLK_IS_BASIC)
+               return;
+
+       c = to_clk_hw_omap(hw);
+       list_add(&c->node, &clk_hw_omap_clocks);
+}
+
+/**
+ * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Enable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them.  This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code.  Returns 0.
+ */
+int omap2_clk_enable_autoidle_all(void)
+{
+       struct clk_hw_omap *c;
+
+       list_for_each_entry(c, &clk_hw_omap_clocks, node)
+               if (c->ops && c->ops->allow_idle)
+                       c->ops->allow_idle(c);
+
+       _clk_generic_allow_autoidle_all();
+
+       return 0;
+}
+
+/**
+ * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
+ * support it
+ *
+ * Disable clock autoidle on all OMAP clocks that have allow_idle
+ * function pointers associated with them.  This function is intended
+ * to be temporary until support for this is added to the common clock
+ * code.  Returns 0.
+ */
+int omap2_clk_disable_autoidle_all(void)
+{
+       struct clk_hw_omap *c;
+
+       list_for_each_entry(c, &clk_hw_omap_clocks, node)
+               if (c->ops && c->ops->deny_idle)
+                       c->ops->deny_idle(c);
+
+       _clk_generic_deny_autoidle_all();
+
+       return 0;
+}
index c808ab3d2bb22e7ceca914de1a7287c73d0cf5cb..657c4fe07a955e615026d1724976789451d561ff 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
-#include <linux/clk-provider.h>
+#include <linux/clk.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk omap2xxx_clks[] = {
        DT_CLK(NULL, "func_32k_ck", "func_32k_ck"),
        DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"),
index 028b33783d383c695a8c3ef6a467e09634094ad5..ef2ec64fe5471aa47b39588c0a8647d0938b6c6e 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk am33xx_clks[] = {
        DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
        DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
index 0b61548d569bc11acf976a9db71c846242e683aa..0fbf8a9179555d052c65251dfdfbf4a322b9c6d3 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
index 757636d166cff45035a355dc83830511c3640c74..676ee8f6d8136729a9665cfb9c29e7faed123781 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
+/*
+ * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define DPLL5_FREQ_FOR_USBHOST         120000000
+
+#define OMAP3430ES2_ST_DSS_IDLE_SHIFT                  1
+#define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT             5
+#define OMAP3430ES2_ST_SSI_IDLE_SHIFT                  8
+
+#define OMAP34XX_CM_IDLEST_VAL                         1
+
+/*
+ * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
+ * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
+ * at an offset of 4 from ICK enable bit.
+ */
+#define AM35XX_IPSS_ICK_MASK                   0xF
+#define AM35XX_IPSS_ICK_EN_ACK_OFFSET          0x4
+#define AM35XX_IPSS_ICK_FCK_OFFSET             0x8
+#define AM35XX_IPSS_CLK_IDLEST_VAL             0
+
+#define AM35XX_ST_IPSS_SHIFT                   5
+
+/**
+ * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
+ * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
+                                           void __iomem **idlest_reg,
+                                           u8 *idlest_bit,
+                                           u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/**
+ * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
+ * target IDLEST bits.  For our purposes, we are concerned with the
+ * target IDLEST bits, which exist at a different bit position than
+ * the *CLKEN bit position for these modules (DSS and USBHOST) (The
+ * default find_idlest code assumes that they are at the same
+ * position.)  No return value.
+ */
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
+                                                   void __iomem **idlest_reg,
+                                                   u8 *idlest_bit,
+                                                   u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       /* USBHOST_IDLE has same shift */
+       *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
+       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/**
+ * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
+ * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
+                                                void __iomem **idlest_reg,
+                                                u8 *idlest_bit,
+                                                u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/**
+ * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The interface clocks on AM35xx IPSS reflects the clock idle status
+ * in the enable register itsel at a bit offset of 4 from the enable
+ * bit. A value of 1 indicates that clock is enabled.
+ */
+static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
+                                  void __iomem **idlest_reg,
+                                  u8 *idlest_bit,
+                                  u8 *idlest_val)
+{
+       *idlest_reg = (__force void __iomem *)(clk->enable_reg);
+       *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
+       *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
+}
+
+/**
+ * am35xx_clk_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as HECC) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
+ */
+static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
+                                     void __iomem **other_reg,
+                                     u8 *other_bit)
+{
+       *other_reg = (__force void __iomem *)(clk->enable_reg);
+       if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
+               *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
+       else
+       *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
+}
+
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
+       .find_idlest    = am35xx_clk_find_idlest,
+       .find_companion = am35xx_clk_find_companion,
+};
+
+/**
+ * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * The IPSS target CM_IDLEST bit is at a different shift from the
+ * CM_{I,F}CLKEN bit.  Pass back the correct info via @idlest_reg
+ * and @idlest_bit.  No return value.
+ */
+static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
+                                       void __iomem **idlest_reg,
+                                       u8 *idlest_bit,
+                                       u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = AM35XX_ST_IPSS_SHIFT;
+       *idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
+
+const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = am35xx_clk_ipss_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
 
 static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "apb_pclk", "dummy_apb_pclk"),
@@ -324,6 +535,30 @@ enum {
        OMAP3_SOC_OMAP3630,
 };
 
+/**
+ * omap3_clk_lock_dpll5 - locks DPLL5
+ *
+ * Locks DPLL5 to a pre-defined frequency. This is required for proper
+ * operation of USB.
+ */
+void __init omap3_clk_lock_dpll5(void)
+{
+       struct clk *dpll5_clk;
+       struct clk *dpll5_m2_clk;
+
+       dpll5_clk = clk_get(NULL, "dpll5_ck");
+       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_prepare_enable(dpll5_clk);
+
+       /* Program dpll5_m2_clk divider for no division */
+       dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
+       clk_prepare_enable(dpll5_m2_clk);
+       clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+
+       clk_disable_unprepare(dpll5_m2_clk);
+       clk_disable_unprepare(dpll5_clk);
+}
+
 static int __init omap3xxx_dt_clk_init(int soc_type)
 {
        if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 ||
index 3795fce8a8303e66a004fe12bcf6d9008a7d5c63..72411fbcb6f306a007f6da7eb0ee136c17101fc7 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk am43xx_clks[] = {
        DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
        DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
index 581db7711f511245ab95956427ca51225c5b5c83..7a8b51b35f9fe799388a24d8d8b67ea7eabfbd8a 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 /*
  * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
  * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
index 96c69a335975a2a7cdccbd4060389f6e79378ba1..59ce2fa2c104a3a79e1cd490962a04aca8f2ab28 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/io.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #define OMAP5_DPLL_ABE_DEFFREQ                         98304000
 
 /*
index 63b8323df91836265203015b120af5e2bce82e0c..9b5b289e633456206e81268d00bc212a7f9f62cc 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #define DRA7_DPLL_ABE_DEFFREQ                          180633600
 #define DRA7_DPLL_GMAC_DEFFREQ                         1000000000
 #define DRA7_DPLL_USB_DEFFREQ                          960000000
 
-
 static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
        DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
index 9451e651a1ff748ee69b8ad5feb587a3c86769bb..c69352b24dba1cec5242984d9501c32548ce5264 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 static struct ti_dt_clk dm816x_clks[] = {
        DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"),
        DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
index 19e543a32e2bad1e4591fb3106258d9f6769551b..2e14dfb588f445f7cb2a3d3c997c6786ca67a3de 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
index 64bb5e8a3b8cd845952bb4e97ffdead89f366d97..b5bcd77e8d0f5e31b3887ebdd3a4f441c7909a46 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/ti.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/list.h>
+#include <linux/regmap.h>
+#include <linux/bootmem.h>
 
 #include "clock.h"
 
 struct ti_clk_ll_ops *ti_clk_ll_ops;
 static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
 
+static struct ti_clk_features ti_clk_features;
+
+struct clk_iomap {
+       struct regmap *regmap;
+       void __iomem *mem;
+};
+
+static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
+
+static void clk_memmap_writel(u32 val, void __iomem *reg)
+{
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_write(io->regmap, r->offset, val);
+       else
+               writel_relaxed(val, io->mem + r->offset);
+}
+
+static u32 clk_memmap_readl(void __iomem *reg)
+{
+       u32 val;
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_read(io->regmap, r->offset, &val);
+       else
+               val = readl_relaxed(io->mem + r->offset);
+
+       return val;
+}
+
+/**
+ * ti_clk_setup_ll_ops - setup low level clock operations
+ * @ops: low level clock ops descriptor
+ *
+ * Sets up low level clock operations for TI clock driver. This is used
+ * to provide various callbacks for the clock driver towards platform
+ * specific code. Returns 0 on success, -EBUSY if ll_ops have been
+ * registered already.
+ */
+int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
+{
+       if (ti_clk_ll_ops) {
+               pr_err("Attempt to register ll_ops multiple times.\n");
+               return -EBUSY;
+       }
+
+       ti_clk_ll_ops = ops;
+       ops->clk_readl = clk_memmap_readl;
+       ops->clk_writel = clk_memmap_writel;
+
+       return 0;
+}
+
 /**
  * ti_dt_clocks_register - register DT alias clocks during boot
  * @oclks: list of clocks to register
@@ -134,32 +194,67 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
 
        reg->offset = val;
 
-       return (void __iomem *)tmp;
+       return (__force void __iomem *)tmp;
 }
 
 /**
- * ti_dt_clk_init_provider - init master clock provider
+ * omap2_clk_provider_init - init master clock provider
  * @parent: master node
  * @index: internal index for clk_reg_ops
+ * @syscon: syscon regmap pointer for accessing clock registers
+ * @mem: iomem pointer for the clock provider memory area, only used if
+ *       syscon is not provided
  *
  * Initializes a master clock IP block. This basically sets up the
  * mapping from clocks node to the memory map index. All the clocks
  * are then initialized through the common of_clk_init call, and the
  * clocks will access their memory maps based on the node layout.
+ * Returns 0 in success.
  */
-void ti_dt_clk_init_provider(struct device_node *parent, int index)
+int __init omap2_clk_provider_init(struct device_node *parent, int index,
+                                  struct regmap *syscon, void __iomem *mem)
 {
        struct device_node *clocks;
+       struct clk_iomap *io;
 
        /* get clocks for this parent */
        clocks = of_get_child_by_name(parent, "clocks");
        if (!clocks) {
                pr_err("%s missing 'clocks' child node.\n", parent->name);
-               return;
+               return -EINVAL;
        }
 
        /* add clocks node info */
        clocks_node_ptr[index] = clocks;
+
+       io = kzalloc(sizeof(*io), GFP_KERNEL);
+       if (!io)
+               return -ENOMEM;
+
+       io->regmap = syscon;
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
+
+       return 0;
+}
+
+/**
+ * omap2_clk_legacy_provider_init - initialize a legacy clock provider
+ * @index: index for the clock provider
+ * @mem: iomem pointer for the clock provider memory area
+ *
+ * Initializes a legacy clock provider memory mapping.
+ */
+void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
+{
+       struct clk_iomap *io;
+
+       io = memblock_virt_alloc(sizeof(*io), 0);
+
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
 }
 
 /**
@@ -244,11 +339,11 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
        if (!IS_ERR(clk)) {
                setup->clk = clk;
                if (setup->clkdm_name) {
-                       if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+                       clk_hw = __clk_get_hw(clk);
+                       if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
                                pr_warn("can't setup clkdm for basic clk %s\n",
                                        setup->name);
                        } else {
-                               clk_hw = __clk_get_hw(clk);
                                to_clk_hw_omap(clk_hw)->clkdm_name =
                                        setup->clkdm_name;
                                omap2_init_clk_clkdm(clk_hw);
@@ -311,3 +406,50 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
        return 0;
 }
 #endif
+
+/**
+ * ti_clk_setup_features - setup clock features flags
+ * @features: features definition to use
+ *
+ * Initializes the clock driver features flags based on platform
+ * provided data. No return value.
+ */
+void __init ti_clk_setup_features(struct ti_clk_features *features)
+{
+       memcpy(&ti_clk_features, features, sizeof(*features));
+}
+
+/**
+ * ti_clk_get_features - get clock driver features flags
+ *
+ * Get TI clock driver features description. Returns a pointer
+ * to the current feature setup.
+ */
+const struct ti_clk_features *ti_clk_get_features(void)
+{
+       return &ti_clk_features;
+}
+
+/**
+ * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
+ * @clk_names: ptr to an array of strings of clock names to enable
+ * @num_clocks: number of clock names in @clk_names
+ *
+ * Prepare and enable a list of clocks, named by @clk_names.  No
+ * return value. XXX Deprecated; only needed until these clocks are
+ * properly claimed and enabled by the drivers or core code that uses
+ * them.  XXX What code disables & calls clk_put on these clocks?
+ */
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
+{
+       struct clk *init_clk;
+       int i;
+
+       for (i = 0; i < num_clocks; i++) {
+               init_clk = clk_get(NULL, clk_names[i]);
+               if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
+                        clk_names[i]))
+                       continue;
+               clk_prepare_enable(init_clk);
+       }
+}
diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c
new file mode 100644 (file)
index 0000000..90d7d8a
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Default clock type
+ *
+ * Copyright (C) 2005-2008, 2015 Texas Instruments, Inc.
+ * Copyright (C) 2004-2010 Nokia Corporation
+ *
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
+ * Tero Kristo <t-kristo@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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/clk/ti.h>
+#include <linux/delay.h>
+
+#include "clock.h"
+
+/*
+ * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
+ * for a module to indicate that it is no longer in idle
+ */
+#define MAX_MODULE_ENABLE_WAIT         100000
+
+/*
+ * CM module register offsets, used for calculating the companion
+ * register addresses.
+ */
+#define CM_FCLKEN                      0x0000
+#define CM_ICLKEN                      0x0010
+
+/**
+ * _wait_idlest_generic - wait for a module to leave the idle state
+ * @clk: module clock to wait for (needed for register offsets)
+ * @reg: virtual address of module IDLEST register
+ * @mask: value to mask against to determine if the module is active
+ * @idlest: idle state indicator (0 or 1) for the clock
+ * @name: name of the clock (for printk)
+ *
+ * Wait for a module to leave idle, where its idle-status register is
+ * not inside the CM module.  Returns 1 if the module left idle
+ * promptly, or 0 if the module did not leave idle before the timeout
+ * elapsed.  XXX Deprecated - should be moved into drivers for the
+ * individual IP block that the IDLEST register exists in.
+ */
+static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
+                               u32 mask, u8 idlest, const char *name)
+{
+       int i = 0, ena = 0;
+
+       ena = (idlest) ? 0 : mask;
+
+       /* Wait until module enters enabled state */
+       for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
+               if ((ti_clk_ll_ops->clk_readl(reg) & mask) == ena)
+                       break;
+               udelay(1);
+       }
+
+       if (i < MAX_MODULE_ENABLE_WAIT)
+               pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
+                        name, i);
+       else
+               pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
+                      name, MAX_MODULE_ENABLE_WAIT);
+
+       return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
+}
+
+/**
+ * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
+ * @clk: struct clk * belonging to the module
+ *
+ * If the necessary clocks for the OMAP hardware IP block that
+ * corresponds to clock @clk are enabled, then wait for the module to
+ * indicate readiness (i.e., to leave IDLE).  This code does not
+ * belong in the clock code and will be moved in the medium term to
+ * module-dependent code.  No return value.
+ */
+static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
+{
+       void __iomem *companion_reg, *idlest_reg;
+       u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
+       s16 prcm_mod;
+       int r;
+
+       /* Not all modules have multiple clocks that their IDLEST depends on */
+       if (clk->ops->find_companion) {
+               clk->ops->find_companion(clk, &companion_reg, &other_bit);
+               if (!(ti_clk_ll_ops->clk_readl(companion_reg) &
+                     (1 << other_bit)))
+                       return;
+       }
+
+       clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
+       r = ti_clk_ll_ops->cm_split_idlest_reg(idlest_reg, &prcm_mod,
+                                              &idlest_reg_id);
+       if (r) {
+               /* IDLEST register not in the CM module */
+               _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
+                                    idlest_val, clk_hw_get_name(&clk->hw));
+       } else {
+               ti_clk_ll_ops->cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
+                                                   idlest_bit);
+       }
+}
+
+/**
+ * omap2_clk_dflt_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
+ *
+ * Note: We don't need special code here for INVERT_ENABLE for the
+ * time being since INVERT_ENABLE only applies to clocks enabled by
+ * CM_CLKEN_PLL
+ *
+ * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
+ * just a matter of XORing the bits.
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as MAILBOXES) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
+ */
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+                                  void __iomem **other_reg, u8 *other_bit)
+{
+       u32 r;
+
+       /*
+        * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
+        * it's just a matter of XORing the bits.
+        */
+       r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
+
+       *other_reg = (__force void __iomem *)r;
+       *other_bit = clk->enable_bit;
+}
+
+/**
+ * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
+ * @clk: struct clk * to find IDLEST info for
+ * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
+ * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
+ * @idlest_val: u8 * to return the idle status indicator
+ *
+ * Return the CM_IDLEST register address and bit shift corresponding
+ * to the module that "owns" this clock.  This default code assumes
+ * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
+ * the IDLEST register address ID corresponds to the CM_*CLKEN
+ * register address ID (e.g., that CM_FCLKEN2 corresponds to
+ * CM_IDLEST2).  This is not true for all modules.  No return value.
+ */
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+                               void __iomem **idlest_reg, u8 *idlest_bit,
+                               u8 *idlest_val)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = clk->enable_bit;
+
+       /*
+        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+        * 34xx reverses this, just to keep us on our toes
+        * AM35xx uses both, depending on the module.
+        */
+       *idlest_val = ti_clk_get_features()->cm_idlest_val;
+}
+
+/**
+ * omap2_dflt_clk_enable - enable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to enable
+ *
+ * Enable the clock @hw in the hardware.  We first call into the OMAP
+ * clockdomain code to "enable" the corresponding clockdomain if this
+ * is the first enabled user of the clockdomain.  Then program the
+ * hardware to enable the clock.  Then wait for the IP block that uses
+ * this clock to leave idle (if applicable).  Returns the error value
+ * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
+ * if @hw has a null clock enable_reg, or zero upon success.
+ */
+int omap2_dflt_clk_enable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+       u32 v;
+       int ret = 0;
+       bool clkdm_control;
+
+       if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL)
+               clkdm_control = false;
+       else
+               clkdm_control = true;
+
+       clk = to_clk_hw_omap(hw);
+
+       if (clkdm_control && clk->clkdm) {
+               ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
+               if (ret) {
+                       WARN(1,
+                            "%s: could not enable %s's clockdomain %s: %d\n",
+                            __func__, clk_hw_get_name(hw),
+                            clk->clkdm_name, ret);
+                       return ret;
+               }
+       }
+
+       if (unlikely(!clk->enable_reg)) {
+               pr_err("%s: %s missing enable_reg\n", __func__,
+                      clk_hw_get_name(hw));
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* FIXME should not have INVERT_ENABLE bit here */
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       if (clk->flags & INVERT_ENABLE)
+               v &= ~(1 << clk->enable_bit);
+       else
+               v |= (1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg); /* OCP barrier */
+
+       if (clk->ops && clk->ops->find_idlest)
+               _omap2_module_wait_ready(clk);
+
+       return 0;
+
+err:
+       if (clkdm_control && clk->clkdm)
+               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+       return ret;
+}
+
+/**
+ * omap2_dflt_clk_disable - disable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to disable
+ *
+ * Disable the clock @hw in the hardware, and call into the OMAP
+ * clockdomain code to "disable" the corresponding clockdomain if all
+ * clocks/hwmods in that clockdomain are now disabled.  No return
+ * value.
+ */
+void omap2_dflt_clk_disable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+       u32 v;
+
+       clk = to_clk_hw_omap(hw);
+       if (!clk->enable_reg) {
+               /*
+                * 'independent' here refers to a clock which is not
+                * controlled by its parent.
+                */
+               pr_err("%s: independent clock %s has no enable_reg\n",
+                      __func__, clk_hw_get_name(hw));
+               return;
+       }
+
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       if (clk->flags & INVERT_ENABLE)
+               v |= (1 << clk->enable_bit);
+       else
+               v &= ~(1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
+       /* No OCP barrier needed here since it is a disable operation */
+
+       if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) &&
+           clk->clkdm)
+               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
+/**
+ * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
+ * @hw: struct clk_hw * to check
+ *
+ * Return 1 if the clock represented by @hw is enabled in the
+ * hardware, or 0 otherwise.  Intended for use in the struct
+ * clk_ops.is_enabled function pointer.
+ */
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       u32 v;
+
+       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+
+       if (clk->flags & INVERT_ENABLE)
+               v ^= BIT(clk->enable_bit);
+
+       v &= BIT(clk->enable_bit);
+
+       return v ? 1 : 0;
+}
+
+const struct clk_hw_omap_ops clkhwops_wait = {
+       .find_idlest    = omap2_clk_dflt_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
similarity index 92%
rename from arch/arm/mach-omap2/clkt_dpll.c
rename to drivers/clk/ti/clkt_dpll.c
index f251a14cbf16a05b1cfd1f3157a83ae0053d8203..9023ca9caf84dde6b02c7ffacdded5244b16795d 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
+#include <linux/clk/ti.h>
 
 #include <asm/div64.h>
 
@@ -74,14 +76,14 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
        dd = clk->dpll_data;
 
        /* DPLL divider must result in a valid jitter correction val */
-       fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
+       fint = clk_hw_get_rate(clk_hw_get_parent(&clk->hw)) / n;
 
        if (dd->flags & DPLL_J_TYPE) {
                fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
                fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
        } else {
-               fint_min = ti_clk_features.fint_min;
-               fint_max = ti_clk_features.fint_max;
+               fint_min = ti_clk_get_features()->fint_min;
+               fint_max = ti_clk_get_features()->fint_max;
        }
 
        if (!fint_min || !fint_max) {
@@ -89,18 +91,18 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
                return DPLL_FINT_INVALID;
        }
 
-       if (fint < ti_clk_features.fint_min) {
+       if (fint < ti_clk_get_features()->fint_min) {
                pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n",
                         n);
                dd->max_divider = n;
                ret = DPLL_FINT_UNDERFLOW;
-       } else if (fint > ti_clk_features.fint_max) {
+       } else if (fint > ti_clk_get_features()->fint_max) {
                pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
                         n);
                dd->min_divider = n;
                ret = DPLL_FINT_INVALID;
-       } else if (fint > ti_clk_features.fint_band1_max &&
-                  fint < ti_clk_features.fint_band2_min) {
+       } else if (fint > ti_clk_get_features()->fint_band1_max &&
+                  fint < ti_clk_get_features()->fint_band2_min) {
                pr_debug("rejecting n=%d due to Fint failure\n", n);
                ret = DPLL_FINT_INVALID;
        }
@@ -183,7 +185,7 @@ static int _omap2_dpll_is_in_bypass(u32 v)
 {
        u8 mask, val;
 
-       mask = ti_clk_features.dpll_bypass_vals;
+       mask = ti_clk_get_features()->dpll_bypass_vals;
 
        /*
         * Each set bit in the mask corresponds to a bypass value equal
@@ -211,7 +213,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
        if (!dd)
                return -EINVAL;
 
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
@@ -247,20 +249,20 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
                return 0;
 
        /* Return bypass rate if DPLL is bypassed */
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
        if (_omap2_dpll_is_in_bypass(v))
-               return __clk_get_rate(dd->clk_bypass);
+               return clk_get_rate(dd->clk_bypass);
 
-       v = omap2_clk_readl(clk, dd->mult_div1_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
        dpll_mult = v & dd->mult_mask;
        dpll_mult >>= __ffs(dd->mult_mask);
        dpll_div = v & dd->div1_mask;
        dpll_div >>= __ffs(dd->div1_mask);
 
-       dpll_clk = (long long) __clk_get_rate(dd->clk_ref) * dpll_mult;
+       dpll_clk = (long long)clk_get_rate(dd->clk_ref) * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
 
        return dpll_clk;
@@ -281,7 +283,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
  * be rounded, or the rounded rate upon success.
  */
 long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-               unsigned long *parent_rate)
+                          unsigned long *parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        int m, n, r, scaled_max_m;
@@ -299,8 +301,8 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 
        dd = clk->dpll_data;
 
-       ref_rate = __clk_get_rate(dd->clk_ref);
-       clk_name = __clk_get_name(hw->clk);
+       ref_rate = clk_get_rate(dd->clk_ref);
+       clk_name = clk_hw_get_name(hw);
        pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n",
                 clk_name, target_rate);
 
@@ -310,7 +312,6 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
        dd->last_rounded_rate = 0;
 
        for (n = dd->min_divider; n <= dd->max_divider; n++) {
-
                /* Is the (input clk, divider) pair valid for the DPLL? */
                r = _dpll_test_fint(clk, n);
                if (r == DPLL_FINT_UNDERFLOW)
@@ -367,4 +368,3 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 
        return dd->last_rounded_rate;
 }
-
diff --git a/drivers/clk/ti/clkt_iclk.c b/drivers/clk/ti/clkt_iclk.c
new file mode 100644 (file)
index 0000000..38c3690
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * OMAP2/3 interface clock control
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/clk/ti.h>
+
+#include "clock.h"
+
+/* Register offsets */
+#define OMAP24XX_CM_FCLKEN2            0x04
+#define CM_AUTOIDLE                    0x30
+#define CM_ICLKEN                      0x10
+#define CM_IDLEST                      0x20
+
+#define OMAP24XX_CM_IDLEST_VAL         0
+
+/* Private functions */
+
+/* XXX */
+void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
+{
+       u32 v;
+       void __iomem *r;
+
+       r = (__force void __iomem *)
+               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+       v = ti_clk_ll_ops->clk_readl(r);
+       v |= (1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, r);
+}
+
+/* XXX */
+void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
+{
+       u32 v;
+       void __iomem *r;
+
+       r = (__force void __iomem *)
+               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+       v = ti_clk_ll_ops->clk_readl(r);
+       v &= ~(1 << clk->enable_bit);
+       ti_clk_ll_ops->clk_writel(v, r);
+}
+
+/**
+ * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
+ *
+ * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
+ * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
+ * passes back the correct CM_IDLEST register address for I2CHS
+ * modules.  No return value.
+ */
+static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
+                                          void __iomem **idlest_reg,
+                                          u8 *idlest_bit,
+                                          u8 *idlest_val)
+{
+       u32 r;
+
+       r = ((__force u32)clk->enable_reg ^ (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST));
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = clk->enable_bit;
+       *idlest_val = OMAP24XX_CM_IDLEST_VAL;
+}
+
+/* Public data */
+
+const struct clk_hw_omap_ops clkhwops_iclk = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+};
+
+const struct clk_hw_omap_ops clkhwops_iclk_wait = {
+       .allow_idle     = omap2_clkt_iclk_allow_idle,
+       .deny_idle      = omap2_clkt_iclk_deny_idle,
+       .find_idlest    = omap2_clk_dflt_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+/* 2430 I2CHS has non-standard IDLEST register */
+const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
+       .find_idlest    = omap2430_clk_i2chs_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
index 404158d2d7f8800757cb95255525aa4fe87ee501..90f3f472ae1c4c70e537c69a7a58e2d1168abddd 100644 (file)
@@ -154,6 +154,35 @@ struct ti_clk_dpll {
        u8 recal_st_bit;
 };
 
+/* Composite clock component types */
+enum {
+       CLK_COMPONENT_TYPE_GATE = 0,
+       CLK_COMPONENT_TYPE_DIVIDER,
+       CLK_COMPONENT_TYPE_MUX,
+       CLK_COMPONENT_TYPE_MAX,
+};
+
+/**
+ * struct ti_dt_clk - OMAP DT clock alias declarations
+ * @lk: clock lookup definition
+ * @node_name: clock DT node to map to
+ */
+struct ti_dt_clk {
+       struct clk_lookup               lk;
+       char                            *node_name;
+};
+
+#define DT_CLK(dev, con, name)         \
+       {                               \
+               .lk = {                 \
+                       .dev_id = dev,  \
+                       .con_id = con,  \
+               },                      \
+               .node_name = name,      \
+       }
+
+typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
+
 struct clk *ti_clk_register_gate(struct ti_clk *setup);
 struct clk *ti_clk_register_interface(struct ti_clk *setup);
 struct clk *ti_clk_register_mux(struct ti_clk *setup);
@@ -169,4 +198,80 @@ void ti_clk_patch_legacy_clks(struct ti_clk **patch);
 struct clk *ti_clk_register_clk(struct ti_clk *setup);
 int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
 
+void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
+void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
+                     ti_of_clk_init_cb_t func);
+int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
+
+void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw);
+int of_ti_clk_autoidle_setup(struct device_node *node);
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
+
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_iclk;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
+
+extern const struct clk_ops ti_clk_divider_ops;
+extern const struct clk_ops ti_clk_mux_ops;
+
+int omap2_clkops_enable_clkdm(struct clk_hw *hw);
+void omap2_clkops_disable_clkdm(struct clk_hw *hw);
+
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
+                                  void __iomem **other_reg,
+                                  u8 *other_bit);
+void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
+                               void __iomem **idlest_reg,
+                               u8 *idlest_bit, u8 *idlest_val);
+
+void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
+void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
+
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+int omap3_noncore_dpll_enable(struct clk_hw *hw);
+void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate);
+int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
+                                          unsigned long rate,
+                                          unsigned long parent_rate,
+                                          u8 index);
+int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req);
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+                          unsigned long *parent_rate);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+                                   unsigned long parent_rate);
+
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
+int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
+                        unsigned long parent_rate);
+int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate, u8 index);
+void omap3_clk_lock_dpll5(void);
+
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+                                        unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+                                   unsigned long target_rate,
+                                   unsigned long *parent_rate);
+int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
+                                      struct clk_rate_request *req);
+
+extern struct ti_clk_ll_ops *ti_clk_ll_ops;
+
 #endif
index b82ef07f340341052fa8a92ddacd8f65845ba843..b9bc3b8df659d853ba0a51a631f98d9a0f1c33c1 100644 (file)
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
+/**
+ * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being enabled
+ *
+ * Increment the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 1, the clockdomain will be "enabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_enable() as
+ * their enable function pointer.  Passes along the return value of
+ * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
+ * clockdomain, or 0 if clock framework-based clockdomain control is
+ * not implemented.
+ */
+int omap2_clkops_enable_clkdm(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+       int ret = 0;
+
+       clk = to_clk_hw_omap(hw);
+
+       if (unlikely(!clk->clkdm)) {
+               pr_err("%s: %s: no clkdm set ?!\n", __func__,
+                      clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       if (unlikely(clk->enable_reg))
+               pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
+                      clk_hw_get_name(hw));
+
+       if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
+               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+                      __func__, clk_hw_get_name(hw));
+               return 0;
+       }
+
+       ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
+       WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
+            __func__, clk_hw_get_name(hw), clk->clkdm_name, ret);
+
+       return ret;
+}
+
+/**
+ * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
+ * @hw: struct clk_hw * of the clock being disabled
+ *
+ * Decrement the usecount of the clockdomain of the clock pointed to
+ * by @hw; if the usecount is 0, the clockdomain will be "disabled."
+ * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
+ * disable function pointer.  No return value.
+ */
+void omap2_clkops_disable_clkdm(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk;
+
+       clk = to_clk_hw_omap(hw);
+
+       if (unlikely(!clk->clkdm)) {
+               pr_err("%s: %s: no clkdm set ?!\n", __func__,
+                      clk_hw_get_name(hw));
+               return;
+       }
+
+       if (unlikely(clk->enable_reg))
+               pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
+                      clk_hw_get_name(hw));
+
+       if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
+               pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
+                      __func__, clk_hw_get_name(hw));
+               return;
+       }
+
+       ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
+}
+
 static void __init of_ti_clockdomain_setup(struct device_node *node)
 {
        struct clk *clk;
@@ -41,12 +120,12 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
                               __func__, node->full_name, i, PTR_ERR(clk));
                        continue;
                }
-               if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+               clk_hw = __clk_get_hw(clk);
+               if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
                        pr_warn("can't setup clkdm for basic clk %s\n",
                                __clk_get_name(clk));
                        continue;
                }
-               clk_hw = __clk_get_hw(clk);
                to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name;
                omap2_init_clk_clkdm(clk_hw);
        }
index 96f83cedb4b3ca6426d1351bd5db6bbcc292fb90..dbef218fe5ecd3ad64319700ac1b142d9c42a89c 100644 (file)
@@ -276,7 +276,6 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
        int num_parents;
        const char **parent_names;
        struct component_clk *clk;
-       int i;
 
        num_parents = of_clk_get_parent_count(node);
 
@@ -289,8 +288,7 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
        if (!parent_names)
                return -ENOMEM;
 
-       for (i = 0; i < num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, num_parents);
 
        clk = kzalloc(sizeof(*clk), GFP_KERNEL);
        if (!clk) {
index ff5f117950a933b354c3bf5ba339e3e1a5b2dcd3..5b1726829e6df038de9e8502471cbb6b70414fd5 100644 (file)
@@ -109,7 +109,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
        if (!div) {
                WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
                     "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
-                    __clk_get_name(hw->clk));
+                    clk_hw_get_name(hw));
                return parent_rate;
        }
 
@@ -155,7 +155,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        maxdiv = _get_maxdiv(divider);
 
-       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
                parent_rate = *best_parent_rate;
                bestdiv = DIV_ROUND_UP(parent_rate, rate);
                bestdiv = bestdiv == 0 ? 1 : bestdiv;
@@ -181,7 +181,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
                        *best_parent_rate = parent_rate_saved;
                        return i;
                }
-               parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+               parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
                                MULT_ROUND_UP(rate, i));
                now = DIV_ROUND_UP(parent_rate, i);
                if (now <= rate && now > best) {
@@ -194,7 +194,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
        if (!bestdiv) {
                bestdiv = _get_maxdiv(divider);
                *best_parent_rate =
-                       __clk_round_rate(__clk_get_parent(hw->clk), 1);
+                       clk_hw_round_rate(clk_hw_get_parent(hw), 1);
        }
 
        return bestdiv;
index 2aacf7a3bcaeb137e4e7bb973cea2874ff1aa6a7..5519b386edc02f74992620d99d8d32921523b5b0 100644 (file)
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -162,7 +163,7 @@ static void __init _register_dpll(struct clk_hw *hw,
        clk = clk_register(NULL, &clk_hw->hw);
 
        if (!IS_ERR(clk)) {
-               omap2_init_clk_hw_omap_clocks(clk);
+               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(clk_hw->hw.init->parent_names);
                kfree(clk_hw->hw.init);
@@ -319,7 +320,7 @@ static void _register_dpll_x2(struct device_node *node,
        if (IS_ERR(clk)) {
                kfree(clk_hw);
        } else {
-               omap2_init_clk_hw_omap_clocks(clk);
+               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
        }
 }
@@ -341,7 +342,6 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        struct clk_init_data *init = NULL;
        const char **parent_names = NULL;
        struct dpll_data *dd = NULL;
-       int i;
        u8 dpll_mode = 0;
 
        dd = kzalloc(sizeof(*dd), GFP_KERNEL);
@@ -370,8 +370,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        if (!parent_names)
                goto cleanup;
 
-       for (i = 0; i < init->num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, init->num_parents);
 
        init->parent_names = parent_names;
 
similarity index 79%
rename from arch/arm/mach-omap2/dpll3xxx.c
rename to drivers/clk/ti/dpll3xxx.c
index 44e57ec225d4401c1e2a81fcbfd929e499e65d58..f4dec00fb684f7743b0fcda3df6f245ac46b7b43 100644 (file)
@@ -27,8 +27,8 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
+#include <linux/clk/ti.h>
 
-#include "clockdomain.h"
 #include "clock.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 
 #define MAX_DPLL_WAIT_TRIES            1000000
 
+#define OMAP3XXX_EN_DPLL_LOCKED                0x7
+
+/* Forward declarations */
+static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
+static void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
+static void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
+
 /* Private functions */
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -47,10 +54,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
 
        dd = clk->dpll_data;
 
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        v &= ~dd->enable_mask;
        v |= clken_bits << __ffs(dd->enable_mask);
-       omap2_clk_writel(v, clk, dd->control_reg);
+       ti_clk_ll_ops->clk_writel(v, dd->control_reg);
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -62,18 +69,18 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
        const char *clk_name;
 
        dd = clk->dpll_data;
-       clk_name = __clk_get_name(clk->hw.clk);
+       clk_name = clk_hw_get_name(&clk->hw);
 
        state <<= __ffs(dd->idlest_mask);
 
-       while (((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask)
+       while (((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask)
                != state) && i < MAX_DPLL_WAIT_TRIES) {
                i++;
                udelay(1);
        }
 
        if (i == MAX_DPLL_WAIT_TRIES) {
-               printk(KERN_ERR "clock: %s failed transition to '%s'\n",
+               pr_err("clock: %s failed transition to '%s'\n",
                       clk_name, (state) ? "locked" : "bypassed");
        } else {
                pr_debug("clock: %s transition to '%s' in %d loops\n",
@@ -91,7 +98,7 @@ static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
        unsigned long fint;
        u16 f = 0;
 
-       fint = __clk_get_rate(clk->dpll_data->clk_ref) / n;
+       fint = clk_get_rate(clk->dpll_data->clk_ref) / n;
 
        pr_debug("clock: fint is %lu\n", fint);
 
@@ -138,13 +145,14 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
        u8 state = 1;
        int r = 0;
 
-       pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk->hw.clk));
+       pr_debug("clock: locking DPLL %s\n", clk_hw_get_name(&clk->hw));
 
        dd = clk->dpll_data;
        state <<= __ffs(dd->idlest_mask);
 
        /* Check if already locked */
-       if ((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) == state)
+       if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) ==
+           state)
                goto done;
 
        ai = omap3_dpll_autoidle_read(clk);
@@ -185,7 +193,7 @@ static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
                return -EINVAL;
 
        pr_debug("clock: configuring DPLL %s for low-power bypass\n",
-                __clk_get_name(clk->hw.clk));
+                clk_hw_get_name(&clk->hw));
 
        ai = omap3_dpll_autoidle_read(clk);
 
@@ -215,7 +223,7 @@ static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
        if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
                return -EINVAL;
 
-       pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk->hw.clk));
+       pr_debug("clock: stopping DPLL %s\n", clk_hw_get_name(&clk->hw));
 
        ai = omap3_dpll_autoidle_read(clk);
 
@@ -243,7 +251,7 @@ static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
 {
        unsigned long fint, clkinp; /* watch out for overflow */
 
-       clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
+       clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
        fint = (clkinp / n) * m;
 
        if (fint < 1000000000)
@@ -269,7 +277,7 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
        unsigned long clkinp, sd; /* watch out for overflow */
        int mod1, mod2;
 
-       clkinp = __clk_get_rate(__clk_get_parent(clk->hw.clk));
+       clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
 
        /*
         * target sigma-delta to near 250MHz
@@ -307,15 +315,15 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
         * Set jitter correction. Jitter correction applicable for OMAP343X
         * only since freqsel field is no longer present on other devices.
         */
-       if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
-               v = omap2_clk_readl(clk, dd->control_reg);
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
+               v = ti_clk_ll_ops->clk_readl(dd->control_reg);
                v &= ~dd->freqsel_mask;
                v |= freqsel << __ffs(dd->freqsel_mask);
-               omap2_clk_writel(v, clk, dd->control_reg);
+               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
        }
 
        /* Set DPLL multiplier, divider */
-       v = omap2_clk_readl(clk, dd->mult_div1_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
 
        /* Handle Duty Cycle Correction */
        if (dd->dcc_mask) {
@@ -342,11 +350,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                v |= sd_div << __ffs(dd->sddiv_mask);
        }
 
-       omap2_clk_writel(v, clk, dd->mult_div1_reg);
+       ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg);
 
        /* Set 4X multiplier and low-power mode */
        if (dd->m4xen_mask || dd->lpmode_mask) {
-               v = omap2_clk_readl(clk, dd->control_reg);
+               v = ti_clk_ll_ops->clk_readl(dd->control_reg);
 
                if (dd->m4xen_mask) {
                        if (dd->last_rounded_m4xen)
@@ -362,7 +370,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                                v &= ~dd->lpmode_mask;
                }
 
-               omap2_clk_writel(v, clk, dd->control_reg);
+               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
        }
 
        /* We let the clock framework set the other output dividers later */
@@ -417,19 +425,19 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
                return -EINVAL;
 
        if (clk->clkdm) {
-               r = clkdm_clk_enable(clk->clkdm, hw->clk);
+               r = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
                if (r) {
                        WARN(1,
                             "%s: could not enable %s's clockdomain %s: %d\n",
-                            __func__, __clk_get_name(hw->clk),
-                            clk->clkdm->name, r);
+                            __func__, clk_hw_get_name(hw),
+                            clk->clkdm_name, r);
                        return r;
                }
        }
 
-       parent = __clk_get_hw(__clk_get_parent(hw->clk));
+       parent = clk_hw_get_parent(hw);
 
-       if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
+       if (clk_hw_get_rate(hw) == clk_get_rate(dd->clk_bypass)) {
                WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
@@ -453,52 +461,46 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
 
        _omap3_noncore_dpll_stop(clk);
        if (clk->clkdm)
-               clkdm_clk_disable(clk->clkdm, hw->clk);
+               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
 }
 
-
 /* Non-CORE DPLL rate set code */
 
 /**
  * omap3_noncore_dpll_determine_rate - determine rate for a DPLL
  * @hw: pointer to the clock to determine rate for
- * @rate: target rate for the DPLL
- * @best_parent_rate: pointer for returning best parent rate
- * @best_parent_clk: pointer for returning best parent clock
+ * @req: target rate request
  *
  * Determines which DPLL mode to use for reaching a desired target rate.
  * Checks whether the DPLL shall be in bypass or locked mode, and if
  * locked, calculates the M,N values for the DPLL via round-rate.
- * Returns a positive clock rate with success, negative error value
- * in failure.
+ * Returns a 0 on success, negative error value in failure.
  */
-long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long min_rate,
-                                      unsigned long max_rate,
-                                      unsigned long *best_parent_rate,
-                                      struct clk_hw **best_parent_clk)
+int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        struct dpll_data *dd;
 
-       if (!hw || !rate)
+       if (!req->rate)
                return -EINVAL;
 
        dd = clk->dpll_data;
        if (!dd)
                return -EINVAL;
 
-       if (__clk_get_rate(dd->clk_bypass) == rate &&
+       if (clk_get_rate(dd->clk_bypass) == req->rate &&
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               *best_parent_clk = __clk_get_hw(dd->clk_bypass);
+               req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
        } else {
-               rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
-               *best_parent_clk = __clk_get_hw(dd->clk_ref);
+               req->rate = omap2_dpll_round_rate(hw, req->rate,
+                                         &req->best_parent_rate);
+               req->best_parent_hw = __clk_get_hw(dd->clk_ref);
        }
 
-       *best_parent_rate = rate;
+       req->best_parent_rate = req->rate;
 
-       return rate;
+       return 0;
 }
 
 /**
@@ -551,21 +553,20 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!dd)
                return -EINVAL;
 
-       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
-           __clk_get_hw(dd->clk_ref))
+       if (clk_hw_get_parent(hw) != __clk_get_hw(dd->clk_ref))
                return -EINVAL;
 
        if (dd->last_rounded_rate == 0)
                return -EINVAL;
 
        /* Freqsel is available only on OMAP343X devices */
-       if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
                freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
                WARN_ON(!freqsel);
        }
 
        pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
-                __clk_get_name(hw->clk), rate);
+                clk_hw_get_name(hw), rate);
 
        ret = omap3_noncore_dpll_program(clk, freqsel);
 
@@ -618,7 +619,7 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
  * -EINVAL if passed a null pointer or if the struct clk does not
  * appear to refer to a DPLL.
  */
-u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
+static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
 {
        const struct dpll_data *dd;
        u32 v;
@@ -631,7 +632,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
        if (!dd->autoidle_reg)
                return -EINVAL;
 
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
        v &= dd->autoidle_mask;
        v >>= __ffs(dd->autoidle_mask);
 
@@ -647,7 +648,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
  * OMAP3430.  The DPLL will enter low-power stop when its downstream
  * clocks are gated.  No return value.
  */
-void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
+static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
 {
        const struct dpll_data *dd;
        u32 v;
@@ -665,11 +666,10 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
         * by writing 0x5 instead of 0x1.  Add some mechanism to
         * optionally enter this mode.
         */
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
-       omap2_clk_writel(v, clk, dd->autoidle_reg);
-
+       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
 }
 
 /**
@@ -678,7 +678,7 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
  *
  * Disable DPLL automatic idle control.  No return value.
  */
-void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
+static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 {
        const struct dpll_data *dd;
        u32 v;
@@ -691,11 +691,10 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
        if (!dd->autoidle_reg)
                return;
 
-       v = omap2_clk_readl(clk, dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
-       omap2_clk_writel(v, clk, dd->autoidle_reg);
-
+       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
 }
 
 /* Clock control for DPLL outputs */
@@ -704,14 +703,12 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
 {
        struct clk_hw_omap *pclk = NULL;
-       struct clk *parent;
 
        /* Walk up the parents of clk, looking for a DPLL */
        do {
                do {
-                       parent = __clk_get_parent(hw->clk);
-                       hw = __clk_get_hw(parent);
-               } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+                       hw = clk_hw_get_parent(hw);
+               } while (hw && (clk_hw_get_flags(hw) & CLK_IS_BASIC));
                if (!hw)
                        break;
                pclk = to_clk_hw_omap(hw);
@@ -753,7 +750,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 
        WARN_ON(!dd->enable_mask);
 
-       v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg) & dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
        if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
                rate = parent_rate;
@@ -762,57 +759,59 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
        return rate;
 }
 
-int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long parent_rate)
-{
-       return 0;
-}
+/* OMAP3/4 non-CORE DPLL clkops */
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
+       .allow_idle     = omap3_dpll_allow_idle,
+       .deny_idle      = omap3_dpll_deny_idle,
+};
 
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *prate)
+/**
+ * omap3_dpll4_set_rate - set rate for omap3 per-dpll
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Check if the current SoC supports the per-dpll reprogram operation
+ * or not, and then do the rate change if supported. Returns -EINVAL
+ * if not supported, 0 for success, and potential error codes from the
+ * clock rate change.
+ */
+int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
+                        unsigned long parent_rate)
 {
-       const struct dpll_data *dd;
-       u32 v;
-       struct clk_hw_omap *pclk = NULL;
-
-       if (!*prate)
-               return 0;
-
-       pclk = omap3_find_clkoutx2_dpll(hw);
-
-       if (!pclk)
-               return 0;
-
-       dd = pclk->dpll_data;
-
-       /* TYPE J does not have a clkoutx2 */
-       if (dd->flags & DPLL_J_TYPE) {
-               *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
-               return *prate;
+       /*
+        * According to the 12-5 CDP code from TI, "Limitation 2.5"
+        * on 3430ES1 prevents us from changing DPLL multipliers or dividers
+        * on DPLL4.
+        */
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
+               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
+               return -EINVAL;
        }
 
-       WARN_ON(!dd->enable_mask);
-
-       v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
-       v >>= __ffs(dd->enable_mask);
-
-       /* If in bypass, the rate is fixed to the bypass rate*/
-       if (v != OMAP3XXX_EN_DPLL_LOCKED)
-               return *prate;
-
-       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
-               unsigned long best_parent;
+       return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
 
-               best_parent = (rate / 2);
-               *prate = __clk_round_rate(__clk_get_parent(hw->clk),
-                               best_parent);
+/**
+ * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ * @index: parent index, 0 - reference clock, 1 - bypass clock
+ *
+ * Check if the current SoC support the per-dpll reprogram operation
+ * or not, and then do the rate + parent change if supported. Returns
+ * -EINVAL if not supported, 0 for success, and potential error codes
+ * from the clock rate change.
+ */
+int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate, u8 index)
+{
+       if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
+               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
+               return -EINVAL;
        }
 
-       return *prate * 2;
+       return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
+                                                     index);
 }
-
-/* OMAP3/4 non-CORE DPLL clkops */
-const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
-       .allow_idle     = omap3_dpll_allow_idle,
-       .deny_idle      = omap3_dpll_deny_idle,
-};
similarity index 79%
rename from arch/arm/mach-omap2/dpll44xx.c
rename to drivers/clk/ti/dpll44xx.c
index f231be05b9a638de8e52cfe03d78765433815764..660d7436ac243a89a2ac2573a8b67a019bac0301 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/clk/ti.h>
 
 #include "clock.h"
 
 /*
  * Bitfield declarations
  */
-#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK            (1 << 8)
-#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK          (1 << 10)
-#define OMAP4430_DPLL_REGM4XEN_MASK                    (1 << 11)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK            BIT(8)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK          BIT(10)
+#define OMAP4430_DPLL_REGM4XEN_MASK                    BIT(11)
 
 /* Static rate multiplier for OMAP4 REGM4XEN clocks */
 #define OMAP4430_REGM4XEN_MULT                         4
 
-void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
+static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
 {
        u32 v;
        u32 mask;
@@ -48,13 +49,13 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = omap2_clk_readl(clk, clk->clksel_reg);
+       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
        /* Clear the bit to allow gatectrl */
        v &= ~mask;
-       omap2_clk_writel(v, clk, clk->clksel_reg);
+       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
 }
 
-void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
+static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
 {
        u32 v;
        u32 mask;
@@ -66,10 +67,10 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = omap2_clk_readl(clk, clk->clksel_reg);
+       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
        /* Set the bit to deny gatectrl */
        v |= mask;
-       omap2_clk_writel(v, clk, clk->clksel_reg);
+       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
 }
 
 const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
@@ -93,7 +94,7 @@ static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
 {
        long fint, fout;
 
-       fint = __clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1);
+       fint = clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1);
        fout = fint * dd->last_rounded_m;
 
        if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX))
@@ -112,7 +113,7 @@ static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
  * upon success, or 0 upon error.
  */
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-                       unsigned long parent_rate)
+                                        unsigned long parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        u32 v;
@@ -127,7 +128,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
        rate = omap2_get_dpll_rate(clk);
 
        /* regm4xen adds a multiplier of 4 to DPLL calculations */
-       v = omap2_clk_readl(clk, dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
        if (v & OMAP4430_DPLL_REGM4XEN_MASK)
                rate *= OMAP4430_REGM4XEN_MULT;
 
@@ -191,42 +192,36 @@ out:
 /**
  * omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
  * @hw: pointer to the clock to determine rate for
- * @rate: target rate for the DPLL
- * @best_parent_rate: pointer for returning best parent rate
- * @best_parent_clk: pointer for returning best parent clock
+ * @req: target rate request
  *
  * Determines which DPLL mode to use for reaching a desired rate.
  * Checks whether the DPLL shall be in bypass or locked mode, and if
  * locked, calculates the M,N values for the DPLL via round-rate.
- * Returns a positive clock rate with success, negative error value
- * in failure.
+ * Returns 0 on success and a negative error value otherwise.
  */
-long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk)
+int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
+                                      struct clk_rate_request *req)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        struct dpll_data *dd;
 
-       if (!hw || !rate)
+       if (!req->rate)
                return -EINVAL;
 
        dd = clk->dpll_data;
        if (!dd)
                return -EINVAL;
 
-       if (__clk_get_rate(dd->clk_bypass) == rate &&
+       if (clk_get_rate(dd->clk_bypass) == req->rate &&
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               *best_parent_clk = __clk_get_hw(dd->clk_bypass);
+               req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
        } else {
-               rate = omap4_dpll_regm4xen_round_rate(hw, rate,
-                                                     best_parent_rate);
-               *best_parent_clk = __clk_get_hw(dd->clk_ref);
+               req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate,
+                                               &req->best_parent_rate);
+               req->best_parent_hw = __clk_get_hw(dd->clk_ref);
        }
 
-       *best_parent_rate = rate;
+       req->best_parent_rate = req->rate;
 
-       return rate;
+       return 0;
 }
index 730aa62454a2454f6a5311adbd16bfff57e366d2..f4b2e9888bdf3c3079b0854b1c04c65a5201c5db 100644 (file)
@@ -9,6 +9,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -558,8 +559,7 @@ static void __init ti_fapll_setup(struct device_node *node)
                goto free;
        }
 
-       parent_name[0] = of_clk_get_parent_name(node, 0);
-       parent_name[1] = of_clk_get_parent_name(node, 1);
+       of_clk_parent_fill(node, parent_name, 2);
        init->parent_names = parent_name;
 
        fd->clk_ref = of_clk_get(node, 0);
index c2c8a287408c914a5b6a7e3c0be4a8594d1894c9..3cd40676890969b1853256d32061b8bfd29093a7 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
 
+#include "clock.h"
+
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
index 0c6fdfcd5f93a911178e334a87f371576bd18939..5429d35343639632a821548ef7837ccacd172a31 100644 (file)
@@ -62,7 +62,7 @@ static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
  * (Any other value different from the Read value) to the
  * corresponding CM_CLKSEL register will refresh the dividers.
  */
-static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
 {
        struct clk_divider *parent;
        struct clk_hw *parent_hw;
@@ -70,10 +70,10 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
        int ret;
 
        /* Clear PWRDN bit of HSDIVIDER */
-       ret = omap2_dflt_clk_enable(clk);
+       ret = omap2_dflt_clk_enable(hw);
 
        /* Parent is the x2 node, get parent of parent for the m2 div */
-       parent_hw = __clk_get_hw(__clk_get_parent(__clk_get_parent(clk->clk)));
+       parent_hw = clk_hw_get_parent(clk_hw_get_parent(hw));
        parent = to_clk_divider(parent_hw);
 
        /* Restore the dividers */
index c76230d8dd0464a073097cb70c4303cdf0e06056..e505e6f8228da6ada5ccb4beffd7aa0de78f1f1d 100644 (file)
@@ -63,7 +63,7 @@ static struct clk *_register_interface(struct device *dev, const char *name,
        if (IS_ERR(clk))
                kfree(clk_hw);
        else
-               omap2_init_clk_hw_omap_clocks(clk);
+               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
 
        return clk;
 }
index 5cdeed538b08a2eec168de48a94399c11af33472..69f08a1d047d8672a758e441fcd718bbf64bb946 100644 (file)
@@ -31,7 +31,7 @@
 static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
 {
        struct clk_mux *mux = to_clk_mux(hw);
-       int num_parents = __clk_get_num_parents(hw->clk);
+       int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
        /*
@@ -190,7 +190,6 @@ static void of_mux_clk_setup(struct device_node *node)
        void __iomem *reg;
        int num_parents;
        const char **parent_names;
-       int i;
        u8 clk_mux_flags = 0;
        u32 mask = 0;
        u32 shift = 0;
@@ -205,8 +204,7 @@ static void of_mux_clk_setup(struct device_node *node)
        if (!parent_names)
                goto cleanup;
 
-       for (i = 0; i < num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(node, i);
+       of_clk_parent_fill(node, parent_names, num_parents);
 
        reg = ti_clk_get_reg_addr(node, 0);
 
index 521483f0ba335f67a5bf7dc96e26adf3ca89fbcf..f3baef29859c46cd927d6bbf299a4cd5fe62e95d 100644 (file)
@@ -9,7 +9,6 @@ obj-y += clk-sysctrl.o
 
 # Clock definitions
 obj-y += u8500_of_clk.o
-obj-y += u8500_clk.o
 obj-y += u9540_clk.o
 obj-y += u8540_clk.o
 
index 3e5e05101302e569d5bda1a68451abc56b6bb4d0..222425d08ab6ac3faf05b6385d51c2df1b33713f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/mfd/abx500/ab8500-sysctrl.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
index bf63c96acb1a2947ce7e274f2869b51ab8e95550..7f343821f4e4aef06b7261e60ad381c2bafee3af 100644 (file)
@@ -43,7 +43,7 @@ static void clk_prcmu_unprepare(struct clk_hw *hw)
        struct clk_prcmu *clk = to_clk_prcmu(hw);
        if (prcmu_request_clock(clk->cg_sel, false))
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
        else
                clk->is_prepared = 0;
 }
@@ -101,11 +101,11 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw)
 
        if (!clk->opp_requested) {
                err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
-                                               (char *)__clk_get_name(hw->clk),
+                                               (char *)clk_hw_get_name(hw),
                                                100);
                if (err) {
                        pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
-                               __func__, __clk_get_name(hw->clk));
+                               __func__, clk_hw_get_name(hw));
                        return err;
                }
                clk->opp_requested = 1;
@@ -114,7 +114,7 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw)
        err = prcmu_request_clock(clk->cg_sel, true);
        if (err) {
                prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
-                                       (char *)__clk_get_name(hw->clk));
+                                       (char *)clk_hw_get_name(hw));
                clk->opp_requested = 0;
                return err;
        }
@@ -129,13 +129,13 @@ static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
 
        if (prcmu_request_clock(clk->cg_sel, false)) {
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return;
        }
 
        if (clk->opp_requested) {
                prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
-                                       (char *)__clk_get_name(hw->clk));
+                                       (char *)clk_hw_get_name(hw));
                clk->opp_requested = 0;
        }
 
@@ -151,7 +151,7 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
                err = prcmu_request_ape_opp_100_voltage(true);
                if (err) {
                        pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
-                               __func__, __clk_get_name(hw->clk));
+                               __func__, clk_hw_get_name(hw));
                        return err;
                }
                clk->opp_requested = 1;
@@ -174,7 +174,7 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
 
        if (prcmu_request_clock(clk->cg_sel, false)) {
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       __clk_get_name(hw->clk));
+                       clk_hw_get_name(hw));
                return;
        }
 
index e364c9d4aa60e38b05085926297d3514da319048..266ddea630d22de9a9ae5a8f339edbfc81887946 100644 (file)
@@ -52,7 +52,7 @@ static void clk_sysctrl_unprepare(struct clk_hw *hw)
        struct clk_sysctrl *clk = to_clk_sysctrl(hw);
        if (ab8500_sysctrl_clear(clk->reg_sel[0], clk->reg_mask[0]))
                dev_err(clk->dev, "clk_sysctrl: %s fail to clear %s.\n",
-                       __func__, __clk_get_name(hw->clk));
+                       __func__, clk_hw_get_name(hw));
 }
 
 static unsigned long clk_sysctrl_recalc_rate(struct clk_hw *hw,
index a2bb92d85ee0a980ad458745f93c2ca00acf4266..b42485da704eaa495ab56d976668e063dd9f8dde 100644 (file)
 #ifndef __UX500_CLK_H
 #define __UX500_CLK_H
 
-#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/types.h>
 
+struct clk;
+
 struct clk *clk_reg_prcc_pclk(const char *name,
                              const char *parent_name,
                              resource_size_t phy_base,
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
deleted file mode 100644 (file)
index 4626b97..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Clock definitions for u8500 platform.
- *
- * Copyright (C) 2012 ST-Ericsson SA
- * Author: Ulf Hansson <ulf.hansson@linaro.org>
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/mfd/dbx500-prcmu.h>
-#include <linux/platform_data/clk-ux500.h>
-#include "clk.h"
-
-void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base)
-{
-       struct prcmu_fw_version *fw_version;
-       const char *sgaclk_parent = NULL;
-       struct clk *clk;
-
-       /* Clock sources */
-       clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "soc0_pll", NULL);
-
-       clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "soc1_pll", NULL);
-
-       clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "ddr_pll", NULL);
-
-       /* FIXME: Add sys, ulp and int clocks here. */
-
-       clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL",
-                               CLK_IS_ROOT|CLK_IGNORE_UNUSED,
-                               32768);
-       clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
-
-       /* PRCMU clocks */
-       fw_version = prcmu_get_fw_version();
-       if (fw_version != NULL) {
-               switch (fw_version->project) {
-               case PRCMU_FW_PROJECT_U8500_C2:
-               case PRCMU_FW_PROJECT_U8520:
-               case PRCMU_FW_PROJECT_U8420:
-                       sgaclk_parent = "soc0_pll";
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (sgaclk_parent)
-               clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent,
-                                       PRCMU_SGACLK, 0);
-       else
-               clk = clk_reg_prcmu_gate("sgclk", NULL,
-                                       PRCMU_SGACLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "mali");
-
-       clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "UART");
-
-       clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "MSP02");
-
-       clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "MSP1");
-
-       clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "I2C");
-
-       clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "slim");
-
-       clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH1");
-
-       clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH2");
-
-       clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH3");
-
-       clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH5");
-
-       clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH6");
-
-       clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "PERIPH7");
-
-       clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "lcd");
-       clk_register_clkdev(clk, "lcd", "mcde");
-
-       clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "bml");
-
-       clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-
-       clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-
-       clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "hdmi");
-       clk_register_clkdev(clk, "hdmi", "mcde");
-
-       clk = clk_reg_prcmu_scalable("apeatclk", NULL, PRCMU_APEATCLK, 0,
-                                    CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "apeat");
-
-       clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "apetrace");
-
-       clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "mcde");
-       clk_register_clkdev(clk, "mcde", "mcde");
-       clk_register_clkdev(clk, "dsisys", "dsilink.0");
-       clk_register_clkdev(clk, "dsisys", "dsilink.1");
-       clk_register_clkdev(clk, "dsisys", "dsilink.2");
-
-       clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK,
-                               CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "ipi2");
-
-       clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK,
-                               CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "dsialt");
-
-       clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "dma40.0");
-
-       clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "b2r2");
-       clk_register_clkdev(clk, NULL, "b2r2_core");
-       clk_register_clkdev(clk, NULL, "U8500-B2R2.0");
-
-       clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
-                               CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "tv");
-       clk_register_clkdev(clk, "tv", "mcde");
-
-       clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "SSP");
-
-       clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "rngclk");
-
-       clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "uicc");
-
-       clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
-       clk_register_clkdev(clk, NULL, "mtu0");
-       clk_register_clkdev(clk, NULL, "mtu1");
-
-       clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
-                                       100000000,
-                                       CLK_IS_ROOT|CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdmmc");
-
-       clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
-                               PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs2", "mcde");
-       clk_register_clkdev(clk, "dsihs2", "dsilink.2");
-
-
-       clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
-                               PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs0", "mcde");
-       clk_register_clkdev(clk, "dsihs0", "dsilink.0");
-
-       clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
-                               PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsihs1", "mcde");
-       clk_register_clkdev(clk, "dsihs1", "dsilink.1");
-
-       clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
-                               PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilp0", "dsilink.0");
-       clk_register_clkdev(clk, "dsilp0", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
-                               PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilp1", "dsilink.1");
-       clk_register_clkdev(clk, "dsilp1", "mcde");
-
-       clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
-                               PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, "dsilp2", "dsilink.2");
-       clk_register_clkdev(clk, "dsilp2", "mcde");
-
-       clk = clk_reg_prcmu_scalable_rate("armss", NULL,
-                               PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
-       clk_register_clkdev(clk, "armss", NULL);
-
-       clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
-                               CLK_IGNORE_UNUSED, 1, 2);
-       clk_register_clkdev(clk, NULL, "smp_twd");
-
-       /*
-        * FIXME: Add special handled PRCMU clocks here:
-        * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
-        * 2. ab9540_clkout1yuv, see clkout0yuv
-        */
-
-       /* PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp0");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp1");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
-
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
-
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, NULL, "spi3");
-
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
-                               BIT(8), 0);
-       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
-                               BIT(9), 0);
-       clk_register_clkdev(clk, NULL, "gpio.0");
-       clk_register_clkdev(clk, NULL, "gpio.1");
-       clk_register_clkdev(clk, NULL, "gpioblock0");
-
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
-
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
-                               BIT(11), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp3");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "spi2");
-
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, NULL, "spi1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, NULL, "pwl");
-
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi4");
-
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "msp2");
-       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
-
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi3");
-
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
-                               BIT(8), 0);
-       clk_register_clkdev(clk, NULL, "spi0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
-                               BIT(9), 0);
-       clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
-                               BIT(10), 0);
-       clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
-
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
-                               BIT(11), 0);
-       clk_register_clkdev(clk, NULL, "gpio.6");
-       clk_register_clkdev(clk, NULL, "gpio.7");
-       clk_register_clkdev(clk, NULL, "gpioblock1");
-
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
-                               BIT(12), 0);
-
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "fsmc", NULL);
-       clk_register_clkdev(clk, NULL, "smsc911x.0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ssp0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ssp1");
-
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
-
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, "apb_pclk", "ske");
-       clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
-
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "uart2");
-
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "sdi5");
-
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
-                               BIT(8), 0);
-       clk_register_clkdev(clk, NULL, "gpio.2");
-       clk_register_clkdev(clk, NULL, "gpio.3");
-       clk_register_clkdev(clk, NULL, "gpio.4");
-       clk_register_clkdev(clk, NULL, "gpio.5");
-       clk_register_clkdev(clk, NULL, "gpioblock2");
-
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "usb", "musb-ux500.0");
-
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "gpio.8");
-       clk_register_clkdev(clk, NULL, "gpioblock3");
-
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
-                               BIT(0), 0);
-       clk_register_clkdev(clk, "apb_pclk", "rng");
-
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
-                               BIT(1), 0);
-       clk_register_clkdev(clk, NULL, "cryp0");
-       clk_register_clkdev(clk, NULL, "cryp1");
-
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
-                               BIT(2), 0);
-       clk_register_clkdev(clk, NULL, "hash0");
-
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
-                               BIT(3), 0);
-       clk_register_clkdev(clk, NULL, "pka");
-
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
-                               BIT(4), 0);
-       clk_register_clkdev(clk, NULL, "hash1");
-
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
-                               BIT(5), 0);
-       clk_register_clkdev(clk, NULL, "cfgreg");
-
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
-                               BIT(6), 0);
-       clk_register_clkdev(clk, "apb_pclk", "mtu0");
-
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
-                               BIT(7), 0);
-       clk_register_clkdev(clk, "apb_pclk", "mtu1");
-
-       /* PRCC K-clocks
-        *
-        * FIXME: Some drivers requires PERPIH[n| to be automatically enabled
-        * by enabling just the K-clock, even if it is not a valid parent to
-        * the K-clock. Until drivers get fixed we might need some kind of
-        * "parent muxed join".
-        */
-
-       /* Periph1 */
-       clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart0");
-
-       clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart1");
-
-       clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
-
-       clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp0");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
-
-       clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp1");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
-
-       clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
-                       clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi0");
-
-       clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
-
-       clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "slimbus0");
-
-       clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
-
-       clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp3");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
-
-       /* Periph2 */
-       clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
-
-       clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi4");
-
-       clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "msp2");
-       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
-
-       clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi1");
-
-       clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi3");
-
-       /* Note that rate is received from parent. */
-       clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       clkrst2_base, BIT(6),
-                       CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
-       clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       clkrst2_base, BIT(7),
-                       CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
-
-       /* Periph3 */
-       clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ssp0");
-
-       clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ssp1");
-
-       clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
-
-       clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi2");
-
-       clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "ske");
-       clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
-
-       clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "uart2");
-
-       clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "sdi5");
-
-       /* Periph6 */
-       clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
-                       clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
-       clk_register_clkdev(clk, NULL, "rng");
-}
index e319ef912dc6c27bbaba940a42a4ef97a5bf07a0..271c09644652c72e3f057e8d90b2ebcb1d1f258c 100644 (file)
@@ -8,8 +8,7 @@
  */
 
 #include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/of_address.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
@@ -54,14 +53,25 @@ static const struct of_device_id u8500_clk_of_match[] = {
        { },
 };
 
-void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                      u32 clkrst5_base, u32 clkrst6_base)
+/* CLKRST4 is missing making it hard to index things */
+enum clkrst_index {
+       CLKRST1_INDEX = 0,
+       CLKRST2_INDEX,
+       CLKRST3_INDEX,
+       CLKRST5_INDEX,
+       CLKRST6_INDEX,
+       CLKRST_MAX,
+};
+
+void u8500_clk_init(void)
 {
        struct prcmu_fw_version *fw_version;
        struct device_node *np = NULL;
        struct device_node *child = NULL;
        const char *sgaclk_parent = NULL;
        struct clk *clk, *rtc_clk, *twd_clk;
+       u32 bases[CLKRST_MAX];
+       int i;
 
        if (of_have_populated_dt())
                np = of_find_matching_node(NULL, u8500_clk_of_match);
@@ -69,6 +79,15 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
                pr_err("Either DT or U8500 Clock node not found\n");
                return;
        }
+       for (i = 0; i < ARRAY_SIZE(bases); i++) {
+               struct resource r;
+
+               if (of_address_to_resource(np, i, &r))
+                       /* Not much choice but to continue */
+                       pr_err("failed to get CLKRST %d base address\n",
+                              i + 1);
+               bases[i] = r.start;
+       }
 
        /* Clock sources */
        clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
@@ -246,179 +265,179 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
         */
 
        /* PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 1, 0);
 
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 1, 1);
 
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 1, 2);
 
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 1, 3);
 
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 1, 4);
 
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 1, 5);
 
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 1, 6);
 
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 1, 7);
 
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX],
                                BIT(8), 0);
        PRCC_PCLK_STORE(clk, 1, 8);
 
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX],
                                BIT(9), 0);
        PRCC_PCLK_STORE(clk, 1, 9);
 
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX],
                                BIT(10), 0);
        PRCC_PCLK_STORE(clk, 1, 10);
 
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX],
                                BIT(11), 0);
        PRCC_PCLK_STORE(clk, 1, 11);
 
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 2, 0);
 
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 2, 1);
 
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 2, 2);
 
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 2, 3);
 
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 2, 4);
 
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 2, 5);
 
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 2, 6);
 
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 2, 7);
 
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX],
                                BIT(8), 0);
        PRCC_PCLK_STORE(clk, 2, 8);
 
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX],
                                BIT(9), 0);
        PRCC_PCLK_STORE(clk, 2, 9);
 
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX],
                                BIT(10), 0);
        PRCC_PCLK_STORE(clk, 2, 10);
 
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX],
                                BIT(11), 0);
        PRCC_PCLK_STORE(clk, 2, 11);
 
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX],
                                BIT(12), 0);
        PRCC_PCLK_STORE(clk, 2, 12);
 
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 3, 0);
 
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 3, 1);
 
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 3, 2);
 
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 3, 3);
 
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 3, 4);
 
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 3, 5);
 
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 3, 6);
 
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 3, 7);
 
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX],
                                BIT(8), 0);
        PRCC_PCLK_STORE(clk, 3, 8);
 
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 5, 0);
 
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 5, 1);
 
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX],
                                BIT(0), 0);
        PRCC_PCLK_STORE(clk, 6, 0);
 
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX],
                                BIT(1), 0);
        PRCC_PCLK_STORE(clk, 6, 1);
 
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX],
                                BIT(2), 0);
        PRCC_PCLK_STORE(clk, 6, 2);
 
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX],
                                BIT(3), 0);
        PRCC_PCLK_STORE(clk, 6, 3);
 
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX],
                                BIT(4), 0);
        PRCC_PCLK_STORE(clk, 6, 4);
 
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX],
                                BIT(5), 0);
        PRCC_PCLK_STORE(clk, 6, 5);
 
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX],
                                BIT(6), 0);
        PRCC_PCLK_STORE(clk, 6, 6);
 
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX],
                                BIT(7), 0);
        PRCC_PCLK_STORE(clk, 6, 7);
 
@@ -432,109 +451,109 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 
        /* Periph1 */
        clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 0);
 
        clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 1);
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 2);
 
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 3);
 
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 4);
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
-                       clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 5);
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 6);
 
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 8);
 
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 9);
 
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 1, 10);
 
        /* Periph2 */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 0);
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 2);
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 3);
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 4);
 
        clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 2, 5);
 
        /* Note that rate is received from parent. */
        clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       clkrst2_base, BIT(6),
+                       bases[CLKRST2_INDEX], BIT(6),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        PRCC_KCLK_STORE(clk, 2, 6);
 
        clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       clkrst2_base, BIT(7),
+                       bases[CLKRST2_INDEX], BIT(7),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        PRCC_KCLK_STORE(clk, 2, 7);
 
        /* Periph3 */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 1);
 
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 2);
 
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 3);
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 4);
 
        clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 5);
 
        clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 6);
 
        clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 3, 7);
 
        /* Periph6 */
        clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
-                       clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
        PRCC_KCLK_STORE(clk, 6, 0);
 
        for_each_child_of_node(np, child) {
index 20c8add90d110db1575e0ccb5695499581853af5..d7bcb7a86615f91f518c1719f812b29f783c23d3 100644 (file)
@@ -7,17 +7,51 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
 #include "clk.h"
 
-void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base)
+static const struct of_device_id u8540_clk_of_match[] = {
+       { .compatible = "stericsson,u8540-clks", },
+       { }
+};
+
+/* CLKRST4 is missing making it hard to index things */
+enum clkrst_index {
+       CLKRST1_INDEX = 0,
+       CLKRST2_INDEX,
+       CLKRST3_INDEX,
+       CLKRST5_INDEX,
+       CLKRST6_INDEX,
+       CLKRST_MAX,
+};
+
+void u8540_clk_init(void)
 {
        struct clk *clk;
+       struct device_node *np = NULL;
+       u32 bases[CLKRST_MAX];
+       int i;
+
+       if (of_have_populated_dt())
+               np = of_find_matching_node(NULL, u8540_clk_of_match);
+       if (!np) {
+               pr_err("Either DT or U8540 Clock node not found\n");
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(bases); i++) {
+               struct resource r;
+
+               if (of_address_to_resource(np, i, &r))
+                       /* Not much choice but to continue */
+                       pr_err("failed to get CLKRST %d base address\n",
+                              i + 1);
+               bases[i] = r.start;
+       }
 
        /* Clock sources. */
        /* Fixed ClockGen */
@@ -219,151 +253,151 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 
        /* PRCC P-clocks */
        /* Peripheral 1 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", bases[CLKRST1_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart1");
 
-       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", bases[CLKRST1_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
 
-       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", bases[CLKRST1_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp0");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", bases[CLKRST1_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp1");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.1");
 
-       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", bases[CLKRST1_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", bases[CLKRST1_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
 
-       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", bases[CLKRST1_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, NULL, "spi3");
 
-       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", bases[CLKRST1_INDEX],
                                BIT(8), 0);
        clk_register_clkdev(clk, "apb_pclk", "slimbus0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", bases[CLKRST1_INDEX],
                                BIT(9), 0);
        clk_register_clkdev(clk, NULL, "gpio.0");
        clk_register_clkdev(clk, NULL, "gpio.1");
        clk_register_clkdev(clk, NULL, "gpioblock0");
        clk_register_clkdev(clk, "apb_pclk", "ab85xx-codec.0");
 
-       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", bases[CLKRST1_INDEX],
                                BIT(10), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
 
-       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
+       clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", bases[CLKRST1_INDEX],
                                BIT(11), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp3");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.3");
 
        /* Peripheral 2 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", bases[CLKRST2_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
 
-       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", bases[CLKRST2_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, NULL, "spi2");
 
-       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", bases[CLKRST2_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, NULL, "spi1");
 
-       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", bases[CLKRST2_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, NULL, "pwl");
 
-       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", bases[CLKRST2_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi4");
 
-       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", bases[CLKRST2_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, "apb_pclk", "msp2");
        clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.2");
 
-       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", bases[CLKRST2_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi1");
 
-       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", bases[CLKRST2_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi3");
 
-       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", bases[CLKRST2_INDEX],
                                BIT(8), 0);
        clk_register_clkdev(clk, NULL, "spi0");
 
-       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", bases[CLKRST2_INDEX],
                                BIT(9), 0);
        clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
 
-       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", bases[CLKRST2_INDEX],
                                BIT(10), 0);
        clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
 
-       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", bases[CLKRST2_INDEX],
                                BIT(11), 0);
        clk_register_clkdev(clk, NULL, "gpio.6");
        clk_register_clkdev(clk, NULL, "gpio.7");
        clk_register_clkdev(clk, NULL, "gpioblock1");
 
-       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
+       clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", bases[CLKRST2_INDEX],
                                BIT(12), 0);
        clk_register_clkdev(clk, "msp4-pclk", "ab85xx-codec.0");
 
        /* Peripheral 3 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", bases[CLKRST3_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, NULL, "fsmc");
 
-       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", bases[CLKRST3_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, "apb_pclk", "ssp0");
 
-       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", bases[CLKRST3_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, "apb_pclk", "ssp1");
 
-       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", bases[CLKRST3_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
 
-       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", bases[CLKRST3_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi2");
 
-       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", bases[CLKRST3_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, "apb_pclk", "ske");
        clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
 
-       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", bases[CLKRST3_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart2");
 
-       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", bases[CLKRST3_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi5");
 
-       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", bases[CLKRST3_INDEX],
                                BIT(8), 0);
        clk_register_clkdev(clk, NULL, "gpio.2");
        clk_register_clkdev(clk, NULL, "gpio.3");
@@ -371,64 +405,64 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
        clk_register_clkdev(clk, NULL, "gpio.5");
        clk_register_clkdev(clk, NULL, "gpioblock2");
 
-       clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", bases[CLKRST3_INDEX],
                                BIT(9), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.5");
 
-       clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", bases[CLKRST3_INDEX],
                                BIT(10), 0);
        clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.6");
 
-       clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", bases[CLKRST3_INDEX],
                                BIT(11), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart3");
 
-       clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", clkrst3_base,
+       clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", bases[CLKRST3_INDEX],
                                BIT(12), 0);
        clk_register_clkdev(clk, "apb_pclk", "uart4");
 
        /* Peripheral 5 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", bases[CLKRST5_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "usb", "musb-ux500.0");
        clk_register_clkdev(clk, "usbclk", "ab-iddet.0");
 
-       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
+       clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", bases[CLKRST5_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, NULL, "gpio.8");
        clk_register_clkdev(clk, NULL, "gpioblock3");
 
        /* Peripheral 6 : PRCC P-clocks */
-       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", bases[CLKRST6_INDEX],
                                BIT(0), 0);
        clk_register_clkdev(clk, "apb_pclk", "rng");
 
-       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", bases[CLKRST6_INDEX],
                                BIT(1), 0);
        clk_register_clkdev(clk, NULL, "cryp0");
        clk_register_clkdev(clk, NULL, "cryp1");
 
-       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", bases[CLKRST6_INDEX],
                                BIT(2), 0);
        clk_register_clkdev(clk, NULL, "hash0");
 
-       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", bases[CLKRST6_INDEX],
                                BIT(3), 0);
        clk_register_clkdev(clk, NULL, "pka");
 
-       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", bases[CLKRST6_INDEX],
                                BIT(4), 0);
        clk_register_clkdev(clk, NULL, "db8540-hash1");
 
-       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", bases[CLKRST6_INDEX],
                                BIT(5), 0);
        clk_register_clkdev(clk, NULL, "cfgreg");
 
-       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", bases[CLKRST6_INDEX],
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "mtu0");
 
-       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
+       clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", bases[CLKRST6_INDEX],
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "mtu1");
 
@@ -442,138 +476,138 @@ void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 
        /* Peripheral 1 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
-                       clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(0), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart0");
 
        clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
-                       clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(1), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart1");
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
-                       clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(2), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.1");
 
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
-                       clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(3), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp0");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.0");
 
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
-                       clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(4), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp1");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.1");
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmchclk",
-                       clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(5), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi0");
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
-                       clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(6), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.2");
 
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(8), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "slimbus0");
 
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
-                       clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(9), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.4");
 
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
-                       clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
+                       bases[CLKRST1_INDEX], BIT(10), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp3");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.3");
 
        /* Peripheral 2 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
-                       clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(0), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.3");
 
        clk = clk_reg_prcc_kclk("p2_pwl_kclk", "rtc32k",
-                       clkrst2_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(1), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "pwl");
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmchclk",
-                       clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(2), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi4");
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
-                       clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(3), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp2");
        clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.2");
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmchclk",
-                       clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(4), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi1");
 
        clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
-                       clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(5), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi3");
 
        clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
-                       clkrst2_base, BIT(6),
+                       bases[CLKRST2_INDEX], BIT(6),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        clk_register_clkdev(clk, "hsir_hsirxclk", "ste_hsi.0");
 
        clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
-                       clkrst2_base, BIT(7),
+                       bases[CLKRST2_INDEX], BIT(7),
                        CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
        clk_register_clkdev(clk, "hsit_hsitxclk", "ste_hsi.0");
 
        /* Should only be 9540, but might be added for 85xx as well */
        clk = clk_reg_prcc_kclk("p2_msp4_kclk", "msp02clk",
-                       clkrst2_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST2_INDEX], BIT(9), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "msp4");
        clk_register_clkdev(clk, "msp4", "ab85xx-codec.0");
 
        /* Peripheral 3 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
-                       clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(1), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "ssp0");
 
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
-                       clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(2), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "ssp1");
 
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
-                       clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(3), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.0");
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmchclk",
-                       clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(4), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi2");
 
        clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
-                       clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(5), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "ske");
        clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
 
        clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
-                       clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(6), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart2");
 
        clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
-                       clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(7), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdi5");
 
        clk = clk_reg_prcc_kclk("p3_i2c5_kclk", "i2cclk",
-                       clkrst3_base, BIT(8), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(8), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.5");
 
        clk = clk_reg_prcc_kclk("p3_i2c6_kclk", "i2cclk",
-                       clkrst3_base, BIT(9), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(9), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "nmk-i2c.6");
 
        clk = clk_reg_prcc_kclk("p3_uart3_kclk", "uartclk",
-                       clkrst3_base, BIT(10), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(10), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart3");
 
        clk = clk_reg_prcc_kclk("p3_uart4_kclk", "uartclk",
-                       clkrst3_base, BIT(11), CLK_SET_RATE_GATE);
+                       bases[CLKRST3_INDEX], BIT(11), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "uart4");
 
        /* Peripheral 6 : PRCC K-clocks */
        clk = clk_reg_prcc_kclk("p6_rng_kclk", "rngclk",
-                       clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
+                       bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "rng");
 }
index 44794782e7e01681414ad123809bf1b8ce35be0b..2138a4c8cbcaa23de8e8d8bd9f79d8c0ee606521 100644 (file)
@@ -7,15 +7,12 @@
  * License terms: GNU General Public License (GPL) version 2
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/platform_data/clk-ux500.h>
 #include "clk.h"
 
-void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base)
+void u9540_clk_init(void)
 {
        /* register clocks here */
 }
index bc96f103bd7caac9c95a977bb3c8559d638bbf9b..a3893ea2199dafa5412207711a1d33fca04c287f 100644 (file)
@@ -13,8 +13,9 @@
  * ICST clock code from the ARM tree should probably be merged into this
  * file.
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/err.h>
 #include <linux/clk-provider.h>
 #include <linux/io.h>
index 1cc1330dc5709bc1cc24f887349291aeff705200..65c842a21c6243149d8d3740cacbd270792bfa0d 100644 (file)
@@ -7,7 +7,6 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
index c8b523117fb7ed4e971b5582f802cab0fb7c0eee..86f70997d59dce436d34c9c5aef74be0f367f869 100644 (file)
@@ -6,7 +6,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -33,13 +32,13 @@ static const struct icst_params realview_oscvco_params = {
        .idx2s          = icst307_idx2s,
 };
 
-static const struct clk_icst_desc __initdata realview_osc0_desc = {
+static const struct clk_icst_desc realview_osc0_desc __initconst = {
        .params = &realview_oscvco_params,
        .vco_offset = REALVIEW_SYS_OSC0_OFFSET,
        .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
 };
 
-static const struct clk_icst_desc __initdata realview_osc4_desc = {
+static const struct clk_icst_desc realview_osc4_desc __initconst = {
        .params = &realview_oscvco_params,
        .vco_offset = REALVIEW_SYS_OSC4_OFFSET,
        .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
index a96dd8e53fdb2d9537a363c480418db859c8c0b1..a1cdef6b0f9045be6dd3e47b712f02b8e485de50 100644 (file)
@@ -12,7 +12,8 @@
  */
 
 #include <linux/amba/sp810.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/of.h>
@@ -32,12 +33,9 @@ struct clk_sp810_timerclken {
 
 struct clk_sp810 {
        struct device_node *node;
-       int refclk_index, timclk_index;
        void __iomem *base;
        spinlock_t lock;
        struct clk_sp810_timerclken timerclken[4];
-       struct clk *refclk;
-       struct clk *timclk;
 };
 
 static u8 clk_sp810_timerclken_get_parent(struct clk_hw *hw)
@@ -70,55 +68,7 @@ static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index)
        return 0;
 }
 
-/*
- * FIXME - setting the parent every time .prepare is invoked is inefficient.
- * This is better handled by a dedicated clock tree configuration mechanism at
- * init-time.  Revisit this later when such a mechanism exists
- */
-static int clk_sp810_timerclken_prepare(struct clk_hw *hw)
-{
-       struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw);
-       struct clk_sp810 *sp810 = timerclken->sp810;
-       struct clk *old_parent = __clk_get_parent(hw->clk);
-       struct clk *new_parent;
-
-       if (!sp810->refclk)
-               sp810->refclk = of_clk_get(sp810->node, sp810->refclk_index);
-
-       if (!sp810->timclk)
-               sp810->timclk = of_clk_get(sp810->node, sp810->timclk_index);
-
-       if (WARN_ON(IS_ERR(sp810->refclk) || IS_ERR(sp810->timclk)))
-               return -ENOENT;
-
-       /* Select fastest parent */
-       if (clk_get_rate(sp810->refclk) > clk_get_rate(sp810->timclk))
-               new_parent = sp810->refclk;
-       else
-               new_parent = sp810->timclk;
-
-       /* Switch the parent if necessary */
-       if (old_parent != new_parent) {
-               clk_prepare(new_parent);
-               clk_set_parent(hw->clk, new_parent);
-               clk_unprepare(old_parent);
-       }
-
-       return 0;
-}
-
-static void clk_sp810_timerclken_unprepare(struct clk_hw *hw)
-{
-       struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw);
-       struct clk_sp810 *sp810 = timerclken->sp810;
-
-       clk_put(sp810->timclk);
-       clk_put(sp810->refclk);
-}
-
 static const struct clk_ops clk_sp810_timerclken_ops = {
-       .prepare = clk_sp810_timerclken_prepare,
-       .unprepare = clk_sp810_timerclken_unprepare,
        .get_parent = clk_sp810_timerclken_get_parent,
        .set_parent = clk_sp810_timerclken_set_parent,
 };
@@ -128,8 +78,8 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec,
 {
        struct clk_sp810 *sp810 = data;
 
-       if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
-                       ARRAY_SIZE(sp810->timerclken)))
+       if (WARN_ON(clkspec->args_count != 1 ||
+                   clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken)))
                return NULL;
 
        return sp810->timerclken[clkspec->args[0]].clk;
@@ -139,24 +89,18 @@ static void __init clk_sp810_of_setup(struct device_node *node)
 {
        struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL);
        const char *parent_names[2];
+       int num = ARRAY_SIZE(parent_names);
        char name[12];
        struct clk_init_data init;
        int i;
+       bool deprecated;
 
        if (!sp810) {
                pr_err("Failed to allocate memory for SP810!\n");
                return;
        }
 
-       sp810->refclk_index = of_property_match_string(node, "clock-names",
-                       "refclk");
-       parent_names[0] = of_clk_get_parent_name(node, sp810->refclk_index);
-
-       sp810->timclk_index = of_property_match_string(node, "clock-names",
-                       "timclk");
-       parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index);
-
-       if (!parent_names[0] || !parent_names[1]) {
+       if (of_clk_parent_fill(node, parent_names, num) != num) {
                pr_warn("Failed to obtain parent clocks for SP810!\n");
                return;
        }
@@ -169,7 +113,9 @@ static void __init clk_sp810_of_setup(struct device_node *node)
        init.ops = &clk_sp810_timerclken_ops;
        init.flags = CLK_IS_BASIC;
        init.parent_names = parent_names;
-       init.num_parents = ARRAY_SIZE(parent_names);
+       init.num_parents = num;
+
+       deprecated = !of_find_property(node, "assigned-clock-parents", NULL);
 
        for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) {
                snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
@@ -178,6 +124,15 @@ static void __init clk_sp810_of_setup(struct device_node *node)
                sp810->timerclken[i].channel = i;
                sp810->timerclken[i].hw.init = &init;
 
+               /*
+                * If DT isn't setting the parent, force it to be
+                * the 1 MHz clock without going through the framework.
+                * We do this before clk_register() so that it can determine
+                * the parent and setup the tree properly.
+                */
+               if (deprecated)
+                       init.ops->set_parent(&sp810->timerclken[i].hw, 1);
+
                sp810->timerclken[i].clk = clk_register(NULL,
                                &sp810->timerclken[i].hw);
                WARN_ON(IS_ERR(sp810->timerclken[i].clk));
index 7a4f8635bd1eb31ce8bbb68e755f124bd5f12f00..a89a927567e0cfae45df95b8aed7cc2218509fc3 100644 (file)
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
  */
 #include <linux/clk-provider.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -35,7 +33,7 @@ static const struct icst_params cp_auxosc_params = {
        .idx2s          = icst525_idx2s,
 };
 
-static const struct clk_icst_desc __initdata cm_auxosc_desc = {
+static const struct clk_icst_desc cm_auxosc_desc __initconst = {
        .params = &cp_auxosc_params,
        .vco_offset = 0x1c,
        .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
index 95b707c18108c475908dcec1f1904ddb1db0c270..74005aa322a2d7d26a1d16deaa2da26b4da1f02b 100644 (file)
@@ -1,2 +1,2 @@
-obj-y := clk-pll.o
+obj-y := clk.o
 obj-$(CONFIG_SOC_ZX296702) += clk-zx296702.o
index 929d033594af5202fbe9664703df422573ebfdde..ebd20d852e733ea788269246f20f3ccb02acae6a 100644 (file)
@@ -36,10 +36,21 @@ static struct clk_onecell_data lsp1clk_data;
 #define CLK_MUX1               (topcrm_base + 0x8c)
 
 #define CLK_SDMMC1             (lsp0crpm_base + 0x0c)
+#define CLK_GPIO               (lsp0crpm_base + 0x2c)
+#define CLK_SPDIF0             (lsp0crpm_base + 0x10)
+#define SPDIF0_DIV             (lsp0crpm_base + 0x14)
+#define CLK_I2S0               (lsp0crpm_base + 0x18)
+#define I2S0_DIV               (lsp0crpm_base + 0x1c)
+#define CLK_I2S1               (lsp0crpm_base + 0x20)
+#define I2S1_DIV               (lsp0crpm_base + 0x24)
+#define CLK_I2S2               (lsp0crpm_base + 0x34)
+#define I2S2_DIV               (lsp0crpm_base + 0x38)
 
 #define CLK_UART0              (lsp1crpm_base + 0x20)
 #define CLK_UART1              (lsp1crpm_base + 0x24)
 #define CLK_SDMMC0             (lsp1crpm_base + 0x2c)
+#define CLK_SPDIF1             (lsp1crpm_base + 0x30)
+#define SPDIF1_DIV             (lsp1crpm_base + 0x34)
 
 static const struct zx_pll_config pll_a9_config[] = {
        { .rate = 700000000, .cfg0 = 0x800405d1, .cfg1 = 0x04555555 },
@@ -72,104 +83,119 @@ static const struct clk_div_table sec_wclk_divider[] = {
        { /* sentinel */ }
 };
 
-static const char * matrix_aclk_sel[] = {
+static const char * const matrix_aclk_sel[] = {
        "pll_mm0_198M",
        "osc",
        "clk_148M5",
        "pll_lsp_104M",
 };
 
-static const char * a9_wclk_sel[] = {
+static const char * const a9_wclk_sel[] = {
        "pll_a9",
        "osc",
        "clk_500",
        "clk_250",
 };
 
-static const char * a9_as1_aclk_sel[] = {
+static const char * const a9_as1_aclk_sel[] = {
        "clk_250",
        "osc",
        "pll_mm0_396M",
        "pll_mac_333M",
 };
 
-static const char * a9_trace_clkin_sel[] = {
+static const char * const a9_trace_clkin_sel[] = {
        "clk_74M25",
        "pll_mm1_108M",
        "clk_125",
        "clk_148M5",
 };
 
-static const char * decppu_aclk_sel[] = {
+static const char * const decppu_aclk_sel[] = {
        "clk_250",
        "pll_mm0_198M",
        "pll_lsp_104M",
        "pll_audio_294M912",
 };
 
-static const char * vou_main_wclk_sel[] = {
+static const char * const vou_main_wclk_sel[] = {
        "clk_148M5",
        "clk_74M25",
        "clk_27",
        "pll_mm1_54M",
 };
 
-static const char * vou_scaler_wclk_sel[] = {
+static const char * const vou_scaler_wclk_sel[] = {
        "clk_250",
        "pll_mac_333M",
        "pll_audio_294M912",
        "pll_mm0_198M",
 };
 
-static const char * r2d_wclk_sel[] = {
+static const char * const r2d_wclk_sel[] = {
        "pll_audio_294M912",
        "pll_mac_333M",
        "pll_a9_350M",
        "pll_mm0_396M",
 };
 
-static const char * ddr_wclk_sel[] = {
+static const char * const ddr_wclk_sel[] = {
        "pll_mac_333M",
        "pll_ddr_266M",
        "pll_audio_294M912",
        "pll_mm0_198M",
 };
 
-static const char * nand_wclk_sel[] = {
+static const char * const nand_wclk_sel[] = {
        "pll_lsp_104M",
        "osc",
 };
 
-static const char * lsp_26_wclk_sel[] = {
+static const char * const lsp_26_wclk_sel[] = {
        "pll_lsp_26M",
        "osc",
 };
 
-static const char * vl0_sel[] = {
+static const char * const vl0_sel[] = {
        "vou_main_channel_div",
        "vou_aux_channel_div",
 };
 
-static const char * hdmi_sel[] = {
+static const char * const hdmi_sel[] = {
        "vou_main_channel_wclk",
        "vou_aux_channel_wclk",
 };
 
-static const char * sdmmc0_wclk_sel[] = {
+static const char * const sdmmc0_wclk_sel[] = {
        "lsp1_104M_wclk",
        "lsp1_26M_wclk",
 };
 
-static const char * sdmmc1_wclk_sel[] = {
+static const char * const sdmmc1_wclk_sel[] = {
        "lsp0_104M_wclk",
        "lsp0_26M_wclk",
 };
 
-static const char * uart_wclk_sel[] = {
+static const char * const uart_wclk_sel[] = {
        "lsp1_104M_wclk",
        "lsp1_26M_wclk",
 };
 
+static const char * const spdif0_wclk_sel[] = {
+       "lsp0_104M_wclk",
+       "lsp0_26M_wclk",
+};
+
+static const char * const spdif1_wclk_sel[] = {
+       "lsp1_104M_wclk",
+       "lsp1_26M_wclk",
+};
+
+static const char * const i2s_wclk_sel[] = {
+       "lsp0_104M_wclk",
+       "lsp0_26M_wclk",
+};
+
 static inline struct clk *zx_divtbl(const char *name, const char *parent,
                                    void __iomem *reg, u8 shift, u8 width,
                                    const struct clk_div_table *table)
@@ -185,7 +211,7 @@ static inline struct clk *zx_div(const char *name, const char *parent,
                                    reg, shift, width, 0, &reg_lock);
 }
 
-static inline struct clk *zx_mux(const char *name, const char **parents,
+static inline struct clk *zx_mux(const char *name, const char * const *parents,
                int num_parents, void __iomem *reg, u8 shift, u8 width)
 {
        return clk_register_mux(NULL, name, parents, num_parents,
@@ -196,7 +222,7 @@ static inline struct clk *zx_gate(const char *name, const char *parent,
                                  void __iomem *reg, u8 shift)
 {
        return clk_register_gate(NULL, name, parent, CLK_IGNORE_UNUSED,
-                                reg, shift, 0, &reg_lock);
+                                reg, shift, CLK_SET_RATE_PARENT, &reg_lock);
 }
 
 static void __init zx296702_top_clocks_init(struct device_node *np)
@@ -585,7 +611,57 @@ static void __init zx296702_lsp0_clocks_init(struct device_node *np)
        clk[ZX296702_SDMMC1_WCLK] =
                zx_gate("sdmmc1_wclk", "sdmmc1_wclk_div", CLK_SDMMC1, 1);
        clk[ZX296702_SDMMC1_PCLK] =
-               zx_gate("sdmmc1_pclk", "lsp1_apb_pclk", CLK_SDMMC1, 0);
+               zx_gate("sdmmc1_pclk", "lsp0_apb_pclk", CLK_SDMMC1, 0);
+
+       clk[ZX296702_GPIO_CLK] =
+               zx_gate("gpio_clk", "lsp0_apb_pclk", CLK_GPIO, 0);
+
+       /* SPDIF */
+       clk[ZX296702_SPDIF0_WCLK_MUX] =
+               zx_mux("spdif0_wclk_mux", spdif0_wclk_sel,
+                               ARRAY_SIZE(spdif0_wclk_sel), CLK_SPDIF0, 4, 1);
+       clk[ZX296702_SPDIF0_WCLK] =
+               zx_gate("spdif0_wclk", "spdif0_wclk_mux", CLK_SPDIF0, 1);
+       clk[ZX296702_SPDIF0_PCLK] =
+               zx_gate("spdif0_pclk", "lsp0_apb_pclk", CLK_SPDIF0, 0);
+
+       clk[ZX296702_SPDIF0_DIV] =
+               clk_register_zx_audio("spdif0_div", "spdif0_wclk", 0,
+                               SPDIF0_DIV);
+
+       /* I2S */
+       clk[ZX296702_I2S0_WCLK_MUX] =
+               zx_mux("i2s0_wclk_mux", i2s_wclk_sel,
+                               ARRAY_SIZE(i2s_wclk_sel), CLK_I2S0, 4, 1);
+       clk[ZX296702_I2S0_WCLK] =
+               zx_gate("i2s0_wclk", "i2s0_wclk_mux", CLK_I2S0, 1);
+       clk[ZX296702_I2S0_PCLK] =
+               zx_gate("i2s0_pclk", "lsp0_apb_pclk", CLK_I2S0, 0);
+
+       clk[ZX296702_I2S0_DIV] =
+               clk_register_zx_audio("i2s0_div", "i2s0_wclk", 0, I2S0_DIV);
+
+       clk[ZX296702_I2S1_WCLK_MUX] =
+               zx_mux("i2s1_wclk_mux", i2s_wclk_sel,
+                               ARRAY_SIZE(i2s_wclk_sel), CLK_I2S1, 4, 1);
+       clk[ZX296702_I2S1_WCLK] =
+               zx_gate("i2s1_wclk", "i2s1_wclk_mux", CLK_I2S1, 1);
+       clk[ZX296702_I2S1_PCLK] =
+               zx_gate("i2s1_pclk", "lsp0_apb_pclk", CLK_I2S1, 0);
+
+       clk[ZX296702_I2S1_DIV] =
+               clk_register_zx_audio("i2s1_div", "i2s1_wclk", 0, I2S1_DIV);
+
+       clk[ZX296702_I2S2_WCLK_MUX] =
+               zx_mux("i2s2_wclk_mux", i2s_wclk_sel,
+                               ARRAY_SIZE(i2s_wclk_sel), CLK_I2S2, 4, 1);
+       clk[ZX296702_I2S2_WCLK] =
+               zx_gate("i2s2_wclk", "i2s2_wclk_mux", CLK_I2S2, 1);
+       clk[ZX296702_I2S2_PCLK] =
+               zx_gate("i2s2_pclk", "lsp0_apb_pclk", CLK_I2S2, 0);
+
+       clk[ZX296702_I2S2_DIV] =
+               clk_register_zx_audio("i2s2_div", "i2s2_wclk", 0, I2S2_DIV);
 
        for (i = 0; i < ARRAY_SIZE(lsp0clk); i++) {
                if (IS_ERR(clk[i])) {
@@ -641,6 +717,18 @@ static void __init zx296702_lsp1_clocks_init(struct device_node *np)
        clk[ZX296702_SDMMC0_PCLK] =
                zx_gate("sdmmc0_pclk", "lsp1_apb_pclk", CLK_SDMMC0, 0);
 
+       clk[ZX296702_SPDIF1_WCLK_MUX] =
+               zx_mux("spdif1_wclk_mux", spdif1_wclk_sel,
+                               ARRAY_SIZE(spdif1_wclk_sel), CLK_SPDIF1, 4, 1);
+       clk[ZX296702_SPDIF1_WCLK] =
+               zx_gate("spdif1_wclk", "spdif1_wclk_mux", CLK_SPDIF1, 1);
+       clk[ZX296702_SPDIF1_PCLK] =
+               zx_gate("spdif1_pclk", "lsp1_apb_pclk", CLK_SPDIF1, 0);
+
+       clk[ZX296702_SPDIF1_DIV] =
+               clk_register_zx_audio("spdif1_div", "spdif1_wclk", 0,
+                               SPDIF1_DIV);
+
        for (i = 0; i < ARRAY_SIZE(lsp1clk); i++) {
                if (IS_ERR(clk[i])) {
                        pr_err("zx296702 clk %d: register failed with %ld\n",
similarity index 55%
rename from drivers/clk/zte/clk-pll.c
rename to drivers/clk/zte/clk.c
index c3b221ae6cd7b8527ba0eb6a243c7d06a8075d6a..7c73c538c43d8a12ee8c64e78bb2cc84ed61867d 100644 (file)
 #include <linux/iopoll.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <asm/div64.h>
 
 #include "clk.h"
 
 #define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
+#define to_clk_zx_audio(_hw) container_of(_hw, struct clk_zx_audio, hw)
 
 #define CFG0_CFG1_OFFSET 4
 #define LOCK_FLAG BIT(30)
@@ -141,8 +143,9 @@ static const struct clk_ops zx_pll_ops = {
 };
 
 struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
-       unsigned long flags, void __iomem *reg_base,
-       const struct zx_pll_config *lookup_table, int count, spinlock_t *lock)
+                               unsigned long flags, void __iomem *reg_base,
+                               const struct zx_pll_config *lookup_table,
+                               int count, spinlock_t *lock)
 {
        struct clk_zx_pll *zx_pll;
        struct clk *clk;
@@ -170,3 +173,137 @@ struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
 
        return clk;
 }
+
+#define BPAR 1000000
+static u32 calc_reg(u32 parent_rate, u32 rate)
+{
+       u32 sel, integ, fra_div, tmp;
+       u64 tmp64 = (u64)parent_rate * BPAR;
+
+       do_div(tmp64, rate);
+       integ = (u32)tmp64 / BPAR;
+       integ = integ >> 1;
+
+       tmp = (u32)tmp64 % BPAR;
+       sel = tmp / BPAR;
+
+       tmp = tmp % BPAR;
+       fra_div = tmp * 0xff / BPAR;
+       tmp = (sel << 24) | (integ << 16) | (0xff << 8) | fra_div;
+
+       /* Set I2S integer divider as 1. This bit is reserved for SPDIF
+        * and do no harm.
+        */
+       tmp |= BIT(28);
+       return tmp;
+}
+
+static u32 calc_rate(u32 reg, u32 parent_rate)
+{
+       u32 sel, integ, fra_div, tmp;
+       u64 tmp64 = (u64)parent_rate * BPAR;
+
+       tmp = reg;
+       sel = (tmp >> 24) & BIT(0);
+       integ = (tmp >> 16) & 0xff;
+       fra_div = tmp & 0xff;
+
+       tmp = fra_div * BPAR;
+       tmp = tmp / 0xff;
+       tmp += sel * BPAR;
+       tmp += 2 * integ * BPAR;
+       do_div(tmp64, tmp);
+
+       return (u32)tmp64;
+}
+
+static unsigned long zx_audio_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = readl_relaxed(zx_audio->reg_base);
+       return calc_rate(reg, parent_rate);
+}
+
+static long zx_audio_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       u32 reg;
+
+       if (rate * 2 > *prate)
+               return -EINVAL;
+
+       reg = calc_reg(*prate, rate);
+       return calc_rate(reg, *prate);
+}
+
+static int zx_audio_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = calc_reg(parent_rate, rate);
+       writel_relaxed(reg, zx_audio->reg_base);
+
+       return 0;
+}
+
+#define ZX_AUDIO_EN BIT(25)
+static int zx_audio_enable(struct clk_hw *hw)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = readl_relaxed(zx_audio->reg_base);
+       writel_relaxed(reg & ~ZX_AUDIO_EN, zx_audio->reg_base);
+       return 0;
+}
+
+static void zx_audio_disable(struct clk_hw *hw)
+{
+       struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
+       u32 reg;
+
+       reg = readl_relaxed(zx_audio->reg_base);
+       writel_relaxed(reg | ZX_AUDIO_EN, zx_audio->reg_base);
+}
+
+static const struct clk_ops zx_audio_ops = {
+       .recalc_rate = zx_audio_recalc_rate,
+       .round_rate = zx_audio_round_rate,
+       .set_rate = zx_audio_set_rate,
+       .enable = zx_audio_enable,
+       .disable = zx_audio_disable,
+};
+
+struct clk *clk_register_zx_audio(const char *name,
+                                 const char * const parent_name,
+                                 unsigned long flags,
+                                 void __iomem *reg_base)
+{
+       struct clk_zx_audio *zx_audio;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       zx_audio = kzalloc(sizeof(*zx_audio), GFP_KERNEL);
+       if (!zx_audio)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &zx_audio_ops;
+       init.flags = flags;
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.num_parents = parent_name ? 1 : 0;
+
+       zx_audio->reg_base = reg_base;
+       zx_audio->hw.init = &init;
+
+       clk = clk_register(NULL, &zx_audio->hw);
+       if (IS_ERR(clk))
+               kfree(zx_audio);
+
+       return clk;
+}
index 0914a82d0535743cf869b7dd58aba07de45a9c17..65ae08b818d3f836809199341f130c8aff1f0811 100644 (file)
@@ -29,4 +29,13 @@ struct clk_zx_pll {
 struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
        unsigned long flags, void __iomem *reg_base,
        const struct zx_pll_config *lookup_table, int count, spinlock_t *lock);
+
+struct clk_zx_audio {
+       struct clk_hw hw;
+       void __iomem *reg_base;
+};
+
+struct clk *clk_register_zx_audio(const char *name,
+                                 const char * const parent_name,
+                                 unsigned long flags, void __iomem *reg_base);
 #endif
index de614384bb447512344e089a9ed56ea657f731f3..38a65c3e62fc247c39ecaff4853cfd45c3148168 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/clk/zynq.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index 510c8a1d37b375841bc49879e3dd0dfccb00470b..5ea91e3818d0ccd7a4496d0401f266bb2dd67505 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/of_address.h>
index b8ff3c64cc452a16fc4108426fb6e5b1c54e91e8..c96de14036a0adebfc7628dc9f9cd5413b5c5495 100644 (file)
@@ -661,6 +661,9 @@ static void sh_cmt_clocksource_suspend(struct clocksource *cs)
 {
        struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 
+       if (!ch->cs_enabled)
+               return;
+
        sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
        pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
 }
@@ -669,6 +672,9 @@ static void sh_cmt_clocksource_resume(struct clocksource *cs)
 {
        struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 
+       if (!ch->cs_enabled)
+               return;
+
        pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
        sh_cmt_start(ch, FLAG_CLOCKSOURCE);
 }
index 2d59038dec43512e40ca46f4a0989c3b1253e0af..86c7eb66bdfb2e18628997319aa047b1aedc1da1 100644 (file)
@@ -462,6 +462,7 @@ void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
        BUG_ON(!imxtm->base);
 
        imxtm->type = type;
+       imxtm->irq = irq;
 
        _mxc_timer_init(imxtm);
 }
index 7a3c30c4336f3cb9b7b67d5965b77175b4cad53f..9bb09ce98d047813e094cd8e5993c0368febc62e 100644 (file)
@@ -1521,13 +1521,13 @@ static int __cpufreq_remove_dev_finish(struct device *dev)
  *
  * Removes the cpufreq interface for a CPU device.
  */
-static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
+static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int cpu = dev->id;
        struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
 
        if (!policy)
-               return 0;
+               return;
 
        if (cpu_online(cpu)) {
                __cpufreq_remove_dev_prepare(dev);
@@ -1538,7 +1538,7 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
 
        if (cpumask_empty(policy->real_cpus)) {
                cpufreq_policy_free(policy, true);
-               return 0;
+               return;
        }
 
        if (cpu != policy->kobj_cpu) {
@@ -1557,8 +1557,6 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
                policy->kobj_cpu = new_cpu;
                WARN_ON(kobject_move(&policy->kobj, &new_dev->kobj));
        }
-
-       return 0;
 }
 
 static void handle_update(struct work_struct *work)
index ae5b2bd3a9785c63646e3e922fbe17330678b481..fa3dd840a83771735e474a658a5c6516c62f76a0 100644 (file)
@@ -180,7 +180,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
                ret = exynos5250_cpufreq_init(exynos_info);
        } else {
                pr_err("%s: Unknown SoC type\n", __func__);
-               return -ENODEV;
+               ret = -ENODEV;
        }
 
        if (ret)
@@ -188,12 +188,14 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
 
        if (exynos_info->set_freq == NULL) {
                dev_err(&pdev->dev, "No set_freq function (ERR)\n");
+               ret = -EINVAL;
                goto err_vdd_arm;
        }
 
        arm_regulator = regulator_get(NULL, "vdd_arm");
        if (IS_ERR(arm_regulator)) {
                dev_err(&pdev->dev, "failed to get resource vdd_arm\n");
+               ret = -EINVAL;
                goto err_vdd_arm;
        }
 
@@ -225,7 +227,7 @@ err_cpufreq_reg:
        regulator_put(arm_regulator);
 err_vdd_arm:
        kfree(exynos_info);
-       return -EINVAL;
+       return ret;
 }
 
 static struct platform_driver exynos_cpufreq_platdrv = {
index 4044125fb5d5fa7589e2cbcb12623546d0effa75..07bc7aa6b224aeeb7ada29b08aec61966d3b3b2e 100644 (file)
@@ -480,4 +480,21 @@ config CRYPTO_DEV_IMGTEC_HASH
          hardware hash accelerator. Supporting MD5/SHA1/SHA224/SHA256
          hashing algorithms.
 
+config CRYPTO_DEV_SUN4I_SS
+       tristate "Support for Allwinner Security System cryptographic accelerator"
+       depends on ARCH_SUNXI
+       select CRYPTO_MD5
+       select CRYPTO_SHA1
+       select CRYPTO_AES
+       select CRYPTO_DES
+       select CRYPTO_BLKCIPHER
+       help
+         Some Allwinner SoC have a crypto accelerator named
+         Security System. Select this if you want to use it.
+         The Security System handle AES/DES/3DES ciphers in CBC mode
+         and SHA1 and MD5 hash algorithms.
+
+         To compile this driver as a module, choose M here: the module
+         will be called sun4i-ss.
+
 endif # CRYPTO_HW
index e35c07a8da8568c59d56e35f0f9c30b2362ecbca..c3ced6fbd1b8f9877a7d6a03acad9deacbf5d378 100644 (file)
@@ -28,3 +28,4 @@ obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
 obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/
 obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
 obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
+obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/
index 3b28e8c3de28d1181e7f36a45af196ebfa457701..192a8fa325c1ccc8c71dd8617d84f509a1b6dfae 100644 (file)
@@ -1113,7 +1113,7 @@ static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data)
        struct device *dev = (struct device *)data;
        struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
 
-       if (core_dev->dev->ce_base == 0)
+       if (!core_dev->dev->ce_base)
                return 0;
 
        writel(PPC4XX_INTERRUPT_CLR,
index e286e285aa8a48f462b205638986d7b52cb01642..5652a53415dc2efe395069ade7a55517620c2579 100644 (file)
@@ -1,6 +1,6 @@
 config CRYPTO_DEV_FSL_CAAM
        tristate "Freescale CAAM-Multicore driver backend"
-       depends on FSL_SOC
+       depends on FSL_SOC || ARCH_MXC
        help
          Enables the driver module for Freescale's Cryptographic Accelerator
          and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
@@ -112,6 +112,14 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
          To compile this as a module, choose M here: the module
          will be called caamrng.
 
+config CRYPTO_DEV_FSL_CAAM_IMX
+       def_bool SOC_IMX6 || SOC_IMX7D
+       depends on CRYPTO_DEV_FSL_CAAM
+
+config CRYPTO_DEV_FSL_CAAM_LE
+       def_bool CRYPTO_DEV_FSL_CAAM_IMX || SOC_LS1021A
+       depends on CRYPTO_DEV_FSL_CAAM
+
 config CRYPTO_DEV_FSL_CAAM_DEBUG
        bool "Enable debug output in CAAM driver"
        depends on CRYPTO_DEV_FSL_CAAM
index daca933a82ec9ea1c918a868516e859ffcdbca98..ba79d638f78200a189bda8763f2997222d60709d 100644 (file)
 #define AEAD_DESC_JOB_IO_LEN           (DESC_JOB_IO_LEN + CAAM_CMD_SZ * 2)
 #define GCM_DESC_JOB_IO_LEN            (AEAD_DESC_JOB_IO_LEN + \
                                         CAAM_CMD_SZ * 4)
+#define AUTHENC_DESC_JOB_IO_LEN                (AEAD_DESC_JOB_IO_LEN + \
+                                        CAAM_CMD_SZ * 5)
 
 /* length of descriptors text */
 #define DESC_AEAD_BASE                 (4 * CAAM_CMD_SZ)
-#define DESC_AEAD_ENC_LEN              (DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
-#define DESC_AEAD_DEC_LEN              (DESC_AEAD_BASE + 18 * CAAM_CMD_SZ)
-#define DESC_AEAD_GIVENC_LEN           (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+#define DESC_AEAD_ENC_LEN              (DESC_AEAD_BASE + 11 * CAAM_CMD_SZ)
+#define DESC_AEAD_DEC_LEN              (DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
+#define DESC_AEAD_GIVENC_LEN           (DESC_AEAD_ENC_LEN + 9 * CAAM_CMD_SZ)
 
 /* Note: Nonce is counted in enckeylen */
-#define DESC_AEAD_CTR_RFC3686_LEN      (6 * CAAM_CMD_SZ)
+#define DESC_AEAD_CTR_RFC3686_LEN      (4 * CAAM_CMD_SZ)
 
 #define DESC_AEAD_NULL_BASE            (3 * CAAM_CMD_SZ)
-#define DESC_AEAD_NULL_ENC_LEN         (DESC_AEAD_NULL_BASE + 14 * CAAM_CMD_SZ)
-#define DESC_AEAD_NULL_DEC_LEN         (DESC_AEAD_NULL_BASE + 17 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_ENC_LEN         (DESC_AEAD_NULL_BASE + 11 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_DEC_LEN         (DESC_AEAD_NULL_BASE + 13 * CAAM_CMD_SZ)
 
 #define DESC_GCM_BASE                  (3 * CAAM_CMD_SZ)
 #define DESC_GCM_ENC_LEN               (DESC_GCM_BASE + 16 * CAAM_CMD_SZ)
 #define DESC_GCM_DEC_LEN               (DESC_GCM_BASE + 12 * CAAM_CMD_SZ)
 
 #define DESC_RFC4106_BASE              (3 * CAAM_CMD_SZ)
-#define DESC_RFC4106_ENC_LEN           (DESC_RFC4106_BASE + 10 * CAAM_CMD_SZ)
-#define DESC_RFC4106_DEC_LEN           (DESC_RFC4106_BASE + 10 * CAAM_CMD_SZ)
+#define DESC_RFC4106_ENC_LEN           (DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ)
+#define DESC_RFC4106_DEC_LEN           (DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ)
 
 #define DESC_RFC4543_BASE              (3 * CAAM_CMD_SZ)
 #define DESC_RFC4543_ENC_LEN           (DESC_RFC4543_BASE + 11 * CAAM_CMD_SZ)
 #endif
 static struct list_head alg_list;
 
+struct caam_alg_entry {
+       int class1_alg_type;
+       int class2_alg_type;
+       int alg_op;
+       bool rfc3686;
+       bool geniv;
+};
+
+struct caam_aead_alg {
+       struct aead_alg aead;
+       struct caam_alg_entry caam;
+       bool registered;
+};
+
 /* Set DK bit in class 1 operation if shared */
 static inline void append_dec_op1(u32 *desc, u32 type)
 {
@@ -144,18 +160,6 @@ static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
                             KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
 }
 
-/*
- * For aead encrypt and decrypt, read iv for both classes
- */
-static inline void aead_append_ld_iv(u32 *desc, int ivsize, int ivoffset)
-{
-       append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
-                       LDST_SRCDST_BYTE_CONTEXT |
-                       (ivoffset << LDST_OFFSET_SHIFT));
-       append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO |
-                   (ivoffset << MOVE_OFFSET_SHIFT) | ivsize);
-}
-
 /*
  * For ablkcipher encrypt and decrypt, read from req->src and
  * write to req->dst
@@ -169,13 +173,6 @@ static inline void ablkcipher_append_src_dst(u32 *desc)
        append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
 }
 
-/*
- * If all data, including src (with assoc and iv) or dst (with iv only) are
- * contiguous
- */
-#define GIV_SRC_CONTIG         1
-#define GIV_DST_CONTIG         (1 << 1)
-
 /*
  * per-session context
  */
@@ -259,7 +256,6 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
 
 static int aead_null_set_sh_desc(struct crypto_aead *aead)
 {
-       unsigned int ivsize = crypto_aead_ivsize(aead);
        struct caam_ctx *ctx = crypto_aead_ctx(aead);
        struct device *jrdev = ctx->jrdev;
        bool keys_fit_inline = false;
@@ -270,11 +266,11 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead)
         * Job Descriptor and Shared Descriptors
         * must all fit into the 64-word Descriptor h/w Buffer
         */
-       if (DESC_AEAD_NULL_ENC_LEN + DESC_JOB_IO_LEN +
+       if (DESC_AEAD_NULL_ENC_LEN + AEAD_DESC_JOB_IO_LEN +
            ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
                keys_fit_inline = true;
 
-       /* old_aead_encrypt shared descriptor */
+       /* aead_encrypt shared descriptor */
        desc = ctx->sh_desc_enc;
 
        init_sh_desc(desc, HDR_SHARE_SERIAL);
@@ -291,20 +287,10 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead)
                           KEY_DEST_MDHA_SPLIT | KEY_ENC);
        set_jump_tgt_here(desc, key_jump_cmd);
 
-       /* cryptlen = seqoutlen - authsize */
-       append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
-
-       /*
-        * NULL encryption; IV is zero
-        * assoclen = (assoclen + cryptlen) - cryptlen
-        */
-       append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
-
-       /* read assoc before reading payload */
-       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
-                            KEY_VLF);
+       /* assoclen + cryptlen = seqinlen */
+       append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
 
-       /* Prepare to read and write cryptlen bytes */
+       /* Prepare to read and write cryptlen + assoclen bytes */
        append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
        append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
@@ -363,7 +349,7 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead)
 
        desc = ctx->sh_desc_dec;
 
-       /* old_aead_decrypt shared descriptor */
+       /* aead_decrypt shared descriptor */
        init_sh_desc(desc, HDR_SHARE_SERIAL);
 
        /* Skip if already shared */
@@ -382,18 +368,10 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead)
        append_operation(desc, ctx->class2_alg_type |
                         OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
 
-       /* assoclen + cryptlen = seqinlen - ivsize - authsize */
-       append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
-                               ctx->authsize + ivsize);
-       /* assoclen = (assoclen + cryptlen) - cryptlen */
+       /* assoclen + cryptlen = seqoutlen */
        append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-       append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
 
-       /* read assoc before reading payload */
-       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
-                            KEY_VLF);
-
-       /* Prepare to read and write cryptlen bytes */
+       /* Prepare to read and write cryptlen + assoclen bytes */
        append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
        append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
 
@@ -450,10 +428,10 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead)
 
 static int aead_set_sh_desc(struct crypto_aead *aead)
 {
+       struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead),
+                                                struct caam_aead_alg, aead);
        unsigned int ivsize = crypto_aead_ivsize(aead);
        struct caam_ctx *ctx = crypto_aead_ctx(aead);
-       struct crypto_tfm *ctfm = crypto_aead_tfm(aead);
-       const char *alg_name = crypto_tfm_alg_name(ctfm);
        struct device *jrdev = ctx->jrdev;
        bool keys_fit_inline;
        u32 geniv, moveiv;
@@ -461,11 +439,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        u32 *desc;
        const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) ==
                               OP_ALG_AAI_CTR_MOD128);
-       const bool is_rfc3686 = (ctr_mode &&
-                                (strstr(alg_name, "rfc3686") != NULL));
-
-       if (!ctx->authsize)
-               return 0;
+       const bool is_rfc3686 = alg->caam.rfc3686;
 
        /* NULL encryption / decryption */
        if (!ctx->enckeylen)
@@ -486,18 +460,21 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        if (is_rfc3686)
                ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE;
 
+       if (alg->caam.geniv)
+               goto skip_enc;
+
        /*
         * Job Descriptor and Shared Descriptors
         * must all fit into the 64-word Descriptor h/w Buffer
         */
        keys_fit_inline = false;
-       if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN +
+       if (DESC_AEAD_ENC_LEN + AUTHENC_DESC_JOB_IO_LEN +
            ctx->split_key_pad_len + ctx->enckeylen +
            (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0) <=
            CAAM_DESC_BYTES_MAX)
                keys_fit_inline = true;
 
-       /* old_aead_encrypt shared descriptor */
+       /* aead_encrypt shared descriptor */
        desc = ctx->sh_desc_enc;
 
        /* Note: Context registers are saved. */
@@ -507,19 +484,16 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        append_operation(desc, ctx->class2_alg_type |
                         OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
 
-       /* cryptlen = seqoutlen - authsize */
-       append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
-
-       /* assoclen + cryptlen = seqinlen - ivsize */
-       append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, ivsize);
+       /* Read and write assoclen bytes */
+       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
-       /* assoclen = (assoclen + cryptlen) - cryptlen */
-       append_math_sub(desc, VARSEQINLEN, REG2, REG3, CAAM_CMD_SZ);
+       /* Skip assoc data */
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
 
        /* read assoc before reading payload */
        append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
-                            KEY_VLF);
-       aead_append_ld_iv(desc, ivsize, ctx1_iv_off);
+                                     FIFOLDST_VLF);
 
        /* Load Counter into CONTEXT1 reg */
        if (is_rfc3686)
@@ -534,8 +508,8 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
                         OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
 
        /* Read and write cryptlen bytes */
-       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-       append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
        aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
 
        /* Write ICV */
@@ -555,18 +529,19 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
                       desc_bytes(desc), 1);
 #endif
 
+skip_enc:
        /*
         * Job Descriptor and Shared Descriptors
         * must all fit into the 64-word Descriptor h/w Buffer
         */
        keys_fit_inline = false;
-       if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN +
+       if (DESC_AEAD_DEC_LEN + AUTHENC_DESC_JOB_IO_LEN +
            ctx->split_key_pad_len + ctx->enckeylen +
            (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0) <=
            CAAM_DESC_BYTES_MAX)
                keys_fit_inline = true;
 
-       /* old_aead_decrypt shared descriptor */
+       /* aead_decrypt shared descriptor */
        desc = ctx->sh_desc_dec;
 
        /* Note: Context registers are saved. */
@@ -576,19 +551,17 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        append_operation(desc, ctx->class2_alg_type |
                         OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
 
-       /* assoclen + cryptlen = seqinlen - ivsize - authsize */
-       append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
-                               ctx->authsize + ivsize);
-       /* assoclen = (assoclen + cryptlen) - cryptlen */
-       append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-       append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
+       /* Read and write assoclen bytes */
+       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+       /* Skip assoc data */
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
 
        /* read assoc before reading payload */
        append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
                             KEY_VLF);
 
-       aead_append_ld_iv(desc, ivsize, ctx1_iv_off);
-
        /* Load Counter into CONTEXT1 reg */
        if (is_rfc3686)
                append_load_imm_u32(desc, be32_to_cpu(1), LDST_IMM |
@@ -605,8 +578,8 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
                append_dec_op1(desc, ctx->class1_alg_type);
 
        /* Read and write cryptlen bytes */
-       append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
-       append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
        aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
 
        /* Load ICV */
@@ -626,12 +599,15 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
                       desc_bytes(desc), 1);
 #endif
 
+       if (!alg->caam.geniv)
+               goto skip_givenc;
+
        /*
         * Job Descriptor and Shared Descriptors
         * must all fit into the 64-word Descriptor h/w Buffer
         */
        keys_fit_inline = false;
-       if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN +
+       if (DESC_AEAD_GIVENC_LEN + AUTHENC_DESC_JOB_IO_LEN +
            ctx->split_key_pad_len + ctx->enckeylen +
            (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0) <=
            CAAM_DESC_BYTES_MAX)
@@ -643,6 +619,9 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        /* Note: Context registers are saved. */
        init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
 
+       if (is_rfc3686)
+               goto copy_iv;
+
        /* Generate IV */
        geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
                NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
@@ -656,6 +635,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
                    (ivsize << MOVE_LEN_SHIFT));
        append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
 
+copy_iv:
        /* Copy IV to class 1 context */
        append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO |
                    (ctx1_iv_off << MOVE_OFFSET_SHIFT) |
@@ -668,8 +648,12 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        /* ivsize + cryptlen = seqoutlen - authsize */
        append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
 
-       /* assoclen = seqinlen - (ivsize + cryptlen) */
-       append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+       /* Read and write assoclen bytes */
+       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+       append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+       /* Skip assoc data */
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
 
        /* read assoc before reading payload */
        append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
@@ -710,9 +694,9 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
        append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
                         LDST_SRCDST_BYTE_CONTEXT);
 
-       ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc,
-                                                desc_bytes(desc),
-                                                DMA_TO_DEVICE);
+       ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+                                             desc_bytes(desc),
+                                             DMA_TO_DEVICE);
        if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
                dev_err(jrdev, "unable to map shared descriptor\n");
                return -ENOMEM;
@@ -723,6 +707,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
                       desc_bytes(desc), 1);
 #endif
 
+skip_givenc:
        return 0;
 }
 
@@ -976,22 +961,28 @@ static int rfc4106_set_sh_desc(struct crypto_aead *aead)
        append_operation(desc, ctx->class1_alg_type |
                         OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
 
-       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+       append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
        append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
-       /* Skip assoc data */
-       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
        /* Read assoc data */
        append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
                             FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
 
-       /* cryptlen = seqoutlen - assoclen */
-       append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+       /* Skip IV */
+       append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
 
        /* Will read cryptlen bytes */
        append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
 
+       /* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
+       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
+
+       /* Skip assoc data */
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+       /* cryptlen = seqoutlen - assoclen */
+       append_math_sub(desc, VARSEQOUTLEN, VARSEQINLEN, REG0, CAAM_CMD_SZ);
+
        /* Write encrypted data */
        append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
 
@@ -1044,21 +1035,27 @@ static int rfc4106_set_sh_desc(struct crypto_aead *aead)
        append_operation(desc, ctx->class1_alg_type |
                         OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
 
-       append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+       append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
        append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 
-       /* Skip assoc data */
-       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
        /* Read assoc data */
        append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
                             FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
 
-       /* Will write cryptlen bytes */
-       append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+       /* Skip IV */
+       append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
 
        /* Will read cryptlen bytes */
-       append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+       append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG3, CAAM_CMD_SZ);
+
+       /* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
+       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
+
+       /* Skip assoc data */
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+       /* Will write cryptlen bytes */
+       append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
 
        /* Store payload data */
        append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
@@ -1793,22 +1790,6 @@ static void aead_unmap(struct device *dev,
                   edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
 }
 
-static void old_aead_unmap(struct device *dev,
-                          struct aead_edesc *edesc,
-                          struct aead_request *req)
-{
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       int ivsize = crypto_aead_ivsize(aead);
-
-       dma_unmap_sg_chained(dev, req->assoc, edesc->assoc_nents,
-                            DMA_TO_DEVICE, edesc->assoc_chained);
-
-       caam_unmap(dev, req->src, req->dst,
-                  edesc->src_nents, edesc->src_chained, edesc->dst_nents,
-                  edesc->dst_chained, edesc->iv_dma, ivsize,
-                  edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
-}
-
 static void ablkcipher_unmap(struct device *dev,
                             struct ablkcipher_edesc *edesc,
                             struct ablkcipher_request *req)
@@ -1844,45 +1825,6 @@ static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
        aead_request_complete(req, err);
 }
 
-static void old_aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
-                                 void *context)
-{
-       struct aead_request *req = context;
-       struct aead_edesc *edesc;
-#ifdef DEBUG
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct caam_ctx *ctx = crypto_aead_ctx(aead);
-       int ivsize = crypto_aead_ivsize(aead);
-
-       dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
-#endif
-
-       edesc = (struct aead_edesc *)((char *)desc -
-                offsetof(struct aead_edesc, hw_desc));
-
-       if (err)
-               caam_jr_strstatus(jrdev, err);
-
-       old_aead_unmap(jrdev, edesc, req);
-
-#ifdef DEBUG
-       print_hex_dump(KERN_ERR, "assoc  @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
-                      req->assoclen , 1);
-       print_hex_dump(KERN_ERR, "dstiv  @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src) - ivsize,
-                      edesc->src_nents ? 100 : ivsize, 1);
-       print_hex_dump(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
-                      edesc->src_nents ? 100 : req->cryptlen +
-                      ctx->authsize + 4, 1);
-#endif
-
-       kfree(edesc);
-
-       aead_request_complete(req, err);
-}
-
 static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
                                   void *context)
 {
@@ -1911,62 +1853,6 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
        aead_request_complete(req, err);
 }
 
-static void old_aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
-                                 void *context)
-{
-       struct aead_request *req = context;
-       struct aead_edesc *edesc;
-#ifdef DEBUG
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct caam_ctx *ctx = crypto_aead_ctx(aead);
-       int ivsize = crypto_aead_ivsize(aead);
-
-       dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
-#endif
-
-       edesc = (struct aead_edesc *)((char *)desc -
-                offsetof(struct aead_edesc, hw_desc));
-
-#ifdef DEBUG
-       print_hex_dump(KERN_ERR, "dstiv  @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
-                      ivsize, 1);
-       print_hex_dump(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
-                      req->cryptlen - ctx->authsize, 1);
-#endif
-
-       if (err)
-               caam_jr_strstatus(jrdev, err);
-
-       old_aead_unmap(jrdev, edesc, req);
-
-       /*
-        * verify hw auth check passed else return -EBADMSG
-        */
-       if ((err & JRSTA_CCBERR_ERRID_MASK) == JRSTA_CCBERR_ERRID_ICVCHK)
-               err = -EBADMSG;
-
-#ifdef DEBUG
-       print_hex_dump(KERN_ERR, "iphdrout@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4,
-                      ((char *)sg_virt(req->assoc) - sizeof(struct iphdr)),
-                      sizeof(struct iphdr) + req->assoclen +
-                      ((req->cryptlen > 1500) ? 1500 : req->cryptlen) +
-                      ctx->authsize + 36, 1);
-       if (!err && edesc->sec4_sg_bytes) {
-               struct scatterlist *sg = sg_last(req->src, edesc->src_nents);
-               print_hex_dump(KERN_ERR, "sglastout@"__stringify(__LINE__)": ",
-                              DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(sg),
-                       sg->length + ctx->authsize + 16, 1);
-       }
-#endif
-
-       kfree(edesc);
-
-       aead_request_complete(req, err);
-}
-
 static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
                                   void *context)
 {
@@ -2032,91 +1918,6 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
        ablkcipher_request_complete(req, err);
 }
 
-/*
- * Fill in aead job descriptor
- */
-static void old_init_aead_job(u32 *sh_desc, dma_addr_t ptr,
-                             struct aead_edesc *edesc,
-                             struct aead_request *req,
-                             bool all_contig, bool encrypt)
-{
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct caam_ctx *ctx = crypto_aead_ctx(aead);
-       int ivsize = crypto_aead_ivsize(aead);
-       int authsize = ctx->authsize;
-       u32 *desc = edesc->hw_desc;
-       u32 out_options = 0, in_options;
-       dma_addr_t dst_dma, src_dma;
-       int len, sec4_sg_index = 0;
-       bool is_gcm = false;
-
-#ifdef DEBUG
-       debug("assoclen %d cryptlen %d authsize %d\n",
-             req->assoclen, req->cryptlen, authsize);
-       print_hex_dump(KERN_ERR, "assoc  @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
-                      req->assoclen , 1);
-       print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
-                      edesc->src_nents ? 100 : ivsize, 1);
-       print_hex_dump(KERN_ERR, "src    @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
-                       edesc->src_nents ? 100 : req->cryptlen, 1);
-       print_hex_dump(KERN_ERR, "shrdesc@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
-                      desc_bytes(sh_desc), 1);
-#endif
-
-       if (((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) ==
-             OP_ALG_ALGSEL_AES) &&
-           ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_GCM))
-               is_gcm = true;
-
-       len = desc_len(sh_desc);
-       init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
-
-       if (all_contig) {
-               if (is_gcm)
-                       src_dma = edesc->iv_dma;
-               else
-                       src_dma = sg_dma_address(req->assoc);
-               in_options = 0;
-       } else {
-               src_dma = edesc->sec4_sg_dma;
-               sec4_sg_index += (edesc->assoc_nents ? : 1) + 1 +
-                                (edesc->src_nents ? : 1);
-               in_options = LDST_SGF;
-       }
-
-       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
-                         in_options);
-
-       if (likely(req->src == req->dst)) {
-               if (all_contig) {
-                       dst_dma = sg_dma_address(req->src);
-               } else {
-                       dst_dma = src_dma + sizeof(struct sec4_sg_entry) *
-                                 ((edesc->assoc_nents ? : 1) + 1);
-                       out_options = LDST_SGF;
-               }
-       } else {
-               if (!edesc->dst_nents) {
-                       dst_dma = sg_dma_address(req->dst);
-               } else {
-                       dst_dma = edesc->sec4_sg_dma +
-                                 sec4_sg_index *
-                                 sizeof(struct sec4_sg_entry);
-                       out_options = LDST_SGF;
-               }
-       }
-       if (encrypt)
-               append_seq_out_ptr(desc, dst_dma, req->cryptlen + authsize,
-                                  out_options);
-       else
-               append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
-                                  out_options);
-}
-
 /*
  * Fill in aead job descriptor
  */
@@ -2208,80 +2009,43 @@ static void init_gcm_job(struct aead_request *req,
        /* End of blank commands */
 }
 
-/*
- * Fill in aead givencrypt job descriptor
- */
-static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
-                             struct aead_edesc *edesc,
-                             struct aead_request *req,
-                             int contig)
+static void init_authenc_job(struct aead_request *req,
+                            struct aead_edesc *edesc,
+                            bool all_contig, bool encrypt)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
+       struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead),
+                                                struct caam_aead_alg, aead);
+       unsigned int ivsize = crypto_aead_ivsize(aead);
        struct caam_ctx *ctx = crypto_aead_ctx(aead);
-       int ivsize = crypto_aead_ivsize(aead);
-       int authsize = ctx->authsize;
+       const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) ==
+                              OP_ALG_AAI_CTR_MOD128);
+       const bool is_rfc3686 = alg->caam.rfc3686;
        u32 *desc = edesc->hw_desc;
-       u32 out_options = 0, in_options;
-       dma_addr_t dst_dma, src_dma;
-       int len, sec4_sg_index = 0;
-       bool is_gcm = false;
+       u32 ivoffset = 0;
 
-#ifdef DEBUG
-       debug("assoclen %d cryptlen %d authsize %d\n",
-             req->assoclen, req->cryptlen, authsize);
-       print_hex_dump(KERN_ERR, "assoc  @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
-                      req->assoclen , 1);
-       print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, req->iv, ivsize, 1);
-       print_hex_dump(KERN_ERR, "src    @"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
-                       edesc->src_nents > 1 ? 100 : req->cryptlen, 1);
-       print_hex_dump(KERN_ERR, "shrdesc@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
-                      desc_bytes(sh_desc), 1);
-#endif
+       /*
+        * AES-CTR needs to load IV in CONTEXT1 reg
+        * at an offset of 128bits (16bytes)
+        * CONTEXT1[255:128] = IV
+        */
+       if (ctr_mode)
+               ivoffset = 16;
 
-       if (((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) ==
-             OP_ALG_ALGSEL_AES) &&
-           ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_GCM))
-               is_gcm = true;
+       /*
+        * RFC3686 specific:
+        *      CONTEXT1[255:128] = {NONCE, IV, COUNTER}
+        */
+       if (is_rfc3686)
+               ivoffset = 16 + CTR_RFC3686_NONCE_SIZE;
 
-       len = desc_len(sh_desc);
-       init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
+       init_aead_job(req, edesc, all_contig, encrypt);
 
-       if (contig & GIV_SRC_CONTIG) {
-               if (is_gcm)
-                       src_dma = edesc->iv_dma;
-               else
-                       src_dma = sg_dma_address(req->assoc);
-               in_options = 0;
-       } else {
-               src_dma = edesc->sec4_sg_dma;
-               sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents;
-               in_options = LDST_SGF;
-       }
-       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
-                         in_options);
-
-       if (contig & GIV_DST_CONTIG) {
-               dst_dma = edesc->iv_dma;
-       } else {
-               if (likely(req->src == req->dst)) {
-                       dst_dma = src_dma + sizeof(struct sec4_sg_entry) *
-                                 (edesc->assoc_nents +
-                                  (is_gcm ? 1 + edesc->src_nents : 0));
-                       out_options = LDST_SGF;
-               } else {
-                       dst_dma = edesc->sec4_sg_dma +
-                                 sec4_sg_index *
-                                 sizeof(struct sec4_sg_entry);
-                       out_options = LDST_SGF;
-               }
-       }
-
-       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen + authsize,
-                          out_options);
+       if (ivsize && (is_rfc3686 || !(alg->caam.geniv && encrypt)))
+               append_load_as_imm(desc, req->iv, ivsize,
+                                  LDST_CLASS_1_CCB |
+                                  LDST_SRCDST_BYTE_CONTEXT |
+                                  (ivoffset << LDST_OFFSET_SHIFT));
 }
 
 /*
@@ -2389,150 +2153,6 @@ static void init_ablkcipher_giv_job(u32 *sh_desc, dma_addr_t ptr,
        append_seq_out_ptr(desc, dst_dma, req->nbytes + ivsize, out_options);
 }
 
-/*
- * allocate and map the aead extended descriptor
- */
-static struct aead_edesc *old_aead_edesc_alloc(struct aead_request *req,
-                                              int desc_bytes,
-                                              bool *all_contig_ptr,
-                                              bool encrypt)
-{
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct caam_ctx *ctx = crypto_aead_ctx(aead);
-       struct device *jrdev = ctx->jrdev;
-       gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
-                      CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
-       int assoc_nents, src_nents, dst_nents = 0;
-       struct aead_edesc *edesc;
-       dma_addr_t iv_dma = 0;
-       int sgc;
-       bool all_contig = true;
-       bool assoc_chained = false, src_chained = false, dst_chained = false;
-       int ivsize = crypto_aead_ivsize(aead);
-       int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
-       unsigned int authsize = ctx->authsize;
-       bool is_gcm = false;
-
-       assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
-
-       if (unlikely(req->dst != req->src)) {
-               src_nents = sg_count(req->src, req->cryptlen, &src_chained);
-               dst_nents = sg_count(req->dst,
-                                    req->cryptlen +
-                                       (encrypt ? authsize : (-authsize)),
-                                    &dst_chained);
-       } else {
-               src_nents = sg_count(req->src,
-                                    req->cryptlen +
-                                       (encrypt ? authsize : 0),
-                                    &src_chained);
-       }
-
-       sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
-                                DMA_TO_DEVICE, assoc_chained);
-       if (likely(req->src == req->dst)) {
-               sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
-                                        DMA_BIDIRECTIONAL, src_chained);
-       } else {
-               sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
-                                        DMA_TO_DEVICE, src_chained);
-               sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
-                                        DMA_FROM_DEVICE, dst_chained);
-       }
-
-       iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, iv_dma)) {
-               dev_err(jrdev, "unable to map IV\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       if (((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) ==
-             OP_ALG_ALGSEL_AES) &&
-           ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_GCM))
-               is_gcm = true;
-
-       /*
-        * Check if data are contiguous.
-        * GCM expected input sequence: IV, AAD, text
-        * All other - expected input sequence: AAD, IV, text
-        */
-       if (is_gcm)
-               all_contig = (!assoc_nents &&
-                             iv_dma + ivsize == sg_dma_address(req->assoc) &&
-                             !src_nents && sg_dma_address(req->assoc) +
-                             req->assoclen == sg_dma_address(req->src));
-       else
-               all_contig = (!assoc_nents && sg_dma_address(req->assoc) +
-                             req->assoclen == iv_dma && !src_nents &&
-                             iv_dma + ivsize == sg_dma_address(req->src));
-       if (!all_contig) {
-               assoc_nents = assoc_nents ? : 1;
-               src_nents = src_nents ? : 1;
-               sec4_sg_len = assoc_nents + 1 + src_nents;
-       }
-
-       sec4_sg_len += dst_nents;
-
-       sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
-
-       /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
-                       sec4_sg_bytes, GFP_DMA | flags);
-       if (!edesc) {
-               dev_err(jrdev, "could not allocate extended descriptor\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       edesc->assoc_nents = assoc_nents;
-       edesc->assoc_chained = assoc_chained;
-       edesc->src_nents = src_nents;
-       edesc->src_chained = src_chained;
-       edesc->dst_nents = dst_nents;
-       edesc->dst_chained = dst_chained;
-       edesc->iv_dma = iv_dma;
-       edesc->sec4_sg_bytes = sec4_sg_bytes;
-       edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
-                        desc_bytes;
-       *all_contig_ptr = all_contig;
-
-       sec4_sg_index = 0;
-       if (!all_contig) {
-               if (!is_gcm) {
-                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
-                                         edesc->sec4_sg + sec4_sg_index);
-                       sec4_sg_index += assoc_nents;
-               }
-
-               dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
-                                  iv_dma, ivsize, 0);
-               sec4_sg_index += 1;
-
-               if (is_gcm) {
-                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
-                                         edesc->sec4_sg + sec4_sg_index);
-                       sec4_sg_index += assoc_nents;
-               }
-
-               sg_to_sec4_sg_last(req->src,
-                                  src_nents,
-                                  edesc->sec4_sg +
-                                  sec4_sg_index, 0);
-               sec4_sg_index += src_nents;
-       }
-       if (dst_nents) {
-               sg_to_sec4_sg_last(req->dst, dst_nents,
-                                  edesc->sec4_sg + sec4_sg_index, 0);
-       }
-       edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-                                           sec4_sg_bytes, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
-               dev_err(jrdev, "unable to map S/G table\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       return edesc;
-}
-
 /*
  * allocate and map the aead extended descriptor
  */
@@ -2579,8 +2199,8 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
        sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kzalloc(sizeof(struct aead_edesc) + desc_bytes +
-                       sec4_sg_bytes, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return ERR_PTR(-ENOMEM);
@@ -2685,7 +2305,15 @@ static int gcm_encrypt(struct aead_request *req)
        return ret;
 }
 
-static int old_aead_encrypt(struct aead_request *req)
+static int ipsec_gcm_encrypt(struct aead_request *req)
+{
+       if (req->assoclen < 8)
+               return -EINVAL;
+
+       return gcm_encrypt(req);
+}
+
+static int aead_encrypt(struct aead_request *req)
 {
        struct aead_edesc *edesc;
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
@@ -2696,14 +2324,13 @@ static int old_aead_encrypt(struct aead_request *req)
        int ret = 0;
 
        /* allocate extended descriptor */
-       edesc = old_aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                    CAAM_CMD_SZ, &all_contig, true);
+       edesc = aead_edesc_alloc(req, AUTHENC_DESC_JOB_IO_LEN,
+                                &all_contig, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
        /* Create and submit job descriptor */
-       old_init_aead_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req,
-                         all_contig, true);
+       init_authenc_job(req, edesc, all_contig, true);
 #ifdef DEBUG
        print_hex_dump(KERN_ERR, "aead jobdesc@"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
@@ -2711,11 +2338,11 @@ static int old_aead_encrypt(struct aead_request *req)
 #endif
 
        desc = edesc->hw_desc;
-       ret = caam_jr_enqueue(jrdev, desc, old_aead_encrypt_done, req);
+       ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req);
        if (!ret) {
                ret = -EINPROGRESS;
        } else {
-               old_aead_unmap(jrdev, edesc, req);
+               aead_unmap(jrdev, edesc, req);
                kfree(edesc);
        }
 
@@ -2757,7 +2384,15 @@ static int gcm_decrypt(struct aead_request *req)
        return ret;
 }
 
-static int old_aead_decrypt(struct aead_request *req)
+static int ipsec_gcm_decrypt(struct aead_request *req)
+{
+       if (req->assoclen < 8)
+               return -EINVAL;
+
+       return gcm_decrypt(req);
+}
+
+static int aead_decrypt(struct aead_request *req)
 {
        struct aead_edesc *edesc;
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
@@ -2768,20 +2403,19 @@ static int old_aead_decrypt(struct aead_request *req)
        int ret = 0;
 
        /* allocate extended descriptor */
-       edesc = old_aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                    CAAM_CMD_SZ, &all_contig, false);
+       edesc = aead_edesc_alloc(req, AUTHENC_DESC_JOB_IO_LEN,
+                                &all_contig, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
 #ifdef DEBUG
        print_hex_dump(KERN_ERR, "dec src@"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
-                      req->cryptlen, 1);
+                      req->assoclen + req->cryptlen, 1);
 #endif
 
        /* Create and submit job descriptor*/
-       old_init_aead_job(ctx->sh_desc_dec,
-                         ctx->sh_desc_dec_dma, edesc, req, all_contig, false);
+       init_authenc_job(req, edesc, all_contig, false);
 #ifdef DEBUG
        print_hex_dump(KERN_ERR, "aead jobdesc@"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
@@ -2789,49 +2423,58 @@ static int old_aead_decrypt(struct aead_request *req)
 #endif
 
        desc = edesc->hw_desc;
-       ret = caam_jr_enqueue(jrdev, desc, old_aead_decrypt_done, req);
+       ret = caam_jr_enqueue(jrdev, desc, aead_decrypt_done, req);
        if (!ret) {
                ret = -EINPROGRESS;
        } else {
-               old_aead_unmap(jrdev, edesc, req);
+               aead_unmap(jrdev, edesc, req);
                kfree(edesc);
        }
 
        return ret;
 }
 
+static int aead_givdecrypt(struct aead_request *req)
+{
+       struct crypto_aead *aead = crypto_aead_reqtfm(req);
+       unsigned int ivsize = crypto_aead_ivsize(aead);
+
+       if (req->cryptlen < ivsize)
+               return -EINVAL;
+
+       req->cryptlen -= ivsize;
+       req->assoclen += ivsize;
+
+       return aead_decrypt(req);
+}
+
 /*
- * allocate and map the aead extended descriptor for aead givencrypt
+ * allocate and map the ablkcipher extended descriptor for ablkcipher
  */
-static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
-                                              *greq, int desc_bytes,
-                                              u32 *contig_ptr)
+static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
+                                                      *req, int desc_bytes,
+                                                      bool *iv_contig_out)
 {
-       struct aead_request *req = &greq->areq;
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct caam_ctx *ctx = crypto_aead_ctx(aead);
+       struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+       struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
        struct device *jrdev = ctx->jrdev;
        gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
-                      CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
-       int assoc_nents, src_nents, dst_nents = 0;
-       struct aead_edesc *edesc;
+                                         CRYPTO_TFM_REQ_MAY_SLEEP)) ?
+                      GFP_KERNEL : GFP_ATOMIC;
+       int src_nents, dst_nents = 0, sec4_sg_bytes;
+       struct ablkcipher_edesc *edesc;
        dma_addr_t iv_dma = 0;
+       bool iv_contig = false;
        int sgc;
-       u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG;
-       int ivsize = crypto_aead_ivsize(aead);
-       bool assoc_chained = false, src_chained = false, dst_chained = false;
-       int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
-       bool is_gcm = false;
+       int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+       bool src_chained = false, dst_chained = false;
+       int sec4_sg_index;
 
-       assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
-       src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+       src_nents = sg_count(req->src, req->nbytes, &src_chained);
 
-       if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen + ctx->authsize,
-                                    &dst_chained);
+       if (req->dst != req->src)
+               dst_nents = sg_count(req->dst, req->nbytes, &dst_chained);
 
-       sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
-                                DMA_TO_DEVICE, assoc_chained);
        if (likely(req->src == req->dst)) {
                sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
                                         DMA_BIDIRECTIONAL, src_chained);
@@ -2842,121 +2485,52 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
                                         DMA_FROM_DEVICE, dst_chained);
        }
 
-       iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE);
+       iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
        if (dma_mapping_error(jrdev, iv_dma)) {
                dev_err(jrdev, "unable to map IV\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       if (((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) ==
-             OP_ALG_ALGSEL_AES) &&
-           ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_GCM))
-               is_gcm = true;
-
        /*
-        * Check if data are contiguous.
-        * GCM expected input sequence: IV, AAD, text
-        * All other - expected input sequence: AAD, IV, text
+        * Check if iv can be contiguous with source and destination.
+        * If so, include it. If not, create scatterlist.
         */
-
-       if (is_gcm) {
-               if (assoc_nents || iv_dma + ivsize !=
-                   sg_dma_address(req->assoc) || src_nents ||
-                   sg_dma_address(req->assoc) + req->assoclen !=
-                   sg_dma_address(req->src))
-                       contig &= ~GIV_SRC_CONTIG;
-       } else {
-               if (assoc_nents ||
-                   sg_dma_address(req->assoc) + req->assoclen != iv_dma ||
-                   src_nents || iv_dma + ivsize != sg_dma_address(req->src))
-                       contig &= ~GIV_SRC_CONTIG;
-       }
-
-       if (dst_nents || iv_dma + ivsize != sg_dma_address(req->dst))
-               contig &= ~GIV_DST_CONTIG;
-
-       if (!(contig & GIV_SRC_CONTIG)) {
-               assoc_nents = assoc_nents ? : 1;
+       if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src))
+               iv_contig = true;
+       else
                src_nents = src_nents ? : 1;
-               sec4_sg_len += assoc_nents + 1 + src_nents;
-               if (req->src == req->dst &&
-                   (src_nents || iv_dma + ivsize != sg_dma_address(req->src)))
-                       contig &= ~GIV_DST_CONTIG;
-       }
-
-       /*
-        * Add new sg entries for GCM output sequence.
-        * Expected output sequence: IV, encrypted text.
-        */
-       if (is_gcm && req->src == req->dst && !(contig & GIV_DST_CONTIG))
-               sec4_sg_len += 1 + src_nents;
-
-       if (unlikely(req->src != req->dst)) {
-               dst_nents = dst_nents ? : 1;
-               sec4_sg_len += 1 + dst_nents;
-       }
-
-       sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
+       sec4_sg_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) *
+                       sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
-                       sec4_sg_bytes, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       edesc->assoc_nents = assoc_nents;
-       edesc->assoc_chained = assoc_chained;
        edesc->src_nents = src_nents;
        edesc->src_chained = src_chained;
        edesc->dst_nents = dst_nents;
        edesc->dst_chained = dst_chained;
-       edesc->iv_dma = iv_dma;
        edesc->sec4_sg_bytes = sec4_sg_bytes;
-       edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
+       edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
                         desc_bytes;
-       *contig_ptr = contig;
 
        sec4_sg_index = 0;
-       if (!(contig & GIV_SRC_CONTIG)) {
-               if (!is_gcm) {
-                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
-                                         edesc->sec4_sg + sec4_sg_index);
-                       sec4_sg_index += assoc_nents;
-               }
-
-               dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
-                                  iv_dma, ivsize, 0);
-               sec4_sg_index += 1;
-
-               if (is_gcm) {
-                       sg_to_sec4_sg_len(req->assoc, req->assoclen,
-                                         edesc->sec4_sg + sec4_sg_index);
-                       sec4_sg_index += assoc_nents;
-               }
-
-               sg_to_sec4_sg_last(req->src, src_nents,
-                                  edesc->sec4_sg +
-                                  sec4_sg_index, 0);
-               sec4_sg_index += src_nents;
-       }
-
-       if (is_gcm && req->src == req->dst && !(contig & GIV_DST_CONTIG)) {
-               dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
-                                  iv_dma, ivsize, 0);
-               sec4_sg_index += 1;
+       if (!iv_contig) {
+               dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
                sg_to_sec4_sg_last(req->src, src_nents,
-                                  edesc->sec4_sg + sec4_sg_index, 0);
+                                  edesc->sec4_sg + 1, 0);
+               sec4_sg_index += 1 + src_nents;
        }
 
-       if (unlikely(req->src != req->dst && !(contig & GIV_DST_CONTIG))) {
-               dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
-                                  iv_dma, ivsize, 0);
-               sec4_sg_index += 1;
+       if (dst_nents) {
                sg_to_sec4_sg_last(req->dst, dst_nents,
-                                  edesc->sec4_sg + sec4_sg_index, 0);
+                       edesc->sec4_sg + sec4_sg_index, 0);
        }
+
        edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
                                            sec4_sg_bytes, DMA_TO_DEVICE);
        if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
@@ -2964,201 +2538,58 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
                return ERR_PTR(-ENOMEM);
        }
 
+       edesc->iv_dma = iv_dma;
+
+#ifdef DEBUG
+       print_hex_dump(KERN_ERR, "ablkcipher sec4_sg@"__stringify(__LINE__)": ",
+                      DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg,
+                      sec4_sg_bytes, 1);
+#endif
+
+       *iv_contig_out = iv_contig;
        return edesc;
 }
 
-static int old_aead_givencrypt(struct aead_givcrypt_request *areq)
+static int ablkcipher_encrypt(struct ablkcipher_request *req)
 {
-       struct aead_request *req = &areq->areq;
-       struct aead_edesc *edesc;
-       struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct caam_ctx *ctx = crypto_aead_ctx(aead);
+       struct ablkcipher_edesc *edesc;
+       struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+       struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
        struct device *jrdev = ctx->jrdev;
-       u32 contig;
+       bool iv_contig;
        u32 *desc;
        int ret = 0;
 
        /* allocate extended descriptor */
-       edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
-                                    CAAM_CMD_SZ, &contig);
-
+       edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
+                                      CAAM_CMD_SZ, &iv_contig);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
-#ifdef DEBUG
-       print_hex_dump(KERN_ERR, "giv src@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
-                      req->cryptlen, 1);
-#endif
-
        /* Create and submit job descriptor*/
-       init_aead_giv_job(ctx->sh_desc_givenc,
-                         ctx->sh_desc_givenc_dma, edesc, req, contig);
+       init_ablkcipher_job(ctx->sh_desc_enc,
+               ctx->sh_desc_enc_dma, edesc, req, iv_contig);
 #ifdef DEBUG
-       print_hex_dump(KERN_ERR, "aead jobdesc@"__stringify(__LINE__)": ",
+       print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
                       desc_bytes(edesc->hw_desc), 1);
 #endif
-
        desc = edesc->hw_desc;
-       ret = caam_jr_enqueue(jrdev, desc, old_aead_encrypt_done, req);
+       ret = caam_jr_enqueue(jrdev, desc, ablkcipher_encrypt_done, req);
+
        if (!ret) {
                ret = -EINPROGRESS;
        } else {
-               old_aead_unmap(jrdev, edesc, req);
+               ablkcipher_unmap(jrdev, edesc, req);
                kfree(edesc);
        }
 
        return ret;
 }
 
-static int aead_null_givencrypt(struct aead_givcrypt_request *areq)
-{
-       return old_aead_encrypt(&areq->areq);
-}
-
-/*
- * allocate and map the ablkcipher extended descriptor for ablkcipher
- */
-static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
-                                                      *req, int desc_bytes,
-                                                      bool *iv_contig_out)
+static int ablkcipher_decrypt(struct ablkcipher_request *req)
 {
-       struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
-       struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
-       struct device *jrdev = ctx->jrdev;
-       gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
-                                         CRYPTO_TFM_REQ_MAY_SLEEP)) ?
-                      GFP_KERNEL : GFP_ATOMIC;
-       int src_nents, dst_nents = 0, sec4_sg_bytes;
-       struct ablkcipher_edesc *edesc;
-       dma_addr_t iv_dma = 0;
-       bool iv_contig = false;
-       int sgc;
-       int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
-       bool src_chained = false, dst_chained = false;
-       int sec4_sg_index;
-
-       src_nents = sg_count(req->src, req->nbytes, &src_chained);
-
-       if (req->dst != req->src)
-               dst_nents = sg_count(req->dst, req->nbytes, &dst_chained);
-
-       if (likely(req->src == req->dst)) {
-               sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
-                                        DMA_BIDIRECTIONAL, src_chained);
-       } else {
-               sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
-                                        DMA_TO_DEVICE, src_chained);
-               sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
-                                        DMA_FROM_DEVICE, dst_chained);
-       }
-
-       iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, iv_dma)) {
-               dev_err(jrdev, "unable to map IV\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       /*
-        * Check if iv can be contiguous with source and destination.
-        * If so, include it. If not, create scatterlist.
-        */
-       if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src))
-               iv_contig = true;
-       else
-               src_nents = src_nents ? : 1;
-       sec4_sg_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) *
-                       sizeof(struct sec4_sg_entry);
-
-       /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct ablkcipher_edesc) + desc_bytes +
-                       sec4_sg_bytes, GFP_DMA | flags);
-       if (!edesc) {
-               dev_err(jrdev, "could not allocate extended descriptor\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       edesc->src_nents = src_nents;
-       edesc->src_chained = src_chained;
-       edesc->dst_nents = dst_nents;
-       edesc->dst_chained = dst_chained;
-       edesc->sec4_sg_bytes = sec4_sg_bytes;
-       edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
-                        desc_bytes;
-
-       sec4_sg_index = 0;
-       if (!iv_contig) {
-               dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
-               sg_to_sec4_sg_last(req->src, src_nents,
-                                  edesc->sec4_sg + 1, 0);
-               sec4_sg_index += 1 + src_nents;
-       }
-
-       if (dst_nents) {
-               sg_to_sec4_sg_last(req->dst, dst_nents,
-                       edesc->sec4_sg + sec4_sg_index, 0);
-       }
-
-       edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
-                                           sec4_sg_bytes, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
-               dev_err(jrdev, "unable to map S/G table\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
-       edesc->iv_dma = iv_dma;
-
-#ifdef DEBUG
-       print_hex_dump(KERN_ERR, "ablkcipher sec4_sg@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg,
-                      sec4_sg_bytes, 1);
-#endif
-
-       *iv_contig_out = iv_contig;
-       return edesc;
-}
-
-static int ablkcipher_encrypt(struct ablkcipher_request *req)
-{
-       struct ablkcipher_edesc *edesc;
-       struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
-       struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
-       struct device *jrdev = ctx->jrdev;
-       bool iv_contig;
-       u32 *desc;
-       int ret = 0;
-
-       /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                      CAAM_CMD_SZ, &iv_contig);
-       if (IS_ERR(edesc))
-               return PTR_ERR(edesc);
-
-       /* Create and submit job descriptor*/
-       init_ablkcipher_job(ctx->sh_desc_enc,
-               ctx->sh_desc_enc_dma, edesc, req, iv_contig);
-#ifdef DEBUG
-       print_hex_dump(KERN_ERR, "ablkcipher jobdesc@"__stringify(__LINE__)": ",
-                      DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
-                      desc_bytes(edesc->hw_desc), 1);
-#endif
-       desc = edesc->hw_desc;
-       ret = caam_jr_enqueue(jrdev, desc, ablkcipher_encrypt_done, req);
-
-       if (!ret) {
-               ret = -EINPROGRESS;
-       } else {
-               ablkcipher_unmap(jrdev, edesc, req);
-               kfree(edesc);
-       }
-
-       return ret;
-}
-
-static int ablkcipher_decrypt(struct ablkcipher_request *req)
-{
-       struct ablkcipher_edesc *edesc;
+       struct ablkcipher_edesc *edesc;
        struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
        struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
        struct device *jrdev = ctx->jrdev;
@@ -3251,8 +2682,8 @@ static struct ablkcipher_edesc *ablkcipher_giv_edesc_alloc(
                        sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(*edesc) + desc_bytes +
-                       sec4_sg_bytes, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + desc_bytes + sec4_sg_bytes,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return ERR_PTR(-ENOMEM);
@@ -3347,7 +2778,6 @@ struct caam_alg_template {
        u32 type;
        union {
                struct ablkcipher_alg ablkcipher;
-               struct old_aead_alg aead;
        } template_u;
        u32 class1_alg_type;
        u32 class2_alg_type;
@@ -3355,753 +2785,1426 @@ struct caam_alg_template {
 };
 
 static struct caam_alg_template driver_algs[] = {
-       /* single-pass ipsec_esp descriptor */
-       {
-               .name = "authenc(hmac(md5),ecb(cipher_null))",
-               .driver_name = "authenc-hmac-md5-ecb-cipher_null-caam",
-               .blocksize = NULL_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = aead_null_givencrypt,
-                       .geniv = "<built-in>",
-                       .ivsize = NULL_IV_SIZE,
-                       .maxauthsize = MD5_DIGEST_SIZE,
-                       },
-               .class1_alg_type = 0,
-               .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
-       },
+       /* ablkcipher descriptor */
        {
-               .name = "authenc(hmac(sha1),ecb(cipher_null))",
-               .driver_name = "authenc-hmac-sha1-ecb-cipher_null-caam",
-               .blocksize = NULL_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = aead_null_givencrypt,
+               .name = "cbc(aes)",
+               .driver_name = "cbc-aes-caam",
+               .blocksize = AES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
+               .template_ablkcipher = {
+                       .setkey = ablkcipher_setkey,
+                       .encrypt = ablkcipher_encrypt,
+                       .decrypt = ablkcipher_decrypt,
+                       .givencrypt = ablkcipher_givencrypt,
                        .geniv = "<built-in>",
-                       .ivsize = NULL_IV_SIZE,
-                       .maxauthsize = SHA1_DIGEST_SIZE,
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = 0,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
        },
        {
-               .name = "authenc(hmac(sha224),ecb(cipher_null))",
-               .driver_name = "authenc-hmac-sha224-ecb-cipher_null-caam",
-               .blocksize = NULL_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = aead_null_givencrypt,
+               .name = "cbc(des3_ede)",
+               .driver_name = "cbc-3des-caam",
+               .blocksize = DES3_EDE_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
+               .template_ablkcipher = {
+                       .setkey = ablkcipher_setkey,
+                       .encrypt = ablkcipher_encrypt,
+                       .decrypt = ablkcipher_decrypt,
+                       .givencrypt = ablkcipher_givencrypt,
                        .geniv = "<built-in>",
-                       .ivsize = NULL_IV_SIZE,
-                       .maxauthsize = SHA224_DIGEST_SIZE,
+                       .min_keysize = DES3_EDE_KEY_SIZE,
+                       .max_keysize = DES3_EDE_KEY_SIZE,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = 0,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
        },
        {
-               .name = "authenc(hmac(sha256),ecb(cipher_null))",
-               .driver_name = "authenc-hmac-sha256-ecb-cipher_null-caam",
-               .blocksize = NULL_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = aead_null_givencrypt,
+               .name = "cbc(des)",
+               .driver_name = "cbc-des-caam",
+               .blocksize = DES_BLOCK_SIZE,
+               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
+               .template_ablkcipher = {
+                       .setkey = ablkcipher_setkey,
+                       .encrypt = ablkcipher_encrypt,
+                       .decrypt = ablkcipher_decrypt,
+                       .givencrypt = ablkcipher_givencrypt,
                        .geniv = "<built-in>",
-                       .ivsize = NULL_IV_SIZE,
-                       .maxauthsize = SHA256_DIGEST_SIZE,
+                       .min_keysize = DES_KEY_SIZE,
+                       .max_keysize = DES_KEY_SIZE,
+                       .ivsize = DES_BLOCK_SIZE,
                        },
-               .class1_alg_type = 0,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
        },
        {
-               .name = "authenc(hmac(sha384),ecb(cipher_null))",
-               .driver_name = "authenc-hmac-sha384-ecb-cipher_null-caam",
-               .blocksize = NULL_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = aead_null_givencrypt,
-                       .geniv = "<built-in>",
-                       .ivsize = NULL_IV_SIZE,
-                       .maxauthsize = SHA384_DIGEST_SIZE,
+               .name = "ctr(aes)",
+               .driver_name = "ctr-aes-caam",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .template_ablkcipher = {
+                       .setkey = ablkcipher_setkey,
+                       .encrypt = ablkcipher_encrypt,
+                       .decrypt = ablkcipher_decrypt,
+                       .geniv = "chainiv",
+                       .min_keysize = AES_MIN_KEY_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE,
+                       .ivsize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = 0,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
        },
        {
-               .name = "authenc(hmac(sha512),ecb(cipher_null))",
-               .driver_name = "authenc-hmac-sha512-ecb-cipher_null-caam",
-               .blocksize = NULL_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = aead_null_givencrypt,
+               .name = "rfc3686(ctr(aes))",
+               .driver_name = "rfc3686-ctr-aes-caam",
+               .blocksize = 1,
+               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
+               .template_ablkcipher = {
+                       .setkey = ablkcipher_setkey,
+                       .encrypt = ablkcipher_encrypt,
+                       .decrypt = ablkcipher_decrypt,
+                       .givencrypt = ablkcipher_givencrypt,
                        .geniv = "<built-in>",
-                       .ivsize = NULL_IV_SIZE,
-                       .maxauthsize = SHA512_DIGEST_SIZE,
+                       .min_keysize = AES_MIN_KEY_SIZE +
+                                      CTR_RFC3686_NONCE_SIZE,
+                       .max_keysize = AES_MAX_KEY_SIZE +
+                                      CTR_RFC3686_NONCE_SIZE,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
                        },
-               .class1_alg_type = 0,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
-       },
+               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
+       }
+};
+
+static struct caam_aead_alg driver_aeads[] = {
        {
-               .name = "authenc(hmac(md5),cbc(aes))",
-               .driver_name = "authenc-hmac-md5-cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
-                       .setkey = aead_setkey,
-                       .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = MD5_DIGEST_SIZE,
+               .aead = {
+                       .base = {
+                               .cra_name = "rfc4106(gcm(aes))",
+                               .cra_driver_name = "rfc4106-gcm-aes-caam",
+                               .cra_blocksize = 1,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .setkey = rfc4106_setkey,
+                       .setauthsize = rfc4106_setauthsize,
+                       .encrypt = ipsec_gcm_encrypt,
+                       .decrypt = ipsec_gcm_decrypt,
+                       .ivsize = 8,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+               },
        },
        {
-               .name = "authenc(hmac(sha1),cbc(aes))",
-               .driver_name = "authenc-hmac-sha1-cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "rfc4543(gcm(aes))",
+                               .cra_driver_name = "rfc4543-gcm-aes-caam",
+                               .cra_blocksize = 1,
+                       },
+                       .setkey = rfc4543_setkey,
+                       .setauthsize = rfc4543_setauthsize,
+                       .encrypt = ipsec_gcm_encrypt,
+                       .decrypt = ipsec_gcm_decrypt,
+                       .ivsize = 8,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+               },
+       },
+       /* Galois Counter Mode */
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "gcm(aes)",
+                               .cra_driver_name = "gcm-aes-caam",
+                               .cra_blocksize = 1,
+                       },
+                       .setkey = gcm_setkey,
+                       .setauthsize = gcm_setauthsize,
+                       .encrypt = gcm_encrypt,
+                       .decrypt = gcm_decrypt,
+                       .ivsize = 12,
+                       .maxauthsize = AES_BLOCK_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+               },
+       },
+       /* single-pass ipsec_esp descriptor */
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),"
+                                           "ecb(cipher_null))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "ecb-cipher_null-caam",
+                               .cra_blocksize = NULL_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = NULL_IV_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),"
+                                           "ecb(cipher_null))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "ecb-cipher_null-caam",
+                               .cra_blocksize = NULL_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = NULL_IV_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),"
+                                           "ecb(cipher_null))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "ecb-cipher_null-caam",
+                               .cra_blocksize = NULL_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = NULL_IV_SIZE,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),"
+                                           "ecb(cipher_null))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "ecb-cipher_null-caam",
+                               .cra_blocksize = NULL_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = NULL_IV_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),"
+                                           "ecb(cipher_null))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "ecb-cipher_null-caam",
+                               .cra_blocksize = NULL_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = NULL_IV_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha512),"
+                                           "ecb(cipher_null))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "ecb-cipher_null-caam",
+                               .cra_blocksize = NULL_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = NULL_IV_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(md5),"
+                                           "cbc(aes)))",
+                               .cra_driver_name = "echainiv-authenc-hmac-md5-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = AES_BLOCK_SIZE,
                        .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha1),"
+                                           "cbc(aes)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha1-cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha224),cbc(aes))",
-               .driver_name = "authenc-hmac-sha224-cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = AES_BLOCK_SIZE,
                        .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha224),"
+                                           "cbc(aes)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha224-cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha256),cbc(aes))",
-               .driver_name = "authenc-hmac-sha256-cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = AES_BLOCK_SIZE,
                        .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha256),"
+                                           "cbc(aes)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha256-cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha384),cbc(aes))",
-               .driver_name = "authenc-hmac-sha384-cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = AES_BLOCK_SIZE,
                        .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha384),"
+                                           "cbc(aes)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha384-cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
-
        {
-               .name = "authenc(hmac(sha512),cbc(aes))",
-               .driver_name = "authenc-hmac-sha512-cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha512),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = AES_BLOCK_SIZE,
                        .maxauthsize = SHA512_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha512),"
+                                           "cbc(aes)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha512-cbc-aes-caam",
+                               .cra_blocksize = AES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(md5),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-md5-cbc-des3_ede-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES3_EDE_BLOCK_SIZE,
                        .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+               }
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(md5),"
+                                           "cbc(des3_ede)))",
+                               .cra_driver_name = "echainiv-authenc-hmac-md5-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               }
        },
        {
-               .name = "authenc(hmac(sha1),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES3_EDE_BLOCK_SIZE,
                        .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha1),"
+                                           "cbc(des3_ede)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha1-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha224),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES3_EDE_BLOCK_SIZE,
                        .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha224),"
+                                           "cbc(des3_ede)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha224-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha256),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES3_EDE_BLOCK_SIZE,
                        .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha256),"
+                                           "cbc(des3_ede)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha256-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha384),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES3_EDE_BLOCK_SIZE,
                        .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha384),"
+                                           "cbc(des3_ede)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha384-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha512),cbc(des3_ede))",
-               .driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha512),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES3_EDE_BLOCK_SIZE,
                        .maxauthsize = SHA512_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha512),"
+                                           "cbc(des3_ede)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha512-"
+                                                  "cbc-des3_ede-caam",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(md5),cbc(des))",
-               .driver_name = "authenc-hmac-md5-cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(des))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES_BLOCK_SIZE,
                        .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(md5),"
+                                           "cbc(des)))",
+                               .cra_driver_name = "echainiv-authenc-hmac-md5-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha1),cbc(des))",
-               .driver_name = "authenc-hmac-sha1-cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),cbc(des))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES_BLOCK_SIZE,
                        .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha1),"
+                                           "cbc(des)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha1-cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha224),cbc(des))",
-               .driver_name = "authenc-hmac-sha224-cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),cbc(des))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES_BLOCK_SIZE,
                        .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha224),"
+                                           "cbc(des)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha224-cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES_BLOCK_SIZE,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha256),cbc(des))",
-               .driver_name = "authenc-hmac-sha256-cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),cbc(des))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES_BLOCK_SIZE,
                        .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha256),"
+                                           "cbc(des)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha256-cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha384),cbc(des))",
-               .driver_name = "authenc-hmac-sha384-cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),cbc(des))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = DES_BLOCK_SIZE,
                        .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha384),"
+                                           "cbc(des)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha384-cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = DES_BLOCK_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
+       },
+       {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha512),cbc(des))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = DES_BLOCK_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+               },
        },
        {
-               .name = "authenc(hmac(sha512),cbc(des))",
-               .driver_name = "authenc-hmac-sha512-cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "echainiv(authenc(hmac(sha512),"
+                                           "cbc(des)))",
+                               .cra_driver_name = "echainiv-authenc-"
+                                                  "hmac-sha512-cbc-des-caam",
+                               .cra_blocksize = DES_BLOCK_SIZE,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
                        .ivsize = DES_BLOCK_SIZE,
                        .maxauthsize = SHA512_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(md5),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-md5-rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),"
+                                           "rfc3686(ctr(aes)))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
                        .maxauthsize = MD5_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-               .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha1-rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "seqiv(authenc("
+                                           "hmac(md5),rfc3686(ctr(aes))))",
+                               .cra_driver_name = "seqiv-authenc-hmac-md5-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA1_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_MD5 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha224),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha224-rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),"
+                                           "rfc3686(ctr(aes)))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA224_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha256),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha256-rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "seqiv(authenc("
+                                           "hmac(sha1),rfc3686(ctr(aes))))",
+                               .cra_driver_name = "seqiv-authenc-hmac-sha1-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA256_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA1 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+                       .geniv = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha384),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha384-rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),"
+                                           "rfc3686(ctr(aes)))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA384_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+               },
        },
        {
-               .name = "authenc(hmac(sha512),rfc3686(ctr(aes)))",
-               .driver_name = "authenc-hmac-sha512-rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_AEAD,
-               .template_aead = {
+               .aead = {
+                       .base = {
+                               .cra_name = "seqiv(authenc("
+                                           "hmac(sha224),rfc3686(ctr(aes))))",
+                               .cra_driver_name = "seqiv-authenc-hmac-sha224-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
+                       },
                        .setkey = aead_setkey,
                        .setauthsize = aead_setauthsize,
-                       .encrypt = old_aead_encrypt,
-                       .decrypt = old_aead_decrypt,
-                       .givencrypt = old_aead_givencrypt,
-                       .geniv = "<built-in>",
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
-                       .maxauthsize = SHA512_DIGEST_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-               .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
-                                  OP_ALG_AAI_HMAC_PRECOMP,
-               .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
-       },
-       /* ablkcipher descriptor */
-       {
-               .name = "cbc(aes)",
-               .driver_name = "cbc-aes-caam",
-               .blocksize = AES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ablkcipher_setkey,
-                       .encrypt = ablkcipher_encrypt,
-                       .decrypt = ablkcipher_decrypt,
-                       .givencrypt = ablkcipher_givencrypt,
-                       .geniv = "<built-in>",
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = AES_BLOCK_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+                       .geniv = true,
+               },
        },
        {
-               .name = "cbc(des3_ede)",
-               .driver_name = "cbc-3des-caam",
-               .blocksize = DES3_EDE_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ablkcipher_setkey,
-                       .encrypt = ablkcipher_encrypt,
-                       .decrypt = ablkcipher_decrypt,
-                       .givencrypt = ablkcipher_givencrypt,
-                       .geniv = "<built-in>",
-                       .min_keysize = DES3_EDE_KEY_SIZE,
-                       .max_keysize = DES3_EDE_KEY_SIZE,
-                       .ivsize = DES3_EDE_BLOCK_SIZE,
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),"
+                                           "rfc3686(ctr(aes)))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+               },
        },
        {
-               .name = "cbc(des)",
-               .driver_name = "cbc-des-caam",
-               .blocksize = DES_BLOCK_SIZE,
-               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ablkcipher_setkey,
-                       .encrypt = ablkcipher_encrypt,
-                       .decrypt = ablkcipher_decrypt,
-                       .givencrypt = ablkcipher_givencrypt,
-                       .geniv = "<built-in>",
-                       .min_keysize = DES_KEY_SIZE,
-                       .max_keysize = DES_KEY_SIZE,
-                       .ivsize = DES_BLOCK_SIZE,
+               .aead = {
+                       .base = {
+                               .cra_name = "seqiv(authenc(hmac(sha256),"
+                                           "rfc3686(ctr(aes))))",
+                               .cra_driver_name = "seqiv-authenc-hmac-sha256-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+                       .geniv = true,
+               },
        },
        {
-               .name = "ctr(aes)",
-               .driver_name = "ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ablkcipher_setkey,
-                       .encrypt = ablkcipher_encrypt,
-                       .decrypt = ablkcipher_decrypt,
-                       .geniv = "chainiv",
-                       .min_keysize = AES_MIN_KEY_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE,
-                       .ivsize = AES_BLOCK_SIZE,
+               .aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),"
+                                           "rfc3686(ctr(aes)))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "rfc3686-ctr-aes-caam",
+                               .cra_blocksize = 1,
                        },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-       },
-       {
-               .name = "rfc3686(ctr(aes))",
-               .driver_name = "rfc3686-ctr-aes-caam",
-               .blocksize = 1,
-               .type = CRYPTO_ALG_TYPE_GIVCIPHER,
-               .template_ablkcipher = {
-                       .setkey = ablkcipher_setkey,
-                       .encrypt = ablkcipher_encrypt,
-                       .decrypt = ablkcipher_decrypt,
-                       .givencrypt = ablkcipher_givencrypt,
-                       .geniv = "<built-in>",
-                       .min_keysize = AES_MIN_KEY_SIZE +
-                                      CTR_RFC3686_NONCE_SIZE,
-                       .max_keysize = AES_MAX_KEY_SIZE +
-                                      CTR_RFC3686_NONCE_SIZE,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
                        .ivsize = CTR_RFC3686_IV_SIZE,
-                       },
-               .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128,
-       }
-};
-
-struct caam_alg_entry {
-       int class1_alg_type;
-       int class2_alg_type;
-       int alg_op;
-};
-
-struct caam_aead_alg {
-       struct aead_alg aead;
-       struct caam_alg_entry caam;
-       bool registered;
-};
-
-static struct caam_aead_alg driver_aeads[] = {
+                       .maxauthsize = SHA384_DIGEST_SIZE,
+               },
+               .caam = {
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+               },
+       },
        {
                .aead = {
                        .base = {
-                               .cra_name = "rfc4106(gcm(aes))",
-                               .cra_driver_name = "rfc4106-gcm-aes-caam",
+                               .cra_name = "seqiv(authenc(hmac(sha384),"
+                                           "rfc3686(ctr(aes))))",
+                               .cra_driver_name = "seqiv-authenc-hmac-sha384-"
+                                                  "rfc3686-ctr-aes-caam",
                                .cra_blocksize = 1,
                        },
-                       .setkey = rfc4106_setkey,
-                       .setauthsize = rfc4106_setauthsize,
-                       .encrypt = gcm_encrypt,
-                       .decrypt = gcm_decrypt,
-                       .ivsize = 8,
-                       .maxauthsize = AES_BLOCK_SIZE,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
                },
                .caam = {
-                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+                       .geniv = true,
                },
        },
        {
                .aead = {
                        .base = {
-                               .cra_name = "rfc4543(gcm(aes))",
-                               .cra_driver_name = "rfc4543-gcm-aes-caam",
+                               .cra_name = "authenc(hmac(sha512),"
+                                           "rfc3686(ctr(aes)))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "rfc3686-ctr-aes-caam",
                                .cra_blocksize = 1,
                        },
-                       .setkey = rfc4543_setkey,
-                       .setauthsize = rfc4543_setauthsize,
-                       .encrypt = gcm_encrypt,
-                       .decrypt = gcm_decrypt,
-                       .ivsize = 8,
-                       .maxauthsize = AES_BLOCK_SIZE,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_decrypt,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
                },
                .caam = {
-                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
                },
        },
-       /* Galois Counter Mode */
        {
                .aead = {
                        .base = {
-                               .cra_name = "gcm(aes)",
-                               .cra_driver_name = "gcm-aes-caam",
+                               .cra_name = "seqiv(authenc(hmac(sha512),"
+                                           "rfc3686(ctr(aes))))",
+                               .cra_driver_name = "seqiv-authenc-hmac-sha512-"
+                                                  "rfc3686-ctr-aes-caam",
                                .cra_blocksize = 1,
                        },
-                       .setkey = gcm_setkey,
-                       .setauthsize = gcm_setauthsize,
-                       .encrypt = gcm_encrypt,
-                       .decrypt = gcm_decrypt,
-                       .ivsize = 12,
-                       .maxauthsize = AES_BLOCK_SIZE,
+                       .setkey = aead_setkey,
+                       .setauthsize = aead_setauthsize,
+                       .encrypt = aead_encrypt,
+                       .decrypt = aead_givdecrypt,
+                       .ivsize = CTR_RFC3686_IV_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
                },
                .caam = {
-                       .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+                       .class1_alg_type = OP_ALG_ALGSEL_AES |
+                                          OP_ALG_AAI_CTR_MOD128,
+                       .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+                                          OP_ALG_AAI_HMAC_PRECOMP,
+                       .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+                       .rfc3686 = true,
+                       .geniv = true,
                },
        },
 };
@@ -4211,7 +4314,7 @@ static struct caam_crypto_alg *caam_alg_alloc(struct caam_alg_template
        struct caam_crypto_alg *t_alg;
        struct crypto_alg *alg;
 
-       t_alg = kzalloc(sizeof(struct caam_crypto_alg), GFP_KERNEL);
+       t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
        if (!t_alg) {
                pr_err("failed to allocate t_alg\n");
                return ERR_PTR(-ENOMEM);
@@ -4240,10 +4343,6 @@ static struct caam_crypto_alg *caam_alg_alloc(struct caam_alg_template
                alg->cra_type = &crypto_ablkcipher_type;
                alg->cra_ablkcipher = template->template_ablkcipher;
                break;
-       case CRYPTO_ALG_TYPE_AEAD:
-               alg->cra_type = &crypto_aead_type;
-               alg->cra_aead = template->template_aead;
-               break;
        }
 
        t_alg->caam.class1_alg_type = template->class1_alg_type;
@@ -4271,8 +4370,10 @@ static int __init caam_algapi_init(void)
        struct device_node *dev_node;
        struct platform_device *pdev;
        struct device *ctrldev;
-       void *priv;
+       struct caam_drv_private *priv;
        int i = 0, err = 0;
+       u32 cha_vid, cha_inst, des_inst, aes_inst, md_inst;
+       unsigned int md_limit = SHA512_DIGEST_SIZE;
        bool registered = false;
 
        dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
@@ -4302,16 +4403,39 @@ static int __init caam_algapi_init(void)
 
        INIT_LIST_HEAD(&alg_list);
 
-       /* register crypto algorithms the device supports */
+       /*
+        * Register crypto algorithms the device supports.
+        * First, detect presence and attributes of DES, AES, and MD blocks.
+        */
+       cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
+       cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
+       des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> CHA_ID_LS_DES_SHIFT;
+       aes_inst = (cha_inst & CHA_ID_LS_AES_MASK) >> CHA_ID_LS_AES_SHIFT;
+       md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
+
+       /* If MD is present, limit digest size based on LP256 */
+       if (md_inst && ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256))
+               md_limit = SHA256_DIGEST_SIZE;
+
        for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
-               /* TODO: check if h/w supports alg */
                struct caam_crypto_alg *t_alg;
+               struct caam_alg_template *alg = driver_algs + i;
+               u32 alg_sel = alg->class1_alg_type & OP_ALG_ALGSEL_MASK;
+
+               /* Skip DES algorithms if not supported by device */
+               if (!des_inst &&
+                   ((alg_sel == OP_ALG_ALGSEL_3DES) ||
+                    (alg_sel == OP_ALG_ALGSEL_DES)))
+                               continue;
+
+               /* Skip AES algorithms if not supported by device */
+               if (!aes_inst && (alg_sel == OP_ALG_ALGSEL_AES))
+                               continue;
 
-               t_alg = caam_alg_alloc(&driver_algs[i]);
+               t_alg = caam_alg_alloc(alg);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
-                       pr_warn("%s alg allocation failed\n",
-                               driver_algs[i].driver_name);
+                       pr_warn("%s alg allocation failed\n", alg->driver_name);
                        continue;
                }
 
@@ -4329,6 +4453,37 @@ static int __init caam_algapi_init(void)
 
        for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) {
                struct caam_aead_alg *t_alg = driver_aeads + i;
+               u32 c1_alg_sel = t_alg->caam.class1_alg_type &
+                                OP_ALG_ALGSEL_MASK;
+               u32 c2_alg_sel = t_alg->caam.class2_alg_type &
+                                OP_ALG_ALGSEL_MASK;
+               u32 alg_aai = t_alg->caam.class1_alg_type & OP_ALG_AAI_MASK;
+
+               /* Skip DES algorithms if not supported by device */
+               if (!des_inst &&
+                   ((c1_alg_sel == OP_ALG_ALGSEL_3DES) ||
+                    (c1_alg_sel == OP_ALG_ALGSEL_DES)))
+                               continue;
+
+               /* Skip AES algorithms if not supported by device */
+               if (!aes_inst && (c1_alg_sel == OP_ALG_ALGSEL_AES))
+                               continue;
+
+               /*
+                * Check support for AES algorithms not available
+                * on LP devices.
+                */
+               if ((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP)
+                       if (alg_aai == OP_ALG_AAI_GCM)
+                               continue;
+
+               /*
+                * Skip algorithms requiring message digests
+                * if MD or MD size is not supported by device.
+                */
+               if (c2_alg_sel &&
+                   (!md_inst || (t_alg->aead.maxauthsize > md_limit)))
+                               continue;
 
                caam_aead_alg_init(t_alg);
 
index dae1e8099969a192b302703ec291da96ebac3429..94433b9fc200dc5f5322d29819ebfe74f3fd90f1 100644 (file)
@@ -127,7 +127,7 @@ struct caam_hash_state {
        int buflen_0;
        u8 buf_1[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
        int buflen_1;
-       u8 caam_ctx[MAX_CTX_LEN];
+       u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned;
        int (*update)(struct ahash_request *req);
        int (*final)(struct ahash_request *req);
        int (*finup)(struct ahash_request *req);
@@ -807,7 +807,7 @@ static int ahash_update_ctx(struct ahash_request *req)
                 * allocate space for base edesc and hw desc commands,
                 * link tables
                 */
-               edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+               edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN +
                                sec4_sg_bytes, GFP_DMA | flags);
                if (!edesc) {
                        dev_err(jrdev,
@@ -829,7 +829,7 @@ static int ahash_update_ctx(struct ahash_request *req)
                state->buf_dma = try_buf_map_to_sec4_sg(jrdev,
                                                        edesc->sec4_sg + 1,
                                                        buf, state->buf_dma,
-                                                       *buflen, last_buflen);
+                                                       *next_buflen, *buflen);
 
                if (src_nents) {
                        src_map_to_sec4_sg(jrdev, req->src, src_nents,
@@ -909,17 +909,18 @@ static int ahash_final_ctx(struct ahash_request *req)
                          state->buflen_1;
        u32 *sh_desc = ctx->sh_desc_fin, *desc;
        dma_addr_t ptr = ctx->sh_desc_fin_dma;
-       int sec4_sg_bytes;
+       int sec4_sg_bytes, sec4_sg_src_index;
        int digestsize = crypto_ahash_digestsize(ahash);
        struct ahash_edesc *edesc;
        int ret = 0;
        int sh_len;
 
-       sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry);
+       sec4_sg_src_index = 1 + (buflen ? 1 : 0);
+       sec4_sg_bytes = sec4_sg_src_index * sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
-                       sec4_sg_bytes, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN + sec4_sg_bytes,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return -ENOMEM;
@@ -942,7 +943,7 @@ static int ahash_final_ctx(struct ahash_request *req)
        state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
                                                buf, state->buf_dma, buflen,
                                                last_buflen);
-       (edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN;
+       (edesc->sec4_sg + sec4_sg_src_index - 1)->len |= SEC4_SG_LEN_FIN;
 
        edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
                                            sec4_sg_bytes, DMA_TO_DEVICE);
@@ -1005,8 +1006,8 @@ static int ahash_finup_ctx(struct ahash_request *req)
                         sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
-                       sec4_sg_bytes, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN + sec4_sg_bytes,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return -ENOMEM;
@@ -1091,8 +1092,8 @@ static int ahash_digest(struct ahash_request *req)
        sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct ahash_edesc) + sec4_sg_bytes +
-                       DESC_JOB_IO_LEN, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + sec4_sg_bytes + DESC_JOB_IO_LEN,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return -ENOMEM;
@@ -1165,8 +1166,7 @@ static int ahash_final_no_ctx(struct ahash_request *req)
        int sh_len;
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN,
-                       GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN, GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return -ENOMEM;
@@ -1245,7 +1245,7 @@ static int ahash_update_no_ctx(struct ahash_request *req)
                 * allocate space for base edesc and hw desc commands,
                 * link tables
                 */
-               edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+               edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN +
                                sec4_sg_bytes, GFP_DMA | flags);
                if (!edesc) {
                        dev_err(jrdev,
@@ -1353,8 +1353,8 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
                         sizeof(struct sec4_sg_entry);
 
        /* allocate space for base edesc and hw desc commands, link tables */
-       edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
-                       sec4_sg_bytes, GFP_DMA | flags);
+       edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN + sec4_sg_bytes,
+                       GFP_DMA | flags);
        if (!edesc) {
                dev_err(jrdev, "could not allocate extended descriptor\n");
                return -ENOMEM;
@@ -1448,7 +1448,7 @@ static int ahash_update_first(struct ahash_request *req)
                 * allocate space for base edesc and hw desc commands,
                 * link tables
                 */
-               edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+               edesc = kzalloc(sizeof(*edesc) + DESC_JOB_IO_LEN +
                                sec4_sg_bytes, GFP_DMA | flags);
                if (!edesc) {
                        dev_err(jrdev,
@@ -1842,7 +1842,7 @@ caam_hash_alloc(struct caam_hash_template *template,
        struct ahash_alg *halg;
        struct crypto_alg *alg;
 
-       t_alg = kzalloc(sizeof(struct caam_hash_alg), GFP_KERNEL);
+       t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
        if (!t_alg) {
                pr_err("failed to allocate t_alg\n");
                return ERR_PTR(-ENOMEM);
@@ -1884,8 +1884,10 @@ static int __init caam_algapi_hash_init(void)
        struct device_node *dev_node;
        struct platform_device *pdev;
        struct device *ctrldev;
-       void *priv;
        int i = 0, err = 0;
+       struct caam_drv_private *priv;
+       unsigned int md_limit = SHA512_DIGEST_SIZE;
+       u32 cha_inst, cha_vid;
 
        dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
        if (!dev_node) {
@@ -1911,19 +1913,40 @@ static int __init caam_algapi_hash_init(void)
        if (!priv)
                return -ENODEV;
 
+       /*
+        * Register crypto algorithms the device supports.  First, identify
+        * presence and attributes of MD block.
+        */
+       cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
+       cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
+
+       /*
+        * Skip registration of any hashing algorithms if MD block
+        * is not present.
+        */
+       if (!((cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT))
+               return -ENODEV;
+
+       /* Limit digest size based on LP256 */
+       if ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256)
+               md_limit = SHA256_DIGEST_SIZE;
+
        INIT_LIST_HEAD(&hash_list);
 
        /* register crypto algorithms the device supports */
        for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
-               /* TODO: check if h/w supports alg */
                struct caam_hash_alg *t_alg;
+               struct caam_hash_template *alg = driver_hash + i;
+
+               /* If MD size is not supported by device, skip registration */
+               if (alg->template_ahash.halg.digestsize > md_limit)
+                       continue;
 
                /* register hmac version */
-               t_alg = caam_hash_alloc(&driver_hash[i], true);
+               t_alg = caam_hash_alloc(alg, true);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
-                       pr_warn("%s alg allocation failed\n",
-                               driver_hash[i].driver_name);
+                       pr_warn("%s alg allocation failed\n", alg->driver_name);
                        continue;
                }
 
@@ -1936,11 +1959,10 @@ static int __init caam_algapi_hash_init(void)
                        list_add_tail(&t_alg->entry, &hash_list);
 
                /* register unkeyed version */
-               t_alg = caam_hash_alloc(&driver_hash[i], false);
+               t_alg = caam_hash_alloc(alg, false);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
-                       pr_warn("%s alg allocation failed\n",
-                               driver_hash[i].driver_name);
+                       pr_warn("%s alg allocation failed\n", alg->driver_name);
                        continue;
                }
 
index 5095337205b830c148696a37d53a8902643b317f..9b92af2c72412fd05390da752956c9e52d84014d 100644 (file)
@@ -108,6 +108,10 @@ static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context)
 
        atomic_set(&bd->empty, BUF_NOT_EMPTY);
        complete(&bd->filled);
+
+       /* Buffer refilled, invalidate cache */
+       dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE);
+
 #ifdef DEBUG
        print_hex_dump(KERN_ERR, "rng refreshed buf@: ",
                       DUMP_PREFIX_ADDRESS, 16, 4, bd->buf, RN_BUF_SIZE, 1);
@@ -311,7 +315,7 @@ static int __init caam_rng_init(void)
        struct device_node *dev_node;
        struct platform_device *pdev;
        struct device *ctrldev;
-       void *priv;
+       struct caam_drv_private *priv;
        int err;
 
        dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
@@ -338,20 +342,32 @@ static int __init caam_rng_init(void)
        if (!priv)
                return -ENODEV;
 
+       /* Check for an instantiated RNG before registration */
+       if (!(rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & CHA_ID_LS_RNG_MASK))
+               return -ENODEV;
+
        dev = caam_jr_alloc();
        if (IS_ERR(dev)) {
                pr_err("Job Ring Device allocation for transform failed\n");
                return PTR_ERR(dev);
        }
-       rng_ctx = kmalloc(sizeof(struct caam_rng_ctx), GFP_DMA);
-       if (!rng_ctx)
-               return -ENOMEM;
+       rng_ctx = kmalloc(sizeof(*rng_ctx), GFP_DMA);
+       if (!rng_ctx) {
+               err = -ENOMEM;
+               goto free_caam_alloc;
+       }
        err = caam_init_rng(rng_ctx, dev);
        if (err)
-               return err;
+               goto free_rng_ctx;
 
        dev_info(dev, "registering rng-caam\n");
        return hwrng_register(&caam_rng);
+
+free_rng_ctx:
+       kfree(rng_ctx);
+free_caam_alloc:
+       caam_jr_free(dev);
+       return err;
 }
 
 module_init(caam_rng_init);
index f57f395db33f73e8fb5630bd7d2c779a4ca2ff7f..b6955ecdfb3f67d39116c9362a16222070de51cd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/debugfs.h>
 #include <linux/circ_buf.h>
+#include <linux/clk.h>
 #include <net/xfrm.h>
 
 #include <crypto/algapi.h>
index efacab7539ef6a8afdacbfb8d9965a0ec4f9ef75..8abb4bc548cc06a7a8ae97779701d308255ff050 100644 (file)
 #include "desc_constr.h"
 #include "error.h"
 
+/*
+ * i.MX targets tend to have clock control subsystems that can
+ * enable/disable clocking to our device.
+ */
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
+static inline struct clk *caam_drv_identify_clk(struct device *dev,
+                                               char *clk_name)
+{
+       return devm_clk_get(dev, clk_name);
+}
+#else
+static inline struct clk *caam_drv_identify_clk(struct device *dev,
+                                               char *clk_name)
+{
+       return NULL;
+}
+#endif
+
 /*
  * Descriptor to instantiate RNG State Handle 0 in normal mode and
  * load the JDKEK, TDKEK and TDSK registers
@@ -121,7 +139,7 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
                flags |= DECO_JQCR_FOUR;
 
        /* Instruct the DECO to execute it */
-       wr_reg32(&deco->jr_ctl_hi, flags);
+       setbits32(&deco->jr_ctl_hi, flags);
 
        timeout = 10000000;
        do {
@@ -175,7 +193,7 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
 {
        struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
        struct caam_ctrl __iomem *ctrl;
-       u32 *desc, status, rdsta_val;
+       u32 *desc, status = 0, rdsta_val;
        int ret = 0, sh_idx;
 
        ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
@@ -207,7 +225,8 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
                 * CAAM eras), then try again.
                 */
                rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
-               if (status || !(rdsta_val & (1 << sh_idx)))
+               if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
+                   !(rdsta_val & (1 << sh_idx)))
                        ret = -EAGAIN;
                if (ret)
                        break;
@@ -279,7 +298,7 @@ static int caam_remove(struct platform_device *pdev)
        struct device *ctrldev;
        struct caam_drv_private *ctrlpriv;
        struct caam_ctrl __iomem *ctrl;
-       int ring, ret = 0;
+       int ring;
 
        ctrldev = &pdev->dev;
        ctrlpriv = dev_get_drvdata(ctrldev);
@@ -303,7 +322,13 @@ static int caam_remove(struct platform_device *pdev)
        /* Unmap controller region */
        iounmap(ctrl);
 
-       return ret;
+       /* shut clocks off before finalizing shutdown */
+       clk_disable_unprepare(ctrlpriv->caam_ipg);
+       clk_disable_unprepare(ctrlpriv->caam_mem);
+       clk_disable_unprepare(ctrlpriv->caam_aclk);
+       clk_disable_unprepare(ctrlpriv->caam_emi_slow);
+
+       return 0;
 }
 
 /*
@@ -370,14 +395,14 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
 int caam_get_era(void)
 {
        struct device_node *caam_node;
-       for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
-               const uint32_t *prop = (uint32_t *)of_get_property(caam_node,
-                               "fsl,sec-era",
-                               NULL);
-               return prop ? *prop : -ENOTSUPP;
-       }
+       int ret;
+       u32 prop;
 
-       return -ENOTSUPP;
+       caam_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+       ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
+       of_node_put(caam_node);
+
+       return IS_ERR_VALUE(ret) ? -ENOTSUPP : prop;
 }
 EXPORT_SYMBOL(caam_get_era);
 
@@ -390,6 +415,7 @@ static int caam_probe(struct platform_device *pdev)
        struct device_node *nprop, *np;
        struct caam_ctrl __iomem *ctrl;
        struct caam_drv_private *ctrlpriv;
+       struct clk *clk;
 #ifdef CONFIG_DEBUG_FS
        struct caam_perfmon *perfmon;
 #endif
@@ -398,8 +424,7 @@ static int caam_probe(struct platform_device *pdev)
        int pg_size;
        int BLOCK_OFFSET = 0;
 
-       ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(struct caam_drv_private),
-                               GFP_KERNEL);
+       ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL);
        if (!ctrlpriv)
                return -ENOMEM;
 
@@ -408,12 +433,76 @@ static int caam_probe(struct platform_device *pdev)
        ctrlpriv->pdev = pdev;
        nprop = pdev->dev.of_node;
 
+       /* Enable clocking */
+       clk = caam_drv_identify_clk(&pdev->dev, "ipg");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM ipg clk: %d\n", ret);
+               return ret;
+       }
+       ctrlpriv->caam_ipg = clk;
+
+       clk = caam_drv_identify_clk(&pdev->dev, "mem");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM mem clk: %d\n", ret);
+               return ret;
+       }
+       ctrlpriv->caam_mem = clk;
+
+       clk = caam_drv_identify_clk(&pdev->dev, "aclk");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM aclk clk: %d\n", ret);
+               return ret;
+       }
+       ctrlpriv->caam_aclk = clk;
+
+       clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               dev_err(&pdev->dev,
+                       "can't identify CAAM emi_slow clk: %d\n", ret);
+               return ret;
+       }
+       ctrlpriv->caam_emi_slow = clk;
+
+       ret = clk_prepare_enable(ctrlpriv->caam_ipg);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_mem);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM secure mem clock: %d\n",
+                       ret);
+               goto disable_caam_ipg;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_aclk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM aclk clock: %d\n", ret);
+               goto disable_caam_mem;
+       }
+
+       ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
+                       ret);
+               goto disable_caam_aclk;
+       }
+
        /* Get configuration properties from device tree */
        /* First, get register page */
        ctrl = of_iomap(nprop, 0);
        if (ctrl == NULL) {
                dev_err(dev, "caam: of_iomap() failed\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto disable_caam_emi_slow;
        }
        /* Finding the page size for using the CTPR_MS register */
        comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms);
@@ -444,8 +533,9 @@ static int caam_probe(struct platform_device *pdev)
         * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel,
         * long pointers in master configuration register
         */
-       setbits32(&ctrl->mcr, MCFGR_WDENABLE |
-                 (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
+       clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH |
+                     MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ?
+                                       MCFGR_LONG_PTR : 0));
 
        /*
         *  Read the Compile Time paramters and SCFGR to determine
@@ -492,12 +582,11 @@ static int caam_probe(struct platform_device *pdev)
                    of_device_is_compatible(np, "fsl,sec4.0-job-ring"))
                        rspec++;
 
-       ctrlpriv->jrpdev = devm_kzalloc(&pdev->dev,
-                                       sizeof(struct platform_device *) * rspec,
-                                       GFP_KERNEL);
+       ctrlpriv->jrpdev = devm_kcalloc(&pdev->dev, rspec,
+                                       sizeof(*ctrlpriv->jrpdev), GFP_KERNEL);
        if (ctrlpriv->jrpdev == NULL) {
-               iounmap(ctrl);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto iounmap_ctrl;
        }
 
        ring = 0;
@@ -537,8 +626,8 @@ static int caam_probe(struct platform_device *pdev)
        /* If no QI and no rings specified, quit and go home */
        if ((!ctrlpriv->qi_present) && (!ctrlpriv->total_jobrs)) {
                dev_err(dev, "no queues configured, terminating\n");
-               caam_remove(pdev);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto caam_remove;
        }
 
        cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls);
@@ -595,8 +684,7 @@ static int caam_probe(struct platform_device *pdev)
                } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
                if (ret) {
                        dev_err(dev, "failed to instantiate RNG");
-                       caam_remove(pdev);
-                       return ret;
+                       goto caam_remove;
                }
                /*
                 * Set handles init'ed by this module as the complement of the
@@ -700,6 +788,20 @@ static int caam_probe(struct platform_device *pdev)
                                                 &ctrlpriv->ctl_tdsk_wrap);
 #endif
        return 0;
+
+caam_remove:
+       caam_remove(pdev);
+iounmap_ctrl:
+       iounmap(ctrl);
+disable_caam_emi_slow:
+       clk_disable_unprepare(ctrlpriv->caam_emi_slow);
+disable_caam_aclk:
+       clk_disable_unprepare(ctrlpriv->caam_aclk);
+disable_caam_mem:
+       clk_disable_unprepare(ctrlpriv->caam_mem);
+disable_caam_ipg:
+       clk_disable_unprepare(ctrlpriv->caam_ipg);
+       return ret;
 }
 
 static struct of_device_id caam_match[] = {
index d397ff9d56fd7ae5a603b76e1b282286c1889398..983d663ef6714c46fd7ee4d724e0e3d1adeb9002 100644 (file)
@@ -8,12 +8,29 @@
 #ifndef DESC_H
 #define DESC_H
 
+/*
+ * 16-byte hardware scatter/gather table
+ * An 8-byte table exists in the hardware spec, but has never been
+ * implemented to date. The 8/16 option is selected at RTL-compile-time.
+ * and this selection is visible in the Compile Time Parameters Register
+ */
+
+#define SEC4_SG_LEN_EXT                0x80000000      /* Entry points to table */
+#define SEC4_SG_LEN_FIN                0x40000000      /* Last ent in table */
+#define SEC4_SG_BPID_MASK      0x000000ff
+#define SEC4_SG_BPID_SHIFT     16
+#define SEC4_SG_LEN_MASK       0x3fffffff      /* Excludes EXT and FINAL */
+#define SEC4_SG_OFFS_MASK      0x00001fff
+
 struct sec4_sg_entry {
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_IMX
+       u32 rsvd1;
+       dma_addr_t ptr;
+#else
        u64 ptr;
-#define SEC4_SG_LEN_FIN 0x40000000
-#define SEC4_SG_LEN_EXT 0x80000000
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_IMX */
        u32 len;
-       u8 reserved;
+       u8 rsvd2;
        u8 buf_pool_id;
        u16 offset;
 };
index 9f79fd7bd4d7d1b7589a2facdc15e7667dbb8d48..98d07de24fc48c975faf1e13e65d248cc48edd90 100644 (file)
@@ -367,7 +367,7 @@ do { \
        if (upper) \
                append_u64(desc, data); \
        else \
-               append_u32(desc, data); \
+               append_u32(desc, lower_32_bits(data)); \
 } while (0)
 
 #define append_math_add_imm_u64(desc, dest, src0, src1, data) \
index 89b94cc9e7a29b57654ad5931e9999be3d80e664..e2bcacc1a921675cf30f70a40816e1306a8c3ef9 100644 (file)
@@ -91,6 +91,11 @@ struct caam_drv_private {
                                   Handles of the RNG4 block are initialized
                                   by this driver */
 
+       struct clk *caam_ipg;
+       struct clk *caam_mem;
+       struct clk *caam_aclk;
+       struct clk *caam_emi_slow;
+
        /*
         * debugfs entries for developer view into driver/device
         * variables at runtime.
index b8b5d47acd7a9c4ea58dc212f29ecffa84ebc915..f7e0d8d4c3da12cebdfb1df13822eb86da081307 100644 (file)
@@ -202,6 +202,13 @@ static void caam_jr_dequeue(unsigned long devarg)
                userdesc = jrp->entinfo[sw_idx].desc_addr_virt;
                userstatus = jrp->outring[hw_idx].jrstatus;
 
+               /*
+                * Make sure all information from the job has been obtained
+                * before telling CAAM that the job has been removed from the
+                * output ring.
+                */
+               mb();
+
                /* set done */
                wr_reg32(&jrp->rregs->outring_rmvd, 1);
 
@@ -351,12 +358,23 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
 
        jrp->inpring[jrp->inp_ring_write_index] = desc_dma;
 
+       /*
+        * Guarantee that the descriptor's DMA address has been written to
+        * the next slot in the ring before the write index is updated, since
+        * other cores may update this index independently.
+        */
        smp_wmb();
 
        jrp->inp_ring_write_index = (jrp->inp_ring_write_index + 1) &
                                    (JOBR_DEPTH - 1);
        jrp->head = (head + 1) & (JOBR_DEPTH - 1);
 
+       /*
+        * Ensure that all job information has been written before
+        * notifying CAAM that a new job was added to the input ring.
+        */
+       wmb();
+
        wr_reg32(&jrp->rregs->inpring_jobadd, 1);
 
        spin_unlock_bh(&jrp->inplock);
@@ -392,18 +410,17 @@ static int caam_jr_init(struct device *dev)
                goto out_free_irq;
 
        error = -ENOMEM;
-       jrp->inpring = dma_alloc_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH,
-                                         &inpbusaddr, GFP_KERNEL);
+       jrp->inpring = dma_alloc_coherent(dev, sizeof(*jrp->inpring) *
+                                         JOBR_DEPTH, &inpbusaddr, GFP_KERNEL);
        if (!jrp->inpring)
                goto out_free_irq;
 
-       jrp->outring = dma_alloc_coherent(dev, sizeof(struct jr_outentry) *
+       jrp->outring = dma_alloc_coherent(dev, sizeof(*jrp->outring) *
                                          JOBR_DEPTH, &outbusaddr, GFP_KERNEL);
        if (!jrp->outring)
                goto out_free_inpring;
 
-       jrp->entinfo = kzalloc(sizeof(struct caam_jrentry_info) * JOBR_DEPTH,
-                              GFP_KERNEL);
+       jrp->entinfo = kcalloc(JOBR_DEPTH, sizeof(*jrp->entinfo), GFP_KERNEL);
        if (!jrp->entinfo)
                goto out_free_outring;
 
@@ -461,8 +478,7 @@ static int caam_jr_probe(struct platform_device *pdev)
        int error;
 
        jrdev = &pdev->dev;
-       jrpriv = devm_kmalloc(jrdev, sizeof(struct caam_drv_private_jr),
-                             GFP_KERNEL);
+       jrpriv = devm_kmalloc(jrdev, sizeof(*jrpriv), GFP_KERNEL);
        if (!jrpriv)
                return -ENOMEM;
 
index 672c97489505340abd440dc694cbc16d97045760..a8a79975682f2c5096e1beccd1c71714530a7176 100644 (file)
  *
  */
 
+#ifdef CONFIG_ARM
+/* These are common macros for Power, put here for ARM */
+#define setbits32(_addr, _v) writel((readl(_addr) | (_v)), (_addr))
+#define clrbits32(_addr, _v) writel((readl(_addr) & ~(_v)), (_addr))
+
+#define out_arch(type, endian, a, v)   __raw_write##type(cpu_to_##endian(v), a)
+#define in_arch(type, endian, a)       endian##_to_cpu(__raw_read##type(a))
+
+#define out_le32(a, v) out_arch(l, le32, a, v)
+#define in_le32(a)     in_arch(l, le32, a)
+
+#define out_be32(a, v) out_arch(l, be32, a, v)
+#define in_be32(a)     in_arch(l, be32, a)
+
+#define clrsetbits(type, addr, clear, set) \
+       out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+#endif
+
 #ifdef __BIG_ENDIAN
 #define wr_reg32(reg, data) out_be32(reg, data)
 #define rd_reg32(reg) in_be32(reg)
+#define clrsetbits_32(addr, clear, set) clrsetbits_be32(addr, clear, set)
 #ifdef CONFIG_64BIT
 #define wr_reg64(reg, data) out_be64(reg, data)
 #define rd_reg64(reg) in_be64(reg)
@@ -76,6 +98,7 @@
 #ifdef __LITTLE_ENDIAN
 #define wr_reg32(reg, data) __raw_writel(data, reg)
 #define rd_reg32(reg) __raw_readl(reg)
+#define clrsetbits_32(addr, clear, set) clrsetbits_le32(addr, clear, set)
 #ifdef CONFIG_64BIT
 #define wr_reg64(reg, data) __raw_writeq(data, reg)
 #define rd_reg64(reg) __raw_readq(reg)
 
 /*
  * The only users of these wr/rd_reg64 functions is the Job Ring (JR).
- * The DMA address registers in the JR are a pair of 32-bit registers.
- * The layout is:
+ * The DMA address registers in the JR are handled differently depending on
+ * platform:
+ *
+ * 1. All BE CAAM platforms and i.MX platforms (LE CAAM):
  *
  *    base + 0x0000 : most-significant 32 bits
  *    base + 0x0004 : least-significant 32 bits
  *
  * The 32-bit version of this core therefore has to write to base + 0x0004
- * to set the 32-bit wide DMA address. This seems to be independent of the
- * endianness of the written/read data.
+ * to set the 32-bit wide DMA address.
+ *
+ * 2. All other LE CAAM platforms (LS1021A etc.)
+ *    base + 0x0000 : least-significant 32 bits
+ *    base + 0x0004 : most-significant 32 bits
  */
 
 #ifndef CONFIG_64BIT
+#if !defined(CONFIG_CRYPTO_DEV_FSL_CAAM_LE) || \
+       defined(CONFIG_CRYPTO_DEV_FSL_CAAM_IMX)
 #define REG64_MS32(reg) ((u32 __iomem *)(reg))
 #define REG64_LS32(reg) ((u32 __iomem *)(reg) + 1)
+#else
+#define REG64_MS32(reg) ((u32 __iomem *)(reg) + 1)
+#define REG64_LS32(reg) ((u32 __iomem *)(reg))
+#endif
 
 static inline void wr_reg64(u64 __iomem *reg, u64 data)
 {
@@ -133,18 +167,28 @@ struct jr_outentry {
 #define CHA_NUM_MS_DECONUM_SHIFT       24
 #define CHA_NUM_MS_DECONUM_MASK        (0xfull << CHA_NUM_MS_DECONUM_SHIFT)
 
-/* CHA Version IDs */
+/*
+ * CHA version IDs / instantiation bitfields
+ * Defined for use with the cha_id fields in perfmon, but the same shift/mask
+ * selectors can be used to pull out the number of instantiated blocks within
+ * cha_num fields in perfmon because the locations are the same.
+ */
 #define CHA_ID_LS_AES_SHIFT    0
-#define CHA_ID_LS_AES_MASK             (0xfull << CHA_ID_LS_AES_SHIFT)
+#define CHA_ID_LS_AES_MASK     (0xfull << CHA_ID_LS_AES_SHIFT)
+#define CHA_ID_LS_AES_LP       (0x3ull << CHA_ID_LS_AES_SHIFT)
+#define CHA_ID_LS_AES_HP       (0x4ull << CHA_ID_LS_AES_SHIFT)
 
 #define CHA_ID_LS_DES_SHIFT    4
-#define CHA_ID_LS_DES_MASK             (0xfull << CHA_ID_LS_DES_SHIFT)
+#define CHA_ID_LS_DES_MASK     (0xfull << CHA_ID_LS_DES_SHIFT)
 
 #define CHA_ID_LS_ARC4_SHIFT   8
 #define CHA_ID_LS_ARC4_MASK    (0xfull << CHA_ID_LS_ARC4_SHIFT)
 
 #define CHA_ID_LS_MD_SHIFT     12
 #define CHA_ID_LS_MD_MASK      (0xfull << CHA_ID_LS_MD_SHIFT)
+#define CHA_ID_LS_MD_LP256     (0x0ull << CHA_ID_LS_MD_SHIFT)
+#define CHA_ID_LS_MD_LP512     (0x1ull << CHA_ID_LS_MD_SHIFT)
+#define CHA_ID_LS_MD_HP                (0x2ull << CHA_ID_LS_MD_SHIFT)
 
 #define CHA_ID_LS_RNG_SHIFT    16
 #define CHA_ID_LS_RNG_MASK     (0xfull << CHA_ID_LS_RNG_SHIFT)
@@ -395,10 +439,16 @@ struct caam_ctrl {
 /* AXI read cache control */
 #define MCFGR_ARCACHE_SHIFT    12
 #define MCFGR_ARCACHE_MASK     (0xf << MCFGR_ARCACHE_SHIFT)
+#define MCFGR_ARCACHE_BUFF     (0x1 << MCFGR_ARCACHE_SHIFT)
+#define MCFGR_ARCACHE_CACH     (0x2 << MCFGR_ARCACHE_SHIFT)
+#define MCFGR_ARCACHE_RALL     (0x4 << MCFGR_ARCACHE_SHIFT)
 
 /* AXI write cache control */
 #define MCFGR_AWCACHE_SHIFT    8
 #define MCFGR_AWCACHE_MASK     (0xf << MCFGR_AWCACHE_SHIFT)
+#define MCFGR_AWCACHE_BUFF     (0x1 << MCFGR_AWCACHE_SHIFT)
+#define MCFGR_AWCACHE_CACH     (0x2 << MCFGR_AWCACHE_SHIFT)
+#define MCFGR_AWCACHE_WALL     (0x8 << MCFGR_AWCACHE_SHIFT)
 
 /* AXI pipeline depth */
 #define MCFGR_AXIPIPE_SHIFT    4
index b68b74cc7b778dcd89eb75d8528fb88bc121b4f3..18cd6d1f587049a63af53d28225cbbe1fb5a866d 100644 (file)
@@ -15,7 +15,6 @@ static inline void dma_to_sec4_sg_one(struct sec4_sg_entry *sec4_sg_ptr,
 {
        sec4_sg_ptr->ptr = dma;
        sec4_sg_ptr->len = len;
-       sec4_sg_ptr->reserved = 0;
        sec4_sg_ptr->buf_pool_id = 0;
        sec4_sg_ptr->offset = offset;
 #ifdef DEBUG
@@ -106,9 +105,15 @@ static inline void dma_unmap_sg_chained(
 {
        if (unlikely(chained)) {
                int i;
+               struct scatterlist *tsg = sg;
+
+               /*
+                * Use a local copy of the sg pointer to avoid moving the
+                * head of the list pointed to by sg as we walk the list.
+                */
                for (i = 0; i < nents; i++) {
-                       dma_unmap_sg(dev, sg, 1, dir);
-                       sg = sg_next(sg);
+                       dma_unmap_sg(dev, tsg, 1, dir);
+                       tsg = sg_next(tsg);
                }
        } else if (nents) {
                dma_unmap_sg(dev, sg, nents, dir);
@@ -119,19 +124,23 @@ static inline int dma_map_sg_chained(
        struct device *dev, struct scatterlist *sg, unsigned int nents,
        enum dma_data_direction dir, bool chained)
 {
-       struct scatterlist *first = sg;
-
        if (unlikely(chained)) {
                int i;
+               struct scatterlist *tsg = sg;
+
+               /*
+                * Use a local copy of the sg pointer to avoid moving the
+                * head of the list pointed to by sg as we walk the list.
+                */
                for (i = 0; i < nents; i++) {
-                       if (!dma_map_sg(dev, sg, 1, dir)) {
-                               dma_unmap_sg_chained(dev, first, i, dir,
+                       if (!dma_map_sg(dev, tsg, 1, dir)) {
+                               dma_unmap_sg_chained(dev, sg, i, dir,
                                                     chained);
                                nents = 0;
                                break;
                        }
 
-                       sg = sg_next(sg);
+                       tsg = sg_next(tsg);
                }
        } else
                nents = dma_map_sg(dev, sg, nents, dir);
index f2e6de361fd1805094b651d3a36c6141d0ad8fbb..bb241c3ab6b9cad5fec5ed22f4a9f96b5d7da551 100644 (file)
@@ -216,6 +216,7 @@ static const struct acpi_device_id ccp_acpi_match[] = {
        { "AMDI0C00", 0 },
        { },
 };
+MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
 #endif
 
 #ifdef CONFIG_OF
@@ -223,6 +224,7 @@ static const struct of_device_id ccp_of_match[] = {
        { .compatible = "amd,ccp-seattle-v1a" },
        { },
 };
+MODULE_DEVICE_TABLE(of, ccp_of_match);
 #endif
 
 static struct platform_driver ccp_platform_driver = {
index ad47d0d6109845c810055fdb2ddaba8fa9d62039..68e8aa90fe01cbc074d70df5d5262b70834567d5 100644 (file)
@@ -334,7 +334,7 @@ static int img_hash_dma_init(struct img_hash_dev *hdev)
 
        hdev->dma_lch = dma_request_slave_channel(hdev->dev, "tx");
        if (!hdev->dma_lch) {
-               dev_err(hdev->dev, "Couldn't aquire a slave DMA channel.\n");
+               dev_err(hdev->dev, "Couldn't acquire a slave DMA channel.\n");
                return -EBUSY;
        }
        dma_conf.direction = DMA_MEM_TO_DEV;
index 402631a19a112770af83f0f4228176703e1c0b44..8f279035328125de8f8c1216392e5674def45753 100644 (file)
@@ -156,7 +156,8 @@ struct ablk_ctx {
 };
 
 struct aead_ctx {
-       struct buffer_desc *buffer;
+       struct buffer_desc *src;
+       struct buffer_desc *dst;
        struct scatterlist ivlist;
        /* used when the hmac is not on one sg entry */
        u8 *hmac_virt;
@@ -198,6 +199,15 @@ struct ixp_alg {
        int registered;
 };
 
+struct ixp_aead_alg {
+       struct aead_alg crypto;
+       const struct ix_hash_algo *hash;
+       u32 cfg_enc;
+       u32 cfg_dec;
+
+       int registered;
+};
+
 static const struct ix_hash_algo hash_alg_md5 = {
        .cfgword        = 0xAA010004,
        .icv            = "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
@@ -339,11 +349,11 @@ static void finish_scattered_hmac(struct crypt_ctl *crypt)
        struct aead_ctx *req_ctx = aead_request_ctx(req);
        struct crypto_aead *tfm = crypto_aead_reqtfm(req);
        int authsize = crypto_aead_authsize(tfm);
-       int decryptlen = req->cryptlen - authsize;
+       int decryptlen = req->assoclen + req->cryptlen - authsize;
 
        if (req_ctx->encrypt) {
                scatterwalk_map_and_copy(req_ctx->hmac_virt,
-                       req->src, decryptlen, authsize, 1);
+                       req->dst, decryptlen, authsize, 1);
        }
        dma_pool_free(buffer_pool, req_ctx->hmac_virt, crypt->icv_rev_aes);
 }
@@ -364,7 +374,8 @@ static void one_packet(dma_addr_t phys)
                struct aead_request *req = crypt->data.aead_req;
                struct aead_ctx *req_ctx = aead_request_ctx(req);
 
-               free_buf_chain(dev, req_ctx->buffer, crypt->src_buf);
+               free_buf_chain(dev, req_ctx->src, crypt->src_buf);
+               free_buf_chain(dev, req_ctx->dst, crypt->dst_buf);
                if (req_ctx->hmac_virt) {
                        finish_scattered_hmac(crypt);
                }
@@ -573,11 +584,10 @@ static int init_tfm_ablk(struct crypto_tfm *tfm)
        return init_tfm(tfm);
 }
 
-static int init_tfm_aead(struct crypto_tfm *tfm)
+static int init_tfm_aead(struct crypto_aead *tfm)
 {
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-                               sizeof(struct aead_ctx));
-       return init_tfm(tfm);
+       crypto_aead_set_reqsize(tfm, sizeof(struct aead_ctx));
+       return init_tfm(crypto_aead_tfm(tfm));
 }
 
 static void exit_tfm(struct crypto_tfm *tfm)
@@ -587,6 +597,11 @@ static void exit_tfm(struct crypto_tfm *tfm)
        free_sa_dir(&ctx->decrypt);
 }
 
+static void exit_tfm_aead(struct crypto_aead *tfm)
+{
+       exit_tfm(crypto_aead_tfm(tfm));
+}
+
 static int register_chain_var(struct crypto_tfm *tfm, u8 xpad, u32 target,
                int init_len, u32 ctx_addr, const u8 *key, int key_len)
 {
@@ -969,24 +984,6 @@ static int ablk_rfc3686_crypt(struct ablkcipher_request *req)
        return ret;
 }
 
-static int hmac_inconsistent(struct scatterlist *sg, unsigned start,
-               unsigned int nbytes)
-{
-       int offset = 0;
-
-       if (!nbytes)
-               return 0;
-
-       for (;;) {
-               if (start < offset + sg->length)
-                       break;
-
-               offset += sg->length;
-               sg = sg_next(sg);
-       }
-       return (start + nbytes > offset + sg->length);
-}
-
 static int aead_perform(struct aead_request *req, int encrypt,
                int cryptoffset, int eff_cryptlen, u8 *iv)
 {
@@ -1002,6 +999,8 @@ static int aead_perform(struct aead_request *req, int encrypt,
        struct device *dev = &pdev->dev;
        gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
                                GFP_KERNEL : GFP_ATOMIC;
+       enum dma_data_direction src_direction = DMA_BIDIRECTIONAL;
+       unsigned int lastlen;
 
        if (qmgr_stat_full(SEND_QID))
                return -EAGAIN;
@@ -1030,35 +1029,55 @@ static int aead_perform(struct aead_request *req, int encrypt,
        crypt->crypt_len = eff_cryptlen;
 
        crypt->auth_offs = 0;
-       crypt->auth_len = req->assoclen + ivsize + cryptlen;
+       crypt->auth_len = req->assoclen + cryptlen;
        BUG_ON(ivsize && !req->iv);
        memcpy(crypt->iv, req->iv, ivsize);
 
+       req_ctx->dst = NULL;
+
        if (req->src != req->dst) {
-               BUG(); /* -ENOTSUP because of my laziness */
+               struct buffer_desc dst_hook;
+
+               crypt->mode |= NPE_OP_NOT_IN_PLACE;
+               src_direction = DMA_TO_DEVICE;
+
+               buf = chainup_buffers(dev, req->dst, crypt->auth_len,
+                                     &dst_hook, flags, DMA_FROM_DEVICE);
+               req_ctx->dst = dst_hook.next;
+               crypt->dst_buf = dst_hook.phys_next;
+
+               if (!buf)
+                       goto free_buf_dst;
+
+               if (encrypt) {
+                       lastlen = buf->buf_len;
+                       if (lastlen >= authsize)
+                               crypt->icv_rev_aes = buf->phys_addr +
+                                                    buf->buf_len - authsize;
+               }
        }
 
-       /* ASSOC data */
-       buf = chainup_buffers(dev, req->assoc, req->assoclen, &src_hook,
-               flags, DMA_TO_DEVICE);
-       req_ctx->buffer = src_hook.next;
+       buf = chainup_buffers(dev, req->src, crypt->auth_len,
+                             &src_hook, flags, src_direction);
+       req_ctx->src = src_hook.next;
        crypt->src_buf = src_hook.phys_next;
        if (!buf)
-               goto out;
-       /* IV */
-       sg_init_table(&req_ctx->ivlist, 1);
-       sg_set_buf(&req_ctx->ivlist, iv, ivsize);
-       buf = chainup_buffers(dev, &req_ctx->ivlist, ivsize, buf, flags,
-                       DMA_BIDIRECTIONAL);
-       if (!buf)
-               goto free_chain;
-       if (unlikely(hmac_inconsistent(req->src, cryptlen, authsize))) {
+               goto free_buf_src;
+
+       if (!encrypt || !req_ctx->dst) {
+               lastlen = buf->buf_len;
+               if (lastlen >= authsize)
+                       crypt->icv_rev_aes = buf->phys_addr +
+                                            buf->buf_len - authsize;
+       }
+
+       if (unlikely(lastlen < authsize)) {
                /* The 12 hmac bytes are scattered,
                 * we need to copy them into a safe buffer */
                req_ctx->hmac_virt = dma_pool_alloc(buffer_pool, flags,
                                &crypt->icv_rev_aes);
                if (unlikely(!req_ctx->hmac_virt))
-                       goto free_chain;
+                       goto free_buf_src;
                if (!encrypt) {
                        scatterwalk_map_and_copy(req_ctx->hmac_virt,
                                req->src, cryptlen, authsize, 0);
@@ -1067,27 +1086,16 @@ static int aead_perform(struct aead_request *req, int encrypt,
        } else {
                req_ctx->hmac_virt = NULL;
        }
-       /* Crypt */
-       buf = chainup_buffers(dev, req->src, cryptlen + authsize, buf, flags,
-                       DMA_BIDIRECTIONAL);
-       if (!buf)
-               goto free_hmac_virt;
-       if (!req_ctx->hmac_virt) {
-               crypt->icv_rev_aes = buf->phys_addr + buf->buf_len - authsize;
-       }
 
        crypt->ctl_flags |= CTL_FLAG_PERFORM_AEAD;
        qmgr_put_entry(SEND_QID, crypt_virt2phys(crypt));
        BUG_ON(qmgr_stat_overflow(SEND_QID));
        return -EINPROGRESS;
-free_hmac_virt:
-       if (req_ctx->hmac_virt) {
-               dma_pool_free(buffer_pool, req_ctx->hmac_virt,
-                               crypt->icv_rev_aes);
-       }
-free_chain:
-       free_buf_chain(dev, req_ctx->buffer, crypt->src_buf);
-out:
+
+free_buf_src:
+       free_buf_chain(dev, req_ctx->src, crypt->src_buf);
+free_buf_dst:
+       free_buf_chain(dev, req_ctx->dst, crypt->dst_buf);
        crypt->ctl_flags = CTL_FLAG_UNUSED;
        return -ENOMEM;
 }
@@ -1173,40 +1181,12 @@ badkey:
 
 static int aead_encrypt(struct aead_request *req)
 {
-       unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(req));
-       return aead_perform(req, 1, req->assoclen + ivsize,
-                       req->cryptlen, req->iv);
+       return aead_perform(req, 1, req->assoclen, req->cryptlen, req->iv);
 }
 
 static int aead_decrypt(struct aead_request *req)
 {
-       unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(req));
-       return aead_perform(req, 0, req->assoclen + ivsize,
-                       req->cryptlen, req->iv);
-}
-
-static int aead_givencrypt(struct aead_givcrypt_request *req)
-{
-       struct crypto_aead *tfm = aead_givcrypt_reqtfm(req);
-       struct ixp_ctx *ctx = crypto_aead_ctx(tfm);
-       unsigned len, ivsize = crypto_aead_ivsize(tfm);
-       __be64 seq;
-
-       /* copied from eseqiv.c */
-       if (!ctx->salted) {
-               get_random_bytes(ctx->salt, ivsize);
-               ctx->salted = 1;
-       }
-       memcpy(req->areq.iv, ctx->salt, ivsize);
-       len = ivsize;
-       if (ivsize > sizeof(u64)) {
-               memset(req->giv, 0, ivsize - sizeof(u64));
-               len = sizeof(u64);
-       }
-       seq = cpu_to_be64(req->seq);
-       memcpy(req->giv + ivsize - len, &seq, len);
-       return aead_perform(&req->areq, 1, req->areq.assoclen,
-                       req->areq.cryptlen +ivsize, req->giv);
+       return aead_perform(req, 0, req->assoclen, req->cryptlen, req->iv);
 }
 
 static struct ixp_alg ixp4xx_algos[] = {
@@ -1319,80 +1299,77 @@ static struct ixp_alg ixp4xx_algos[] = {
        },
        .cfg_enc = CIPH_ENCR | MOD_AES | MOD_CTR,
        .cfg_dec = CIPH_ENCR | MOD_AES | MOD_CTR,
-}, {
+} };
+
+static struct ixp_aead_alg ixp4xx_aeads[] = {
+{
        .crypto = {
-               .cra_name       = "authenc(hmac(md5),cbc(des))",
-               .cra_blocksize  = DES_BLOCK_SIZE,
-               .cra_u          = { .aead = {
-                       .ivsize         = DES_BLOCK_SIZE,
-                       .maxauthsize    = MD5_DIGEST_SIZE,
-                       }
-               }
+               .base = {
+                       .cra_name       = "authenc(hmac(md5),cbc(des))",
+                       .cra_blocksize  = DES_BLOCK_SIZE,
+               },
+               .ivsize         = DES_BLOCK_SIZE,
+               .maxauthsize    = MD5_DIGEST_SIZE,
        },
        .hash = &hash_alg_md5,
        .cfg_enc = CIPH_ENCR | MOD_DES | MOD_CBC_ENC | KEYLEN_192,
        .cfg_dec = CIPH_DECR | MOD_DES | MOD_CBC_DEC | KEYLEN_192,
 }, {
        .crypto = {
-               .cra_name       = "authenc(hmac(md5),cbc(des3_ede))",
-               .cra_blocksize  = DES3_EDE_BLOCK_SIZE,
-               .cra_u          = { .aead = {
-                       .ivsize         = DES3_EDE_BLOCK_SIZE,
-                       .maxauthsize    = MD5_DIGEST_SIZE,
-                       }
-               }
+               .base = {
+                       .cra_name       = "authenc(hmac(md5),cbc(des3_ede))",
+                       .cra_blocksize  = DES3_EDE_BLOCK_SIZE,
+               },
+               .ivsize         = DES3_EDE_BLOCK_SIZE,
+               .maxauthsize    = MD5_DIGEST_SIZE,
        },
        .hash = &hash_alg_md5,
        .cfg_enc = CIPH_ENCR | MOD_3DES | MOD_CBC_ENC | KEYLEN_192,
        .cfg_dec = CIPH_DECR | MOD_3DES | MOD_CBC_DEC | KEYLEN_192,
 }, {
        .crypto = {
-               .cra_name       = "authenc(hmac(sha1),cbc(des))",
-               .cra_blocksize  = DES_BLOCK_SIZE,
-               .cra_u          = { .aead = {
+               .base = {
+                       .cra_name       = "authenc(hmac(sha1),cbc(des))",
+                       .cra_blocksize  = DES_BLOCK_SIZE,
+               },
                        .ivsize         = DES_BLOCK_SIZE,
                        .maxauthsize    = SHA1_DIGEST_SIZE,
-                       }
-               }
        },
        .hash = &hash_alg_sha1,
        .cfg_enc = CIPH_ENCR | MOD_DES | MOD_CBC_ENC | KEYLEN_192,
        .cfg_dec = CIPH_DECR | MOD_DES | MOD_CBC_DEC | KEYLEN_192,
 }, {
        .crypto = {
-               .cra_name       = "authenc(hmac(sha1),cbc(des3_ede))",
-               .cra_blocksize  = DES3_EDE_BLOCK_SIZE,
-               .cra_u          = { .aead = {
-                       .ivsize         = DES3_EDE_BLOCK_SIZE,
-                       .maxauthsize    = SHA1_DIGEST_SIZE,
-                       }
-               }
+               .base = {
+                       .cra_name       = "authenc(hmac(sha1),cbc(des3_ede))",
+                       .cra_blocksize  = DES3_EDE_BLOCK_SIZE,
+               },
+               .ivsize         = DES3_EDE_BLOCK_SIZE,
+               .maxauthsize    = SHA1_DIGEST_SIZE,
        },
        .hash = &hash_alg_sha1,
        .cfg_enc = CIPH_ENCR | MOD_3DES | MOD_CBC_ENC | KEYLEN_192,
        .cfg_dec = CIPH_DECR | MOD_3DES | MOD_CBC_DEC | KEYLEN_192,
 }, {
        .crypto = {
-               .cra_name       = "authenc(hmac(md5),cbc(aes))",
-               .cra_blocksize  = AES_BLOCK_SIZE,
-               .cra_u          = { .aead = {
-                       .ivsize         = AES_BLOCK_SIZE,
-                       .maxauthsize    = MD5_DIGEST_SIZE,
-                       }
-               }
+               .base = {
+                       .cra_name       = "authenc(hmac(md5),cbc(aes))",
+                       .cra_blocksize  = AES_BLOCK_SIZE,
+               },
+               .ivsize         = AES_BLOCK_SIZE,
+               .maxauthsize    = MD5_DIGEST_SIZE,
        },
        .hash = &hash_alg_md5,
        .cfg_enc = CIPH_ENCR | MOD_AES | MOD_CBC_ENC,
        .cfg_dec = CIPH_DECR | MOD_AES | MOD_CBC_DEC,
 }, {
        .crypto = {
-               .cra_name       = "authenc(hmac(sha1),cbc(aes))",
-               .cra_blocksize  = AES_BLOCK_SIZE,
-               .cra_u          = { .aead = {
-                       .ivsize         = AES_BLOCK_SIZE,
-                       .maxauthsize    = SHA1_DIGEST_SIZE,
-                       }
-               }
+               .base = {
+                       .cra_name       = "authenc(hmac(sha1),cbc(aes))",
+                       .cra_blocksize  = AES_BLOCK_SIZE,
+               },
+               .ivsize         = AES_BLOCK_SIZE,
+               .maxauthsize    = SHA1_DIGEST_SIZE,
        },
        .hash = &hash_alg_sha1,
        .cfg_enc = CIPH_ENCR | MOD_AES | MOD_CBC_ENC,
@@ -1436,32 +1413,20 @@ static int __init ixp_module_init(void)
                if (!support_aes && (ixp4xx_algos[i].cfg_enc & MOD_AES)) {
                        continue;
                }
-               if (!ixp4xx_algos[i].hash) {
-                       /* block ciphers */
-                       cra->cra_type = &crypto_ablkcipher_type;
-                       cra->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
-                                        CRYPTO_ALG_KERN_DRIVER_ONLY |
-                                        CRYPTO_ALG_ASYNC;
-                       if (!cra->cra_ablkcipher.setkey)
-                               cra->cra_ablkcipher.setkey = ablk_setkey;
-                       if (!cra->cra_ablkcipher.encrypt)
-                               cra->cra_ablkcipher.encrypt = ablk_encrypt;
-                       if (!cra->cra_ablkcipher.decrypt)
-                               cra->cra_ablkcipher.decrypt = ablk_decrypt;
-                       cra->cra_init = init_tfm_ablk;
-               } else {
-                       /* authenc */
-                       cra->cra_type = &crypto_aead_type;
-                       cra->cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                        CRYPTO_ALG_KERN_DRIVER_ONLY |
-                                        CRYPTO_ALG_ASYNC;
-                       cra->cra_aead.setkey = aead_setkey;
-                       cra->cra_aead.setauthsize = aead_setauthsize;
-                       cra->cra_aead.encrypt = aead_encrypt;
-                       cra->cra_aead.decrypt = aead_decrypt;
-                       cra->cra_aead.givencrypt = aead_givencrypt;
-                       cra->cra_init = init_tfm_aead;
-               }
+
+               /* block ciphers */
+               cra->cra_type = &crypto_ablkcipher_type;
+               cra->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+                                CRYPTO_ALG_KERN_DRIVER_ONLY |
+                                CRYPTO_ALG_ASYNC;
+               if (!cra->cra_ablkcipher.setkey)
+                       cra->cra_ablkcipher.setkey = ablk_setkey;
+               if (!cra->cra_ablkcipher.encrypt)
+                       cra->cra_ablkcipher.encrypt = ablk_encrypt;
+               if (!cra->cra_ablkcipher.decrypt)
+                       cra->cra_ablkcipher.decrypt = ablk_decrypt;
+               cra->cra_init = init_tfm_ablk;
+
                cra->cra_ctxsize = sizeof(struct ixp_ctx);
                cra->cra_module = THIS_MODULE;
                cra->cra_alignmask = 3;
@@ -1473,6 +1438,38 @@ static int __init ixp_module_init(void)
                else
                        ixp4xx_algos[i].registered = 1;
        }
+
+       for (i = 0; i < ARRAY_SIZE(ixp4xx_aeads); i++) {
+               struct aead_alg *cra = &ixp4xx_aeads[i].crypto;
+
+               if (snprintf(cra->base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+                            "%s"IXP_POSTFIX, cra->base.cra_name) >=
+                   CRYPTO_MAX_ALG_NAME)
+                       continue;
+               if (!support_aes && (ixp4xx_algos[i].cfg_enc & MOD_AES))
+                       continue;
+
+               /* authenc */
+               cra->base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |
+                                     CRYPTO_ALG_ASYNC;
+               cra->setkey = aead_setkey;
+               cra->setauthsize = aead_setauthsize;
+               cra->encrypt = aead_encrypt;
+               cra->decrypt = aead_decrypt;
+               cra->init = init_tfm_aead;
+               cra->exit = exit_tfm_aead;
+
+               cra->base.cra_ctxsize = sizeof(struct ixp_ctx);
+               cra->base.cra_module = THIS_MODULE;
+               cra->base.cra_alignmask = 3;
+               cra->base.cra_priority = 300;
+
+               if (crypto_register_aead(cra))
+                       printk(KERN_ERR "Failed to register '%s'\n",
+                               cra->base.cra_driver_name);
+               else
+                       ixp4xx_aeads[i].registered = 1;
+       }
        return 0;
 }
 
@@ -1481,6 +1478,11 @@ static void __exit ixp_module_exit(void)
        int num = ARRAY_SIZE(ixp4xx_algos);
        int i;
 
+       for (i = 0; i < ARRAY_SIZE(ixp4xx_aeads); i++) {
+               if (ixp4xx_aeads[i].registered)
+                       crypto_unregister_aead(&ixp4xx_aeads[i].crypto);
+       }
+
        for (i=0; i< num; i++) {
                if (ixp4xx_algos[i].registered)
                        crypto_unregister_alg(&ixp4xx_algos[i].crypto);
index 1c6f98dd88f4958003d6da53ce43933e9e016d45..0643e3366e3309de88a03e687a2d5353f5715a22 100644 (file)
@@ -533,7 +533,6 @@ static struct platform_driver marvell_cesa = {
        .probe          = mv_cesa_probe,
        .remove         = mv_cesa_remove,
        .driver         = {
-               .owner  = THIS_MODULE,
                .name   = "marvell-cesa",
                .of_match_table = mv_cesa_of_match_table,
        },
index e421c96c763a6781ac1b40f4f30eb5966dad0e91..ad7552a6998c081a61cbc0fbf5f9d2e28c629bcd 100644 (file)
@@ -14,11 +14,14 @@ config CRYPTO_DEV_NX_ENCRYPT
 config CRYPTO_DEV_NX_COMPRESS
        tristate "Compression acceleration support"
        default y
+       select CRYPTO_ALGAPI
+       select 842_DECOMPRESS
        help
          Support for PowerPC Nest (NX) compression acceleration. This
          module supports acceleration for compressing memory with the 842
-         algorithm.  One of the platform drivers must be selected also.
-         If you choose 'M' here, this module will be called nx_compress.
+         algorithm using the cryptographic API.  One of the platform
+         drivers must be selected also.  If you choose 'M' here, this
+         module will be called nx_compress.
 
 if CRYPTO_DEV_NX_COMPRESS
 
@@ -42,14 +45,4 @@ config CRYPTO_DEV_NX_COMPRESS_POWERNV
          algorithm.  This supports NX hardware on the PowerNV platform.
          If you choose 'M' here, this module will be called nx_compress_powernv.
 
-config CRYPTO_DEV_NX_COMPRESS_CRYPTO
-       tristate "Compression acceleration cryptographic interface"
-       select CRYPTO_ALGAPI
-       select 842_DECOMPRESS
-       default y
-       help
-         Support for PowerPC Nest (NX) accelerators using the cryptographic
-         API.  If you choose 'M' here, this module will be called
-         nx_compress_crypto.
-
 endif
index e1684f5adb11e0f19a398496e47038dd924eada5..b727821c8ed4eb9277113859e5530692ce86ed19 100644 (file)
@@ -10,12 +10,8 @@ nx-crypto-objs := nx.o \
                  nx-sha256.o \
                  nx-sha512.o
 
-obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS) += nx-compress.o nx-compress-platform.o
-obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o
-obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o
-obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_CRYPTO) += nx-compress-crypto.o
+obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o
+obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o
 nx-compress-objs := nx-842.o
-nx-compress-platform-objs := nx-842-platform.o
 nx-compress-pseries-objs := nx-842-pseries.o
 nx-compress-powernv-objs := nx-842-powernv.o
-nx-compress-crypto-objs := nx-842-crypto.o
diff --git a/drivers/crypto/nx/nx-842-crypto.c b/drivers/crypto/nx/nx-842-crypto.c
deleted file mode 100644 (file)
index d53a1dc..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Cryptographic API for the NX-842 hardware compression.
- *
- * 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.
- *
- * Copyright (C) IBM Corporation, 2011-2015
- *
- * Original Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
- *                   Seth Jennings <sjenning@linux.vnet.ibm.com>
- *
- * Rewrite: Dan Streetman <ddstreet@ieee.org>
- *
- * This is an interface to the NX-842 compression hardware in PowerPC
- * processors.  Most of the complexity of this drvier is due to the fact that
- * the NX-842 compression hardware requires the input and output data buffers
- * to be specifically aligned, to be a specific multiple in length, and within
- * specific minimum and maximum lengths.  Those restrictions, provided by the
- * nx-842 driver via nx842_constraints, mean this driver must use bounce
- * buffers and headers to correct misaligned in or out buffers, and to split
- * input buffers that are too large.
- *
- * This driver will fall back to software decompression if the hardware
- * decompression fails, so this driver's decompression should never fail as
- * long as the provided compressed buffer is valid.  Any compressed buffer
- * created by this driver will have a header (except ones where the input
- * perfectly matches the constraints); so users of this driver cannot simply
- * pass a compressed buffer created by this driver over to the 842 software
- * decompression library.  Instead, users must use this driver to decompress;
- * if the hardware fails or is unavailable, the compressed buffer will be
- * parsed and the header removed, and the raw 842 buffer(s) passed to the 842
- * software decompression library.
- *
- * This does not fall back to software compression, however, since the caller
- * of this function is specifically requesting hardware compression; if the
- * hardware compression fails, the caller can fall back to software
- * compression, and the raw 842 compressed buffer that the software compressor
- * creates can be passed to this driver for hardware decompression; any
- * buffer without our specific header magic is assumed to be a raw 842 buffer
- * and passed directly to the hardware.  Note that the software compression
- * library will produce a compressed buffer that is incompatible with the
- * hardware decompressor if the original input buffer length is not a multiple
- * of 8; if such a compressed buffer is passed to this driver for
- * decompression, the hardware will reject it and this driver will then pass
- * it over to the software library for decompression.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/crypto.h>
-#include <linux/vmalloc.h>
-#include <linux/sw842.h>
-#include <linux/ratelimit.h>
-
-#include "nx-842.h"
-
-/* The first 5 bits of this magic are 0x1f, which is an invalid 842 5-bit
- * template (see lib/842/842.h), so this magic number will never appear at
- * the start of a raw 842 compressed buffer.  That is important, as any buffer
- * passed to us without this magic is assumed to be a raw 842 compressed
- * buffer, and passed directly to the hardware to decompress.
- */
-#define NX842_CRYPTO_MAGIC     (0xf842)
-#define NX842_CRYPTO_GROUP_MAX (0x20)
-#define NX842_CRYPTO_HEADER_SIZE(g)                            \
-       (sizeof(struct nx842_crypto_header) +                   \
-        sizeof(struct nx842_crypto_header_group) * (g))
-#define NX842_CRYPTO_HEADER_MAX_SIZE                           \
-       NX842_CRYPTO_HEADER_SIZE(NX842_CRYPTO_GROUP_MAX)
-
-/* bounce buffer size */
-#define BOUNCE_BUFFER_ORDER    (2)
-#define BOUNCE_BUFFER_SIZE                                     \
-       ((unsigned int)(PAGE_SIZE << BOUNCE_BUFFER_ORDER))
-
-/* try longer on comp because we can fallback to sw decomp if hw is busy */
-#define COMP_BUSY_TIMEOUT      (250) /* ms */
-#define DECOMP_BUSY_TIMEOUT    (50) /* ms */
-
-struct nx842_crypto_header_group {
-       __be16 padding;                 /* unused bytes at start of group */
-       __be32 compressed_length;       /* compressed bytes in group */
-       __be32 uncompressed_length;     /* bytes after decompression */
-} __packed;
-
-struct nx842_crypto_header {
-       __be16 magic;           /* NX842_CRYPTO_MAGIC */
-       __be16 ignore;          /* decompressed end bytes to ignore */
-       u8 groups;              /* total groups in this header */
-       struct nx842_crypto_header_group group[];
-} __packed;
-
-struct nx842_crypto_param {
-       u8 *in;
-       unsigned int iremain;
-       u8 *out;
-       unsigned int oremain;
-       unsigned int ototal;
-};
-
-static int update_param(struct nx842_crypto_param *p,
-                       unsigned int slen, unsigned int dlen)
-{
-       if (p->iremain < slen)
-               return -EOVERFLOW;
-       if (p->oremain < dlen)
-               return -ENOSPC;
-
-       p->in += slen;
-       p->iremain -= slen;
-       p->out += dlen;
-       p->oremain -= dlen;
-       p->ototal += dlen;
-
-       return 0;
-}
-
-struct nx842_crypto_ctx {
-       u8 *wmem;
-       u8 *sbounce, *dbounce;
-
-       struct nx842_crypto_header header;
-       struct nx842_crypto_header_group group[NX842_CRYPTO_GROUP_MAX];
-};
-
-static int nx842_crypto_init(struct crypto_tfm *tfm)
-{
-       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       ctx->wmem = kmalloc(nx842_workmem_size(), GFP_KERNEL);
-       ctx->sbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER);
-       ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER);
-       if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) {
-               kfree(ctx->wmem);
-               free_page((unsigned long)ctx->sbounce);
-               free_page((unsigned long)ctx->dbounce);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static void nx842_crypto_exit(struct crypto_tfm *tfm)
-{
-       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       kfree(ctx->wmem);
-       free_page((unsigned long)ctx->sbounce);
-       free_page((unsigned long)ctx->dbounce);
-}
-
-static int read_constraints(struct nx842_constraints *c)
-{
-       int ret;
-
-       ret = nx842_constraints(c);
-       if (ret) {
-               pr_err_ratelimited("could not get nx842 constraints : %d\n",
-                                  ret);
-               return ret;
-       }
-
-       /* limit maximum, to always have enough bounce buffer to decompress */
-       if (c->maximum > BOUNCE_BUFFER_SIZE) {
-               c->maximum = BOUNCE_BUFFER_SIZE;
-               pr_info_once("limiting nx842 maximum to %x\n", c->maximum);
-       }
-
-       return 0;
-}
-
-static int nx842_crypto_add_header(struct nx842_crypto_header *hdr, u8 *buf)
-{
-       int s = NX842_CRYPTO_HEADER_SIZE(hdr->groups);
-
-       /* compress should have added space for header */
-       if (s > be16_to_cpu(hdr->group[0].padding)) {
-               pr_err("Internal error: no space for header\n");
-               return -EINVAL;
-       }
-
-       memcpy(buf, hdr, s);
-
-       print_hex_dump_debug("header ", DUMP_PREFIX_OFFSET, 16, 1, buf, s, 0);
-
-       return 0;
-}
-
-static int compress(struct nx842_crypto_ctx *ctx,
-                   struct nx842_crypto_param *p,
-                   struct nx842_crypto_header_group *g,
-                   struct nx842_constraints *c,
-                   u16 *ignore,
-                   unsigned int hdrsize)
-{
-       unsigned int slen = p->iremain, dlen = p->oremain, tmplen;
-       unsigned int adj_slen = slen;
-       u8 *src = p->in, *dst = p->out;
-       int ret, dskip = 0;
-       ktime_t timeout;
-
-       if (p->iremain == 0)
-               return -EOVERFLOW;
-
-       if (p->oremain == 0 || hdrsize + c->minimum > dlen)
-               return -ENOSPC;
-
-       if (slen % c->multiple)
-               adj_slen = round_up(slen, c->multiple);
-       if (slen < c->minimum)
-               adj_slen = c->minimum;
-       if (slen > c->maximum)
-               adj_slen = slen = c->maximum;
-       if (adj_slen > slen || (u64)src % c->alignment) {
-               adj_slen = min(adj_slen, BOUNCE_BUFFER_SIZE);
-               slen = min(slen, BOUNCE_BUFFER_SIZE);
-               if (adj_slen > slen)
-                       memset(ctx->sbounce + slen, 0, adj_slen - slen);
-               memcpy(ctx->sbounce, src, slen);
-               src = ctx->sbounce;
-               slen = adj_slen;
-               pr_debug("using comp sbounce buffer, len %x\n", slen);
-       }
-
-       dst += hdrsize;
-       dlen -= hdrsize;
-
-       if ((u64)dst % c->alignment) {
-               dskip = (int)(PTR_ALIGN(dst, c->alignment) - dst);
-               dst += dskip;
-               dlen -= dskip;
-       }
-       if (dlen % c->multiple)
-               dlen = round_down(dlen, c->multiple);
-       if (dlen < c->minimum) {
-nospc:
-               dst = ctx->dbounce;
-               dlen = min(p->oremain, BOUNCE_BUFFER_SIZE);
-               dlen = round_down(dlen, c->multiple);
-               dskip = 0;
-               pr_debug("using comp dbounce buffer, len %x\n", dlen);
-       }
-       if (dlen > c->maximum)
-               dlen = c->maximum;
-
-       tmplen = dlen;
-       timeout = ktime_add_ms(ktime_get(), COMP_BUSY_TIMEOUT);
-       do {
-               dlen = tmplen; /* reset dlen, if we're retrying */
-               ret = nx842_compress(src, slen, dst, &dlen, ctx->wmem);
-               /* possibly we should reduce the slen here, instead of
-                * retrying with the dbounce buffer?
-                */
-               if (ret == -ENOSPC && dst != ctx->dbounce)
-                       goto nospc;
-       } while (ret == -EBUSY && ktime_before(ktime_get(), timeout));
-       if (ret)
-               return ret;
-
-       dskip += hdrsize;
-
-       if (dst == ctx->dbounce)
-               memcpy(p->out + dskip, dst, dlen);
-
-       g->padding = cpu_to_be16(dskip);
-       g->compressed_length = cpu_to_be32(dlen);
-       g->uncompressed_length = cpu_to_be32(slen);
-
-       if (p->iremain < slen) {
-               *ignore = slen - p->iremain;
-               slen = p->iremain;
-       }
-
-       pr_debug("compress slen %x ignore %x dlen %x padding %x\n",
-                slen, *ignore, dlen, dskip);
-
-       return update_param(p, slen, dskip + dlen);
-}
-
-static int nx842_crypto_compress(struct crypto_tfm *tfm,
-                                const u8 *src, unsigned int slen,
-                                u8 *dst, unsigned int *dlen)
-{
-       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct nx842_crypto_header *hdr = &ctx->header;
-       struct nx842_crypto_param p;
-       struct nx842_constraints c;
-       unsigned int groups, hdrsize, h;
-       int ret, n;
-       bool add_header;
-       u16 ignore = 0;
-
-       p.in = (u8 *)src;
-       p.iremain = slen;
-       p.out = dst;
-       p.oremain = *dlen;
-       p.ototal = 0;
-
-       *dlen = 0;
-
-       ret = read_constraints(&c);
-       if (ret)
-               return ret;
-
-       groups = min_t(unsigned int, NX842_CRYPTO_GROUP_MAX,
-                      DIV_ROUND_UP(p.iremain, c.maximum));
-       hdrsize = NX842_CRYPTO_HEADER_SIZE(groups);
-
-       /* skip adding header if the buffers meet all constraints */
-       add_header = (p.iremain % c.multiple    ||
-                     p.iremain < c.minimum     ||
-                     p.iremain > c.maximum     ||
-                     (u64)p.in % c.alignment   ||
-                     p.oremain % c.multiple    ||
-                     p.oremain < c.minimum     ||
-                     p.oremain > c.maximum     ||
-                     (u64)p.out % c.alignment);
-
-       hdr->magic = cpu_to_be16(NX842_CRYPTO_MAGIC);
-       hdr->groups = 0;
-       hdr->ignore = 0;
-
-       while (p.iremain > 0) {
-               n = hdr->groups++;
-               if (hdr->groups > NX842_CRYPTO_GROUP_MAX)
-                       return -ENOSPC;
-
-               /* header goes before first group */
-               h = !n && add_header ? hdrsize : 0;
-
-               if (ignore)
-                       pr_warn("interal error, ignore is set %x\n", ignore);
-
-               ret = compress(ctx, &p, &hdr->group[n], &c, &ignore, h);
-               if (ret)
-                       return ret;
-       }
-
-       if (!add_header && hdr->groups > 1) {
-               pr_err("Internal error: No header but multiple groups\n");
-               return -EINVAL;
-       }
-
-       /* ignore indicates the input stream needed to be padded */
-       hdr->ignore = cpu_to_be16(ignore);
-       if (ignore)
-               pr_debug("marked %d bytes as ignore\n", ignore);
-
-       if (add_header)
-               ret = nx842_crypto_add_header(hdr, dst);
-       if (ret)
-               return ret;
-
-       *dlen = p.ototal;
-
-       pr_debug("compress total slen %x dlen %x\n", slen, *dlen);
-
-       return 0;
-}
-
-static int decompress(struct nx842_crypto_ctx *ctx,
-                     struct nx842_crypto_param *p,
-                     struct nx842_crypto_header_group *g,
-                     struct nx842_constraints *c,
-                     u16 ignore,
-                     bool usehw)
-{
-       unsigned int slen = be32_to_cpu(g->compressed_length);
-       unsigned int required_len = be32_to_cpu(g->uncompressed_length);
-       unsigned int dlen = p->oremain, tmplen;
-       unsigned int adj_slen = slen;
-       u8 *src = p->in, *dst = p->out;
-       u16 padding = be16_to_cpu(g->padding);
-       int ret, spadding = 0, dpadding = 0;
-       ktime_t timeout;
-
-       if (!slen || !required_len)
-               return -EINVAL;
-
-       if (p->iremain <= 0 || padding + slen > p->iremain)
-               return -EOVERFLOW;
-
-       if (p->oremain <= 0 || required_len - ignore > p->oremain)
-               return -ENOSPC;
-
-       src += padding;
-
-       if (!usehw)
-               goto usesw;
-
-       if (slen % c->multiple)
-               adj_slen = round_up(slen, c->multiple);
-       if (slen < c->minimum)
-               adj_slen = c->minimum;
-       if (slen > c->maximum)
-               goto usesw;
-       if (slen < adj_slen || (u64)src % c->alignment) {
-               /* we can append padding bytes because the 842 format defines
-                * an "end" template (see lib/842/842_decompress.c) and will
-                * ignore any bytes following it.
-                */
-               if (slen < adj_slen)
-                       memset(ctx->sbounce + slen, 0, adj_slen - slen);
-               memcpy(ctx->sbounce, src, slen);
-               src = ctx->sbounce;
-               spadding = adj_slen - slen;
-               slen = adj_slen;
-               pr_debug("using decomp sbounce buffer, len %x\n", slen);
-       }
-
-       if (dlen % c->multiple)
-               dlen = round_down(dlen, c->multiple);
-       if (dlen < required_len || (u64)dst % c->alignment) {
-               dst = ctx->dbounce;
-               dlen = min(required_len, BOUNCE_BUFFER_SIZE);
-               pr_debug("using decomp dbounce buffer, len %x\n", dlen);
-       }
-       if (dlen < c->minimum)
-               goto usesw;
-       if (dlen > c->maximum)
-               dlen = c->maximum;
-
-       tmplen = dlen;
-       timeout = ktime_add_ms(ktime_get(), DECOMP_BUSY_TIMEOUT);
-       do {
-               dlen = tmplen; /* reset dlen, if we're retrying */
-               ret = nx842_decompress(src, slen, dst, &dlen, ctx->wmem);
-       } while (ret == -EBUSY && ktime_before(ktime_get(), timeout));
-       if (ret) {
-usesw:
-               /* reset everything, sw doesn't have constraints */
-               src = p->in + padding;
-               slen = be32_to_cpu(g->compressed_length);
-               spadding = 0;
-               dst = p->out;
-               dlen = p->oremain;
-               dpadding = 0;
-               if (dlen < required_len) { /* have ignore bytes */
-                       dst = ctx->dbounce;
-                       dlen = BOUNCE_BUFFER_SIZE;
-               }
-               pr_info_ratelimited("using software 842 decompression\n");
-               ret = sw842_decompress(src, slen, dst, &dlen);
-       }
-       if (ret)
-               return ret;
-
-       slen -= spadding;
-
-       dlen -= ignore;
-       if (ignore)
-               pr_debug("ignoring last %x bytes\n", ignore);
-
-       if (dst == ctx->dbounce)
-               memcpy(p->out, dst, dlen);
-
-       pr_debug("decompress slen %x padding %x dlen %x ignore %x\n",
-                slen, padding, dlen, ignore);
-
-       return update_param(p, slen + padding, dlen);
-}
-
-static int nx842_crypto_decompress(struct crypto_tfm *tfm,
-                                  const u8 *src, unsigned int slen,
-                                  u8 *dst, unsigned int *dlen)
-{
-       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct nx842_crypto_header *hdr;
-       struct nx842_crypto_param p;
-       struct nx842_constraints c;
-       int n, ret, hdr_len;
-       u16 ignore = 0;
-       bool usehw = true;
-
-       p.in = (u8 *)src;
-       p.iremain = slen;
-       p.out = dst;
-       p.oremain = *dlen;
-       p.ototal = 0;
-
-       *dlen = 0;
-
-       if (read_constraints(&c))
-               usehw = false;
-
-       hdr = (struct nx842_crypto_header *)src;
-
-       /* If it doesn't start with our header magic number, assume it's a raw
-        * 842 compressed buffer and pass it directly to the hardware driver
-        */
-       if (be16_to_cpu(hdr->magic) != NX842_CRYPTO_MAGIC) {
-               struct nx842_crypto_header_group g = {
-                       .padding =              0,
-                       .compressed_length =    cpu_to_be32(p.iremain),
-                       .uncompressed_length =  cpu_to_be32(p.oremain),
-               };
-
-               ret = decompress(ctx, &p, &g, &c, 0, usehw);
-               if (ret)
-                       return ret;
-
-               *dlen = p.ototal;
-
-               return 0;
-       }
-
-       if (!hdr->groups) {
-               pr_err("header has no groups\n");
-               return -EINVAL;
-       }
-       if (hdr->groups > NX842_CRYPTO_GROUP_MAX) {
-               pr_err("header has too many groups %x, max %x\n",
-                      hdr->groups, NX842_CRYPTO_GROUP_MAX);
-               return -EINVAL;
-       }
-
-       hdr_len = NX842_CRYPTO_HEADER_SIZE(hdr->groups);
-       if (hdr_len > slen)
-               return -EOVERFLOW;
-
-       memcpy(&ctx->header, src, hdr_len);
-       hdr = &ctx->header;
-
-       for (n = 0; n < hdr->groups; n++) {
-               /* ignore applies to last group */
-               if (n + 1 == hdr->groups)
-                       ignore = be16_to_cpu(hdr->ignore);
-
-               ret = decompress(ctx, &p, &hdr->group[n], &c, ignore, usehw);
-               if (ret)
-                       return ret;
-       }
-
-       *dlen = p.ototal;
-
-       pr_debug("decompress total slen %x dlen %x\n", slen, *dlen);
-
-       return 0;
-}
-
-static struct crypto_alg alg = {
-       .cra_name               = "842",
-       .cra_driver_name        = "842-nx",
-       .cra_priority           = 300,
-       .cra_flags              = CRYPTO_ALG_TYPE_COMPRESS,
-       .cra_ctxsize            = sizeof(struct nx842_crypto_ctx),
-       .cra_module             = THIS_MODULE,
-       .cra_init               = nx842_crypto_init,
-       .cra_exit               = nx842_crypto_exit,
-       .cra_u                  = { .compress = {
-       .coa_compress           = nx842_crypto_compress,
-       .coa_decompress         = nx842_crypto_decompress } }
-};
-
-static int __init nx842_crypto_mod_init(void)
-{
-       return crypto_register_alg(&alg);
-}
-module_init(nx842_crypto_mod_init);
-
-static void __exit nx842_crypto_mod_exit(void)
-{
-       crypto_unregister_alg(&alg);
-}
-module_exit(nx842_crypto_mod_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IBM PowerPC Nest (NX) 842 Hardware Compression Interface");
-MODULE_ALIAS_CRYPTO("842");
-MODULE_ALIAS_CRYPTO("842-nx");
-MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
diff --git a/drivers/crypto/nx/nx-842-platform.c b/drivers/crypto/nx/nx-842-platform.c
deleted file mode 100644 (file)
index 664f13d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-
-#include "nx-842.h"
-
-/* this is needed, separate from the main nx-842.c driver, because that main
- * driver loads the platform drivers during its init(), and it expects one
- * (or none) of the platform drivers to set this pointer to its driver.
- * That means this pointer can't be in the main nx-842 driver, because it
- * wouldn't be accessible until after the main driver loaded, which wouldn't
- * be possible as it's waiting for the platform driver to load.  So place it
- * here.
- */
-static struct nx842_driver *driver;
-static DEFINE_SPINLOCK(driver_lock);
-
-struct nx842_driver *nx842_platform_driver(void)
-{
-       return driver;
-}
-EXPORT_SYMBOL_GPL(nx842_platform_driver);
-
-bool nx842_platform_driver_set(struct nx842_driver *_driver)
-{
-       bool ret = false;
-
-       spin_lock(&driver_lock);
-
-       if (!driver) {
-               driver = _driver;
-               ret = true;
-       } else
-               WARN(1, "can't set platform driver, already set to %s\n",
-                    driver->name);
-
-       spin_unlock(&driver_lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(nx842_platform_driver_set);
-
-/* only call this from the platform driver exit function */
-void nx842_platform_driver_unset(struct nx842_driver *_driver)
-{
-       spin_lock(&driver_lock);
-
-       if (driver == _driver)
-               driver = NULL;
-       else if (driver)
-               WARN(1, "can't unset platform driver %s, currently set to %s\n",
-                    _driver->name, driver->name);
-       else
-               WARN(1, "can't unset platform driver, already unset\n");
-
-       spin_unlock(&driver_lock);
-}
-EXPORT_SYMBOL_GPL(nx842_platform_driver_unset);
-
-bool nx842_platform_driver_get(void)
-{
-       bool ret = false;
-
-       spin_lock(&driver_lock);
-
-       if (driver)
-               ret = try_module_get(driver->owner);
-
-       spin_unlock(&driver_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(nx842_platform_driver_get);
-
-void nx842_platform_driver_put(void)
-{
-       spin_lock(&driver_lock);
-
-       if (driver)
-               module_put(driver->owner);
-
-       spin_unlock(&driver_lock);
-}
-EXPORT_SYMBOL_GPL(nx842_platform_driver_put);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
-MODULE_DESCRIPTION("842 H/W Compression platform driver");
index 33b3b0abf4ae7f555f12b5b02bd4e0759a6d5e2b..3750e13d872181c425feefafbc259c03024b75e0 100644 (file)
@@ -26,6 +26,8 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
 MODULE_DESCRIPTION("842 H/W Compression driver for IBM PowerNV processors");
+MODULE_ALIAS_CRYPTO("842");
+MODULE_ALIAS_CRYPTO("842-nx");
 
 #define WORKMEM_ALIGN  (CRB_ALIGN)
 #define CSB_WAIT_MAX   (5000) /* ms */
@@ -344,7 +346,8 @@ static int wait_for_csb(struct nx842_workmem *wmem,
        }
 
        /* successful completion */
-       pr_debug_ratelimited("Processed %u bytes in %lu us\n", csb->count,
+       pr_debug_ratelimited("Processed %u bytes in %lu us\n",
+                            be32_to_cpu(csb->count),
                             (unsigned long)ktime_us_delta(now, start));
 
        return 0;
@@ -581,9 +584,29 @@ static struct nx842_driver nx842_powernv_driver = {
        .decompress =   nx842_powernv_decompress,
 };
 
+static int nx842_powernv_crypto_init(struct crypto_tfm *tfm)
+{
+       return nx842_crypto_init(tfm, &nx842_powernv_driver);
+}
+
+static struct crypto_alg nx842_powernv_alg = {
+       .cra_name               = "842",
+       .cra_driver_name        = "842-nx",
+       .cra_priority           = 300,
+       .cra_flags              = CRYPTO_ALG_TYPE_COMPRESS,
+       .cra_ctxsize            = sizeof(struct nx842_crypto_ctx),
+       .cra_module             = THIS_MODULE,
+       .cra_init               = nx842_powernv_crypto_init,
+       .cra_exit               = nx842_crypto_exit,
+       .cra_u                  = { .compress = {
+       .coa_compress           = nx842_crypto_compress,
+       .coa_decompress         = nx842_crypto_decompress } }
+};
+
 static __init int nx842_powernv_init(void)
 {
        struct device_node *dn;
+       int ret;
 
        /* verify workmem size/align restrictions */
        BUILD_BUG_ON(WORKMEM_ALIGN % CRB_ALIGN);
@@ -594,17 +617,14 @@ static __init int nx842_powernv_init(void)
        BUILD_BUG_ON(DDE_BUFFER_ALIGN % DDE_BUFFER_SIZE_MULT);
        BUILD_BUG_ON(DDE_BUFFER_SIZE_MULT % DDE_BUFFER_LAST_MULT);
 
-       pr_info("loading\n");
-
        for_each_compatible_node(dn, NULL, "ibm,power-nx")
                nx842_powernv_probe(dn);
 
-       if (!nx842_ct) {
-               pr_err("no coprocessors found\n");
+       if (!nx842_ct)
                return -ENODEV;
-       }
 
-       if (!nx842_platform_driver_set(&nx842_powernv_driver)) {
+       ret = crypto_register_alg(&nx842_powernv_alg);
+       if (ret) {
                struct nx842_coproc *coproc, *n;
 
                list_for_each_entry_safe(coproc, n, &nx842_coprocs, list) {
@@ -612,11 +632,9 @@ static __init int nx842_powernv_init(void)
                        kfree(coproc);
                }
 
-               return -EEXIST;
+               return ret;
        }
 
-       pr_info("loaded\n");
-
        return 0;
 }
 module_init(nx842_powernv_init);
@@ -625,13 +643,11 @@ static void __exit nx842_powernv_exit(void)
 {
        struct nx842_coproc *coproc, *n;
 
-       nx842_platform_driver_unset(&nx842_powernv_driver);
+       crypto_unregister_alg(&nx842_powernv_alg);
 
        list_for_each_entry_safe(coproc, n, &nx842_coprocs, list) {
                list_del(&coproc->list);
                kfree(coproc);
        }
-
-       pr_info("unloaded\n");
 }
 module_exit(nx842_powernv_exit);
index 3040a6091bf2797a8a959f375651eb84f54464e4..f4cbde03c6adda03c497f0ce08a358081f78d6d6 100644 (file)
@@ -29,6 +29,8 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Robert Jennings <rcj@linux.vnet.ibm.com>");
 MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
+MODULE_ALIAS_CRYPTO("842");
+MODULE_ALIAS_CRYPTO("842-nx");
 
 static struct nx842_constraints nx842_pseries_constraints = {
        .alignment =    DDE_BUFFER_ALIGN,
@@ -99,11 +101,6 @@ struct nx842_workmem {
 #define NX842_HW_PAGE_SIZE     (4096)
 #define NX842_HW_PAGE_MASK     (~(NX842_HW_PAGE_SIZE-1))
 
-enum nx842_status {
-       UNAVAILABLE,
-       AVAILABLE
-};
-
 struct ibm_nx842_counters {
        atomic64_t comp_complete;
        atomic64_t comp_failed;
@@ -121,7 +118,6 @@ static struct nx842_devdata {
        unsigned int max_sg_len;
        unsigned int max_sync_size;
        unsigned int max_sync_sg;
-       enum nx842_status status;
 } __rcu *devdata;
 static DEFINE_SPINLOCK(devdata_mutex);
 
@@ -230,9 +226,12 @@ static int nx842_validate_result(struct device *dev,
        switch (csb->completion_code) {
        case 0: /* Completed without error */
                break;
-       case 64: /* Target bytes > Source bytes during compression */
+       case 64: /* Compression ok, but output larger than input */
+               dev_dbg(dev, "%s: output size larger than input size\n",
+                                       __func__);
+               break;
        case 13: /* Output buffer too small */
-               dev_dbg(dev, "%s: Compression output larger than input\n",
+               dev_dbg(dev, "%s: Out of space in output buffer\n",
                                        __func__);
                return -ENOSPC;
        case 66: /* Input data contains an illegal template field */
@@ -537,41 +536,36 @@ static int nx842_OF_set_defaults(struct nx842_devdata *devdata)
                devdata->max_sync_size = 0;
                devdata->max_sync_sg = 0;
                devdata->max_sg_len = 0;
-               devdata->status = UNAVAILABLE;
                return 0;
        } else
                return -ENOENT;
 }
 
 /**
- * nx842_OF_upd_status -- Update the device info from OF status prop
+ * nx842_OF_upd_status -- Check the device info from OF status prop
  *
  * The status property indicates if the accelerator is enabled.  If the
  * device is in the OF tree it indicates that the hardware is present.
  * The status field indicates if the device is enabled when the status
  * is 'okay'.  Otherwise the device driver will be disabled.
  *
- * @devdata - struct nx842_devdata to update
  * @prop - struct property point containing the maxsyncop for the update
  *
  * Returns:
  *  0 - Device is available
- *  -EINVAL - Device is not available
+ *  -ENODEV - Device is not available
  */
-static int nx842_OF_upd_status(struct nx842_devdata *devdata,
-                                       struct property *prop) {
-       int ret = 0;
+static int nx842_OF_upd_status(struct property *prop)
+{
        const char *status = (const char *)prop->value;
 
-       if (!strncmp(status, "okay", (size_t)prop->length)) {
-               devdata->status = AVAILABLE;
-       } else {
-               dev_info(devdata->dev, "%s: status '%s' is not 'okay'\n",
-                               __func__, status);
-               devdata->status = UNAVAILABLE;
-       }
+       if (!strncmp(status, "okay", (size_t)prop->length))
+               return 0;
+       if (!strncmp(status, "disabled", (size_t)prop->length))
+               return -ENODEV;
+       dev_info(devdata->dev, "%s: unknown status '%s'\n", __func__, status);
 
-       return ret;
+       return -EINVAL;
 }
 
 /**
@@ -735,6 +729,10 @@ static int nx842_OF_upd(struct property *new_prop)
        int ret = 0;
        unsigned long flags;
 
+       new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
+       if (!new_devdata)
+               return -ENOMEM;
+
        spin_lock_irqsave(&devdata_mutex, flags);
        old_devdata = rcu_dereference_check(devdata,
                        lockdep_is_held(&devdata_mutex));
@@ -744,16 +742,10 @@ static int nx842_OF_upd(struct property *new_prop)
        if (!old_devdata || !of_node) {
                pr_err("%s: device is not available\n", __func__);
                spin_unlock_irqrestore(&devdata_mutex, flags);
+               kfree(new_devdata);
                return -ENODEV;
        }
 
-       new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
-       if (!new_devdata) {
-               dev_err(old_devdata->dev, "%s: Could not allocate memory for device data\n", __func__);
-               ret = -ENOMEM;
-               goto error_out;
-       }
-
        memcpy(new_devdata, old_devdata, sizeof(*old_devdata));
        new_devdata->counters = old_devdata->counters;
 
@@ -777,7 +769,7 @@ static int nx842_OF_upd(struct property *new_prop)
                goto out;
 
        /* Perform property updates */
-       ret = nx842_OF_upd_status(new_devdata, status);
+       ret = nx842_OF_upd_status(status);
        if (ret)
                goto error_out;
 
@@ -970,13 +962,43 @@ static struct nx842_driver nx842_pseries_driver = {
        .decompress =   nx842_pseries_decompress,
 };
 
-static int __init nx842_probe(struct vio_dev *viodev,
-                                 const struct vio_device_id *id)
+static int nx842_pseries_crypto_init(struct crypto_tfm *tfm)
+{
+       return nx842_crypto_init(tfm, &nx842_pseries_driver);
+}
+
+static struct crypto_alg nx842_pseries_alg = {
+       .cra_name               = "842",
+       .cra_driver_name        = "842-nx",
+       .cra_priority           = 300,
+       .cra_flags              = CRYPTO_ALG_TYPE_COMPRESS,
+       .cra_ctxsize            = sizeof(struct nx842_crypto_ctx),
+       .cra_module             = THIS_MODULE,
+       .cra_init               = nx842_pseries_crypto_init,
+       .cra_exit               = nx842_crypto_exit,
+       .cra_u                  = { .compress = {
+       .coa_compress           = nx842_crypto_compress,
+       .coa_decompress         = nx842_crypto_decompress } }
+};
+
+static int nx842_probe(struct vio_dev *viodev,
+                      const struct vio_device_id *id)
 {
        struct nx842_devdata *old_devdata, *new_devdata = NULL;
        unsigned long flags;
        int ret = 0;
 
+       new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
+       if (!new_devdata)
+               return -ENOMEM;
+
+       new_devdata->counters = kzalloc(sizeof(*new_devdata->counters),
+                       GFP_NOFS);
+       if (!new_devdata->counters) {
+               kfree(new_devdata);
+               return -ENOMEM;
+       }
+
        spin_lock_irqsave(&devdata_mutex, flags);
        old_devdata = rcu_dereference_check(devdata,
                        lockdep_is_held(&devdata_mutex));
@@ -989,21 +1011,6 @@ static int __init nx842_probe(struct vio_dev *viodev,
 
        dev_set_drvdata(&viodev->dev, NULL);
 
-       new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
-       if (!new_devdata) {
-               dev_err(&viodev->dev, "%s: Could not allocate memory for device data\n", __func__);
-               ret = -ENOMEM;
-               goto error_unlock;
-       }
-
-       new_devdata->counters = kzalloc(sizeof(*new_devdata->counters),
-                       GFP_NOFS);
-       if (!new_devdata->counters) {
-               dev_err(&viodev->dev, "%s: Could not allocate memory for performance counters\n", __func__);
-               ret = -ENOMEM;
-               goto error_unlock;
-       }
-
        new_devdata->vdev = viodev;
        new_devdata->dev = &viodev->dev;
        nx842_OF_set_defaults(new_devdata);
@@ -1016,9 +1023,12 @@ static int __init nx842_probe(struct vio_dev *viodev,
        of_reconfig_notifier_register(&nx842_of_nb);
 
        ret = nx842_OF_upd(NULL);
-       if (ret && ret != -ENODEV) {
-               dev_err(&viodev->dev, "could not parse device tree. %d\n", ret);
-               ret = -1;
+       if (ret)
+               goto error;
+
+       ret = crypto_register_alg(&nx842_pseries_alg);
+       if (ret) {
+               dev_err(&viodev->dev, "could not register comp alg: %d\n", ret);
                goto error;
        }
 
@@ -1043,7 +1053,7 @@ error:
        return ret;
 }
 
-static int __exit nx842_remove(struct vio_dev *viodev)
+static int nx842_remove(struct vio_dev *viodev)
 {
        struct nx842_devdata *old_devdata;
        unsigned long flags;
@@ -1051,6 +1061,8 @@ static int __exit nx842_remove(struct vio_dev *viodev)
        pr_info("Removing IBM Power 842 compression device\n");
        sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
 
+       crypto_unregister_alg(&nx842_pseries_alg);
+
        spin_lock_irqsave(&devdata_mutex, flags);
        old_devdata = rcu_dereference_check(devdata,
                        lockdep_is_held(&devdata_mutex));
@@ -1074,18 +1086,16 @@ static struct vio_device_id nx842_vio_driver_ids[] = {
 static struct vio_driver nx842_vio_driver = {
        .name = KBUILD_MODNAME,
        .probe = nx842_probe,
-       .remove = __exit_p(nx842_remove),
+       .remove = nx842_remove,
        .get_desired_dma = nx842_get_desired_dma,
        .id_table = nx842_vio_driver_ids,
 };
 
-static int __init nx842_init(void)
+static int __init nx842_pseries_init(void)
 {
        struct nx842_devdata *new_devdata;
        int ret;
 
-       pr_info("Registering IBM Power 842 compression driver\n");
-
        if (!of_find_compatible_node(NULL, NULL, "ibm,compression"))
                return -ENODEV;
 
@@ -1095,7 +1105,6 @@ static int __init nx842_init(void)
                pr_err("Could not allocate memory for device data\n");
                return -ENOMEM;
        }
-       new_devdata->status = UNAVAILABLE;
        RCU_INIT_POINTER(devdata, new_devdata);
 
        ret = vio_register_driver(&nx842_vio_driver);
@@ -1106,24 +1115,18 @@ static int __init nx842_init(void)
                return ret;
        }
 
-       if (!nx842_platform_driver_set(&nx842_pseries_driver)) {
-               vio_unregister_driver(&nx842_vio_driver);
-               kfree(new_devdata);
-               return -EEXIST;
-       }
-
        return 0;
 }
 
-module_init(nx842_init);
+module_init(nx842_pseries_init);
 
-static void __exit nx842_exit(void)
+static void __exit nx842_pseries_exit(void)
 {
        struct nx842_devdata *old_devdata;
        unsigned long flags;
 
-       pr_info("Exiting IBM Power 842 compression driver\n");
-       nx842_platform_driver_unset(&nx842_pseries_driver);
+       crypto_unregister_alg(&nx842_pseries_alg);
+
        spin_lock_irqsave(&devdata_mutex, flags);
        old_devdata = rcu_dereference_check(devdata,
                        lockdep_is_held(&devdata_mutex));
@@ -1136,5 +1139,5 @@ static void __exit nx842_exit(void)
        vio_unregister_driver(&nx842_vio_driver);
 }
 
-module_exit(nx842_exit);
+module_exit(nx842_pseries_exit);
 
index 6e5e0d60d0c8c9b887a19fe9e9f7a193ee298882..046c1c45411bbc7fe21b5207479644130183ac68 100644 (file)
@@ -1,10 +1,5 @@
 /*
- * Driver frontend for IBM Power 842 compression accelerator
- *
- * Copyright (C) 2015 Dan Streetman, IBM Corp
- *
- * Designer of the Power data compression engine:
- *   Bulent Abali <abali@us.ibm.com>
+ * Cryptographic API for the NX-842 hardware compression.
  *
  * 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
  * 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) IBM Corporation, 2011-2015
+ *
+ * Designer of the Power data compression engine:
+ *   Bulent Abali <abali@us.ibm.com>
+ *
+ * Original Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
+ *                   Seth Jennings <sjenning@linux.vnet.ibm.com>
+ *
+ * Rewrite: Dan Streetman <ddstreet@ieee.org>
+ *
+ * This is an interface to the NX-842 compression hardware in PowerPC
+ * processors.  Most of the complexity of this drvier is due to the fact that
+ * the NX-842 compression hardware requires the input and output data buffers
+ * to be specifically aligned, to be a specific multiple in length, and within
+ * specific minimum and maximum lengths.  Those restrictions, provided by the
+ * nx-842 driver via nx842_constraints, mean this driver must use bounce
+ * buffers and headers to correct misaligned in or out buffers, and to split
+ * input buffers that are too large.
+ *
+ * This driver will fall back to software decompression if the hardware
+ * decompression fails, so this driver's decompression should never fail as
+ * long as the provided compressed buffer is valid.  Any compressed buffer
+ * created by this driver will have a header (except ones where the input
+ * perfectly matches the constraints); so users of this driver cannot simply
+ * pass a compressed buffer created by this driver over to the 842 software
+ * decompression library.  Instead, users must use this driver to decompress;
+ * if the hardware fails or is unavailable, the compressed buffer will be
+ * parsed and the header removed, and the raw 842 buffer(s) passed to the 842
+ * software decompression library.
+ *
+ * This does not fall back to software compression, however, since the caller
+ * of this function is specifically requesting hardware compression; if the
+ * hardware compression fails, the caller can fall back to software
+ * compression, and the raw 842 compressed buffer that the software compressor
+ * creates can be passed to this driver for hardware decompression; any
+ * buffer without our specific header magic is assumed to be a raw 842 buffer
+ * and passed directly to the hardware.  Note that the software compression
+ * library will produce a compressed buffer that is incompatible with the
+ * hardware decompressor if the original input buffer length is not a multiple
+ * of 8; if such a compressed buffer is passed to this driver for
+ * decompression, the hardware will reject it and this driver will then pass
+ * it over to the software library for decompression.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include "nx-842.h"
+#include <linux/vmalloc.h>
+#include <linux/sw842.h>
+#include <linux/spinlock.h>
 
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
-MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
+#include "nx-842.h"
 
-/**
- * nx842_constraints
- *
- * This provides the driver's constraints.  Different nx842 implementations
- * may have varying requirements.  The constraints are:
- *   @alignment:       All buffers should be aligned to this
- *   @multiple:                All buffer lengths should be a multiple of this
- *   @minimum:         Buffer lengths must not be less than this amount
- *   @maximum:         Buffer lengths must not be more than this amount
- *
- * The constraints apply to all buffers and lengths, both input and output,
- * for both compression and decompression, except for the minimum which
- * only applies to compression input and decompression output; the
- * compressed data can be less than the minimum constraint.  It can be
- * assumed that compressed data will always adhere to the multiple
- * constraint.
- *
- * The driver may succeed even if these constraints are violated;
- * however the driver can return failure or suffer reduced performance
- * if any constraint is not met.
+/* The first 5 bits of this magic are 0x1f, which is an invalid 842 5-bit
+ * template (see lib/842/842.h), so this magic number will never appear at
+ * the start of a raw 842 compressed buffer.  That is important, as any buffer
+ * passed to us without this magic is assumed to be a raw 842 compressed
+ * buffer, and passed directly to the hardware to decompress.
  */
-int nx842_constraints(struct nx842_constraints *c)
+#define NX842_CRYPTO_MAGIC     (0xf842)
+#define NX842_CRYPTO_HEADER_SIZE(g)                            \
+       (sizeof(struct nx842_crypto_header) +                   \
+        sizeof(struct nx842_crypto_header_group) * (g))
+#define NX842_CRYPTO_HEADER_MAX_SIZE                           \
+       NX842_CRYPTO_HEADER_SIZE(NX842_CRYPTO_GROUP_MAX)
+
+/* bounce buffer size */
+#define BOUNCE_BUFFER_ORDER    (2)
+#define BOUNCE_BUFFER_SIZE                                     \
+       ((unsigned int)(PAGE_SIZE << BOUNCE_BUFFER_ORDER))
+
+/* try longer on comp because we can fallback to sw decomp if hw is busy */
+#define COMP_BUSY_TIMEOUT      (250) /* ms */
+#define DECOMP_BUSY_TIMEOUT    (50) /* ms */
+
+struct nx842_crypto_param {
+       u8 *in;
+       unsigned int iremain;
+       u8 *out;
+       unsigned int oremain;
+       unsigned int ototal;
+};
+
+static int update_param(struct nx842_crypto_param *p,
+                       unsigned int slen, unsigned int dlen)
 {
-       memcpy(c, nx842_platform_driver()->constraints, sizeof(*c));
+       if (p->iremain < slen)
+               return -EOVERFLOW;
+       if (p->oremain < dlen)
+               return -ENOSPC;
+
+       p->in += slen;
+       p->iremain -= slen;
+       p->out += dlen;
+       p->oremain -= dlen;
+       p->ototal += dlen;
+
        return 0;
 }
-EXPORT_SYMBOL_GPL(nx842_constraints);
 
-/**
- * nx842_workmem_size
- *
- * Get the amount of working memory the driver requires.
- */
-size_t nx842_workmem_size(void)
+int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver)
 {
-       return nx842_platform_driver()->workmem_size;
+       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       spin_lock_init(&ctx->lock);
+       ctx->driver = driver;
+       ctx->wmem = kmalloc(driver->workmem_size, GFP_KERNEL);
+       ctx->sbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER);
+       ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER);
+       if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) {
+               kfree(ctx->wmem);
+               free_page((unsigned long)ctx->sbounce);
+               free_page((unsigned long)ctx->dbounce);
+               return -ENOMEM;
+       }
+
+       return 0;
 }
-EXPORT_SYMBOL_GPL(nx842_workmem_size);
+EXPORT_SYMBOL_GPL(nx842_crypto_init);
 
-int nx842_compress(const unsigned char *in, unsigned int ilen,
-                  unsigned char *out, unsigned int *olen, void *wmem)
+void nx842_crypto_exit(struct crypto_tfm *tfm)
 {
-       return nx842_platform_driver()->compress(in, ilen, out, olen, wmem);
+       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       kfree(ctx->wmem);
+       free_page((unsigned long)ctx->sbounce);
+       free_page((unsigned long)ctx->dbounce);
 }
-EXPORT_SYMBOL_GPL(nx842_compress);
+EXPORT_SYMBOL_GPL(nx842_crypto_exit);
 
-int nx842_decompress(const unsigned char *in, unsigned int ilen,
-                    unsigned char *out, unsigned int *olen, void *wmem)
+static void check_constraints(struct nx842_constraints *c)
 {
-       return nx842_platform_driver()->decompress(in, ilen, out, olen, wmem);
+       /* limit maximum, to always have enough bounce buffer to decompress */
+       if (c->maximum > BOUNCE_BUFFER_SIZE)
+               c->maximum = BOUNCE_BUFFER_SIZE;
 }
-EXPORT_SYMBOL_GPL(nx842_decompress);
 
-static __init int nx842_init(void)
+static int nx842_crypto_add_header(struct nx842_crypto_header *hdr, u8 *buf)
 {
-       request_module("nx-compress-powernv");
-       request_module("nx-compress-pseries");
+       int s = NX842_CRYPTO_HEADER_SIZE(hdr->groups);
 
-       /* we prevent loading if there's no platform driver, and we get the
-        * module that set it so it won't unload, so we don't need to check
-        * if it's set in any of the above functions
-        */
-       if (!nx842_platform_driver_get()) {
-               pr_err("no nx842 driver found.\n");
-               return -ENODEV;
+       /* compress should have added space for header */
+       if (s > be16_to_cpu(hdr->group[0].padding)) {
+               pr_err("Internal error: no space for header\n");
+               return -EINVAL;
        }
 
+       memcpy(buf, hdr, s);
+
+       print_hex_dump_debug("header ", DUMP_PREFIX_OFFSET, 16, 1, buf, s, 0);
+
        return 0;
 }
-module_init(nx842_init);
 
-static void __exit nx842_exit(void)
+static int compress(struct nx842_crypto_ctx *ctx,
+                   struct nx842_crypto_param *p,
+                   struct nx842_crypto_header_group *g,
+                   struct nx842_constraints *c,
+                   u16 *ignore,
+                   unsigned int hdrsize)
+{
+       unsigned int slen = p->iremain, dlen = p->oremain, tmplen;
+       unsigned int adj_slen = slen;
+       u8 *src = p->in, *dst = p->out;
+       int ret, dskip = 0;
+       ktime_t timeout;
+
+       if (p->iremain == 0)
+               return -EOVERFLOW;
+
+       if (p->oremain == 0 || hdrsize + c->minimum > dlen)
+               return -ENOSPC;
+
+       if (slen % c->multiple)
+               adj_slen = round_up(slen, c->multiple);
+       if (slen < c->minimum)
+               adj_slen = c->minimum;
+       if (slen > c->maximum)
+               adj_slen = slen = c->maximum;
+       if (adj_slen > slen || (u64)src % c->alignment) {
+               adj_slen = min(adj_slen, BOUNCE_BUFFER_SIZE);
+               slen = min(slen, BOUNCE_BUFFER_SIZE);
+               if (adj_slen > slen)
+                       memset(ctx->sbounce + slen, 0, adj_slen - slen);
+               memcpy(ctx->sbounce, src, slen);
+               src = ctx->sbounce;
+               slen = adj_slen;
+               pr_debug("using comp sbounce buffer, len %x\n", slen);
+       }
+
+       dst += hdrsize;
+       dlen -= hdrsize;
+
+       if ((u64)dst % c->alignment) {
+               dskip = (int)(PTR_ALIGN(dst, c->alignment) - dst);
+               dst += dskip;
+               dlen -= dskip;
+       }
+       if (dlen % c->multiple)
+               dlen = round_down(dlen, c->multiple);
+       if (dlen < c->minimum) {
+nospc:
+               dst = ctx->dbounce;
+               dlen = min(p->oremain, BOUNCE_BUFFER_SIZE);
+               dlen = round_down(dlen, c->multiple);
+               dskip = 0;
+               pr_debug("using comp dbounce buffer, len %x\n", dlen);
+       }
+       if (dlen > c->maximum)
+               dlen = c->maximum;
+
+       tmplen = dlen;
+       timeout = ktime_add_ms(ktime_get(), COMP_BUSY_TIMEOUT);
+       do {
+               dlen = tmplen; /* reset dlen, if we're retrying */
+               ret = ctx->driver->compress(src, slen, dst, &dlen, ctx->wmem);
+               /* possibly we should reduce the slen here, instead of
+                * retrying with the dbounce buffer?
+                */
+               if (ret == -ENOSPC && dst != ctx->dbounce)
+                       goto nospc;
+       } while (ret == -EBUSY && ktime_before(ktime_get(), timeout));
+       if (ret)
+               return ret;
+
+       dskip += hdrsize;
+
+       if (dst == ctx->dbounce)
+               memcpy(p->out + dskip, dst, dlen);
+
+       g->padding = cpu_to_be16(dskip);
+       g->compressed_length = cpu_to_be32(dlen);
+       g->uncompressed_length = cpu_to_be32(slen);
+
+       if (p->iremain < slen) {
+               *ignore = slen - p->iremain;
+               slen = p->iremain;
+       }
+
+       pr_debug("compress slen %x ignore %x dlen %x padding %x\n",
+                slen, *ignore, dlen, dskip);
+
+       return update_param(p, slen, dskip + dlen);
+}
+
+int nx842_crypto_compress(struct crypto_tfm *tfm,
+                         const u8 *src, unsigned int slen,
+                         u8 *dst, unsigned int *dlen)
+{
+       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct nx842_crypto_header *hdr = &ctx->header;
+       struct nx842_crypto_param p;
+       struct nx842_constraints c = *ctx->driver->constraints;
+       unsigned int groups, hdrsize, h;
+       int ret, n;
+       bool add_header;
+       u16 ignore = 0;
+
+       check_constraints(&c);
+
+       p.in = (u8 *)src;
+       p.iremain = slen;
+       p.out = dst;
+       p.oremain = *dlen;
+       p.ototal = 0;
+
+       *dlen = 0;
+
+       groups = min_t(unsigned int, NX842_CRYPTO_GROUP_MAX,
+                      DIV_ROUND_UP(p.iremain, c.maximum));
+       hdrsize = NX842_CRYPTO_HEADER_SIZE(groups);
+
+       spin_lock_bh(&ctx->lock);
+
+       /* skip adding header if the buffers meet all constraints */
+       add_header = (p.iremain % c.multiple    ||
+                     p.iremain < c.minimum     ||
+                     p.iremain > c.maximum     ||
+                     (u64)p.in % c.alignment   ||
+                     p.oremain % c.multiple    ||
+                     p.oremain < c.minimum     ||
+                     p.oremain > c.maximum     ||
+                     (u64)p.out % c.alignment);
+
+       hdr->magic = cpu_to_be16(NX842_CRYPTO_MAGIC);
+       hdr->groups = 0;
+       hdr->ignore = 0;
+
+       while (p.iremain > 0) {
+               n = hdr->groups++;
+               ret = -ENOSPC;
+               if (hdr->groups > NX842_CRYPTO_GROUP_MAX)
+                       goto unlock;
+
+               /* header goes before first group */
+               h = !n && add_header ? hdrsize : 0;
+
+               if (ignore)
+                       pr_warn("interal error, ignore is set %x\n", ignore);
+
+               ret = compress(ctx, &p, &hdr->group[n], &c, &ignore, h);
+               if (ret)
+                       goto unlock;
+       }
+
+       if (!add_header && hdr->groups > 1) {
+               pr_err("Internal error: No header but multiple groups\n");
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       /* ignore indicates the input stream needed to be padded */
+       hdr->ignore = cpu_to_be16(ignore);
+       if (ignore)
+               pr_debug("marked %d bytes as ignore\n", ignore);
+
+       if (add_header)
+               ret = nx842_crypto_add_header(hdr, dst);
+       if (ret)
+               goto unlock;
+
+       *dlen = p.ototal;
+
+       pr_debug("compress total slen %x dlen %x\n", slen, *dlen);
+
+unlock:
+       spin_unlock_bh(&ctx->lock);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(nx842_crypto_compress);
+
+static int decompress(struct nx842_crypto_ctx *ctx,
+                     struct nx842_crypto_param *p,
+                     struct nx842_crypto_header_group *g,
+                     struct nx842_constraints *c,
+                     u16 ignore)
 {
-       nx842_platform_driver_put();
+       unsigned int slen = be32_to_cpu(g->compressed_length);
+       unsigned int required_len = be32_to_cpu(g->uncompressed_length);
+       unsigned int dlen = p->oremain, tmplen;
+       unsigned int adj_slen = slen;
+       u8 *src = p->in, *dst = p->out;
+       u16 padding = be16_to_cpu(g->padding);
+       int ret, spadding = 0, dpadding = 0;
+       ktime_t timeout;
+
+       if (!slen || !required_len)
+               return -EINVAL;
+
+       if (p->iremain <= 0 || padding + slen > p->iremain)
+               return -EOVERFLOW;
+
+       if (p->oremain <= 0 || required_len - ignore > p->oremain)
+               return -ENOSPC;
+
+       src += padding;
+
+       if (slen % c->multiple)
+               adj_slen = round_up(slen, c->multiple);
+       if (slen < c->minimum)
+               adj_slen = c->minimum;
+       if (slen > c->maximum)
+               goto usesw;
+       if (slen < adj_slen || (u64)src % c->alignment) {
+               /* we can append padding bytes because the 842 format defines
+                * an "end" template (see lib/842/842_decompress.c) and will
+                * ignore any bytes following it.
+                */
+               if (slen < adj_slen)
+                       memset(ctx->sbounce + slen, 0, adj_slen - slen);
+               memcpy(ctx->sbounce, src, slen);
+               src = ctx->sbounce;
+               spadding = adj_slen - slen;
+               slen = adj_slen;
+               pr_debug("using decomp sbounce buffer, len %x\n", slen);
+       }
+
+       if (dlen % c->multiple)
+               dlen = round_down(dlen, c->multiple);
+       if (dlen < required_len || (u64)dst % c->alignment) {
+               dst = ctx->dbounce;
+               dlen = min(required_len, BOUNCE_BUFFER_SIZE);
+               pr_debug("using decomp dbounce buffer, len %x\n", dlen);
+       }
+       if (dlen < c->minimum)
+               goto usesw;
+       if (dlen > c->maximum)
+               dlen = c->maximum;
+
+       tmplen = dlen;
+       timeout = ktime_add_ms(ktime_get(), DECOMP_BUSY_TIMEOUT);
+       do {
+               dlen = tmplen; /* reset dlen, if we're retrying */
+               ret = ctx->driver->decompress(src, slen, dst, &dlen, ctx->wmem);
+       } while (ret == -EBUSY && ktime_before(ktime_get(), timeout));
+       if (ret) {
+usesw:
+               /* reset everything, sw doesn't have constraints */
+               src = p->in + padding;
+               slen = be32_to_cpu(g->compressed_length);
+               spadding = 0;
+               dst = p->out;
+               dlen = p->oremain;
+               dpadding = 0;
+               if (dlen < required_len) { /* have ignore bytes */
+                       dst = ctx->dbounce;
+                       dlen = BOUNCE_BUFFER_SIZE;
+               }
+               pr_info_ratelimited("using software 842 decompression\n");
+               ret = sw842_decompress(src, slen, dst, &dlen);
+       }
+       if (ret)
+               return ret;
+
+       slen -= spadding;
+
+       dlen -= ignore;
+       if (ignore)
+               pr_debug("ignoring last %x bytes\n", ignore);
+
+       if (dst == ctx->dbounce)
+               memcpy(p->out, dst, dlen);
+
+       pr_debug("decompress slen %x padding %x dlen %x ignore %x\n",
+                slen, padding, dlen, ignore);
+
+       return update_param(p, slen + padding, dlen);
 }
-module_exit(nx842_exit);
+
+int nx842_crypto_decompress(struct crypto_tfm *tfm,
+                           const u8 *src, unsigned int slen,
+                           u8 *dst, unsigned int *dlen)
+{
+       struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct nx842_crypto_header *hdr;
+       struct nx842_crypto_param p;
+       struct nx842_constraints c = *ctx->driver->constraints;
+       int n, ret, hdr_len;
+       u16 ignore = 0;
+
+       check_constraints(&c);
+
+       p.in = (u8 *)src;
+       p.iremain = slen;
+       p.out = dst;
+       p.oremain = *dlen;
+       p.ototal = 0;
+
+       *dlen = 0;
+
+       hdr = (struct nx842_crypto_header *)src;
+
+       spin_lock_bh(&ctx->lock);
+
+       /* If it doesn't start with our header magic number, assume it's a raw
+        * 842 compressed buffer and pass it directly to the hardware driver
+        */
+       if (be16_to_cpu(hdr->magic) != NX842_CRYPTO_MAGIC) {
+               struct nx842_crypto_header_group g = {
+                       .padding =              0,
+                       .compressed_length =    cpu_to_be32(p.iremain),
+                       .uncompressed_length =  cpu_to_be32(p.oremain),
+               };
+
+               ret = decompress(ctx, &p, &g, &c, 0);
+               if (ret)
+                       goto unlock;
+
+               goto success;
+       }
+
+       if (!hdr->groups) {
+               pr_err("header has no groups\n");
+               ret = -EINVAL;
+               goto unlock;
+       }
+       if (hdr->groups > NX842_CRYPTO_GROUP_MAX) {
+               pr_err("header has too many groups %x, max %x\n",
+                      hdr->groups, NX842_CRYPTO_GROUP_MAX);
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       hdr_len = NX842_CRYPTO_HEADER_SIZE(hdr->groups);
+       if (hdr_len > slen) {
+               ret = -EOVERFLOW;
+               goto unlock;
+       }
+
+       memcpy(&ctx->header, src, hdr_len);
+       hdr = &ctx->header;
+
+       for (n = 0; n < hdr->groups; n++) {
+               /* ignore applies to last group */
+               if (n + 1 == hdr->groups)
+                       ignore = be16_to_cpu(hdr->ignore);
+
+               ret = decompress(ctx, &p, &hdr->group[n], &c, ignore);
+               if (ret)
+                       goto unlock;
+       }
+
+success:
+       *dlen = p.ototal;
+
+       pr_debug("decompress total slen %x dlen %x\n", slen, *dlen);
+
+       ret = 0;
+
+unlock:
+       spin_unlock_bh(&ctx->lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(nx842_crypto_decompress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IBM PowerPC Nest (NX) 842 Hardware Compression Driver");
+MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
index ac0ea79d0f8b98c1d8123f1017256eb145cfc8f4..a4eee3bba93736b601ca587fb702b4e88de1b9a9 100644 (file)
@@ -3,8 +3,9 @@
 #define __NX_842_H__
 
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sw842.h>
+#include <linux/crypto.h>
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -104,6 +105,25 @@ static inline unsigned long nx842_get_pa(void *addr)
 #define GET_FIELD(v, m)                (((v) & (m)) >> MASK_LSH(m))
 #define SET_FIELD(v, m, val)   (((v) & ~(m)) | (((val) << MASK_LSH(m)) & (m)))
 
+/**
+ * This provides the driver's constraints.  Different nx842 implementations
+ * may have varying requirements.  The constraints are:
+ *   @alignment:       All buffers should be aligned to this
+ *   @multiple:                All buffer lengths should be a multiple of this
+ *   @minimum:         Buffer lengths must not be less than this amount
+ *   @maximum:         Buffer lengths must not be more than this amount
+ *
+ * The constraints apply to all buffers and lengths, both input and output,
+ * for both compression and decompression, except for the minimum which
+ * only applies to compression input and decompression output; the
+ * compressed data can be less than the minimum constraint.  It can be
+ * assumed that compressed data will always adhere to the multiple
+ * constraint.
+ *
+ * The driver may succeed even if these constraints are violated;
+ * however the driver can return failure or suffer reduced performance
+ * if any constraint is not met.
+ */
 struct nx842_constraints {
        int alignment;
        int multiple;
@@ -126,19 +146,40 @@ struct nx842_driver {
                          void *wrkmem);
 };
 
-struct nx842_driver *nx842_platform_driver(void);
-bool nx842_platform_driver_set(struct nx842_driver *driver);
-void nx842_platform_driver_unset(struct nx842_driver *driver);
-bool nx842_platform_driver_get(void);
-void nx842_platform_driver_put(void);
+struct nx842_crypto_header_group {
+       __be16 padding;                 /* unused bytes at start of group */
+       __be32 compressed_length;       /* compressed bytes in group */
+       __be32 uncompressed_length;     /* bytes after decompression */
+} __packed;
+
+struct nx842_crypto_header {
+       __be16 magic;           /* NX842_CRYPTO_MAGIC */
+       __be16 ignore;          /* decompressed end bytes to ignore */
+       u8 groups;              /* total groups in this header */
+       struct nx842_crypto_header_group group[];
+} __packed;
 
-size_t nx842_workmem_size(void);
+#define NX842_CRYPTO_GROUP_MAX (0x20)
 
-int nx842_constraints(struct nx842_constraints *constraints);
+struct nx842_crypto_ctx {
+       spinlock_t lock;
+
+       u8 *wmem;
+       u8 *sbounce, *dbounce;
+
+       struct nx842_crypto_header header;
+       struct nx842_crypto_header_group group[NX842_CRYPTO_GROUP_MAX];
+
+       struct nx842_driver *driver;
+};
 
-int nx842_compress(const unsigned char *in, unsigned int in_len,
-                  unsigned char *out, unsigned int *out_len, void *wrkmem);
-int nx842_decompress(const unsigned char *in, unsigned int in_len,
-                    unsigned char *out, unsigned int *out_len, void *wrkmem);
+int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver);
+void nx842_crypto_exit(struct crypto_tfm *tfm);
+int nx842_crypto_compress(struct crypto_tfm *tfm,
+                         const u8 *src, unsigned int slen,
+                         u8 *dst, unsigned int *dlen);
+int nx842_crypto_decompress(struct crypto_tfm *tfm,
+                           const u8 *src, unsigned int slen,
+                           u8 *dst, unsigned int *dlen);
 
 #endif /* __NX_842_H__ */
index e4311ce0cd78cfc93eea1cec30a37a9ec3b54d25..73ef499227881e6fd5c71c65d00f486a1f173dd4 100644 (file)
@@ -94,8 +94,6 @@ static int ccm_aes_nx_setauthsize(struct crypto_aead *tfm,
                return -EINVAL;
        }
 
-       crypto_aead_crt(tfm)->authsize = authsize;
-
        return 0;
 }
 
@@ -111,8 +109,6 @@ static int ccm4309_aes_nx_setauthsize(struct crypto_aead *tfm,
                return -EINVAL;
        }
 
-       crypto_aead_crt(tfm)->authsize = authsize;
-
        return 0;
 }
 
@@ -174,6 +170,7 @@ static int generate_pat(u8                   *iv,
                        struct nx_crypto_ctx *nx_ctx,
                        unsigned int          authsize,
                        unsigned int          nbytes,
+                       unsigned int          assoclen,
                        u8                   *out)
 {
        struct nx_sg *nx_insg = nx_ctx->in_sg;
@@ -200,16 +197,16 @@ static int generate_pat(u8                   *iv,
         * greater than 2^32.
         */
 
-       if (!req->assoclen) {
+       if (!assoclen) {
                b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
-       } else if (req->assoclen <= 14) {
+       } else if (assoclen <= 14) {
                /* if associated data is 14 bytes or less, we do 1 GCM
                 * operation on 2 AES blocks, B0 (stored in the csbcpb) and B1,
                 * which is fed in through the source buffers here */
                b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
                b1 = nx_ctx->priv.ccm.iauth_tag;
-               iauth_len = req->assoclen;
-       } else if (req->assoclen <= 65280) {
+               iauth_len = assoclen;
+       } else if (assoclen <= 65280) {
                /* if associated data is less than (2^16 - 2^8), we construct
                 * B1 differently and feed in the associated data to a CCA
                 * operation */
@@ -223,7 +220,7 @@ static int generate_pat(u8                   *iv,
        }
 
        /* generate B0 */
-       rc = generate_b0(iv, req->assoclen, authsize, nbytes, b0);
+       rc = generate_b0(iv, assoclen, authsize, nbytes, b0);
        if (rc)
                return rc;
 
@@ -233,22 +230,22 @@ static int generate_pat(u8                   *iv,
         */
        if (b1) {
                memset(b1, 0, 16);
-               if (req->assoclen <= 65280) {
-                       *(u16 *)b1 = (u16)req->assoclen;
-                       scatterwalk_map_and_copy(b1 + 2, req->assoc, 0,
+               if (assoclen <= 65280) {
+                       *(u16 *)b1 = assoclen;
+                       scatterwalk_map_and_copy(b1 + 2, req->src, 0,
                                         iauth_len, SCATTERWALK_FROM_SG);
                } else {
                        *(u16 *)b1 = (u16)(0xfffe);
-                       *(u32 *)&b1[2] = (u32)req->assoclen;
-                       scatterwalk_map_and_copy(b1 + 6, req->assoc, 0,
+                       *(u32 *)&b1[2] = assoclen;
+                       scatterwalk_map_and_copy(b1 + 6, req->src, 0,
                                         iauth_len, SCATTERWALK_FROM_SG);
                }
        }
 
        /* now copy any remaining AAD to scatterlist and call nx... */
-       if (!req->assoclen) {
+       if (!assoclen) {
                return rc;
-       } else if (req->assoclen <= 14) {
+       } else if (assoclen <= 14) {
                unsigned int len = 16;
 
                nx_insg = nx_build_sg_list(nx_insg, b1, &len, nx_ctx->ap->sglen);
@@ -280,7 +277,7 @@ static int generate_pat(u8                   *iv,
                        return rc;
 
                atomic_inc(&(nx_ctx->stats->aes_ops));
-               atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
+               atomic64_add(assoclen, &nx_ctx->stats->aes_bytes);
 
        } else {
                unsigned int processed = 0, to_process;
@@ -294,15 +291,15 @@ static int generate_pat(u8                   *iv,
                                nx_ctx->ap->databytelen/NX_PAGE_SIZE);
 
                do {
-                       to_process = min_t(u32, req->assoclen - processed,
+                       to_process = min_t(u32, assoclen - processed,
                                           nx_ctx->ap->databytelen);
 
                        nx_insg = nx_walk_and_build(nx_ctx->in_sg,
                                                    nx_ctx->ap->sglen,
-                                                   req->assoc, processed,
+                                                   req->src, processed,
                                                    &to_process);
 
-                       if ((to_process + processed) < req->assoclen) {
+                       if ((to_process + processed) < assoclen) {
                                NX_CPB_FDM(nx_ctx->csbcpb_aead) |=
                                        NX_FDM_INTERMEDIATE;
                        } else {
@@ -328,11 +325,10 @@ static int generate_pat(u8                   *iv,
                        NX_CPB_FDM(nx_ctx->csbcpb_aead) |= NX_FDM_CONTINUATION;
 
                        atomic_inc(&(nx_ctx->stats->aes_ops));
-                       atomic64_add(req->assoclen,
-                                       &(nx_ctx->stats->aes_bytes));
+                       atomic64_add(assoclen, &nx_ctx->stats->aes_bytes);
 
                        processed += to_process;
-               } while (processed < req->assoclen);
+               } while (processed < assoclen);
 
                result = nx_ctx->csbcpb_aead->cpb.aes_cca.out_pat_or_b0;
        }
@@ -343,7 +339,8 @@ static int generate_pat(u8                   *iv,
 }
 
 static int ccm_nx_decrypt(struct aead_request   *req,
-                         struct blkcipher_desc *desc)
+                         struct blkcipher_desc *desc,
+                         unsigned int assoclen)
 {
        struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
        struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
@@ -360,10 +357,10 @@ static int ccm_nx_decrypt(struct aead_request   *req,
 
        /* copy out the auth tag to compare with later */
        scatterwalk_map_and_copy(priv->oauth_tag,
-                                req->src, nbytes, authsize,
+                                req->src, nbytes + req->assoclen, authsize,
                                 SCATTERWALK_FROM_SG);
 
-       rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
+       rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes, assoclen,
                          csbcpb->cpb.aes_ccm.in_pat_or_b0);
        if (rc)
                goto out;
@@ -383,8 +380,8 @@ static int ccm_nx_decrypt(struct aead_request   *req,
                NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
 
                rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src,
-                                       &to_process, processed,
-                                       csbcpb->cpb.aes_ccm.iv_or_ctr);
+                                      &to_process, processed + req->assoclen,
+                                      csbcpb->cpb.aes_ccm.iv_or_ctr);
                if (rc)
                        goto out;
 
@@ -420,7 +417,8 @@ out:
 }
 
 static int ccm_nx_encrypt(struct aead_request   *req,
-                         struct blkcipher_desc *desc)
+                         struct blkcipher_desc *desc,
+                         unsigned int assoclen)
 {
        struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
        struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
@@ -432,7 +430,7 @@ static int ccm_nx_encrypt(struct aead_request   *req,
 
        spin_lock_irqsave(&nx_ctx->lock, irq_flags);
 
-       rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
+       rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes, assoclen,
                          csbcpb->cpb.aes_ccm.in_pat_or_b0);
        if (rc)
                goto out;
@@ -451,7 +449,7 @@ static int ccm_nx_encrypt(struct aead_request   *req,
                NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
 
                rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src,
-                                       &to_process, processed,
+                                      &to_process, processed + req->assoclen,
                                       csbcpb->cpb.aes_ccm.iv_or_ctr);
                if (rc)
                        goto out;
@@ -483,7 +481,7 @@ static int ccm_nx_encrypt(struct aead_request   *req,
 
        /* copy out the auth tag */
        scatterwalk_map_and_copy(csbcpb->cpb.aes_ccm.out_pat_or_mac,
-                                req->dst, nbytes, authsize,
+                                req->dst, nbytes + req->assoclen, authsize,
                                 SCATTERWALK_TO_SG);
 
 out:
@@ -503,9 +501,8 @@ static int ccm4309_aes_nx_encrypt(struct aead_request *req)
        memcpy(iv + 4, req->iv, 8);
 
        desc.info = iv;
-       desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
 
-       return ccm_nx_encrypt(req, &desc);
+       return ccm_nx_encrypt(req, &desc, req->assoclen - 8);
 }
 
 static int ccm_aes_nx_encrypt(struct aead_request *req)
@@ -514,13 +511,12 @@ static int ccm_aes_nx_encrypt(struct aead_request *req)
        int rc;
 
        desc.info = req->iv;
-       desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
 
        rc = crypto_ccm_check_iv(desc.info);
        if (rc)
                return rc;
 
-       return ccm_nx_encrypt(req, &desc);
+       return ccm_nx_encrypt(req, &desc, req->assoclen);
 }
 
 static int ccm4309_aes_nx_decrypt(struct aead_request *req)
@@ -535,9 +531,8 @@ static int ccm4309_aes_nx_decrypt(struct aead_request *req)
        memcpy(iv + 4, req->iv, 8);
 
        desc.info = iv;
-       desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
 
-       return ccm_nx_decrypt(req, &desc);
+       return ccm_nx_decrypt(req, &desc, req->assoclen - 8);
 }
 
 static int ccm_aes_nx_decrypt(struct aead_request *req)
@@ -546,13 +541,12 @@ static int ccm_aes_nx_decrypt(struct aead_request *req)
        int rc;
 
        desc.info = req->iv;
-       desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
 
        rc = crypto_ccm_check_iv(desc.info);
        if (rc)
                return rc;
 
-       return ccm_nx_decrypt(req, &desc);
+       return ccm_nx_decrypt(req, &desc, req->assoclen);
 }
 
 /* tell the block cipher walk routines that this is a stream cipher by
@@ -560,47 +554,42 @@ static int ccm_aes_nx_decrypt(struct aead_request *req)
  * during encrypt/decrypt doesn't solve this problem, because it calls
  * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
  * but instead uses this tfm->blocksize. */
-struct crypto_alg nx_ccm_aes_alg = {
-       .cra_name        = "ccm(aes)",
-       .cra_driver_name = "ccm-aes-nx",
-       .cra_priority    = 300,
-       .cra_flags       = CRYPTO_ALG_TYPE_AEAD |
-                          CRYPTO_ALG_NEED_FALLBACK,
-       .cra_blocksize   = 1,
-       .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
-       .cra_type        = &crypto_aead_type,
-       .cra_module      = THIS_MODULE,
-       .cra_init        = nx_crypto_ctx_aes_ccm_init,
-       .cra_exit        = nx_crypto_ctx_exit,
-       .cra_aead = {
-               .ivsize      = AES_BLOCK_SIZE,
-               .maxauthsize = AES_BLOCK_SIZE,
-               .setkey      = ccm_aes_nx_set_key,
-               .setauthsize = ccm_aes_nx_setauthsize,
-               .encrypt     = ccm_aes_nx_encrypt,
-               .decrypt     = ccm_aes_nx_decrypt,
-       }
+struct aead_alg nx_ccm_aes_alg = {
+       .base = {
+               .cra_name        = "ccm(aes)",
+               .cra_driver_name = "ccm-aes-nx",
+               .cra_priority    = 300,
+               .cra_flags       = CRYPTO_ALG_NEED_FALLBACK,
+               .cra_blocksize   = 1,
+               .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+               .cra_module      = THIS_MODULE,
+       },
+       .init        = nx_crypto_ctx_aes_ccm_init,
+       .exit        = nx_crypto_ctx_aead_exit,
+       .ivsize      = AES_BLOCK_SIZE,
+       .maxauthsize = AES_BLOCK_SIZE,
+       .setkey      = ccm_aes_nx_set_key,
+       .setauthsize = ccm_aes_nx_setauthsize,
+       .encrypt     = ccm_aes_nx_encrypt,
+       .decrypt     = ccm_aes_nx_decrypt,
 };
 
-struct crypto_alg nx_ccm4309_aes_alg = {
-       .cra_name        = "rfc4309(ccm(aes))",
-       .cra_driver_name = "rfc4309-ccm-aes-nx",
-       .cra_priority    = 300,
-       .cra_flags       = CRYPTO_ALG_TYPE_AEAD |
-                          CRYPTO_ALG_NEED_FALLBACK,
-       .cra_blocksize   = 1,
-       .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
-       .cra_type        = &crypto_nivaead_type,
-       .cra_module      = THIS_MODULE,
-       .cra_init        = nx_crypto_ctx_aes_ccm_init,
-       .cra_exit        = nx_crypto_ctx_exit,
-       .cra_aead = {
-               .ivsize      = 8,
-               .maxauthsize = AES_BLOCK_SIZE,
-               .setkey      = ccm4309_aes_nx_set_key,
-               .setauthsize = ccm4309_aes_nx_setauthsize,
-               .encrypt     = ccm4309_aes_nx_encrypt,
-               .decrypt     = ccm4309_aes_nx_decrypt,
-               .geniv       = "seqiv",
-       }
+struct aead_alg nx_ccm4309_aes_alg = {
+       .base = {
+               .cra_name        = "rfc4309(ccm(aes))",
+               .cra_driver_name = "rfc4309-ccm-aes-nx",
+               .cra_priority    = 300,
+               .cra_flags       = CRYPTO_ALG_NEED_FALLBACK,
+               .cra_blocksize   = 1,
+               .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+               .cra_module      = THIS_MODULE,
+       },
+       .init        = nx_crypto_ctx_aes_ccm_init,
+       .exit        = nx_crypto_ctx_aead_exit,
+       .ivsize      = 8,
+       .maxauthsize = AES_BLOCK_SIZE,
+       .setkey      = ccm4309_aes_nx_set_key,
+       .setauthsize = ccm4309_aes_nx_setauthsize,
+       .encrypt     = ccm4309_aes_nx_encrypt,
+       .decrypt     = ccm4309_aes_nx_decrypt,
 };
index dd7e9f3f5b6b2edfb0a4e1c1e442523a30d4f74b..898c0a280511d5c49f8d6e076b4905773c1f3b8f 100644 (file)
@@ -144,27 +144,6 @@ static int ctr3686_aes_nx_crypt(struct blkcipher_desc *desc,
        return ctr_aes_nx_crypt(desc, dst, src, nbytes);
 }
 
-struct crypto_alg nx_ctr_aes_alg = {
-       .cra_name        = "ctr(aes)",
-       .cra_driver_name = "ctr-aes-nx",
-       .cra_priority    = 300,
-       .cra_flags       = CRYPTO_ALG_TYPE_BLKCIPHER,
-       .cra_blocksize   = 1,
-       .cra_ctxsize     = sizeof(struct nx_crypto_ctx),
-       .cra_type        = &crypto_blkcipher_type,
-       .cra_module      = THIS_MODULE,
-       .cra_init        = nx_crypto_ctx_aes_ctr_init,
-       .cra_exit        = nx_crypto_ctx_exit,
-       .cra_blkcipher = {
-               .min_keysize = AES_MIN_KEY_SIZE,
-               .max_keysize = AES_MAX_KEY_SIZE,
-               .ivsize      = AES_BLOCK_SIZE,
-               .setkey      = ctr_aes_nx_set_key,
-               .encrypt     = ctr_aes_nx_crypt,
-               .decrypt     = ctr_aes_nx_crypt,
-       }
-};
-
 struct crypto_alg nx_ctr3686_aes_alg = {
        .cra_name        = "rfc3686(ctr(aes))",
        .cra_driver_name = "rfc3686-ctr-aes-nx",
index 92c993f08213fbd767c897eae178a5129c5af899..eee624f589b6545a310d081e772d5924094ed70d 100644 (file)
 
 #include <crypto/internal/aead.h>
 #include <crypto/aes.h>
-#include <crypto/algapi.h>
 #include <crypto/scatterwalk.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/crypto.h>
 #include <asm/vio.h>
 
 #include "nx_csbcpb.h"
@@ -36,7 +34,7 @@ static int gcm_aes_nx_set_key(struct crypto_aead *tfm,
                              const u8           *in_key,
                              unsigned int        key_len)
 {
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+       struct nx_crypto_ctx *nx_ctx = crypto_aead_ctx(tfm);
        struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
        struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
 
@@ -75,7 +73,7 @@ static int gcm4106_aes_nx_set_key(struct crypto_aead *tfm,
                                  const u8           *in_key,
                                  unsigned int        key_len)
 {
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+       struct nx_crypto_ctx *nx_ctx = crypto_aead_ctx(tfm);
        char *nonce = nx_ctx->priv.gcm.nonce;
        int rc;
 
@@ -110,13 +108,14 @@ static int gcm4106_aes_nx_setauthsize(struct crypto_aead *tfm,
 
 static int nx_gca(struct nx_crypto_ctx  *nx_ctx,
                  struct aead_request   *req,
-                 u8                    *out)
+                 u8                    *out,
+                 unsigned int assoclen)
 {
        int rc;
        struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
        struct scatter_walk walk;
        struct nx_sg *nx_sg = nx_ctx->in_sg;
-       unsigned int nbytes = req->assoclen;
+       unsigned int nbytes = assoclen;
        unsigned int processed = 0, to_process;
        unsigned int max_sg_len;
 
@@ -167,7 +166,7 @@ static int nx_gca(struct nx_crypto_ctx  *nx_ctx,
                NX_CPB_FDM(csbcpb_aead) |= NX_FDM_CONTINUATION;
 
                atomic_inc(&(nx_ctx->stats->aes_ops));
-               atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
+               atomic64_add(assoclen, &(nx_ctx->stats->aes_bytes));
 
                processed += to_process;
        } while (processed < nbytes);
@@ -177,13 +176,15 @@ static int nx_gca(struct nx_crypto_ctx  *nx_ctx,
        return rc;
 }
 
-static int gmac(struct aead_request *req, struct blkcipher_desc *desc)
+static int gmac(struct aead_request *req, struct blkcipher_desc *desc,
+               unsigned int assoclen)
 {
        int rc;
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+       struct nx_crypto_ctx *nx_ctx =
+               crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
        struct nx_sg *nx_sg;
-       unsigned int nbytes = req->assoclen;
+       unsigned int nbytes = assoclen;
        unsigned int processed = 0, to_process;
        unsigned int max_sg_len;
 
@@ -238,7 +239,7 @@ static int gmac(struct aead_request *req, struct blkcipher_desc *desc)
                NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
 
                atomic_inc(&(nx_ctx->stats->aes_ops));
-               atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
+               atomic64_add(assoclen, &(nx_ctx->stats->aes_bytes));
 
                processed += to_process;
        } while (processed < nbytes);
@@ -253,7 +254,8 @@ static int gcm_empty(struct aead_request *req, struct blkcipher_desc *desc,
                     int enc)
 {
        int rc;
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+       struct nx_crypto_ctx *nx_ctx =
+               crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
        char out[AES_BLOCK_SIZE];
        struct nx_sg *in_sg, *out_sg;
@@ -314,9 +316,11 @@ out:
        return rc;
 }
 
-static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
+static int gcm_aes_nx_crypt(struct aead_request *req, int enc,
+                           unsigned int assoclen)
 {
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+       struct nx_crypto_ctx *nx_ctx =
+               crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct nx_gcm_rctx *rctx = aead_request_ctx(req);
        struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
        struct blkcipher_desc desc;
@@ -332,10 +336,10 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
        *(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
 
        if (nbytes == 0) {
-               if (req->assoclen == 0)
+               if (assoclen == 0)
                        rc = gcm_empty(req, &desc, enc);
                else
-                       rc = gmac(req, &desc);
+                       rc = gmac(req, &desc, assoclen);
                if (rc)
                        goto out;
                else
@@ -343,9 +347,10 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
        }
 
        /* Process associated data */
-       csbcpb->cpb.aes_gcm.bit_length_aad = req->assoclen * 8;
-       if (req->assoclen) {
-               rc = nx_gca(nx_ctx, req, csbcpb->cpb.aes_gcm.in_pat_or_aad);
+       csbcpb->cpb.aes_gcm.bit_length_aad = assoclen * 8;
+       if (assoclen) {
+               rc = nx_gca(nx_ctx, req, csbcpb->cpb.aes_gcm.in_pat_or_aad,
+                           assoclen);
                if (rc)
                        goto out;
        }
@@ -363,7 +368,6 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
                to_process = nbytes - processed;
 
                csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8;
-               desc.tfm = (struct crypto_blkcipher *) req->base.tfm;
                rc = nx_build_sg_lists(nx_ctx, &desc, req->dst,
                                       req->src, &to_process,
                                       processed + req->assoclen,
@@ -430,7 +434,7 @@ static int gcm_aes_nx_encrypt(struct aead_request *req)
 
        memcpy(iv, req->iv, 12);
 
-       return gcm_aes_nx_crypt(req, 1);
+       return gcm_aes_nx_crypt(req, 1, req->assoclen);
 }
 
 static int gcm_aes_nx_decrypt(struct aead_request *req)
@@ -440,12 +444,13 @@ static int gcm_aes_nx_decrypt(struct aead_request *req)
 
        memcpy(iv, req->iv, 12);
 
-       return gcm_aes_nx_crypt(req, 0);
+       return gcm_aes_nx_crypt(req, 0, req->assoclen);
 }
 
 static int gcm4106_aes_nx_encrypt(struct aead_request *req)
 {
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+       struct nx_crypto_ctx *nx_ctx =
+               crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct nx_gcm_rctx *rctx = aead_request_ctx(req);
        char *iv = rctx->iv;
        char *nonce = nx_ctx->priv.gcm.nonce;
@@ -453,12 +458,16 @@ static int gcm4106_aes_nx_encrypt(struct aead_request *req)
        memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
        memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
 
-       return gcm_aes_nx_crypt(req, 1);
+       if (req->assoclen < 8)
+               return -EINVAL;
+
+       return gcm_aes_nx_crypt(req, 1, req->assoclen - 8);
 }
 
 static int gcm4106_aes_nx_decrypt(struct aead_request *req)
 {
-       struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+       struct nx_crypto_ctx *nx_ctx =
+               crypto_aead_ctx(crypto_aead_reqtfm(req));
        struct nx_gcm_rctx *rctx = aead_request_ctx(req);
        char *iv = rctx->iv;
        char *nonce = nx_ctx->priv.gcm.nonce;
@@ -466,7 +475,10 @@ static int gcm4106_aes_nx_decrypt(struct aead_request *req)
        memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
        memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
 
-       return gcm_aes_nx_crypt(req, 0);
+       if (req->assoclen < 8)
+               return -EINVAL;
+
+       return gcm_aes_nx_crypt(req, 0, req->assoclen - 8);
 }
 
 /* tell the block cipher walk routines that this is a stream cipher by
index 08f8d5cd633491e3ff0e28ca8204d7f51be2b05b..becb738c897b1b5d93b632e3ab80ed2b146ead5a 100644 (file)
@@ -71,7 +71,6 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
        struct sha256_state *sctx = shash_desc_ctx(desc);
        struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
        struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
-       struct nx_sg *in_sg;
        struct nx_sg *out_sg;
        u64 to_process = 0, leftover, total;
        unsigned long irq_flags;
@@ -97,7 +96,6 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
        NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
        NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
 
-       in_sg = nx_ctx->in_sg;
        max_sg_len = min_t(u64, nx_ctx->ap->sglen,
                        nx_driver.of.max_sg_len/sizeof(struct nx_sg));
        max_sg_len = min_t(u64, max_sg_len,
@@ -114,17 +112,12 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
        }
 
        do {
-               /*
-                * to_process: the SHA256_BLOCK_SIZE data chunk to process in
-                * this update. This value is also restricted by the sg list
-                * limits.
-                */
-               to_process = total - to_process;
-               to_process = to_process & ~(SHA256_BLOCK_SIZE - 1);
+               int used_sgs = 0;
+               struct nx_sg *in_sg = nx_ctx->in_sg;
 
                if (buf_len) {
                        data_len = buf_len;
-                       in_sg = nx_build_sg_list(nx_ctx->in_sg,
+                       in_sg = nx_build_sg_list(in_sg,
                                                 (u8 *) sctx->buf,
                                                 &data_len,
                                                 max_sg_len);
@@ -133,15 +126,27 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
                                rc = -EINVAL;
                                goto out;
                        }
+                       used_sgs = in_sg - nx_ctx->in_sg;
                }
 
+               /* to_process: SHA256_BLOCK_SIZE aligned chunk to be
+                * processed in this iteration. This value is restricted
+                * by sg list limits and number of sgs we already used
+                * for leftover data. (see above)
+                * In ideal case, we could allow NX_PAGE_SIZE * max_sg_len,
+                * but because data may not be aligned, we need to account
+                * for that too. */
+               to_process = min_t(u64, total,
+                       (max_sg_len - 1 - used_sgs) * NX_PAGE_SIZE);
+               to_process = to_process & ~(SHA256_BLOCK_SIZE - 1);
+
                data_len = to_process - buf_len;
                in_sg = nx_build_sg_list(in_sg, (u8 *) data,
                                         &data_len, max_sg_len);
 
                nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
 
-               to_process = (data_len + buf_len);
+               to_process = data_len + buf_len;
                leftover = total - to_process;
 
                /*
index aff0fe58eac0b7aba11b465a192c280ef19fdbac..b6e183d58d73d5a4e38fff2925344783e8e581bc 100644 (file)
@@ -71,7 +71,6 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
        struct sha512_state *sctx = shash_desc_ctx(desc);
        struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
        struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
-       struct nx_sg *in_sg;
        struct nx_sg *out_sg;
        u64 to_process, leftover = 0, total;
        unsigned long irq_flags;
@@ -97,7 +96,6 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
        NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
        NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
 
-       in_sg = nx_ctx->in_sg;
        max_sg_len = min_t(u64, nx_ctx->ap->sglen,
                        nx_driver.of.max_sg_len/sizeof(struct nx_sg));
        max_sg_len = min_t(u64, max_sg_len,
@@ -114,18 +112,12 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
        }
 
        do {
-               /*
-                * to_process: the SHA512_BLOCK_SIZE data chunk to process in
-                * this update. This value is also restricted by the sg list
-                * limits.
-                */
-               to_process = total - leftover;
-               to_process = to_process & ~(SHA512_BLOCK_SIZE - 1);
-               leftover = total - to_process;
+               int used_sgs = 0;
+               struct nx_sg *in_sg = nx_ctx->in_sg;
 
                if (buf_len) {
                        data_len = buf_len;
-                       in_sg = nx_build_sg_list(nx_ctx->in_sg,
+                       in_sg = nx_build_sg_list(in_sg,
                                                 (u8 *) sctx->buf,
                                                 &data_len, max_sg_len);
 
@@ -133,8 +125,20 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
                                rc = -EINVAL;
                                goto out;
                        }
+                       used_sgs = in_sg - nx_ctx->in_sg;
                }
 
+               /* to_process: SHA512_BLOCK_SIZE aligned chunk to be
+                * processed in this iteration. This value is restricted
+                * by sg list limits and number of sgs we already used
+                * for leftover data. (see above)
+                * In ideal case, we could allow NX_PAGE_SIZE * max_sg_len,
+                * but because data may not be aligned, we need to account
+                * for that too. */
+               to_process = min_t(u64, total,
+                       (max_sg_len - 1 - used_sgs) * NX_PAGE_SIZE);
+               to_process = to_process & ~(SHA512_BLOCK_SIZE - 1);
+
                data_len = to_process - buf_len;
                in_sg = nx_build_sg_list(in_sg, (u8 *) data,
                                         &data_len, max_sg_len);
@@ -146,7 +150,7 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
                        goto out;
                }
 
-               to_process = (data_len + buf_len);
+               to_process = data_len + buf_len;
                leftover = total - to_process;
 
                /*
index 436971343ff7732b3be14af822e29fcc922c1e0f..0794f1cc00182f986f03673a1e2305ea1e15e094 100644 (file)
@@ -596,13 +596,9 @@ static int nx_register_algs(void)
        if (rc)
                goto out_unreg_ecb;
 
-       rc = nx_register_alg(&nx_ctr_aes_alg, NX_FC_AES, NX_MODE_AES_CTR);
-       if (rc)
-               goto out_unreg_cbc;
-
        rc = nx_register_alg(&nx_ctr3686_aes_alg, NX_FC_AES, NX_MODE_AES_CTR);
        if (rc)
-               goto out_unreg_ctr;
+               goto out_unreg_cbc;
 
        rc = nx_register_aead(&nx_gcm_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
        if (rc)
@@ -612,11 +608,11 @@ static int nx_register_algs(void)
        if (rc)
                goto out_unreg_gcm;
 
-       rc = nx_register_alg(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
+       rc = nx_register_aead(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
        if (rc)
                goto out_unreg_gcm4106;
 
-       rc = nx_register_alg(&nx_ccm4309_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
+       rc = nx_register_aead(&nx_ccm4309_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
        if (rc)
                goto out_unreg_ccm;
 
@@ -644,17 +640,15 @@ out_unreg_s256:
        nx_unregister_shash(&nx_shash_sha256_alg, NX_FC_SHA, NX_MODE_SHA,
                            NX_PROPS_SHA256);
 out_unreg_ccm4309:
-       nx_unregister_alg(&nx_ccm4309_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
+       nx_unregister_aead(&nx_ccm4309_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
 out_unreg_ccm:
-       nx_unregister_alg(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
+       nx_unregister_aead(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
 out_unreg_gcm4106:
        nx_unregister_aead(&nx_gcm4106_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
 out_unreg_gcm:
        nx_unregister_aead(&nx_gcm_aes_alg, NX_FC_AES, NX_MODE_AES_GCM);
 out_unreg_ctr3686:
        nx_unregister_alg(&nx_ctr3686_aes_alg, NX_FC_AES, NX_MODE_AES_CTR);
-out_unreg_ctr:
-       nx_unregister_alg(&nx_ctr_aes_alg, NX_FC_AES, NX_MODE_AES_CTR);
 out_unreg_cbc:
        nx_unregister_alg(&nx_cbc_aes_alg, NX_FC_AES, NX_MODE_AES_CBC);
 out_unreg_ecb:
@@ -711,11 +705,10 @@ static int nx_crypto_ctx_init(struct nx_crypto_ctx *nx_ctx, u32 fc, u32 mode)
 }
 
 /* entry points from the crypto tfm initializers */
-int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm)
+int nx_crypto_ctx_aes_ccm_init(struct crypto_aead *tfm)
 {
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-                               sizeof(struct nx_ccm_rctx));
-       return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+       crypto_aead_set_reqsize(tfm, sizeof(struct nx_ccm_rctx));
+       return nx_crypto_ctx_init(crypto_aead_ctx(tfm), NX_FC_AES,
                                  NX_MODE_AES_CCM);
 }
 
@@ -813,16 +806,15 @@ static int nx_remove(struct vio_dev *viodev)
                                    NX_FC_SHA, NX_MODE_SHA, NX_PROPS_SHA256);
                nx_unregister_shash(&nx_shash_sha256_alg,
                                    NX_FC_SHA, NX_MODE_SHA, NX_PROPS_SHA512);
-               nx_unregister_alg(&nx_ccm4309_aes_alg,
-                                 NX_FC_AES, NX_MODE_AES_CCM);
-               nx_unregister_alg(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
+               nx_unregister_aead(&nx_ccm4309_aes_alg,
+                                  NX_FC_AES, NX_MODE_AES_CCM);
+               nx_unregister_aead(&nx_ccm_aes_alg, NX_FC_AES, NX_MODE_AES_CCM);
                nx_unregister_aead(&nx_gcm4106_aes_alg,
                                   NX_FC_AES, NX_MODE_AES_GCM);
                nx_unregister_aead(&nx_gcm_aes_alg,
                                   NX_FC_AES, NX_MODE_AES_GCM);
                nx_unregister_alg(&nx_ctr3686_aes_alg,
                                  NX_FC_AES, NX_MODE_AES_CTR);
-               nx_unregister_alg(&nx_ctr_aes_alg, NX_FC_AES, NX_MODE_AES_CTR);
                nx_unregister_alg(&nx_cbc_aes_alg, NX_FC_AES, NX_MODE_AES_CBC);
                nx_unregister_alg(&nx_ecb_aes_alg, NX_FC_AES, NX_MODE_AES_ECB);
        }
index cdff03a42ae7e883648a981779bed47bb9909c92..9347878d4f30c13a06ee6e781e72f1c04ef1d7c2 100644 (file)
@@ -149,8 +149,10 @@ struct nx_crypto_ctx {
        } priv;
 };
 
+struct crypto_aead;
+
 /* prototypes */
-int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_ccm_init(struct crypto_aead *tfm);
 int nx_crypto_ctx_aes_gcm_init(struct crypto_aead *tfm);
 int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm);
 int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm);
@@ -187,10 +189,9 @@ extern struct crypto_alg nx_cbc_aes_alg;
 extern struct crypto_alg nx_ecb_aes_alg;
 extern struct aead_alg nx_gcm_aes_alg;
 extern struct aead_alg nx_gcm4106_aes_alg;
-extern struct crypto_alg nx_ctr_aes_alg;
 extern struct crypto_alg nx_ctr3686_aes_alg;
-extern struct crypto_alg nx_ccm_aes_alg;
-extern struct crypto_alg nx_ccm4309_aes_alg;
+extern struct aead_alg nx_ccm_aes_alg;
+extern struct aead_alg nx_ccm4309_aes_alg;
 extern struct shash_alg nx_shash_aes_xcbc_alg;
 extern struct shash_alg nx_shash_sha512_alg;
 extern struct shash_alg nx_shash_sha256_alg;
index 9a28b7e07c71a88c2d4e6e89d3a0c01f323f3efa..eba23147c0ee1de8552aabe4b5d0aeeffa2e6aba 100644 (file)
 #define AES_REG_IV(dd, x)              ((dd)->pdata->iv_ofs + ((x) * 0x04))
 
 #define AES_REG_CTRL(dd)               ((dd)->pdata->ctrl_ofs)
-#define AES_REG_CTRL_CTR_WIDTH_MASK    (3 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_32              (0 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_64              (1 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_96              (2 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_128             (3 << 7)
-#define AES_REG_CTRL_CTR               (1 << 6)
-#define AES_REG_CTRL_CBC               (1 << 5)
-#define AES_REG_CTRL_KEY_SIZE          (3 << 3)
-#define AES_REG_CTRL_DIRECTION         (1 << 2)
-#define AES_REG_CTRL_INPUT_READY       (1 << 1)
-#define AES_REG_CTRL_OUTPUT_READY      (1 << 0)
+#define AES_REG_CTRL_CTR_WIDTH_MASK    GENMASK(8, 7)
+#define AES_REG_CTRL_CTR_WIDTH_32      0
+#define AES_REG_CTRL_CTR_WIDTH_64      BIT(7)
+#define AES_REG_CTRL_CTR_WIDTH_96      BIT(8)
+#define AES_REG_CTRL_CTR_WIDTH_128     GENMASK(8, 7)
+#define AES_REG_CTRL_CTR               BIT(6)
+#define AES_REG_CTRL_CBC               BIT(5)
+#define AES_REG_CTRL_KEY_SIZE          GENMASK(4, 3)
+#define AES_REG_CTRL_DIRECTION         BIT(2)
+#define AES_REG_CTRL_INPUT_READY       BIT(1)
+#define AES_REG_CTRL_OUTPUT_READY      BIT(0)
+#define AES_REG_CTRL_MASK              GENMASK(24, 2)
 
 #define AES_REG_DATA_N(dd, x)          ((dd)->pdata->data_ofs + ((x) * 0x04))
 
 #define AES_REG_REV(dd)                        ((dd)->pdata->rev_ofs)
 
 #define AES_REG_MASK(dd)               ((dd)->pdata->mask_ofs)
-#define AES_REG_MASK_SIDLE             (1 << 6)
-#define AES_REG_MASK_START             (1 << 5)
-#define AES_REG_MASK_DMA_OUT_EN                (1 << 3)
-#define AES_REG_MASK_DMA_IN_EN         (1 << 2)
-#define AES_REG_MASK_SOFTRESET         (1 << 1)
-#define AES_REG_AUTOIDLE               (1 << 0)
+#define AES_REG_MASK_SIDLE             BIT(6)
+#define AES_REG_MASK_START             BIT(5)
+#define AES_REG_MASK_DMA_OUT_EN                BIT(3)
+#define AES_REG_MASK_DMA_IN_EN         BIT(2)
+#define AES_REG_MASK_SOFTRESET         BIT(1)
+#define AES_REG_AUTOIDLE               BIT(0)
 
 #define AES_REG_LENGTH_N(x)            (0x54 + ((x) * 0x04))
 
@@ -254,7 +255,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
 {
        unsigned int key32;
        int i, err;
-       u32 val, mask = 0;
+       u32 val;
 
        err = omap_aes_hw_init(dd);
        if (err)
@@ -274,17 +275,13 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
        val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
        if (dd->flags & FLAGS_CBC)
                val |= AES_REG_CTRL_CBC;
-       if (dd->flags & FLAGS_CTR) {
+       if (dd->flags & FLAGS_CTR)
                val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128;
-               mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
-       }
+
        if (dd->flags & FLAGS_ENCRYPT)
                val |= AES_REG_CTRL_DIRECTION;
 
-       mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
-                       AES_REG_CTRL_KEY_SIZE;
-
-       omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
+       omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, AES_REG_CTRL_MASK);
 
        return 0;
 }
@@ -558,6 +555,9 @@ static int omap_aes_check_aligned(struct scatterlist *sg, int total)
 {
        int len = 0;
 
+       if (!IS_ALIGNED(total, AES_BLOCK_SIZE))
+               return -EINVAL;
+
        while (sg) {
                if (!IS_ALIGNED(sg->offset, 4))
                        return -1;
@@ -577,9 +577,10 @@ static int omap_aes_check_aligned(struct scatterlist *sg, int total)
 static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
 {
        void *buf_in, *buf_out;
-       int pages;
+       int pages, total;
 
-       pages = get_order(dd->total);
+       total = ALIGN(dd->total, AES_BLOCK_SIZE);
+       pages = get_order(total);
 
        buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
        buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
@@ -594,11 +595,11 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
        sg_copy_buf(buf_in, dd->in_sg, 0, dd->total, 0);
 
        sg_init_table(&dd->in_sgl, 1);
-       sg_set_buf(&dd->in_sgl, buf_in, dd->total);
+       sg_set_buf(&dd->in_sgl, buf_in, total);
        dd->in_sg = &dd->in_sgl;
 
        sg_init_table(&dd->out_sgl, 1);
-       sg_set_buf(&dd->out_sgl, buf_out, dd->total);
+       sg_set_buf(&dd->out_sgl, buf_out, total);
        dd->out_sg = &dd->out_sgl;
 
        return 0;
@@ -611,7 +612,7 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
        struct omap_aes_ctx *ctx;
        struct omap_aes_reqctx *rctx;
        unsigned long flags;
-       int err, ret = 0;
+       int err, ret = 0, len;
 
        spin_lock_irqsave(&dd->lock, flags);
        if (req)
@@ -650,8 +651,9 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
                dd->sgs_copied = 0;
        }
 
-       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total);
-       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total);
+       len = ALIGN(dd->total, AES_BLOCK_SIZE);
+       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, len);
+       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, len);
        BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0);
 
        rctx = ablkcipher_request_ctx(req);
@@ -678,7 +680,7 @@ static void omap_aes_done_task(unsigned long data)
 {
        struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
        void *buf_in, *buf_out;
-       int pages;
+       int pages, len;
 
        pr_debug("enter done_task\n");
 
@@ -697,7 +699,8 @@ static void omap_aes_done_task(unsigned long data)
 
                sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1);
 
-               pages = get_order(dd->total_save);
+               len = ALIGN(dd->total_save, AES_BLOCK_SIZE);
+               pages = get_order(len);
                free_pages((unsigned long)buf_in, pages);
                free_pages((unsigned long)buf_out, pages);
        }
@@ -726,11 +729,6 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
                  !!(mode & FLAGS_ENCRYPT),
                  !!(mode & FLAGS_CBC));
 
-       if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-               pr_err("request size is not exact amount of AES blocks\n");
-               return -EINVAL;
-       }
-
        dd = omap_aes_find_dev(ctx);
        if (!dd)
                return -ENODEV;
@@ -833,7 +831,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
 {
        .cra_name               = "ecb(aes)",
        .cra_driver_name        = "ecb-aes-omap",
-       .cra_priority           = 100,
+       .cra_priority           = 300,
        .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                  CRYPTO_ALG_KERN_DRIVER_ONLY |
                                  CRYPTO_ALG_ASYNC,
@@ -855,7 +853,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
 {
        .cra_name               = "cbc(aes)",
        .cra_driver_name        = "cbc-aes-omap",
-       .cra_priority           = 100,
+       .cra_priority           = 300,
        .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                  CRYPTO_ALG_KERN_DRIVER_ONLY |
                                  CRYPTO_ALG_ASYNC,
@@ -881,7 +879,7 @@ static struct crypto_alg algs_ctr[] = {
 {
        .cra_name               = "ctr(aes)",
        .cra_driver_name        = "ctr-aes-omap",
-       .cra_priority           = 100,
+       .cra_priority           = 300,
        .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                  CRYPTO_ALG_KERN_DRIVER_ONLY |
                                  CRYPTO_ALG_ASYNC,
@@ -1046,9 +1044,7 @@ static irqreturn_t omap_aes_irq(int irq, void *dev_id)
                        }
                }
 
-               dd->total -= AES_BLOCK_SIZE;
-
-               BUG_ON(dd->total < 0);
+               dd->total -= min_t(size_t, AES_BLOCK_SIZE, dd->total);
 
                /* Clear IRQ status */
                status &= ~AES_REG_IRQ_DATA_OUT;
index 4f56f3681abdfc6e2a4ecf95e34f3ea30c231961..da36de26a4dc1074859fc5e5082630adc57897f3 100644 (file)
@@ -99,11 +99,16 @@ struct spacc_req {
        dma_addr_t                      src_addr, dst_addr;
        struct spacc_ddt                *src_ddt, *dst_ddt;
        void                            (*complete)(struct spacc_req *req);
+};
 
-       /* AEAD specific bits. */
-       u8                              *giv;
-       size_t                          giv_len;
-       dma_addr_t                      giv_pa;
+struct spacc_aead {
+       unsigned long                   ctrl_default;
+       unsigned long                   type;
+       struct aead_alg                 alg;
+       struct spacc_engine             *engine;
+       struct list_head                entry;
+       int                             key_offs;
+       int                             iv_offs;
 };
 
 struct spacc_engine {
@@ -121,6 +126,9 @@ struct spacc_engine {
        struct spacc_alg                *algs;
        unsigned                        num_algs;
        struct list_head                registered_algs;
+       struct spacc_aead               *aeads;
+       unsigned                        num_aeads;
+       struct list_head                registered_aeads;
        size_t                          cipher_pg_sz;
        size_t                          hash_pg_sz;
        const char                      *name;
@@ -174,8 +182,6 @@ struct spacc_aead_ctx {
        u8                              cipher_key_len;
        u8                              hash_key_len;
        struct crypto_aead              *sw_cipher;
-       size_t                          auth_size;
-       u8                              salt[AES_BLOCK_SIZE];
 };
 
 static int spacc_ablk_submit(struct spacc_req *req);
@@ -185,6 +191,11 @@ static inline struct spacc_alg *to_spacc_alg(struct crypto_alg *alg)
        return alg ? container_of(alg, struct spacc_alg, alg) : NULL;
 }
 
+static inline struct spacc_aead *to_spacc_aead(struct aead_alg *alg)
+{
+       return container_of(alg, struct spacc_aead, alg);
+}
+
 static inline int spacc_fifo_cmd_full(struct spacc_engine *engine)
 {
        u32 fifo_stat = readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET);
@@ -310,120 +321,117 @@ out:
        return NULL;
 }
 
-static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
+static int spacc_aead_make_ddts(struct aead_request *areq)
 {
-       struct aead_request *areq = container_of(req->req, struct aead_request,
-                                                base);
+       struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+       struct spacc_req *req = aead_request_ctx(areq);
        struct spacc_engine *engine = req->engine;
        struct spacc_ddt *src_ddt, *dst_ddt;
-       unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(areq));
-       unsigned nents = sg_count(areq->src, areq->cryptlen);
        unsigned total;
-       dma_addr_t iv_addr;
+       unsigned int src_nents, dst_nents;
        struct scatterlist *cur;
-       int i, dst_ents, src_ents, assoc_ents;
-       u8 *iv = giv ? giv : areq->iv;
+       int i, dst_ents, src_ents;
+
+       total = areq->assoclen + areq->cryptlen;
+       if (req->is_encrypt)
+               total += crypto_aead_authsize(aead);
+
+       src_nents = sg_count(areq->src, total);
+       if (src_nents + 1 > MAX_DDT_LEN)
+               return -E2BIG;
+
+       dst_nents = 0;
+       if (areq->src != areq->dst) {
+               dst_nents = sg_count(areq->dst, total);
+               if (src_nents + 1 > MAX_DDT_LEN)
+                       return -E2BIG;
+       }
 
        src_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->src_addr);
        if (!src_ddt)
-               return -ENOMEM;
+               goto err;
 
        dst_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->dst_addr);
-       if (!dst_ddt) {
-               dma_pool_free(engine->req_pool, src_ddt, req->src_addr);
-               return -ENOMEM;
-       }
+       if (!dst_ddt)
+               goto err_free_src;
 
        req->src_ddt = src_ddt;
        req->dst_ddt = dst_ddt;
 
-       assoc_ents = dma_map_sg(engine->dev, areq->assoc,
-               sg_count(areq->assoc, areq->assoclen), DMA_TO_DEVICE);
-       if (areq->src != areq->dst) {
-               src_ents = dma_map_sg(engine->dev, areq->src, nents,
+       if (dst_nents) {
+               src_ents = dma_map_sg(engine->dev, areq->src, src_nents,
                                      DMA_TO_DEVICE);
-               dst_ents = dma_map_sg(engine->dev, areq->dst, nents,
+               if (!src_ents)
+                       goto err_free_dst;
+
+               dst_ents = dma_map_sg(engine->dev, areq->dst, dst_nents,
                                      DMA_FROM_DEVICE);
+
+               if (!dst_ents) {
+                       dma_unmap_sg(engine->dev, areq->src, src_nents,
+                                    DMA_TO_DEVICE);
+                       goto err_free_dst;
+               }
        } else {
-               src_ents = dma_map_sg(engine->dev, areq->src, nents,
+               src_ents = dma_map_sg(engine->dev, areq->src, src_nents,
                                      DMA_BIDIRECTIONAL);
-               dst_ents = 0;
+               if (!src_ents)
+                       goto err_free_dst;
+               dst_ents = src_ents;
        }
 
        /*
-        * Map the IV/GIV. For the GIV it needs to be bidirectional as it is
-        * formed by the crypto block and sent as the ESP IV for IPSEC.
+        * Now map in the payload for the source and destination and terminate
+        * with the NULL pointers.
         */
-       iv_addr = dma_map_single(engine->dev, iv, ivsize,
-                                giv ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
-       req->giv_pa = iv_addr;
+       for_each_sg(areq->src, cur, src_ents, i)
+               ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
 
-       /*
-        * Map the associated data. For decryption we don't copy the
-        * associated data.
-        */
-       total = areq->assoclen;
-       for_each_sg(areq->assoc, cur, assoc_ents, i) {
+       /* For decryption we need to skip the associated data. */
+       total = req->is_encrypt ? 0 : areq->assoclen;
+       for_each_sg(areq->dst, cur, dst_ents, i) {
                unsigned len = sg_dma_len(cur);
 
-               if (len > total)
-                       len = total;
-
-               total -= len;
+               if (len <= total) {
+                       total -= len;
+                       continue;
+               }
 
-               ddt_set(src_ddt++, sg_dma_address(cur), len);
-               if (req->is_encrypt)
-                       ddt_set(dst_ddt++, sg_dma_address(cur), len);
+               ddt_set(dst_ddt++, sg_dma_address(cur) + total, len - total);
        }
-       ddt_set(src_ddt++, iv_addr, ivsize);
-
-       if (giv || req->is_encrypt)
-               ddt_set(dst_ddt++, iv_addr, ivsize);
-
-       /*
-        * Now map in the payload for the source and destination and terminate
-        * with the NULL pointers.
-        */
-       for_each_sg(areq->src, cur, src_ents, i) {
-               ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
-               if (areq->src == areq->dst)
-                       ddt_set(dst_ddt++, sg_dma_address(cur),
-                               sg_dma_len(cur));
-       }
-
-       for_each_sg(areq->dst, cur, dst_ents, i)
-               ddt_set(dst_ddt++, sg_dma_address(cur),
-                       sg_dma_len(cur));
 
        ddt_set(src_ddt, 0, 0);
        ddt_set(dst_ddt, 0, 0);
 
        return 0;
+
+err_free_dst:
+       dma_pool_free(engine->req_pool, dst_ddt, req->dst_addr);
+err_free_src:
+       dma_pool_free(engine->req_pool, src_ddt, req->src_addr);
+err:
+       return -ENOMEM;
 }
 
 static void spacc_aead_free_ddts(struct spacc_req *req)
 {
        struct aead_request *areq = container_of(req->req, struct aead_request,
                                                 base);
-       struct spacc_alg *alg = to_spacc_alg(req->req->tfm->__crt_alg);
-       struct spacc_ablk_ctx *aead_ctx = crypto_tfm_ctx(req->req->tfm);
+       struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+       unsigned total = areq->assoclen + areq->cryptlen +
+                        (req->is_encrypt ? crypto_aead_authsize(aead) : 0);
+       struct spacc_aead_ctx *aead_ctx = crypto_aead_ctx(aead);
        struct spacc_engine *engine = aead_ctx->generic.engine;
-       unsigned ivsize = alg->alg.cra_aead.ivsize;
-       unsigned nents = sg_count(areq->src, areq->cryptlen);
+       unsigned nents = sg_count(areq->src, total);
 
        if (areq->src != areq->dst) {
                dma_unmap_sg(engine->dev, areq->src, nents, DMA_TO_DEVICE);
                dma_unmap_sg(engine->dev, areq->dst,
-                            sg_count(areq->dst, areq->cryptlen),
+                            sg_count(areq->dst, total),
                             DMA_FROM_DEVICE);
        } else
                dma_unmap_sg(engine->dev, areq->src, nents, DMA_BIDIRECTIONAL);
 
-       dma_unmap_sg(engine->dev, areq->assoc,
-                    sg_count(areq->assoc, areq->assoclen), DMA_TO_DEVICE);
-
-       dma_unmap_single(engine->dev, req->giv_pa, ivsize, DMA_BIDIRECTIONAL);
-
        dma_pool_free(engine->req_pool, req->src_ddt, req->src_addr);
        dma_pool_free(engine->req_pool, req->dst_ddt, req->dst_addr);
 }
@@ -438,65 +446,22 @@ static void spacc_free_ddt(struct spacc_req *req, struct spacc_ddt *ddt,
        dma_pool_free(req->engine->req_pool, ddt, ddt_addr);
 }
 
-/*
- * Set key for a DES operation in an AEAD cipher. This also performs weak key
- * checking if required.
- */
-static int spacc_aead_des_setkey(struct crypto_aead *aead, const u8 *key,
-                                unsigned int len)
-{
-       struct crypto_tfm *tfm = crypto_aead_tfm(aead);
-       struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
-       u32 tmp[DES_EXPKEY_WORDS];
-
-       if (unlikely(!des_ekey(tmp, key)) &&
-           (crypto_aead_get_flags(aead)) & CRYPTO_TFM_REQ_WEAK_KEY) {
-               tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
-               return -EINVAL;
-       }
-
-       memcpy(ctx->cipher_key, key, len);
-       ctx->cipher_key_len = len;
-
-       return 0;
-}
-
-/* Set the key for the AES block cipher component of the AEAD transform. */
-static int spacc_aead_aes_setkey(struct crypto_aead *aead, const u8 *key,
-                                unsigned int len)
-{
-       struct crypto_tfm *tfm = crypto_aead_tfm(aead);
-       struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       /*
-        * IPSec engine only supports 128 and 256 bit AES keys. If we get a
-        * request for any other size (192 bits) then we need to do a software
-        * fallback.
-        */
-       if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256) {
-               /*
-                * Set the fallback transform to use the same request flags as
-                * the hardware transform.
-                */
-               ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
-               ctx->sw_cipher->base.crt_flags |=
-                       tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
-               return crypto_aead_setkey(ctx->sw_cipher, key, len);
-       }
-
-       memcpy(ctx->cipher_key, key, len);
-       ctx->cipher_key_len = len;
-
-       return 0;
-}
-
 static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
                             unsigned int keylen)
 {
        struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
        struct crypto_authenc_keys keys;
-       int err = -EINVAL;
+       int err;
+
+       crypto_aead_clear_flags(ctx->sw_cipher, CRYPTO_TFM_REQ_MASK);
+       crypto_aead_set_flags(ctx->sw_cipher, crypto_aead_get_flags(tfm) &
+                                             CRYPTO_TFM_REQ_MASK);
+       err = crypto_aead_setkey(ctx->sw_cipher, key, keylen);
+       crypto_aead_clear_flags(tfm, CRYPTO_TFM_RES_MASK);
+       crypto_aead_set_flags(tfm, crypto_aead_get_flags(ctx->sw_cipher) &
+                                  CRYPTO_TFM_RES_MASK);
+       if (err)
+               return err;
 
        if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
                goto badkey;
@@ -507,14 +472,8 @@ static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        if (keys.authkeylen > sizeof(ctx->hash_ctx))
                goto badkey;
 
-       if ((alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
-           SPA_CTRL_CIPH_ALG_AES)
-               err = spacc_aead_aes_setkey(tfm, keys.enckey, keys.enckeylen);
-       else
-               err = spacc_aead_des_setkey(tfm, keys.enckey, keys.enckeylen);
-
-       if (err)
-               goto badkey;
+       memcpy(ctx->cipher_key, keys.enckey, keys.enckeylen);
+       ctx->cipher_key_len = keys.enckeylen;
 
        memcpy(ctx->hash_ctx, keys.authkey, keys.authkeylen);
        ctx->hash_key_len = keys.authkeylen;
@@ -531,9 +490,7 @@ static int spacc_aead_setauthsize(struct crypto_aead *tfm,
 {
        struct spacc_aead_ctx *ctx = crypto_tfm_ctx(crypto_aead_tfm(tfm));
 
-       ctx->auth_size = authsize;
-
-       return 0;
+       return crypto_aead_setauthsize(ctx->sw_cipher, authsize);
 }
 
 /*
@@ -541,15 +498,13 @@ static int spacc_aead_setauthsize(struct crypto_aead *tfm,
  * be completed in hardware because the hardware may not support certain key
  * sizes. In these cases we need to complete the request in software.
  */
-static int spacc_aead_need_fallback(struct spacc_req *req)
+static int spacc_aead_need_fallback(struct aead_request *aead_req)
 {
-       struct aead_request *aead_req;
-       struct crypto_tfm *tfm = req->req->tfm;
-       struct crypto_alg *alg = req->req->tfm->__crt_alg;
-       struct spacc_alg *spacc_alg = to_spacc_alg(alg);
-       struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
+       struct aead_alg *alg = crypto_aead_alg(aead);
+       struct spacc_aead *spacc_alg = to_spacc_aead(alg);
+       struct spacc_aead_ctx *ctx = crypto_aead_ctx(aead);
 
-       aead_req = container_of(req->req, struct aead_request, base);
        /*
         * If we have a non-supported key-length, then we need to do a
         * software fallback.
@@ -568,22 +523,17 @@ static int spacc_aead_do_fallback(struct aead_request *req, unsigned alg_type,
 {
        struct crypto_tfm *old_tfm = crypto_aead_tfm(crypto_aead_reqtfm(req));
        struct spacc_aead_ctx *ctx = crypto_tfm_ctx(old_tfm);
-       int err;
+       struct aead_request *subreq = aead_request_ctx(req);
 
-       if (ctx->sw_cipher) {
-               /*
-                * Change the request to use the software fallback transform,
-                * and once the ciphering has completed, put the old transform
-                * back into the request.
-                */
-               aead_request_set_tfm(req, ctx->sw_cipher);
-               err = is_encrypt ? crypto_aead_encrypt(req) :
-                   crypto_aead_decrypt(req);
-               aead_request_set_tfm(req, __crypto_aead_cast(old_tfm));
-       } else
-               err = -EINVAL;
+       aead_request_set_tfm(subreq, ctx->sw_cipher);
+       aead_request_set_callback(subreq, req->base.flags,
+                                 req->base.complete, req->base.data);
+       aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
+                              req->iv);
+       aead_request_set_ad(subreq, req->assoclen);
 
-       return err;
+       return is_encrypt ? crypto_aead_encrypt(subreq) :
+                           crypto_aead_decrypt(subreq);
 }
 
 static void spacc_aead_complete(struct spacc_req *req)
@@ -594,18 +544,19 @@ static void spacc_aead_complete(struct spacc_req *req)
 
 static int spacc_aead_submit(struct spacc_req *req)
 {
-       struct crypto_tfm *tfm = req->req->tfm;
-       struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct crypto_alg *alg = req->req->tfm->__crt_alg;
-       struct spacc_alg *spacc_alg = to_spacc_alg(alg);
-       struct spacc_engine *engine = ctx->generic.engine;
-       u32 ctrl, proc_len, assoc_len;
        struct aead_request *aead_req =
                container_of(req->req, struct aead_request, base);
+       struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
+       unsigned int authsize = crypto_aead_authsize(aead);
+       struct spacc_aead_ctx *ctx = crypto_aead_ctx(aead);
+       struct aead_alg *alg = crypto_aead_alg(aead);
+       struct spacc_aead *spacc_alg = to_spacc_aead(alg);
+       struct spacc_engine *engine = ctx->generic.engine;
+       u32 ctrl, proc_len, assoc_len;
 
        req->result = -EINPROGRESS;
        req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->cipher_key,
-               ctx->cipher_key_len, aead_req->iv, alg->cra_aead.ivsize,
+               ctx->cipher_key_len, aead_req->iv, crypto_aead_ivsize(aead),
                ctx->hash_ctx, ctx->hash_key_len);
 
        /* Set the source and destination DDT pointers. */
@@ -616,26 +567,16 @@ static int spacc_aead_submit(struct spacc_req *req)
        assoc_len = aead_req->assoclen;
        proc_len = aead_req->cryptlen + assoc_len;
 
-       /*
-        * If we aren't generating an IV, then we need to include the IV in the
-        * associated data so that it is included in the hash.
-        */
-       if (!req->giv) {
-               assoc_len += crypto_aead_ivsize(crypto_aead_reqtfm(aead_req));
-               proc_len += crypto_aead_ivsize(crypto_aead_reqtfm(aead_req));
-       } else
-               proc_len += req->giv_len;
-
        /*
         * If we are decrypting, we need to take the length of the ICV out of
         * the processing length.
         */
        if (!req->is_encrypt)
-               proc_len -= ctx->auth_size;
+               proc_len -= authsize;
 
        writel(proc_len, engine->regs + SPA_PROC_LEN_REG_OFFSET);
        writel(assoc_len, engine->regs + SPA_AAD_LEN_REG_OFFSET);
-       writel(ctx->auth_size, engine->regs + SPA_ICV_LEN_REG_OFFSET);
+       writel(authsize, engine->regs + SPA_ICV_LEN_REG_OFFSET);
        writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
        writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
 
@@ -674,32 +615,29 @@ static void spacc_push(struct spacc_engine *engine)
 /*
  * Setup an AEAD request for processing. This will configure the engine, load
  * the context and then start the packet processing.
- *
- * @giv Pointer to destination address for a generated IV. If the
- *     request does not need to generate an IV then this should be set to NULL.
  */
-static int spacc_aead_setup(struct aead_request *req, u8 *giv,
+static int spacc_aead_setup(struct aead_request *req,
                            unsigned alg_type, bool is_encrypt)
 {
-       struct crypto_alg *alg = req->base.tfm->__crt_alg;
-       struct spacc_engine *engine = to_spacc_alg(alg)->engine;
+       struct crypto_aead *aead = crypto_aead_reqtfm(req);
+       struct aead_alg *alg = crypto_aead_alg(aead);
+       struct spacc_engine *engine = to_spacc_aead(alg)->engine;
        struct spacc_req *dev_req = aead_request_ctx(req);
-       int err = -EINPROGRESS;
+       int err;
        unsigned long flags;
-       unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(req));
 
-       dev_req->giv            = giv;
-       dev_req->giv_len        = ivsize;
        dev_req->req            = &req->base;
        dev_req->is_encrypt     = is_encrypt;
        dev_req->result         = -EBUSY;
        dev_req->engine         = engine;
        dev_req->complete       = spacc_aead_complete;
 
-       if (unlikely(spacc_aead_need_fallback(dev_req)))
+       if (unlikely(spacc_aead_need_fallback(req) ||
+                    ((err = spacc_aead_make_ddts(req)) == -E2BIG)))
                return spacc_aead_do_fallback(req, alg_type, is_encrypt);
 
-       spacc_aead_make_ddts(dev_req, dev_req->giv);
+       if (err)
+               goto out;
 
        err = -EINPROGRESS;
        spin_lock_irqsave(&engine->hw_lock, flags);
@@ -728,70 +666,44 @@ out:
 static int spacc_aead_encrypt(struct aead_request *req)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct crypto_tfm *tfm = crypto_aead_tfm(aead);
-       struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+       struct spacc_aead *alg = to_spacc_aead(crypto_aead_alg(aead));
 
-       return spacc_aead_setup(req, NULL, alg->type, 1);
-}
-
-static int spacc_aead_givencrypt(struct aead_givcrypt_request *req)
-{
-       struct crypto_aead *tfm = aead_givcrypt_reqtfm(req);
-       struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       size_t ivsize = crypto_aead_ivsize(tfm);
-       struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
-       unsigned len;
-       __be64 seq;
-
-       memcpy(req->areq.iv, ctx->salt, ivsize);
-       len = ivsize;
-       if (ivsize > sizeof(u64)) {
-               memset(req->giv, 0, ivsize - sizeof(u64));
-               len = sizeof(u64);
-       }
-       seq = cpu_to_be64(req->seq);
-       memcpy(req->giv + ivsize - len, &seq, len);
-
-       return spacc_aead_setup(&req->areq, req->giv, alg->type, 1);
+       return spacc_aead_setup(req, alg->type, 1);
 }
 
 static int spacc_aead_decrypt(struct aead_request *req)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
-       struct crypto_tfm *tfm = crypto_aead_tfm(aead);
-       struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+       struct spacc_aead  *alg = to_spacc_aead(crypto_aead_alg(aead));
 
-       return spacc_aead_setup(req, NULL, alg->type, 0);
+       return spacc_aead_setup(req, alg->type, 0);
 }
 
 /*
  * Initialise a new AEAD context. This is responsible for allocating the
  * fallback cipher and initialising the context.
  */
-static int spacc_aead_cra_init(struct crypto_tfm *tfm)
+static int spacc_aead_cra_init(struct crypto_aead *tfm)
 {
-       struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct crypto_alg *alg = tfm->__crt_alg;
-       struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+       struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+       struct aead_alg *alg = crypto_aead_alg(tfm);
+       struct spacc_aead *spacc_alg = to_spacc_aead(alg);
        struct spacc_engine *engine = spacc_alg->engine;
 
        ctx->generic.flags = spacc_alg->type;
        ctx->generic.engine = engine;
-       ctx->sw_cipher = crypto_alloc_aead(alg->cra_name, 0,
-                                          CRYPTO_ALG_ASYNC |
+       ctx->sw_cipher = crypto_alloc_aead(alg->base.cra_name, 0,
                                           CRYPTO_ALG_NEED_FALLBACK);
-       if (IS_ERR(ctx->sw_cipher)) {
-               dev_warn(engine->dev, "failed to allocate fallback for %s\n",
-                        alg->cra_name);
-               ctx->sw_cipher = NULL;
-       }
+       if (IS_ERR(ctx->sw_cipher))
+               return PTR_ERR(ctx->sw_cipher);
        ctx->generic.key_offs = spacc_alg->key_offs;
        ctx->generic.iv_offs = spacc_alg->iv_offs;
 
-       get_random_bytes(ctx->salt, sizeof(ctx->salt));
-
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-                               sizeof(struct spacc_req));
+       crypto_aead_set_reqsize(
+               tfm,
+               max(sizeof(struct spacc_req),
+                   sizeof(struct aead_request) +
+                   crypto_aead_reqsize(ctx->sw_cipher)));
 
        return 0;
 }
@@ -800,13 +712,11 @@ static int spacc_aead_cra_init(struct crypto_tfm *tfm)
  * Destructor for an AEAD context. This is called when the transform is freed
  * and must free the fallback cipher.
  */
-static void spacc_aead_cra_exit(struct crypto_tfm *tfm)
+static void spacc_aead_cra_exit(struct crypto_aead *tfm)
 {
-       struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
 
-       if (ctx->sw_cipher)
-               crypto_free_aead(ctx->sw_cipher);
-       ctx->sw_cipher = NULL;
+       crypto_free_aead(ctx->sw_cipher);
 }
 
 /*
@@ -1458,180 +1368,188 @@ static struct spacc_alg ipsec_engine_algs[] = {
                        .cra_exit = spacc_ablk_cra_exit,
                },
        },
+};
+
+static struct spacc_aead ipsec_engine_aeads[] = {
        {
-               .ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
-                               SPA_CTRL_HASH_ALG_SHA | SPA_CTRL_HASH_MODE_HMAC,
+               .ctrl_default = SPA_CTRL_CIPH_ALG_AES |
+                               SPA_CTRL_CIPH_MODE_CBC |
+                               SPA_CTRL_HASH_ALG_SHA |
+                               SPA_CTRL_HASH_MODE_HMAC,
                .key_offs = 0,
                .iv_offs = AES_MAX_KEY_SIZE,
                .alg = {
-                       .cra_name = "authenc(hmac(sha1),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha1-cbc-aes-picoxcell",
-                       .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                       CRYPTO_ALG_ASYNC |
-                                       CRYPTO_ALG_KERN_DRIVER_ONLY,
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_ctxsize = sizeof(struct spacc_aead_ctx),
-                       .cra_type = &crypto_aead_type,
-                       .cra_module = THIS_MODULE,
-                       .cra_aead = {
-                               .setkey = spacc_aead_setkey,
-                               .setauthsize = spacc_aead_setauthsize,
-                               .encrypt = spacc_aead_encrypt,
-                               .decrypt = spacc_aead_decrypt,
-                               .givencrypt = spacc_aead_givencrypt,
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA1_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-aes-picoxcell",
+                               .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_NEED_FALLBACK |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct spacc_aead_ctx),
+                               .cra_module = THIS_MODULE,
                        },
-                       .cra_init = spacc_aead_cra_init,
-                       .cra_exit = spacc_aead_cra_exit,
+                       .setkey = spacc_aead_setkey,
+                       .setauthsize = spacc_aead_setauthsize,
+                       .encrypt = spacc_aead_encrypt,
+                       .decrypt = spacc_aead_decrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+                       .init = spacc_aead_cra_init,
+                       .exit = spacc_aead_cra_exit,
                },
        },
        {
-               .ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+               .ctrl_default = SPA_CTRL_CIPH_ALG_AES |
+                               SPA_CTRL_CIPH_MODE_CBC |
                                SPA_CTRL_HASH_ALG_SHA256 |
                                SPA_CTRL_HASH_MODE_HMAC,
                .key_offs = 0,
                .iv_offs = AES_MAX_KEY_SIZE,
                .alg = {
-                       .cra_name = "authenc(hmac(sha256),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha256-cbc-aes-picoxcell",
-                       .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                       CRYPTO_ALG_ASYNC |
-                                       CRYPTO_ALG_KERN_DRIVER_ONLY,
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_ctxsize = sizeof(struct spacc_aead_ctx),
-                       .cra_type = &crypto_aead_type,
-                       .cra_module = THIS_MODULE,
-                       .cra_aead = {
-                               .setkey = spacc_aead_setkey,
-                               .setauthsize = spacc_aead_setauthsize,
-                               .encrypt = spacc_aead_encrypt,
-                               .decrypt = spacc_aead_decrypt,
-                               .givencrypt = spacc_aead_givencrypt,
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA256_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-aes-picoxcell",
+                               .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_NEED_FALLBACK |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct spacc_aead_ctx),
+                               .cra_module = THIS_MODULE,
                        },
-                       .cra_init = spacc_aead_cra_init,
-                       .cra_exit = spacc_aead_cra_exit,
+                       .setkey = spacc_aead_setkey,
+                       .setauthsize = spacc_aead_setauthsize,
+                       .encrypt = spacc_aead_encrypt,
+                       .decrypt = spacc_aead_decrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+                       .init = spacc_aead_cra_init,
+                       .exit = spacc_aead_cra_exit,
                },
        },
        {
                .key_offs = 0,
                .iv_offs = AES_MAX_KEY_SIZE,
-               .ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
-                               SPA_CTRL_HASH_ALG_MD5 | SPA_CTRL_HASH_MODE_HMAC,
+               .ctrl_default = SPA_CTRL_CIPH_ALG_AES |
+                               SPA_CTRL_CIPH_MODE_CBC |
+                               SPA_CTRL_HASH_ALG_MD5 |
+                               SPA_CTRL_HASH_MODE_HMAC,
                .alg = {
-                       .cra_name = "authenc(hmac(md5),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-md5-cbc-aes-picoxcell",
-                       .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                       CRYPTO_ALG_ASYNC |
-                                       CRYPTO_ALG_KERN_DRIVER_ONLY,
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_ctxsize = sizeof(struct spacc_aead_ctx),
-                       .cra_type = &crypto_aead_type,
-                       .cra_module = THIS_MODULE,
-                       .cra_aead = {
-                               .setkey = spacc_aead_setkey,
-                               .setauthsize = spacc_aead_setauthsize,
-                               .encrypt = spacc_aead_encrypt,
-                               .decrypt = spacc_aead_decrypt,
-                               .givencrypt = spacc_aead_givencrypt,
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = MD5_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-aes-picoxcell",
+                               .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_NEED_FALLBACK |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct spacc_aead_ctx),
+                               .cra_module = THIS_MODULE,
                        },
-                       .cra_init = spacc_aead_cra_init,
-                       .cra_exit = spacc_aead_cra_exit,
+                       .setkey = spacc_aead_setkey,
+                       .setauthsize = spacc_aead_setauthsize,
+                       .encrypt = spacc_aead_encrypt,
+                       .decrypt = spacc_aead_decrypt,
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+                       .init = spacc_aead_cra_init,
+                       .exit = spacc_aead_cra_exit,
                },
        },
        {
                .key_offs = DES_BLOCK_SIZE,
                .iv_offs = 0,
-               .ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC |
-                               SPA_CTRL_HASH_ALG_SHA | SPA_CTRL_HASH_MODE_HMAC,
+               .ctrl_default = SPA_CTRL_CIPH_ALG_DES |
+                               SPA_CTRL_CIPH_MODE_CBC |
+                               SPA_CTRL_HASH_ALG_SHA |
+                               SPA_CTRL_HASH_MODE_HMAC,
                .alg = {
-                       .cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha1-cbc-3des-picoxcell",
-                       .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                       CRYPTO_ALG_ASYNC |
-                                       CRYPTO_ALG_KERN_DRIVER_ONLY,
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_ctxsize = sizeof(struct spacc_aead_ctx),
-                       .cra_type = &crypto_aead_type,
-                       .cra_module = THIS_MODULE,
-                       .cra_aead = {
-                               .setkey = spacc_aead_setkey,
-                               .setauthsize = spacc_aead_setauthsize,
-                               .encrypt = spacc_aead_encrypt,
-                               .decrypt = spacc_aead_decrypt,
-                               .givencrypt = spacc_aead_givencrypt,
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA1_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-3des-picoxcell",
+                               .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_NEED_FALLBACK |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct spacc_aead_ctx),
+                               .cra_module = THIS_MODULE,
                        },
-                       .cra_init = spacc_aead_cra_init,
-                       .cra_exit = spacc_aead_cra_exit,
+                       .setkey = spacc_aead_setkey,
+                       .setauthsize = spacc_aead_setauthsize,
+                       .encrypt = spacc_aead_encrypt,
+                       .decrypt = spacc_aead_decrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
+                       .init = spacc_aead_cra_init,
+                       .exit = spacc_aead_cra_exit,
                },
        },
        {
                .key_offs = DES_BLOCK_SIZE,
                .iv_offs = 0,
-               .ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+               .ctrl_default = SPA_CTRL_CIPH_ALG_AES |
+                               SPA_CTRL_CIPH_MODE_CBC |
                                SPA_CTRL_HASH_ALG_SHA256 |
                                SPA_CTRL_HASH_MODE_HMAC,
                .alg = {
-                       .cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha256-cbc-3des-picoxcell",
-                       .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                       CRYPTO_ALG_ASYNC |
-                                       CRYPTO_ALG_KERN_DRIVER_ONLY,
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_ctxsize = sizeof(struct spacc_aead_ctx),
-                       .cra_type = &crypto_aead_type,
-                       .cra_module = THIS_MODULE,
-                       .cra_aead = {
-                               .setkey = spacc_aead_setkey,
-                               .setauthsize = spacc_aead_setauthsize,
-                               .encrypt = spacc_aead_encrypt,
-                               .decrypt = spacc_aead_decrypt,
-                               .givencrypt = spacc_aead_givencrypt,
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA256_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-3des-picoxcell",
+                               .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_NEED_FALLBACK |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct spacc_aead_ctx),
+                               .cra_module = THIS_MODULE,
                        },
-                       .cra_init = spacc_aead_cra_init,
-                       .cra_exit = spacc_aead_cra_exit,
+                       .setkey = spacc_aead_setkey,
+                       .setauthsize = spacc_aead_setauthsize,
+                       .encrypt = spacc_aead_encrypt,
+                       .decrypt = spacc_aead_decrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
+                       .init = spacc_aead_cra_init,
+                       .exit = spacc_aead_cra_exit,
                },
        },
        {
                .key_offs = DES_BLOCK_SIZE,
                .iv_offs = 0,
-               .ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC |
-                               SPA_CTRL_HASH_ALG_MD5 | SPA_CTRL_HASH_MODE_HMAC,
+               .ctrl_default = SPA_CTRL_CIPH_ALG_DES |
+                               SPA_CTRL_CIPH_MODE_CBC |
+                               SPA_CTRL_HASH_ALG_MD5 |
+                               SPA_CTRL_HASH_MODE_HMAC,
                .alg = {
-                       .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-md5-cbc-3des-picoxcell",
-                       .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD |
-                                       CRYPTO_ALG_ASYNC |
-                                       CRYPTO_ALG_KERN_DRIVER_ONLY,
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_ctxsize = sizeof(struct spacc_aead_ctx),
-                       .cra_type = &crypto_aead_type,
-                       .cra_module = THIS_MODULE,
-                       .cra_aead = {
-                               .setkey = spacc_aead_setkey,
-                               .setauthsize = spacc_aead_setauthsize,
-                               .encrypt = spacc_aead_encrypt,
-                               .decrypt = spacc_aead_decrypt,
-                               .givencrypt = spacc_aead_givencrypt,
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = MD5_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-3des-picoxcell",
+                               .cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_NEED_FALLBACK |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct spacc_aead_ctx),
+                               .cra_module = THIS_MODULE,
                        },
-                       .cra_init = spacc_aead_cra_init,
-                       .cra_exit = spacc_aead_cra_exit,
+                       .setkey = spacc_aead_setkey,
+                       .setauthsize = spacc_aead_setauthsize,
+                       .encrypt = spacc_aead_encrypt,
+                       .decrypt = spacc_aead_decrypt,
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
+                       .init = spacc_aead_cra_init,
+                       .exit = spacc_aead_cra_exit,
                },
        },
 };
@@ -1707,6 +1625,8 @@ static int spacc_probe(struct platform_device *pdev)
                engine->fifo_sz         = SPACC_CRYPTO_IPSEC_FIFO_SZ;
                engine->algs            = ipsec_engine_algs;
                engine->num_algs        = ARRAY_SIZE(ipsec_engine_algs);
+               engine->aeads           = ipsec_engine_aeads;
+               engine->num_aeads       = ARRAY_SIZE(ipsec_engine_aeads);
        } else if (spacc_is_compatible(pdev, "picochip,spacc-l2")) {
                engine->max_ctxs        = SPACC_CRYPTO_L2_MAX_CTXS;
                engine->cipher_pg_sz    = SPACC_CRYPTO_L2_CIPHER_PG_SZ;
@@ -1815,17 +1735,40 @@ static int spacc_probe(struct platform_device *pdev)
                                engine->algs[i].alg.cra_name);
        }
 
+       INIT_LIST_HEAD(&engine->registered_aeads);
+       for (i = 0; i < engine->num_aeads; ++i) {
+               engine->aeads[i].engine = engine;
+               err = crypto_register_aead(&engine->aeads[i].alg);
+               if (!err) {
+                       list_add_tail(&engine->aeads[i].entry,
+                                     &engine->registered_aeads);
+                       ret = 0;
+               }
+               if (err)
+                       dev_err(engine->dev, "failed to register alg \"%s\"\n",
+                               engine->aeads[i].alg.base.cra_name);
+               else
+                       dev_dbg(engine->dev, "registered alg \"%s\"\n",
+                               engine->aeads[i].alg.base.cra_name);
+       }
+
        return ret;
 }
 
 static int spacc_remove(struct platform_device *pdev)
 {
+       struct spacc_aead *aead, *an;
        struct spacc_alg *alg, *next;
        struct spacc_engine *engine = platform_get_drvdata(pdev);
 
        del_timer_sync(&engine->packet_timeout);
        device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
 
+       list_for_each_entry_safe(aead, an, &engine->registered_aeads, entry) {
+               list_del(&aead->entry);
+               crypto_unregister_aead(&aead->alg);
+       }
+
        list_for_each_entry_safe(alg, next, &engine->registered_algs, entry) {
                list_del(&alg->entry);
                crypto_unregister_alg(&alg->alg);
index 6fdb9e8b22a75247971fca0b500414b8028bc7dd..eefccf7b8be749ca4a0c24df900ec879608f0a74 100644 (file)
@@ -3,11 +3,13 @@ config CRYPTO_DEV_QAT
        select CRYPTO_AEAD
        select CRYPTO_AUTHENC
        select CRYPTO_BLKCIPHER
+       select CRYPTO_AKCIPHER
        select CRYPTO_HMAC
        select CRYPTO_SHA1
        select CRYPTO_SHA256
        select CRYPTO_SHA512
        select FW_LOADER
+       select ASN1
 
 config CRYPTO_DEV_QAT_DH895xCC
        tristate "Support for Intel(R) DH895xCC"
@@ -19,3 +21,16 @@ config CRYPTO_DEV_QAT_DH895xCC
 
          To compile this as a module, choose M here: the module
          will be called qat_dh895xcc.
+
+config CRYPTO_DEV_QAT_DH895xCCVF
+       tristate "Support for Intel(R) DH895xCC Virtual Function"
+       depends on X86 && PCI
+       select PCI_IOV
+       select CRYPTO_DEV_QAT
+
+       help
+         Support for Intel(R) DH895xcc with Intel(R) QuickAssist Technology
+         Virtual Function for accelerating crypto and compression workloads.
+
+         To compile this as a module, choose M here: the module
+         will be called qat_dh895xccvf.
index d11481be225e5788273f61b7e10e92da26dcf2ad..a3ce0b70e32ff3f3767456039e871ea8d5c64961 100644 (file)
@@ -1,2 +1,3 @@
 obj-$(CONFIG_CRYPTO_DEV_QAT) += qat_common/
 obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc/
+obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCCVF) += qat_dh895xccvf/
diff --git a/drivers/crypto/qat/qat_common/.gitignore b/drivers/crypto/qat/qat_common/.gitignore
new file mode 100644 (file)
index 0000000..ee32837
--- /dev/null
@@ -0,0 +1 @@
+*-asn1.[ch]
index e0424dc382feb1543784b704b4c33984927739a1..df20a9de1c586ef26bb3c5ba513ed052c35d573c 100644 (file)
@@ -1,3 +1,6 @@
+$(obj)/qat_rsakey-asn1.o: $(obj)/qat_rsakey-asn1.c $(obj)/qat_rsakey-asn1.h
+clean-files += qat_rsakey-asn1.c qat_rsakey-asn1.h
+
 obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
 intel_qat-objs := adf_cfg.o \
        adf_ctl_drv.o \
@@ -6,9 +9,14 @@ intel_qat-objs := adf_cfg.o \
        adf_accel_engine.o \
        adf_aer.o \
        adf_transport.o \
+       adf_admin.o \
+       adf_hw_arbiter.o \
        qat_crypto.o \
        qat_algs.o \
+       qat_rsakey-asn1.o \
+       qat_asym_algs.o \
        qat_uclo.o \
        qat_hal.o
 
 intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o
+intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_pf2vf_msg.o
index 5fe90296762083e12690e70ace018b273d9e5569..ca853d50b4b78154779a8ac50f7cfeb5428c28f3 100644 (file)
 */
 #ifndef ADF_ACCEL_DEVICES_H_
 #define ADF_ACCEL_DEVICES_H_
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/ratelimit.h>
 #include "adf_cfg_common.h"
 
 #define ADF_DH895XCC_DEVICE_NAME "dh895xcc"
+#define ADF_DH895XCCVF_DEVICE_NAME "dh895xccvf"
 #define ADF_DH895XCC_PCI_DEVICE_ID 0x435
+#define ADF_DH895XCCIOV_PCI_DEVICE_ID 0x443
 #define ADF_PCI_MAX_BARS 3
 #define ADF_DEVICE_NAME_LENGTH 32
 #define ADF_ETR_MAX_RINGS_PER_BANK 16
@@ -79,6 +83,7 @@ struct adf_bar {
 struct adf_accel_msix {
        struct msix_entry *entries;
        char **names;
+       u32 num_entries;
 } __packed;
 
 struct adf_accel_pci {
@@ -99,6 +104,7 @@ enum dev_sku_info {
        DEV_SKU_2,
        DEV_SKU_3,
        DEV_SKU_4,
+       DEV_SKU_VF,
        DEV_SKU_UNKNOWN,
 };
 
@@ -113,6 +119,8 @@ static inline const char *get_sku_info(enum dev_sku_info info)
                return "SKU3";
        case DEV_SKU_4:
                return "SKU4";
+       case DEV_SKU_VF:
+               return "SKUVF";
        case DEV_SKU_UNKNOWN:
        default:
                break;
@@ -135,23 +143,29 @@ struct adf_hw_device_data {
        struct adf_hw_device_class *dev_class;
        uint32_t (*get_accel_mask)(uint32_t fuse);
        uint32_t (*get_ae_mask)(uint32_t fuse);
+       uint32_t (*get_sram_bar_id)(struct adf_hw_device_data *self);
        uint32_t (*get_misc_bar_id)(struct adf_hw_device_data *self);
        uint32_t (*get_etr_bar_id)(struct adf_hw_device_data *self);
        uint32_t (*get_num_aes)(struct adf_hw_device_data *self);
        uint32_t (*get_num_accels)(struct adf_hw_device_data *self);
+       uint32_t (*get_pf2vf_offset)(uint32_t i);
+       uint32_t (*get_vintmsk_offset)(uint32_t i);
        enum dev_sku_info (*get_sku)(struct adf_hw_device_data *self);
-       void (*hw_arb_ring_enable)(struct adf_etr_ring_data *ring);
-       void (*hw_arb_ring_disable)(struct adf_etr_ring_data *ring);
        int (*alloc_irq)(struct adf_accel_dev *accel_dev);
        void (*free_irq)(struct adf_accel_dev *accel_dev);
        void (*enable_error_correction)(struct adf_accel_dev *accel_dev);
        int (*init_admin_comms)(struct adf_accel_dev *accel_dev);
        void (*exit_admin_comms)(struct adf_accel_dev *accel_dev);
+       int (*send_admin_init)(struct adf_accel_dev *accel_dev);
        int (*init_arb)(struct adf_accel_dev *accel_dev);
        void (*exit_arb)(struct adf_accel_dev *accel_dev);
+       void (*get_arb_mapping)(struct adf_accel_dev *accel_dev,
+                               const uint32_t **cfg);
+       void (*disable_iov)(struct adf_accel_dev *accel_dev);
        void (*enable_ints)(struct adf_accel_dev *accel_dev);
+       int (*enable_vf2pf_comms)(struct adf_accel_dev *accel_dev);
        const char *fw_name;
-       uint32_t pci_dev_id;
+       const char *fw_mmp_name;
        uint32_t fuses;
        uint32_t accel_capabilities_mask;
        uint16_t accel_mask;
@@ -163,6 +177,7 @@ struct adf_hw_device_data {
        uint8_t num_accel;
        uint8_t num_logical_accel;
        uint8_t num_engines;
+       uint8_t min_iov_compat_ver;
 } __packed;
 
 /* CSR write macro */
@@ -184,6 +199,16 @@ struct icp_qat_fw_loader_handle;
 struct adf_fw_loader_data {
        struct icp_qat_fw_loader_handle *fw_loader;
        const struct firmware *uof_fw;
+       const struct firmware *mmp_fw;
+};
+
+struct adf_accel_vf_info {
+       struct adf_accel_dev *accel_dev;
+       struct tasklet_struct vf2pf_bh_tasklet;
+       struct mutex pf2vf_lock; /* protect CSR access for PF2VF messages */
+       struct ratelimit_state vf2pf_ratelimit;
+       u32 vf_nr;
+       bool init;
 };
 
 struct adf_accel_dev {
@@ -199,6 +224,21 @@ struct adf_accel_dev {
        struct list_head list;
        struct module *owner;
        struct adf_accel_pci accel_pci_dev;
+       union {
+               struct {
+                       /* vf_info is non-zero when SR-IOV is init'ed */
+                       struct adf_accel_vf_info *vf_info;
+               } pf;
+               struct {
+                       char *irq_name;
+                       struct tasklet_struct pf2vf_bh_tasklet;
+                       struct mutex vf2pf_lock; /* protect CSR access */
+                       struct completion iov_msg_completion;
+                       uint8_t compatible;
+                       uint8_t pf_version;
+               } vf;
+       };
+       bool is_vf;
        uint8_t accel_id;
 } __packed;
 #endif
index fdda8e7ae302511bec5c0e1c18d2c5c4b2b3d351..20b08bdcb1466f4ba8d15ccd933abd7ea4663a29 100644 (file)
@@ -55,24 +55,36 @@ int adf_ae_fw_load(struct adf_accel_dev *accel_dev)
 {
        struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
        struct adf_hw_device_data *hw_device = accel_dev->hw_device;
-       void *uof_addr;
-       uint32_t uof_size;
+       void *uof_addr, *mmp_addr;
+       u32 uof_size, mmp_size;
 
+       if (!hw_device->fw_name)
+               return 0;
+
+       if (request_firmware(&loader_data->mmp_fw, hw_device->fw_mmp_name,
+                            &accel_dev->accel_pci_dev.pci_dev->dev)) {
+               dev_err(&GET_DEV(accel_dev), "Failed to load MMP firmware %s\n",
+                       hw_device->fw_mmp_name);
+               return -EFAULT;
+       }
        if (request_firmware(&loader_data->uof_fw, hw_device->fw_name,
                             &accel_dev->accel_pci_dev.pci_dev->dev)) {
-               dev_err(&GET_DEV(accel_dev), "Failed to load firmware %s\n",
+               dev_err(&GET_DEV(accel_dev), "Failed to load UOF firmware %s\n",
                        hw_device->fw_name);
-               return -EFAULT;
+               goto out_err;
        }
 
        uof_size = loader_data->uof_fw->size;
        uof_addr = (void *)loader_data->uof_fw->data;
+       mmp_size = loader_data->mmp_fw->size;
+       mmp_addr = (void *)loader_data->mmp_fw->data;
+       qat_uclo_wr_mimage(loader_data->fw_loader, mmp_addr, mmp_size);
        if (qat_uclo_map_uof_obj(loader_data->fw_loader, uof_addr, uof_size)) {
                dev_err(&GET_DEV(accel_dev), "Failed to map UOF\n");
                goto out_err;
        }
        if (qat_uclo_wr_all_uimage(loader_data->fw_loader)) {
-               dev_err(&GET_DEV(accel_dev), "Failed to map UOF\n");
+               dev_err(&GET_DEV(accel_dev), "Failed to load UOF\n");
                goto out_err;
        }
        return 0;
@@ -85,11 +97,17 @@ out_err:
 void adf_ae_fw_release(struct adf_accel_dev *accel_dev)
 {
        struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+       struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+
+       if (!hw_device->fw_name)
+               return;
 
        qat_uclo_del_uof_obj(loader_data->fw_loader);
        qat_hal_deinit(loader_data->fw_loader);
        release_firmware(loader_data->uof_fw);
+       release_firmware(loader_data->mmp_fw);
        loader_data->uof_fw = NULL;
+       loader_data->mmp_fw = NULL;
        loader_data->fw_loader = NULL;
 }
 
@@ -99,6 +117,9 @@ int adf_ae_start(struct adf_accel_dev *accel_dev)
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
 
+       if (!hw_data->fw_name)
+               return 0;
+
        for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
                if (hw_data->ae_mask & (1 << ae)) {
                        qat_hal_start(loader_data->fw_loader, ae, 0xFF);
@@ -117,6 +138,9 @@ int adf_ae_stop(struct adf_accel_dev *accel_dev)
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
 
+       if (!hw_data->fw_name)
+               return 0;
+
        for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
                if (hw_data->ae_mask & (1 << ae)) {
                        qat_hal_stop(loader_data->fw_loader, ae, 0xFF);
@@ -143,6 +167,10 @@ static int adf_ae_reset(struct adf_accel_dev *accel_dev, int ae)
 int adf_ae_init(struct adf_accel_dev *accel_dev)
 {
        struct adf_fw_loader_data *loader_data;
+       struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+
+       if (!hw_device->fw_name)
+               return 0;
 
        loader_data = kzalloc(sizeof(*loader_data), GFP_KERNEL);
        if (!loader_data)
@@ -166,6 +194,10 @@ int adf_ae_init(struct adf_accel_dev *accel_dev)
 int adf_ae_shutdown(struct adf_accel_dev *accel_dev)
 {
        struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+       struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+
+       if (!hw_device->fw_name)
+               return 0;
 
        qat_hal_deinit(loader_data->fw_loader);
        kfree(accel_dev->fw_loader);
diff --git a/drivers/crypto/qat/qat_common/adf_admin.c b/drivers/crypto/qat/qat_common/adf_admin.c
new file mode 100644 (file)
index 0000000..147d755
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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/types.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include "adf_accel_devices.h"
+#include "icp_qat_fw_init_admin.h"
+
+/* Admin Messages Registers */
+#define ADF_DH895XCC_ADMINMSGUR_OFFSET (0x3A000 + 0x574)
+#define ADF_DH895XCC_ADMINMSGLR_OFFSET (0x3A000 + 0x578)
+#define ADF_DH895XCC_MAILBOX_BASE_OFFSET 0x20970
+#define ADF_DH895XCC_MAILBOX_STRIDE 0x1000
+#define ADF_ADMINMSG_LEN 32
+
+static const u8 const_tab[1024] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76,
+0x54, 0x32, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab,
+0x89, 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x05, 0x9e,
+0xd8, 0x36, 0x7c, 0xd5, 0x07, 0x30, 0x70, 0xdd, 0x17, 0xf7, 0x0e, 0x59, 0x39,
+0xff, 0xc0, 0x0b, 0x31, 0x68, 0x58, 0x15, 0x11, 0x64, 0xf9, 0x8f, 0xa7, 0xbe,
+0xfa, 0x4f, 0xa4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae,
+0x85, 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f,
+0x9b, 0x05, 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19, 0x05,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29,
+0x2a, 0x36, 0x7c, 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, 0xdd, 0x17,
+0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39, 0x67, 0x33, 0x26, 0x67, 0xff,
+0xc0, 0x0b, 0x31, 0x8e, 0xb4, 0x4a, 0x87, 0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c,
+0x2e, 0x0d, 0x64, 0xf9, 0x8f, 0xa7, 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f,
+0xa4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb,
+0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94,
+0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, 0x0e, 0x52,
+0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
+0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13,
+0x7e, 0x21, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+struct adf_admin_comms {
+       dma_addr_t phy_addr;
+       dma_addr_t const_tbl_addr;
+       void *virt_addr;
+       void __iomem *mailbox_addr;
+       struct mutex lock;      /* protects adf_admin_comms struct */
+};
+
+static int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev, u32 ae,
+                                 void *in, void *out)
+{
+       struct adf_admin_comms *admin = accel_dev->admin;
+       int offset = ae * ADF_ADMINMSG_LEN * 2;
+       void __iomem *mailbox = admin->mailbox_addr;
+       int mb_offset = ae * ADF_DH895XCC_MAILBOX_STRIDE;
+       int times, received;
+
+       mutex_lock(&admin->lock);
+
+       if (ADF_CSR_RD(mailbox, mb_offset) == 1) {
+               mutex_unlock(&admin->lock);
+               return -EAGAIN;
+       }
+
+       memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN);
+       ADF_CSR_WR(mailbox, mb_offset, 1);
+       received = 0;
+       for (times = 0; times < 50; times++) {
+               msleep(20);
+               if (ADF_CSR_RD(mailbox, mb_offset) == 0) {
+                       received = 1;
+                       break;
+               }
+       }
+       if (received)
+               memcpy(out, admin->virt_addr + offset +
+                      ADF_ADMINMSG_LEN, ADF_ADMINMSG_LEN);
+       else
+               dev_err(&GET_DEV(accel_dev),
+                       "Failed to send admin msg to accelerator\n");
+
+       mutex_unlock(&admin->lock);
+       return received ? 0 : -EFAULT;
+}
+
+static int adf_send_admin_cmd(struct adf_accel_dev *accel_dev, int cmd)
+{
+       struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+       struct icp_qat_fw_init_admin_req req;
+       struct icp_qat_fw_init_admin_resp resp;
+       int i;
+
+       memset(&req, 0, sizeof(struct icp_qat_fw_init_admin_req));
+       req.init_admin_cmd_id = cmd;
+
+       if (cmd == ICP_QAT_FW_CONSTANTS_CFG) {
+               req.init_cfg_sz = 1024;
+               req.init_cfg_ptr = accel_dev->admin->const_tbl_addr;
+       }
+       for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
+               memset(&resp, 0, sizeof(struct icp_qat_fw_init_admin_resp));
+               if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) ||
+                   resp.init_resp_hdr.status)
+                       return -EFAULT;
+       }
+       return 0;
+}
+
+/**
+ * adf_send_admin_init() - Function sends init message to FW
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function sends admin init message to the FW
+ *
+ * Return: 0 on success, error code otherwise.
+ */
+int adf_send_admin_init(struct adf_accel_dev *accel_dev)
+{
+       int ret = adf_send_admin_cmd(accel_dev, ICP_QAT_FW_INIT_ME);
+
+       if (ret)
+               return ret;
+       return adf_send_admin_cmd(accel_dev, ICP_QAT_FW_CONSTANTS_CFG);
+}
+EXPORT_SYMBOL_GPL(adf_send_admin_init);
+
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
+{
+       struct adf_admin_comms *admin;
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_bar *pmisc =
+               &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       void __iomem *csr = pmisc->virt_addr;
+       void __iomem *mailbox = csr + ADF_DH895XCC_MAILBOX_BASE_OFFSET;
+       u64 reg_val;
+
+       admin = kzalloc_node(sizeof(*accel_dev->admin), GFP_KERNEL,
+                            dev_to_node(&GET_DEV(accel_dev)));
+       if (!admin)
+               return -ENOMEM;
+       admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+                                              &admin->phy_addr, GFP_KERNEL);
+       if (!admin->virt_addr) {
+               dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
+               kfree(admin);
+               return -ENOMEM;
+       }
+
+       admin->const_tbl_addr = dma_map_single(&GET_DEV(accel_dev),
+                                              (void *) const_tab, 1024,
+                                              DMA_TO_DEVICE);
+
+       if (unlikely(dma_mapping_error(&GET_DEV(accel_dev),
+                                      admin->const_tbl_addr))) {
+               dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+                                 admin->virt_addr, admin->phy_addr);
+               kfree(admin);
+               return -ENOMEM;
+       }
+       reg_val = (u64)admin->phy_addr;
+       ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGUR_OFFSET, reg_val >> 32);
+       ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGLR_OFFSET, reg_val);
+       mutex_init(&admin->lock);
+       admin->mailbox_addr = mailbox;
+       accel_dev->admin = admin;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(adf_init_admin_comms);
+
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev)
+{
+       struct adf_admin_comms *admin = accel_dev->admin;
+
+       if (!admin)
+               return;
+
+       if (admin->virt_addr)
+               dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+                                 admin->virt_addr, admin->phy_addr);
+
+       dma_unmap_single(&GET_DEV(accel_dev), admin->const_tbl_addr, 1024,
+                        DMA_TO_DEVICE);
+       mutex_destroy(&admin->lock);
+       kfree(admin);
+       accel_dev->admin = NULL;
+}
+EXPORT_SYMBOL_GPL(adf_exit_admin_comms);
index 2dbc733b8ab2483e8790d26a2f509239c681573d..a57b4194de2845aaee3eb77d9e7bd268cf63184f 100644 (file)
@@ -91,6 +91,9 @@ static void adf_dev_restore(struct adf_accel_dev *accel_dev)
        dev_info(&GET_DEV(accel_dev), "Resetting device qat_dev%d\n",
                 accel_dev->accel_id);
 
+       if (!parent)
+               parent = pdev;
+
        if (!pci_wait_for_pending_transaction(pdev))
                dev_info(&GET_DEV(accel_dev),
                         "Transaction still in progress. Proceeding\n");
@@ -206,7 +209,7 @@ static struct pci_error_handlers adf_err_handler = {
  * QAT acceleration device accel_dev.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf)
 {
index ab65bc274561dc58000f644d68bef6bf3b2b7926..d0879790561fa68efdebcc3a643d946cacd8257d 100644 (file)
@@ -123,7 +123,7 @@ static const struct file_operations qat_dev_cfg_fops = {
  * The table stores device specific config values.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
 {
@@ -178,6 +178,9 @@ void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
 {
        struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
 
+       if (!dev_cfg_data)
+               return;
+
        down_write(&dev_cfg_data->lock);
        adf_cfg_section_del_all(&dev_cfg_data->sec_list);
        up_write(&dev_cfg_data->lock);
@@ -276,7 +279,7 @@ static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
  * in the given acceleration device
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
                                const char *section_name,
@@ -327,7 +330,7 @@ EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
  * will be stored.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
 {
index 88b82187ac3543e25d869972287cef8bad5f72fa..c697fb1cdfb5af2a47697b42f39e10649dab2adc 100644 (file)
@@ -60,7 +60,7 @@
 #define ADF_CFG_NO_DEVICE 0xFF
 #define ADF_CFG_AFFINITY_WHATEVER 0xFF
 #define MAX_DEVICE_NAME_SIZE 32
-#define ADF_MAX_DEVICES 32
+#define ADF_MAX_DEVICES (32 * 32)
 
 enum adf_cfg_val_type {
        ADF_DEC,
@@ -71,6 +71,7 @@ enum adf_cfg_val_type {
 enum adf_device_type {
        DEV_UNKNOWN = 0,
        DEV_DH895XCC,
+       DEV_DH895XCCVF,
 };
 
 struct adf_dev_status_info {
index 27e16c09230bffa24e505a03c8848fc7ab2bb40d..7836dffc3d4728abbe54dc0fc15af920cff9f84f 100644 (file)
@@ -54,8 +54,8 @@
 #include "icp_qat_hal.h"
 
 #define ADF_MAJOR_VERSION      0
-#define ADF_MINOR_VERSION      1
-#define ADF_BUILD_VERSION      3
+#define ADF_MINOR_VERSION      2
+#define ADF_BUILD_VERSION      0
 #define ADF_DRV_VERSION                __stringify(ADF_MAJOR_VERSION) "." \
                                __stringify(ADF_MINOR_VERSION) "." \
                                __stringify(ADF_BUILD_VERSION)
@@ -91,9 +91,13 @@ struct service_hndl {
        unsigned long start_status;
        char *name;
        struct list_head list;
-       int admin;
 };
 
+static inline int get_current_node(void)
+{
+       return topology_physical_package_id(smp_processor_id());
+}
+
 int adf_service_register(struct service_hndl *service);
 int adf_service_unregister(struct service_hndl *service);
 
@@ -102,13 +106,24 @@ int adf_dev_start(struct adf_accel_dev *accel_dev);
 int adf_dev_stop(struct adf_accel_dev *accel_dev);
 void adf_dev_shutdown(struct adf_accel_dev *accel_dev);
 
+void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
+void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
+int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr);
+void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev);
+int adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev);
+void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info);
+void adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data);
+void adf_clean_vf_map(bool);
+
 int adf_ctl_dev_register(void);
 void adf_ctl_dev_unregister(void);
 int adf_processes_dev_register(void);
 void adf_processes_dev_unregister(void);
 
-int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev);
-void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev);
+int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev,
+                      struct adf_accel_dev *pf);
+void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev,
+                      struct adf_accel_dev *pf);
 struct list_head *adf_devmgr_get_head(void);
 struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id);
 struct adf_accel_dev *adf_devmgr_get_first(void);
@@ -130,6 +145,12 @@ int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf);
 void adf_disable_aer(struct adf_accel_dev *accel_dev);
 int adf_init_aer(void);
 void adf_exit_aer(void);
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
+int adf_send_admin_init(struct adf_accel_dev *accel_dev);
+int adf_init_arb(struct adf_accel_dev *accel_dev);
+void adf_exit_arb(struct adf_accel_dev *accel_dev);
+void adf_update_ring_arb(struct adf_etr_ring_data *ring);
 
 int adf_dev_get(struct adf_accel_dev *accel_dev);
 void adf_dev_put(struct adf_accel_dev *accel_dev);
@@ -141,10 +162,13 @@ int qat_crypto_unregister(void);
 struct qat_crypto_instance *qat_crypto_get_instance_node(int node);
 void qat_crypto_put_instance(struct qat_crypto_instance *inst);
 void qat_alg_callback(void *resp);
+void qat_alg_asym_callback(void *resp);
 int qat_algs_init(void);
 void qat_algs_exit(void);
 int qat_algs_register(void);
 int qat_algs_unregister(void);
+int qat_asym_algs_register(void);
+void qat_asym_algs_unregister(void);
 
 int qat_hal_init(struct adf_accel_dev *accel_dev);
 void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle);
@@ -196,4 +220,23 @@ int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle);
 void qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle);
 int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
                         void *addr_ptr, int mem_size);
+void qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle,
+                       void *addr_ptr, int mem_size);
+#if defined(CONFIG_PCI_IOV)
+int adf_sriov_configure(struct pci_dev *pdev, int numvfs);
+void adf_disable_sriov(struct adf_accel_dev *accel_dev);
+void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
+                                 uint32_t vf_mask);
+void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
+                                uint32_t vf_mask);
+#else
+static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
+{
+       return 0;
+}
+
+static inline void adf_disable_sriov(struct adf_accel_dev *accel_dev)
+{
+}
+#endif
 #endif
index e056b9e9bf8a99068aa0c0097fc57fe9da25a27f..cd8a12af8ec53467019683d5ce962947eaa72f57 100644 (file)
@@ -398,10 +398,9 @@ static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
        }
 
        accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
-       if (!accel_dev) {
-               pr_err("QAT: Device %d not found\n", dev_info.accel_id);
+       if (!accel_dev)
                return -ENODEV;
-       }
+
        hw_data = accel_dev->hw_device;
        dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
        dev_info.num_ae = hw_data->get_num_aes(hw_data);
@@ -495,6 +494,7 @@ static void __exit adf_unregister_ctl_device_driver(void)
        adf_exit_aer();
        qat_crypto_unregister();
        qat_algs_exit();
+       adf_clean_vf_map(false);
        mutex_destroy(&adf_ctl_lock);
 }
 
index 3f0ff9e7d84060918b55321b09be752533e166e2..8dfdb8f907973359bb3bd4da893d94f46540cd7c 100644 (file)
 #include "adf_common_drv.h"
 
 static LIST_HEAD(accel_table);
+static LIST_HEAD(vfs_table);
 static DEFINE_MUTEX(table_lock);
 static uint32_t num_devices;
 
+struct vf_id_map {
+       u32 bdf;
+       u32 id;
+       u32 fake_id;
+       bool attached;
+       struct list_head list;
+};
+
+static int adf_get_vf_id(struct adf_accel_dev *vf)
+{
+       return ((7 * (PCI_SLOT(accel_to_pci_dev(vf)->devfn) - 1)) +
+               PCI_FUNC(accel_to_pci_dev(vf)->devfn) +
+               (PCI_SLOT(accel_to_pci_dev(vf)->devfn) - 1));
+}
+
+static int adf_get_vf_num(struct adf_accel_dev *vf)
+{
+       return (accel_to_pci_dev(vf)->bus->number << 8) | adf_get_vf_id(vf);
+}
+
+static struct vf_id_map *adf_find_vf(u32 bdf)
+{
+       struct list_head *itr;
+
+       list_for_each(itr, &vfs_table) {
+               struct vf_id_map *ptr =
+                       list_entry(itr, struct vf_id_map, list);
+
+               if (ptr->bdf == bdf)
+                       return ptr;
+       }
+       return NULL;
+}
+
+static int adf_get_vf_real_id(u32 fake)
+{
+       struct list_head *itr;
+
+       list_for_each(itr, &vfs_table) {
+               struct vf_id_map *ptr =
+                       list_entry(itr, struct vf_id_map, list);
+               if (ptr->fake_id == fake)
+                       return ptr->id;
+       }
+       return -1;
+}
+
+/**
+ * adf_clean_vf_map() - Cleans VF id mapings
+ *
+ * Function cleans internal ids for virtual functions.
+ * @vf: flag indicating whether mappings is cleaned
+ *     for vfs only or for vfs and pfs
+ */
+void adf_clean_vf_map(bool vf)
+{
+       struct vf_id_map *map;
+       struct list_head *ptr, *tmp;
+
+       mutex_lock(&table_lock);
+       list_for_each_safe(ptr, tmp, &vfs_table) {
+               map = list_entry(ptr, struct vf_id_map, list);
+               if (map->bdf != -1)
+                       num_devices--;
+
+               if (vf && map->bdf == -1)
+                       continue;
+
+               list_del(ptr);
+               kfree(map);
+       }
+       mutex_unlock(&table_lock);
+}
+EXPORT_SYMBOL_GPL(adf_clean_vf_map);
+
+/**
+ * adf_devmgr_update_class_index() - Update internal index
+ * @hw_data:  Pointer to internal device data.
+ *
+ * Function updates internal dev index for VFs
+ */
+void adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data)
+{
+       struct adf_hw_device_class *class = hw_data->dev_class;
+       struct list_head *itr;
+       int i = 0;
+
+       list_for_each(itr, &accel_table) {
+               struct adf_accel_dev *ptr =
+                               list_entry(itr, struct adf_accel_dev, list);
+
+               if (ptr->hw_device->dev_class == class)
+                       ptr->hw_device->instance_id = i++;
+
+               if (i == class->instances)
+                               break;
+       }
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_update_class_index);
+
 /**
  * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework
  * @accel_dev:  Pointer to acceleration device.
+ * @pf:                Corresponding PF if the accel_dev is a VF
  *
  * Function adds acceleration device to the acceleration framework.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
-int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev)
+int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev,
+                      struct adf_accel_dev *pf)
 {
        struct list_head *itr;
+       int ret = 0;
 
        if (num_devices == ADF_MAX_DEVICES) {
                dev_err(&GET_DEV(accel_dev), "Only support up to %d devices\n",
@@ -73,20 +177,77 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev)
        }
 
        mutex_lock(&table_lock);
-       list_for_each(itr, &accel_table) {
-               struct adf_accel_dev *ptr =
+       atomic_set(&accel_dev->ref_count, 0);
+
+       /* PF on host or VF on guest */
+       if (!accel_dev->is_vf || (accel_dev->is_vf && !pf)) {
+               struct vf_id_map *map;
+
+               list_for_each(itr, &accel_table) {
+                       struct adf_accel_dev *ptr =
                                list_entry(itr, struct adf_accel_dev, list);
 
-               if (ptr == accel_dev) {
-                       mutex_unlock(&table_lock);
-                       return -EEXIST;
+                       if (ptr == accel_dev) {
+                               ret = -EEXIST;
+                               goto unlock;
+                       }
                }
+
+               list_add_tail(&accel_dev->list, &accel_table);
+               accel_dev->accel_id = num_devices++;
+
+               map = kzalloc(sizeof(*map), GFP_KERNEL);
+               if (!map) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
+               map->bdf = ~0;
+               map->id = accel_dev->accel_id;
+               map->fake_id = map->id;
+               map->attached = true;
+               list_add_tail(&map->list, &vfs_table);
+       } else if (accel_dev->is_vf && pf) {
+               /* VF on host */
+               struct adf_accel_vf_info *vf_info;
+               struct vf_id_map *map;
+
+               vf_info = pf->pf.vf_info + adf_get_vf_id(accel_dev);
+
+               map = adf_find_vf(adf_get_vf_num(accel_dev));
+               if (map) {
+                       struct vf_id_map *next;
+
+                       accel_dev->accel_id = map->id;
+                       list_add_tail(&accel_dev->list, &accel_table);
+                       map->fake_id++;
+                       map->attached = true;
+                       next = list_next_entry(map, list);
+                       while (next && &next->list != &vfs_table) {
+                               next->fake_id++;
+                               next = list_next_entry(next, list);
+                       }
+
+                       ret = 0;
+                       goto unlock;
+               }
+
+               map = kzalloc(sizeof(*map), GFP_KERNEL);
+               if (!map) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
+
+               accel_dev->accel_id = num_devices++;
+               list_add_tail(&accel_dev->list, &accel_table);
+               map->bdf = adf_get_vf_num(accel_dev);
+               map->id = accel_dev->accel_id;
+               map->fake_id = map->id;
+               map->attached = true;
+               list_add_tail(&map->list, &vfs_table);
        }
-       atomic_set(&accel_dev->ref_count, 0);
-       list_add_tail(&accel_dev->list, &accel_table);
-       accel_dev->accel_id = num_devices++;
+unlock:
        mutex_unlock(&table_lock);
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(adf_devmgr_add_dev);
 
@@ -98,17 +259,37 @@ struct list_head *adf_devmgr_get_head(void)
 /**
  * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework.
  * @accel_dev:  Pointer to acceleration device.
+ * @pf:                Corresponding PF if the accel_dev is a VF
  *
  * Function removes acceleration device from the acceleration framework.
  * To be used by QAT device specific drivers.
  *
  * Return: void
  */
-void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev)
+void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev,
+                      struct adf_accel_dev *pf)
 {
        mutex_lock(&table_lock);
+       if (!accel_dev->is_vf || (accel_dev->is_vf && !pf)) {
+               num_devices--;
+       } else if (accel_dev->is_vf && pf) {
+               struct vf_id_map *map, *next;
+
+               map = adf_find_vf(adf_get_vf_num(accel_dev));
+               if (!map) {
+                       dev_err(&GET_DEV(accel_dev), "Failed to find VF map\n");
+                       goto unlock;
+               }
+               map->fake_id--;
+               map->attached = false;
+               next = list_next_entry(map, list);
+               while (next && &next->list != &vfs_table) {
+                       next->fake_id--;
+                       next = list_next_entry(next, list);
+               }
+       }
+unlock:
        list_del(&accel_dev->list);
-       num_devices--;
        mutex_unlock(&table_lock);
 }
 EXPORT_SYMBOL_GPL(adf_devmgr_rm_dev);
@@ -154,17 +335,24 @@ EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev);
 struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id)
 {
        struct list_head *itr;
+       int real_id;
 
        mutex_lock(&table_lock);
+       real_id = adf_get_vf_real_id(id);
+       if (real_id < 0)
+               goto unlock;
+
+       id = real_id;
+
        list_for_each(itr, &accel_table) {
                struct adf_accel_dev *ptr =
                                list_entry(itr, struct adf_accel_dev, list);
-
                if (ptr->accel_id == id) {
                        mutex_unlock(&table_lock);
                        return ptr;
                }
        }
+unlock:
        mutex_unlock(&table_lock);
        return NULL;
 }
@@ -180,21 +368,52 @@ int adf_devmgr_verify_id(uint32_t id)
        return -ENODEV;
 }
 
-void adf_devmgr_get_num_dev(uint32_t *num)
+static int adf_get_num_dettached_vfs(void)
 {
        struct list_head *itr;
+       int vfs = 0;
 
-       *num = 0;
-       list_for_each(itr, &accel_table) {
-               (*num)++;
+       mutex_lock(&table_lock);
+       list_for_each(itr, &vfs_table) {
+               struct vf_id_map *ptr =
+                       list_entry(itr, struct vf_id_map, list);
+               if (ptr->bdf != ~0 && !ptr->attached)
+                       vfs++;
        }
+       mutex_unlock(&table_lock);
+       return vfs;
+}
+
+void adf_devmgr_get_num_dev(uint32_t *num)
+{
+       *num = num_devices - adf_get_num_dettached_vfs();
 }
 
+/**
+ * adf_dev_in_use() - Check whether accel_dev is currently in use
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 1 when device is in use, 0 otherwise.
+ */
 int adf_dev_in_use(struct adf_accel_dev *accel_dev)
 {
        return atomic_read(&accel_dev->ref_count) != 0;
 }
+EXPORT_SYMBOL_GPL(adf_dev_in_use);
 
+/**
+ * adf_dev_get() - Increment accel_dev reference count
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Increment the accel_dev refcount and if this is the first time
+ * incrementing it during this period the accel_dev is in use,
+ * increment the module refcount too.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 when successful, EFAULT when fail to bump module refcount
+ */
 int adf_dev_get(struct adf_accel_dev *accel_dev)
 {
        if (atomic_add_return(1, &accel_dev->ref_count) == 1)
@@ -202,19 +421,50 @@ int adf_dev_get(struct adf_accel_dev *accel_dev)
                        return -EFAULT;
        return 0;
 }
+EXPORT_SYMBOL_GPL(adf_dev_get);
 
+/**
+ * adf_dev_put() - Decrement accel_dev reference count
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Decrement the accel_dev refcount and if this is the last time
+ * decrementing it during this period the accel_dev is in use,
+ * decrement the module refcount too.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
 void adf_dev_put(struct adf_accel_dev *accel_dev)
 {
        if (atomic_sub_return(1, &accel_dev->ref_count) == 0)
                module_put(accel_dev->owner);
 }
+EXPORT_SYMBOL_GPL(adf_dev_put);
 
+/**
+ * adf_devmgr_in_reset() - Check whether device is in reset
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 1 when the device is being reset, 0 otherwise.
+ */
 int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev)
 {
        return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
 }
+EXPORT_SYMBOL_GPL(adf_devmgr_in_reset);
 
+/**
+ * adf_dev_started() - Check whether device has started
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 1 when the device has started, 0 otherwise
+ */
 int adf_dev_started(struct adf_accel_dev *accel_dev)
 {
        return test_bit(ADF_STATUS_STARTED, &accel_dev->status);
 }
+EXPORT_SYMBOL_GPL(adf_dev_started);
similarity index 85%
rename from drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c
rename to drivers/crypto/qat/qat_common/adf_hw_arbiter.c
index 1864bdb36f8fef6d02b85aa30d1891203671077e..6849422e04bb4e6cb6a8420395c133575a455e40 100644 (file)
@@ -44,9 +44,8 @@
   (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 <adf_accel_devices.h>
-#include <adf_transport_internal.h>
-#include "adf_drv.h"
+#include "adf_accel_devices.h"
+#include "adf_transport_internal.h"
 
 #define ADF_ARB_NUM 4
 #define ADF_ARB_REQ_RING_NUM 8
@@ -58,7 +57,6 @@
 #define ADF_ARB_RO_EN_OFFSET 0x090
 #define ADF_ARB_WQCFG_OFFSET 0x100
 #define ADF_ARB_WRK_2_SER_MAP_OFFSET 0x180
-#define ADF_ARB_WRK_2_SER_MAP 10
 #define ADF_ARB_RINGSRVARBEN_OFFSET 0x19C
 
 #define WRITE_CSR_ARB_RINGSRVARBEN(csr_addr, index, value) \
 
 int adf_init_arb(struct adf_accel_dev *accel_dev)
 {
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        void __iomem *csr = accel_dev->transport->banks[0].csr_addr;
-       uint32_t arb_cfg = 0x1 << 31 | 0x4 << 4 | 0x1;
-       uint32_t arb, i;
-       const uint32_t *thd_2_arb_cfg;
+       u32 arb_cfg = 0x1 << 31 | 0x4 << 4 | 0x1;
+       u32 arb, i;
+       const u32 *thd_2_arb_cfg;
 
        /* Service arb configured for 32 bytes responses and
         * ring flow control check enabled. */
@@ -109,30 +108,39 @@ int adf_init_arb(struct adf_accel_dev *accel_dev)
                WRITE_CSR_ARB_RESPORDERING(csr, i, 0xFFFFFFFF);
 
        /* Setup worker queue registers */
-       for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+       for (i = 0; i < hw_data->num_engines; i++)
                WRITE_CSR_ARB_WQCFG(csr, i, i);
 
        /* Map worker threads to service arbiters */
-       adf_get_arbiter_mapping(accel_dev, &thd_2_arb_cfg);
+       hw_data->get_arb_mapping(accel_dev, &thd_2_arb_cfg);
 
        if (!thd_2_arb_cfg)
                return -EFAULT;
 
-       for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+       for (i = 0; i < hw_data->num_engines; i++)
                WRITE_CSR_ARB_WRK_2_SER_MAP(csr, i, *(thd_2_arb_cfg + i));
 
        return 0;
 }
-
-void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring)
+EXPORT_SYMBOL_GPL(adf_init_arb);
+
+/**
+ * adf_update_ring_arb() - update ring arbitration rgister
+ * @accel_dev:  Pointer to ring data.
+ *
+ * Function enables or disables rings for/from arbitration.
+ */
+void adf_update_ring_arb(struct adf_etr_ring_data *ring)
 {
        WRITE_CSR_ARB_RINGSRVARBEN(ring->bank->csr_addr,
                                   ring->bank->bank_number,
                                   ring->bank->ring_mask & 0xFF);
 }
+EXPORT_SYMBOL_GPL(adf_update_ring_arb);
 
 void adf_exit_arb(struct adf_accel_dev *accel_dev)
 {
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        void __iomem *csr;
        unsigned int i;
 
@@ -146,14 +154,15 @@ void adf_exit_arb(struct adf_accel_dev *accel_dev)
                WRITE_CSR_ARB_SARCONFIG(csr, i, 0);
 
        /* Shutdown work queue */
-       for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+       for (i = 0; i < hw_data->num_engines; i++)
                WRITE_CSR_ARB_WQCFG(csr, i, 0);
 
        /* Unmap worker threads to service arbiters */
-       for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+       for (i = 0; i < hw_data->num_engines; i++)
                WRITE_CSR_ARB_WRK_2_SER_MAP(csr, i, 0);
 
        /* Disable arbitration on all rings */
        for (i = 0; i < GET_MAX_BANKS(accel_dev); i++)
                WRITE_CSR_ARB_RINGSRVARBEN(csr, i, 0);
 }
+EXPORT_SYMBOL_GPL(adf_exit_arb);
index 245f43237a2d8b168b034f8a5568753819f027dc..ac37a89965acb6afa936c4949eb84b81bdca9d74 100644 (file)
@@ -69,7 +69,7 @@ static void adf_service_add(struct service_hndl *service)
  * Function adds the acceleration service to the acceleration framework.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_service_register(struct service_hndl *service)
 {
@@ -94,7 +94,7 @@ static void adf_service_remove(struct service_hndl *service)
  * Function remove the acceleration service from the acceleration framework.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_service_unregister(struct service_hndl *service)
 {
@@ -114,7 +114,7 @@ EXPORT_SYMBOL_GPL(adf_service_unregister);
  * Initialize the ring data structures and the admin comms and arbitration
  * services.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_dev_init(struct adf_accel_dev *accel_dev)
 {
@@ -177,20 +177,6 @@ int adf_dev_init(struct adf_accel_dev *accel_dev)
         */
        list_for_each(list_itr, &service_table) {
                service = list_entry(list_itr, struct service_hndl, list);
-               if (!service->admin)
-                       continue;
-               if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
-                       dev_err(&GET_DEV(accel_dev),
-                               "Failed to initialise service %s\n",
-                               service->name);
-                       return -EFAULT;
-               }
-               set_bit(accel_dev->accel_id, &service->init_status);
-       }
-       list_for_each(list_itr, &service_table) {
-               service = list_entry(list_itr, struct service_hndl, list);
-               if (service->admin)
-                       continue;
                if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
                        dev_err(&GET_DEV(accel_dev),
                                "Failed to initialise service %s\n",
@@ -201,6 +187,7 @@ int adf_dev_init(struct adf_accel_dev *accel_dev)
        }
 
        hw_data->enable_error_correction(accel_dev);
+       hw_data->enable_vf2pf_comms(accel_dev);
 
        return 0;
 }
@@ -214,10 +201,11 @@ EXPORT_SYMBOL_GPL(adf_dev_init);
  * is ready to be used.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_dev_start(struct adf_accel_dev *accel_dev)
 {
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        struct service_hndl *service;
        struct list_head *list_itr;
 
@@ -229,22 +217,13 @@ int adf_dev_start(struct adf_accel_dev *accel_dev)
        }
        set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
 
-       list_for_each(list_itr, &service_table) {
-               service = list_entry(list_itr, struct service_hndl, list);
-               if (!service->admin)
-                       continue;
-               if (service->event_hld(accel_dev, ADF_EVENT_START)) {
-                       dev_err(&GET_DEV(accel_dev),
-                               "Failed to start service %s\n",
-                               service->name);
-                       return -EFAULT;
-               }
-               set_bit(accel_dev->accel_id, &service->start_status);
+       if (hw_data->send_admin_init(accel_dev)) {
+               dev_err(&GET_DEV(accel_dev), "Failed to send init message\n");
+               return -EFAULT;
        }
+
        list_for_each(list_itr, &service_table) {
                service = list_entry(list_itr, struct service_hndl, list);
-               if (service->admin)
-                       continue;
                if (service->event_hld(accel_dev, ADF_EVENT_START)) {
                        dev_err(&GET_DEV(accel_dev),
                                "Failed to start service %s\n",
@@ -257,7 +236,8 @@ int adf_dev_start(struct adf_accel_dev *accel_dev)
        clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
        set_bit(ADF_STATUS_STARTED, &accel_dev->status);
 
-       if (qat_algs_register()) {
+       if (!list_empty(&accel_dev->crypto_list) &&
+           (qat_algs_register() || qat_asym_algs_register())) {
                dev_err(&GET_DEV(accel_dev),
                        "Failed to register crypto algs\n");
                set_bit(ADF_STATUS_STARTING, &accel_dev->status);
@@ -276,7 +256,7 @@ EXPORT_SYMBOL_GPL(adf_dev_start);
  * is shuting down.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_dev_stop(struct adf_accel_dev *accel_dev)
 {
@@ -292,14 +272,15 @@ int adf_dev_stop(struct adf_accel_dev *accel_dev)
        clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
        clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
 
-       if (qat_algs_unregister())
+       if (!list_empty(&accel_dev->crypto_list) && qat_algs_unregister())
                dev_err(&GET_DEV(accel_dev),
                        "Failed to unregister crypto algs\n");
 
+       if (!list_empty(&accel_dev->crypto_list))
+               qat_asym_algs_unregister();
+
        list_for_each(list_itr, &service_table) {
                service = list_entry(list_itr, struct service_hndl, list);
-               if (service->admin)
-                       continue;
                if (!test_bit(accel_dev->accel_id, &service->start_status))
                        continue;
                ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
@@ -310,19 +291,6 @@ int adf_dev_stop(struct adf_accel_dev *accel_dev)
                        clear_bit(accel_dev->accel_id, &service->start_status);
                }
        }
-       list_for_each(list_itr, &service_table) {
-               service = list_entry(list_itr, struct service_hndl, list);
-               if (!service->admin)
-                       continue;
-               if (!test_bit(accel_dev->accel_id, &service->start_status))
-                       continue;
-               if (service->event_hld(accel_dev, ADF_EVENT_STOP))
-                       dev_err(&GET_DEV(accel_dev),
-                               "Failed to shutdown service %s\n",
-                               service->name);
-               else
-                       clear_bit(accel_dev->accel_id, &service->start_status);
-       }
 
        if (wait)
                msleep(100);
@@ -373,21 +341,6 @@ void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
 
        list_for_each(list_itr, &service_table) {
                service = list_entry(list_itr, struct service_hndl, list);
-               if (service->admin)
-                       continue;
-               if (!test_bit(accel_dev->accel_id, &service->init_status))
-                       continue;
-               if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
-                       dev_err(&GET_DEV(accel_dev),
-                               "Failed to shutdown service %s\n",
-                               service->name);
-               else
-                       clear_bit(accel_dev->accel_id, &service->init_status);
-       }
-       list_for_each(list_itr, &service_table) {
-               service = list_entry(list_itr, struct service_hndl, list);
-               if (!service->admin)
-                       continue;
                if (!test_bit(accel_dev->accel_id, &service->init_status))
                        continue;
                if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
@@ -413,6 +366,7 @@ void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
        if (hw_data->exit_admin_comms)
                hw_data->exit_admin_comms(accel_dev);
 
+       hw_data->disable_iov(accel_dev);
        adf_cleanup_etr_data(accel_dev);
 }
 EXPORT_SYMBOL_GPL(adf_dev_shutdown);
@@ -424,17 +378,6 @@ int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
 
        list_for_each(list_itr, &service_table) {
                service = list_entry(list_itr, struct service_hndl, list);
-               if (service->admin)
-                       continue;
-               if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
-                       dev_err(&GET_DEV(accel_dev),
-                               "Failed to restart service %s.\n",
-                               service->name);
-       }
-       list_for_each(list_itr, &service_table) {
-               service = list_entry(list_itr, struct service_hndl, list);
-               if (!service->admin)
-                       continue;
                if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
                        dev_err(&GET_DEV(accel_dev),
                                "Failed to restart service %s.\n",
@@ -450,17 +393,6 @@ int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
 
        list_for_each(list_itr, &service_table) {
                service = list_entry(list_itr, struct service_hndl, list);
-               if (service->admin)
-                       continue;
-               if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
-                       dev_err(&GET_DEV(accel_dev),
-                               "Failed to restart service %s.\n",
-                               service->name);
-       }
-       list_for_each(list_itr, &service_table) {
-               service = list_entry(list_itr, struct service_hndl, list);
-               if (!service->admin)
-                       continue;
                if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
                        dev_err(&GET_DEV(accel_dev),
                                "Failed to restart service %s.\n",
diff --git a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c
new file mode 100644 (file)
index 0000000..5fdbad8
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2015 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2015 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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/pci.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_pf2vf_msg.h"
+
+#define ADF_DH895XCC_EP_OFFSET 0x3A000
+#define ADF_DH895XCC_ERRMSK3   (ADF_DH895XCC_EP_OFFSET + 0x1C)
+#define ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask) ((vf_mask & 0xFFFF) << 9)
+#define ADF_DH895XCC_ERRMSK5   (ADF_DH895XCC_EP_OFFSET + 0xDC)
+#define ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask) (vf_mask >> 16)
+
+/**
+ * adf_enable_pf2vf_interrupts() - Enable PF to VF interrupts
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function enables PF to VF interrupts
+ */
+void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev)
+{
+       struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       void __iomem *pmisc_bar_addr =
+               pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;
+
+       ADF_CSR_WR(pmisc_bar_addr, hw_data->get_vintmsk_offset(0), 0x0);
+}
+EXPORT_SYMBOL_GPL(adf_enable_pf2vf_interrupts);
+
+/**
+ * adf_disable_pf2vf_interrupts() - Disable PF to VF interrupts
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function disables PF to VF interrupts
+ */
+void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev)
+{
+       struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       void __iomem *pmisc_bar_addr =
+               pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;
+
+       ADF_CSR_WR(pmisc_bar_addr, hw_data->get_vintmsk_offset(0), 0x2);
+}
+EXPORT_SYMBOL_GPL(adf_disable_pf2vf_interrupts);
+
+void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
+                                u32 vf_mask)
+{
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_bar *pmisc =
+                       &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       void __iomem *pmisc_addr = pmisc->virt_addr;
+       u32 reg;
+
+       /* Enable VF2PF Messaging Ints - VFs 1 through 16 per vf_mask[15:0] */
+       if (vf_mask & 0xFFFF) {
+               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3);
+               reg &= ~ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask);
+               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK3, reg);
+       }
+
+       /* Enable VF2PF Messaging Ints - VFs 17 through 32 per vf_mask[31:16] */
+       if (vf_mask >> 16) {
+               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK5);
+               reg &= ~ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask);
+               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK5, reg);
+       }
+}
+
+/**
+ * adf_disable_pf2vf_interrupts() - Disable VF to PF interrupts
+ * @accel_dev:  Pointer to acceleration device.
+ *
+ * Function disables VF to PF interrupts
+ */
+void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
+{
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_bar *pmisc =
+                       &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       void __iomem *pmisc_addr = pmisc->virt_addr;
+       u32 reg;
+
+       /* Disable VF2PF interrupts for VFs 1 through 16 per vf_mask[15:0] */
+       if (vf_mask & 0xFFFF) {
+               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3) |
+                       ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask);
+               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK3, reg);
+       }
+
+       /* Disable VF2PF interrupts for VFs 17 through 32 per vf_mask[31:16] */
+       if (vf_mask >> 16) {
+               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK5) |
+                       ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask);
+               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK5, reg);
+       }
+}
+EXPORT_SYMBOL_GPL(adf_disable_vf2pf_interrupts);
+
+static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr)
+{
+       struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       void __iomem *pmisc_bar_addr =
+               pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;
+       u32 val, pf2vf_offset, count = 0;
+       u32 local_in_use_mask, local_in_use_pattern;
+       u32 remote_in_use_mask, remote_in_use_pattern;
+       struct mutex *lock;     /* lock preventing concurrent acces of CSR */
+       u32 int_bit;
+       int ret = 0;
+
+       if (accel_dev->is_vf) {
+               pf2vf_offset = hw_data->get_pf2vf_offset(0);
+               lock = &accel_dev->vf.vf2pf_lock;
+               local_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
+               local_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
+               remote_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
+               remote_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
+               int_bit = ADF_VF2PF_INT;
+       } else {
+               pf2vf_offset = hw_data->get_pf2vf_offset(vf_nr);
+               lock = &accel_dev->pf.vf_info[vf_nr].pf2vf_lock;
+               local_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
+               local_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
+               remote_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
+               remote_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
+               int_bit = ADF_PF2VF_INT;
+       }
+
+       mutex_lock(lock);
+
+       /* Check if PF2VF CSR is in use by remote function */
+       val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
+       if ((val & remote_in_use_mask) == remote_in_use_pattern) {
+               dev_dbg(&GET_DEV(accel_dev),
+                       "PF2VF CSR in use by remote function\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* Attempt to get ownership of PF2VF CSR */
+       msg &= ~local_in_use_mask;
+       msg |= local_in_use_pattern;
+       ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg);
+
+       /* Wait in case remote func also attempting to get ownership */
+       msleep(ADF_IOV_MSG_COLLISION_DETECT_DELAY);
+
+       val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
+       if ((val & local_in_use_mask) != local_in_use_pattern) {
+               dev_dbg(&GET_DEV(accel_dev),
+                       "PF2VF CSR in use by remote - collision detected\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /*
+        * This function now owns the PV2VF CSR.  The IN_USE_BY pattern must
+        * remain in the PF2VF CSR for all writes including ACK from remote
+        * until this local function relinquishes the CSR.  Send the message
+        * by interrupting the remote.
+        */
+       ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg | int_bit);
+
+       /* Wait for confirmation from remote func it received the message */
+       do {
+               msleep(ADF_IOV_MSG_ACK_DELAY);
+               val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
+       } while ((val & int_bit) && (count++ < ADF_IOV_MSG_ACK_MAX_RETRY));
+
+       if (val & int_bit) {
+               dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");
+               val &= ~int_bit;
+               ret = -EIO;
+       }
+
+       /* Finished with PF2VF CSR; relinquish it and leave msg in CSR */
+       ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, val & ~local_in_use_mask);
+out:
+       mutex_unlock(lock);
+       return ret;
+}
+
+/**
+ * adf_iov_putmsg() - send PF2VF message
+ * @accel_dev:  Pointer to acceleration device.
+ * @msg:       Message to send
+ * @vf_nr:     VF number to which the message will be sent
+ *
+ * Function sends a messge from the PF to a VF
+ *
+ * Return: 0 on success, error code otherwise.
+ */
+int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr)
+{
+       u32 count = 0;
+       int ret;
+
+       do {
+               ret = __adf_iov_putmsg(accel_dev, msg, vf_nr);
+               if (ret)
+                       msleep(ADF_IOV_MSG_RETRY_DELAY);
+       } while (ret && (count++ < ADF_IOV_MSG_MAX_RETRIES));
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(adf_iov_putmsg);
+
+void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info)
+{
+       struct adf_accel_dev *accel_dev = vf_info->accel_dev;
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       int bar_id = hw_data->get_misc_bar_id(hw_data);
+       struct adf_bar *pmisc = &GET_BARS(accel_dev)[bar_id];
+       void __iomem *pmisc_addr = pmisc->virt_addr;
+       u32 msg, resp = 0, vf_nr = vf_info->vf_nr;
+
+       /* Read message from the VF */
+       msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr));
+
+       /* To ACK, clear the VF2PFINT bit */
+       msg &= ~ADF_VF2PF_INT;
+       ADF_CSR_WR(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr), msg);
+
+       if (!(msg & ADF_VF2PF_MSGORIGIN_SYSTEM))
+               /* Ignore legacy non-system (non-kernel) VF2PF messages */
+               goto err;
+
+       switch ((msg & ADF_VF2PF_MSGTYPE_MASK) >> ADF_VF2PF_MSGTYPE_SHIFT) {
+       case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ:
+               {
+               u8 vf_compat_ver = msg >> ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
+
+               resp = (ADF_PF2VF_MSGORIGIN_SYSTEM |
+                        (ADF_PF2VF_MSGTYPE_VERSION_RESP <<
+                         ADF_PF2VF_MSGTYPE_SHIFT) |
+                        (ADF_PFVF_COMPATIBILITY_VERSION <<
+                         ADF_PF2VF_VERSION_RESP_VERS_SHIFT));
+
+               dev_dbg(&GET_DEV(accel_dev),
+                       "Compatibility Version Request from VF%d vers=%u\n",
+                       vf_nr + 1, vf_compat_ver);
+
+               if (vf_compat_ver < hw_data->min_iov_compat_ver) {
+                       dev_err(&GET_DEV(accel_dev),
+                               "VF (vers %d) incompatible with PF (vers %d)\n",
+                               vf_compat_ver, ADF_PFVF_COMPATIBILITY_VERSION);
+                       resp |= ADF_PF2VF_VF_INCOMPATIBLE <<
+                               ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
+               } else if (vf_compat_ver > ADF_PFVF_COMPATIBILITY_VERSION) {
+                       dev_err(&GET_DEV(accel_dev),
+                               "VF (vers %d) compat with PF (vers %d) unkn.\n",
+                               vf_compat_ver, ADF_PFVF_COMPATIBILITY_VERSION);
+                       resp |= ADF_PF2VF_VF_COMPAT_UNKNOWN <<
+                               ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
+               } else {
+                       dev_dbg(&GET_DEV(accel_dev),
+                               "VF (vers %d) compatible with PF (vers %d)\n",
+                               vf_compat_ver, ADF_PFVF_COMPATIBILITY_VERSION);
+                       resp |= ADF_PF2VF_VF_COMPATIBLE <<
+                               ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
+               }
+               }
+               break;
+       case ADF_VF2PF_MSGTYPE_VERSION_REQ:
+               dev_dbg(&GET_DEV(accel_dev),
+                       "Legacy VersionRequest received from VF%d 0x%x\n",
+                       vf_nr + 1, msg);
+               resp = (ADF_PF2VF_MSGORIGIN_SYSTEM |
+                        (ADF_PF2VF_MSGTYPE_VERSION_RESP <<
+                         ADF_PF2VF_MSGTYPE_SHIFT) |
+                        (ADF_PFVF_COMPATIBILITY_VERSION <<
+                         ADF_PF2VF_VERSION_RESP_VERS_SHIFT));
+               resp |= ADF_PF2VF_VF_COMPATIBLE <<
+                       ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
+               /* Set legacy major and minor version num */
+               resp |= 1 << ADF_PF2VF_MAJORVERSION_SHIFT |
+                       1 << ADF_PF2VF_MINORVERSION_SHIFT;
+               break;
+       case ADF_VF2PF_MSGTYPE_INIT:
+               {
+               dev_dbg(&GET_DEV(accel_dev),
+                       "Init message received from VF%d 0x%x\n",
+                       vf_nr + 1, msg);
+               vf_info->init = true;
+               }
+               break;
+       case ADF_VF2PF_MSGTYPE_SHUTDOWN:
+               {
+               dev_dbg(&GET_DEV(accel_dev),
+                       "Shutdown message received from VF%d 0x%x\n",
+                       vf_nr + 1, msg);
+               vf_info->init = false;
+               }
+               break;
+       default:
+               goto err;
+       }
+
+       if (resp && adf_iov_putmsg(accel_dev, resp, vf_nr))
+               dev_err(&GET_DEV(accel_dev), "Failed to send response to VF\n");
+
+       /* re-enable interrupt on PF from this VF */
+       adf_enable_vf2pf_interrupts(accel_dev, (1 << vf_nr));
+       return;
+err:
+       dev_dbg(&GET_DEV(accel_dev), "Unknown message from VF%d (0x%x);\n",
+               vf_nr + 1, msg);
+}
+
+void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev)
+{
+       struct adf_accel_vf_info *vf;
+       u32 msg = (ADF_PF2VF_MSGORIGIN_SYSTEM |
+               (ADF_PF2VF_MSGTYPE_RESTARTING << ADF_PF2VF_MSGTYPE_SHIFT));
+       int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));
+
+       for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) {
+               if (vf->init && adf_iov_putmsg(accel_dev, msg, i))
+                       dev_err(&GET_DEV(accel_dev),
+                               "Failed to send restarting msg to VF%d\n", i);
+       }
+}
+
+static int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev)
+{
+       unsigned long timeout = msecs_to_jiffies(ADF_IOV_MSG_RESP_TIMEOUT);
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       u32 msg = 0;
+       int ret;
+
+       msg = ADF_VF2PF_MSGORIGIN_SYSTEM;
+       msg |= ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ << ADF_VF2PF_MSGTYPE_SHIFT;
+       msg |= ADF_PFVF_COMPATIBILITY_VERSION << ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
+       BUILD_BUG_ON(ADF_PFVF_COMPATIBILITY_VERSION > 255);
+
+       /* Send request from VF to PF */
+       ret = adf_iov_putmsg(accel_dev, msg, 0);
+       if (ret) {
+               dev_err(&GET_DEV(accel_dev),
+                       "Failed to send Compatibility Version Request.\n");
+               return ret;
+       }
+
+       /* Wait for response */
+       if (!wait_for_completion_timeout(&accel_dev->vf.iov_msg_completion,
+                                        timeout)) {
+               dev_err(&GET_DEV(accel_dev),
+                       "IOV request/response message timeout expired\n");
+               return -EIO;
+       }
+
+       /* Response from PF received, check compatibility */
+       switch (accel_dev->vf.compatible) {
+       case ADF_PF2VF_VF_COMPATIBLE:
+               break;
+       case ADF_PF2VF_VF_COMPAT_UNKNOWN:
+               /* VF is newer than PF and decides whether it is compatible */
+               if (accel_dev->vf.pf_version >= hw_data->min_iov_compat_ver)
+                       break;
+               /* fall through */
+       case ADF_PF2VF_VF_INCOMPATIBLE:
+               dev_err(&GET_DEV(accel_dev),
+                       "PF (vers %d) and VF (vers %d) are not compatible\n",
+                       accel_dev->vf.pf_version,
+                       ADF_PFVF_COMPATIBILITY_VERSION);
+               return -EINVAL;
+       default:
+               dev_err(&GET_DEV(accel_dev),
+                       "Invalid response from PF; assume not compatible\n");
+               return -EINVAL;
+       }
+       return ret;
+}
+
+/**
+ * adf_enable_vf2pf_comms() - Function enables communication from vf to pf
+ *
+ * @accel_dev: Pointer to acceleration device virtual function.
+ *
+ * Return: 0 on success, error code otherwise.
+ */
+int adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
+{
+       adf_enable_pf2vf_interrupts(accel_dev);
+       return adf_vf2pf_request_version(accel_dev);
+}
+EXPORT_SYMBOL_GPL(adf_enable_vf2pf_comms);
diff --git a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.h b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.h
new file mode 100644 (file)
index 0000000..5acd531
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2015 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2015 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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 ADF_PF2VF_MSG_H
+#define ADF_PF2VF_MSG_H
+
+/*
+ * PF<->VF Messaging
+ * The PF has an array of 32-bit PF2VF registers, one for each VF.  The
+ * PF can access all these registers; each VF can access only the one
+ * register associated with that particular VF.
+ *
+ * The register functionally is split into two parts:
+ * The bottom half is for PF->VF messages. In particular when the first
+ * bit of this register (bit 0) gets set an interrupt will be triggered
+ * in the respective VF.
+ * The top half is for VF->PF messages. In particular when the first bit
+ * of this half of register (bit 16) gets set an interrupt will be triggered
+ * in the PF.
+ *
+ * The remaining bits within this register are available to encode messages.
+ * and implement a collision control mechanism to prevent concurrent use of
+ * the PF2VF register by both the PF and VF.
+ *
+ *  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
+ *  _______________________________________________
+ * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+ * +-----------------------------------------------+
+ *  \___________________________/ \_________/ ^   ^
+ *                ^                    ^      |   |
+ *                |                    |      |   VF2PF Int
+ *                |                    |      Message Origin
+ *                |                    Message Type
+ *                Message-specific Data/Reserved
+ *
+ *  15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
+ *  _______________________________________________
+ * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+ * +-----------------------------------------------+
+ *  \___________________________/ \_________/ ^   ^
+ *                ^                    ^      |   |
+ *                |                    |      |   PF2VF Int
+ *                |                    |      Message Origin
+ *                |                    Message Type
+ *                Message-specific Data/Reserved
+ *
+ * Message Origin (Should always be 1)
+ * A legacy out-of-tree QAT driver allowed for a set of messages not supported
+ * by this driver; these had a Msg Origin of 0 and are ignored by this driver.
+ *
+ * When a PF or VF attempts to send a message in the lower or upper 16 bits,
+ * respectively, the other 16 bits are written to first with a defined
+ * IN_USE_BY pattern as part of a collision control scheme (see adf_iov_putmsg).
+ */
+
+#define ADF_PFVF_COMPATIBILITY_VERSION         0x1     /* PF<->VF compat */
+
+/* PF->VF messages */
+#define ADF_PF2VF_INT                          BIT(0)
+#define ADF_PF2VF_MSGORIGIN_SYSTEM             BIT(1)
+#define ADF_PF2VF_MSGTYPE_MASK                 0x0000003C
+#define ADF_PF2VF_MSGTYPE_SHIFT                        2
+#define ADF_PF2VF_MSGTYPE_RESTARTING           0x01
+#define ADF_PF2VF_MSGTYPE_VERSION_RESP         0x02
+#define ADF_PF2VF_IN_USE_BY_PF                 0x6AC20000
+#define ADF_PF2VF_IN_USE_BY_PF_MASK            0xFFFE0000
+
+/* PF->VF Version Response */
+#define ADF_PF2VF_VERSION_RESP_VERS_MASK       0x00003FC0
+#define ADF_PF2VF_VERSION_RESP_VERS_SHIFT      6
+#define ADF_PF2VF_VERSION_RESP_RESULT_MASK     0x0000C000
+#define ADF_PF2VF_VERSION_RESP_RESULT_SHIFT    14
+#define ADF_PF2VF_MINORVERSION_SHIFT           6
+#define ADF_PF2VF_MAJORVERSION_SHIFT           10
+#define ADF_PF2VF_VF_COMPATIBLE                        1
+#define ADF_PF2VF_VF_INCOMPATIBLE              2
+#define ADF_PF2VF_VF_COMPAT_UNKNOWN            3
+
+/* VF->PF messages */
+#define ADF_VF2PF_IN_USE_BY_VF                 0x00006AC2
+#define ADF_VF2PF_IN_USE_BY_VF_MASK            0x0000FFFE
+#define ADF_VF2PF_INT                          BIT(16)
+#define ADF_VF2PF_MSGORIGIN_SYSTEM             BIT(17)
+#define ADF_VF2PF_MSGTYPE_MASK                 0x003C0000
+#define ADF_VF2PF_MSGTYPE_SHIFT                        18
+#define ADF_VF2PF_MSGTYPE_INIT                 0x3
+#define ADF_VF2PF_MSGTYPE_SHUTDOWN             0x4
+#define ADF_VF2PF_MSGTYPE_VERSION_REQ          0x5
+#define ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ       0x6
+
+/* VF->PF Compatible Version Request */
+#define ADF_VF2PF_COMPAT_VER_REQ_SHIFT         22
+
+/* Collision detection */
+#define ADF_IOV_MSG_COLLISION_DETECT_DELAY     10
+#define ADF_IOV_MSG_ACK_DELAY                  2
+#define ADF_IOV_MSG_ACK_MAX_RETRY              100
+#define ADF_IOV_MSG_RETRY_DELAY                        5
+#define ADF_IOV_MSG_MAX_RETRIES                        3
+#define ADF_IOV_MSG_RESP_TIMEOUT       (ADF_IOV_MSG_ACK_DELAY * \
+                                        ADF_IOV_MSG_ACK_MAX_RETRY + \
+                                        ADF_IOV_MSG_COLLISION_DETECT_DELAY)
+#endif /* ADF_IOV_MSG_H */
diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c
new file mode 100644 (file)
index 0000000..2f77a4a
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2015 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2015 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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/workqueue.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/iommu.h>
+#include "adf_common_drv.h"
+#include "adf_cfg.h"
+#include "adf_pf2vf_msg.h"
+
+static struct workqueue_struct *pf2vf_resp_wq;
+
+#define ME2FUNCTION_MAP_A_OFFSET       (0x3A400 + 0x190)
+#define ME2FUNCTION_MAP_A_NUM_REGS     96
+
+#define ME2FUNCTION_MAP_B_OFFSET       (0x3A400 + 0x310)
+#define ME2FUNCTION_MAP_B_NUM_REGS     12
+
+#define ME2FUNCTION_MAP_REG_SIZE       4
+#define ME2FUNCTION_MAP_VALID          BIT(7)
+
+#define READ_CSR_ME2FUNCTION_MAP_A(pmisc_bar_addr, index)              \
+       ADF_CSR_RD(pmisc_bar_addr, ME2FUNCTION_MAP_A_OFFSET +           \
+                  ME2FUNCTION_MAP_REG_SIZE * index)
+
+#define WRITE_CSR_ME2FUNCTION_MAP_A(pmisc_bar_addr, index, value)      \
+       ADF_CSR_WR(pmisc_bar_addr, ME2FUNCTION_MAP_A_OFFSET +           \
+                  ME2FUNCTION_MAP_REG_SIZE * index, value)
+
+#define READ_CSR_ME2FUNCTION_MAP_B(pmisc_bar_addr, index)              \
+       ADF_CSR_RD(pmisc_bar_addr, ME2FUNCTION_MAP_B_OFFSET +           \
+                  ME2FUNCTION_MAP_REG_SIZE * index)
+
+#define WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_bar_addr, index, value)      \
+       ADF_CSR_WR(pmisc_bar_addr, ME2FUNCTION_MAP_B_OFFSET +           \
+                  ME2FUNCTION_MAP_REG_SIZE * index, value)
+
+struct adf_pf2vf_resp {
+       struct work_struct pf2vf_resp_work;
+       struct adf_accel_vf_info *vf_info;
+};
+
+static void adf_iov_send_resp(struct work_struct *work)
+{
+       struct adf_pf2vf_resp *pf2vf_resp =
+               container_of(work, struct adf_pf2vf_resp, pf2vf_resp_work);
+
+       adf_vf2pf_req_hndl(pf2vf_resp->vf_info);
+       kfree(pf2vf_resp);
+}
+
+static void adf_vf2pf_bh_handler(void *data)
+{
+       struct adf_accel_vf_info *vf_info = (struct adf_accel_vf_info *)data;
+       struct adf_pf2vf_resp *pf2vf_resp;
+
+       pf2vf_resp = kzalloc(sizeof(*pf2vf_resp), GFP_ATOMIC);
+       if (!pf2vf_resp)
+               return;
+
+       pf2vf_resp->vf_info = vf_info;
+       INIT_WORK(&pf2vf_resp->pf2vf_resp_work, adf_iov_send_resp);
+       queue_work(pf2vf_resp_wq, &pf2vf_resp->pf2vf_resp_work);
+}
+
+static int adf_enable_sriov(struct adf_accel_dev *accel_dev)
+{
+       struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+       int totalvfs = pci_sriov_get_totalvfs(pdev);
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_bar *pmisc =
+                       &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       void __iomem *pmisc_addr = pmisc->virt_addr;
+       struct adf_accel_vf_info *vf_info;
+       int i;
+       u32 reg;
+
+       /* Workqueue for PF2VF responses */
+       pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq");
+       if (!pf2vf_resp_wq)
+               return -ENOMEM;
+
+       for (i = 0, vf_info = accel_dev->pf.vf_info; i < totalvfs;
+            i++, vf_info++) {
+               /* This ptr will be populated when VFs will be created */
+               vf_info->accel_dev = accel_dev;
+               vf_info->vf_nr = i;
+
+               tasklet_init(&vf_info->vf2pf_bh_tasklet,
+                            (void *)adf_vf2pf_bh_handler,
+                            (unsigned long)vf_info);
+               mutex_init(&vf_info->pf2vf_lock);
+               ratelimit_state_init(&vf_info->vf2pf_ratelimit,
+                                    DEFAULT_RATELIMIT_INTERVAL,
+                                    DEFAULT_RATELIMIT_BURST);
+       }
+
+       /* Set Valid bits in ME Thread to PCIe Function Mapping Group A */
+       for (i = 0; i < ME2FUNCTION_MAP_A_NUM_REGS; i++) {
+               reg = READ_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i);
+               reg |= ME2FUNCTION_MAP_VALID;
+               WRITE_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i, reg);
+       }
+
+       /* Set Valid bits in ME Thread to PCIe Function Mapping Group B */
+       for (i = 0; i < ME2FUNCTION_MAP_B_NUM_REGS; i++) {
+               reg = READ_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i);
+               reg |= ME2FUNCTION_MAP_VALID;
+               WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i, reg);
+       }
+
+       /* Enable VF to PF interrupts for all VFs */
+       adf_enable_vf2pf_interrupts(accel_dev, GENMASK_ULL(totalvfs - 1, 0));
+
+       /*
+        * Due to the hardware design, when SR-IOV and the ring arbiter
+        * are enabled all the VFs supported in hardware must be enabled in
+        * order for all the hardware resources (i.e. bundles) to be usable.
+        * When SR-IOV is enabled, each of the VFs will own one bundle.
+        */
+       return pci_enable_sriov(pdev, totalvfs);
+}
+
+/**
+ * adf_disable_sriov() - Disable SRIOV for the device
+ * @pdev:  Pointer to pci device.
+ *
+ * Function disables SRIOV for the pci device.
+ *
+ * Return: 0 on success, error code otherwise.
+ */
+void adf_disable_sriov(struct adf_accel_dev *accel_dev)
+{
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       struct adf_bar *pmisc =
+                       &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       void __iomem *pmisc_addr = pmisc->virt_addr;
+       int totalvfs = pci_sriov_get_totalvfs(accel_to_pci_dev(accel_dev));
+       struct adf_accel_vf_info *vf;
+       u32 reg;
+       int i;
+
+       if (!accel_dev->pf.vf_info)
+               return;
+
+       adf_pf2vf_notify_restarting(accel_dev);
+
+       pci_disable_sriov(accel_to_pci_dev(accel_dev));
+
+       /* Disable VF to PF interrupts */
+       adf_disable_vf2pf_interrupts(accel_dev, 0xFFFFFFFF);
+
+       /* Clear Valid bits in ME Thread to PCIe Function Mapping Group A */
+       for (i = 0; i < ME2FUNCTION_MAP_A_NUM_REGS; i++) {
+               reg = READ_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i);
+               reg &= ~ME2FUNCTION_MAP_VALID;
+               WRITE_CSR_ME2FUNCTION_MAP_A(pmisc_addr, i, reg);
+       }
+
+       /* Clear Valid bits in ME Thread to PCIe Function Mapping Group B */
+       for (i = 0; i < ME2FUNCTION_MAP_B_NUM_REGS; i++) {
+               reg = READ_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i);
+               reg &= ~ME2FUNCTION_MAP_VALID;
+               WRITE_CSR_ME2FUNCTION_MAP_B(pmisc_addr, i, reg);
+       }
+
+       for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) {
+               tasklet_disable(&vf->vf2pf_bh_tasklet);
+               tasklet_kill(&vf->vf2pf_bh_tasklet);
+               mutex_destroy(&vf->pf2vf_lock);
+       }
+
+       kfree(accel_dev->pf.vf_info);
+       accel_dev->pf.vf_info = NULL;
+
+       if (pf2vf_resp_wq) {
+               destroy_workqueue(pf2vf_resp_wq);
+               pf2vf_resp_wq = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(adf_disable_sriov);
+
+/**
+ * adf_sriov_configure() - Enable SRIOV for the device
+ * @pdev:  Pointer to pci device.
+ *
+ * Function enables SRIOV for the pci device.
+ *
+ * Return: 0 on success, error code otherwise.
+ */
+int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
+{
+       struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+       int totalvfs = pci_sriov_get_totalvfs(pdev);
+       unsigned long val;
+       int ret;
+
+       if (!accel_dev) {
+               dev_err(&pdev->dev, "Failed to find accel_dev\n");
+               return -EFAULT;
+       }
+
+       if (!iommu_present(&pci_bus_type)) {
+               dev_err(&pdev->dev,
+                       "IOMMU must be enabled for SR-IOV to work\n");
+               return -EINVAL;
+       }
+
+       if (accel_dev->pf.vf_info) {
+               dev_info(&pdev->dev, "Already enabled for this device\n");
+               return -EINVAL;
+       }
+
+       if (adf_dev_started(accel_dev)) {
+               if (adf_devmgr_in_reset(accel_dev) ||
+                   adf_dev_in_use(accel_dev)) {
+                       dev_err(&GET_DEV(accel_dev), "Device busy\n");
+                       return -EBUSY;
+               }
+
+               if (adf_dev_stop(accel_dev)) {
+                       dev_err(&GET_DEV(accel_dev),
+                               "Failed to stop qat_dev%d\n",
+                               accel_dev->accel_id);
+                       return -EFAULT;
+               }
+
+               adf_dev_shutdown(accel_dev);
+       }
+
+       if (adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC))
+               return -EFAULT;
+       val = 0;
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       ADF_NUM_CY, (void *)&val, ADF_DEC))
+               return -EFAULT;
+
+       set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+
+       /* Allocate memory for VF info structs */
+       accel_dev->pf.vf_info = kcalloc(totalvfs,
+                                       sizeof(struct adf_accel_vf_info),
+                                       GFP_KERNEL);
+       if (!accel_dev->pf.vf_info)
+               return -ENOMEM;
+
+       if (adf_dev_init(accel_dev)) {
+               dev_err(&GET_DEV(accel_dev), "Failed to init qat_dev%d\n",
+                       accel_dev->accel_id);
+               return -EFAULT;
+       }
+
+       if (adf_dev_start(accel_dev)) {
+               dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
+                       accel_dev->accel_id);
+               return -EFAULT;
+       }
+
+       ret = adf_enable_sriov(accel_dev);
+       if (ret)
+               return ret;
+
+       return numvfs;
+}
+EXPORT_SYMBOL_GPL(adf_sriov_configure);
index db2926bff8a5bc843741b7cf56facb114ab853b7..3865ae8d96d9cda8a96a01d0ccfe49e70b3cf7b6 100644 (file)
@@ -264,6 +264,10 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
                dev_err(&GET_DEV(accel_dev), "Can't get ring number\n");
                return -EFAULT;
        }
+       if (ring_num >= ADF_ETR_MAX_RINGS_PER_BANK) {
+               dev_err(&GET_DEV(accel_dev), "Invalid ring number\n");
+               return -EFAULT;
+       }
 
        bank = &transport_data->banks[bank_num];
        if (adf_reserve_ring(bank, ring_num)) {
@@ -285,7 +289,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
                goto err;
 
        /* Enable HW arbitration for the given ring */
-       accel_dev->hw_device->hw_arb_ring_enable(ring);
+       adf_update_ring_arb(ring);
 
        if (adf_ring_debugfs_add(ring, ring_name)) {
                dev_err(&GET_DEV(accel_dev),
@@ -302,14 +306,13 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
 err:
        adf_cleanup_ring(ring);
        adf_unreserve_ring(bank, ring_num);
-       accel_dev->hw_device->hw_arb_ring_disable(ring);
+       adf_update_ring_arb(ring);
        return ret;
 }
 
 void adf_remove_ring(struct adf_etr_ring_data *ring)
 {
        struct adf_etr_bank_data *bank = ring->bank;
-       struct adf_accel_dev *accel_dev = bank->accel_dev;
 
        /* Disable interrupts for the given ring */
        adf_disable_ring_irq(bank, ring->ring_number);
@@ -322,7 +325,7 @@ void adf_remove_ring(struct adf_etr_ring_data *ring)
        adf_ring_debugfs_rm(ring);
        adf_unreserve_ring(bank, ring->ring_number);
        /* Disable HW arbitration for the given ring */
-       accel_dev->hw_device->hw_arb_ring_disable(ring);
+       adf_update_ring_arb(ring);
        adf_cleanup_ring(ring);
 }
 
@@ -463,7 +466,7 @@ err:
  * acceleration device accel_dev.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code othewise.
+ * Return: 0 on success, error code otherwise.
  */
 int adf_init_etr_data(struct adf_accel_dev *accel_dev)
 {
index 160c9a36c9198689d957c010e14930e3b3e8ffae..6ad7e4e1edcadd2a839ed866791b0dfb0d60cb47 100644 (file)
@@ -97,8 +97,9 @@
 #define ADF_RING_SIZE_IN_BYTES_TO_SIZE(SIZE) ((1 << (SIZE - 1)) >> 7)
 
 /* Minimum ring bufer size for memory allocation */
-#define ADF_RING_SIZE_BYTES_MIN(SIZE) ((SIZE < ADF_RING_SIZE_4K) ? \
-                               ADF_RING_SIZE_4K : SIZE)
+#define ADF_RING_SIZE_BYTES_MIN(SIZE) \
+       ((SIZE < ADF_SIZE_TO_RING_SIZE_IN_BYTES(ADF_RING_SIZE_4K)) ? \
+               ADF_SIZE_TO_RING_SIZE_IN_BYTES(ADF_RING_SIZE_4K) : SIZE)
 #define ADF_RING_SIZE_MODULO(SIZE) (SIZE + 0x6)
 #define ADF_SIZE_TO_POW(SIZE) ((((SIZE & 0x4) >> 1) | ((SIZE & 0x4) >> 2) | \
                                SIZE) & ~0x4)
index f1e30e24a4191b13f284d863ea096b1b0f5e6c02..46747f01b1d1fe18f3935a444ee76fc75d4349f4 100644 (file)
@@ -249,6 +249,8 @@ struct icp_qat_fw_comn_resp {
 
 #define QAT_COMN_RESP_CRYPTO_STATUS_BITPOS 7
 #define QAT_COMN_RESP_CRYPTO_STATUS_MASK 0x1
+#define QAT_COMN_RESP_PKE_STATUS_BITPOS 6
+#define QAT_COMN_RESP_PKE_STATUS_MASK 0x1
 #define QAT_COMN_RESP_CMP_STATUS_BITPOS 5
 #define QAT_COMN_RESP_CMP_STATUS_MASK 0x1
 #define QAT_COMN_RESP_XLAT_STATUS_BITPOS 4
diff --git a/drivers/crypto/qat/qat_common/icp_qat_fw_pke.h b/drivers/crypto/qat/qat_common/icp_qat_fw_pke.h
new file mode 100644 (file)
index 0000000..0d7a9b5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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 Intel Corporation nor the names of its
+         contributors may be used to endorse or promote products derived
+         from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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 _ICP_QAT_FW_PKE_
+#define _ICP_QAT_FW_PKE_
+
+#include "icp_qat_fw.h"
+
+struct icp_qat_fw_req_hdr_pke_cd_pars {
+       u64 content_desc_addr;
+       u32 content_desc_resrvd;
+       u32 func_id;
+};
+
+struct icp_qat_fw_req_pke_mid {
+       u64 opaque;
+       u64 src_data_addr;
+       u64 dest_data_addr;
+};
+
+struct icp_qat_fw_req_pke_hdr {
+       u8 resrvd1;
+       u8 resrvd2;
+       u8 service_type;
+       u8 hdr_flags;
+       u16 comn_req_flags;
+       u16 resrvd4;
+       struct icp_qat_fw_req_hdr_pke_cd_pars cd_pars;
+};
+
+struct icp_qat_fw_pke_request {
+       struct icp_qat_fw_req_pke_hdr pke_hdr;
+       struct icp_qat_fw_req_pke_mid pke_mid;
+       u8 output_param_count;
+       u8 input_param_count;
+       u16 resrvd1;
+       u32 resrvd2;
+       u64 next_req_adr;
+};
+
+struct icp_qat_fw_resp_pke_hdr {
+       u8 resrvd1;
+       u8 resrvd2;
+       u8 response_type;
+       u8 hdr_flags;
+       u16 comn_resp_flags;
+       u16 resrvd4;
+};
+
+struct icp_qat_fw_pke_resp {
+       struct icp_qat_fw_resp_pke_hdr pke_resp_hdr;
+       u64 opaque;
+       u64 src_data_addr;
+       u64 dest_data_addr;
+};
+
+#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS              7
+#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK                0x1
+#define ICP_QAT_FW_PKE_RESP_PKE_STAT_GET(status_word) \
+       QAT_FIELD_GET(((status_word >> ICP_QAT_FW_COMN_ONE_BYTE_SHIFT) & \
+               ICP_QAT_FW_COMN_SINGLE_BYTE_MASK), \
+               QAT_COMN_RESP_PKE_STATUS_BITPOS, \
+               QAT_COMN_RESP_PKE_STATUS_MASK)
+
+#define ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(hdr_t, val) \
+       QAT_FIELD_SET((hdr_t.hdr_flags), (val), \
+               ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS, \
+               ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK)
+#endif
index df427c0e9e7b2c99c8ee6cbe0c91b98c1ff47c43..2bd913aceaeb5c0370bc428d6c52278d1a4ecd78 100644 (file)
@@ -53,7 +53,6 @@
 #include <crypto/hash.h>
 #include <crypto/algapi.h>
 #include <crypto/authenc.h>
-#include <crypto/rng.h>
 #include <linux/dma-mapping.h>
 #include "adf_accel_devices.h"
 #include "adf_transport.h"
@@ -113,9 +112,6 @@ struct qat_alg_aead_ctx {
        struct crypto_shash *hash_tfm;
        enum icp_qat_hw_auth_algo qat_hash_alg;
        struct qat_crypto_instance *inst;
-       struct crypto_tfm *tfm;
-       uint8_t salt[AES_BLOCK_SIZE];
-       spinlock_t lock;        /* protects qat_alg_aead_ctx struct */
 };
 
 struct qat_alg_ablkcipher_ctx {
@@ -130,11 +126,6 @@ struct qat_alg_ablkcipher_ctx {
        spinlock_t lock;        /* protects qat_alg_ablkcipher_ctx struct */
 };
 
-static int get_current_node(void)
-{
-       return cpu_data(current_thread_info()->cpu).phys_proc_id;
-}
-
 static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg)
 {
        switch (qat_hash_alg) {
@@ -278,12 +269,12 @@ static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header)
                                       ICP_QAT_FW_LA_NO_UPDATE_STATE);
 }
 
-static int qat_alg_aead_init_enc_session(struct qat_alg_aead_ctx *ctx,
+static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm,
                                         int alg,
                                         struct crypto_authenc_keys *keys)
 {
-       struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm);
-       unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize;
+       struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(aead_tfm);
+       unsigned int digestsize = crypto_aead_authsize(aead_tfm);
        struct qat_enc *enc_ctx = &ctx->enc_cd->qat_enc_cd;
        struct icp_qat_hw_cipher_algo_blk *cipher = &enc_ctx->cipher;
        struct icp_qat_hw_auth_algo_blk *hash =
@@ -358,12 +349,12 @@ static int qat_alg_aead_init_enc_session(struct qat_alg_aead_ctx *ctx,
        return 0;
 }
 
-static int qat_alg_aead_init_dec_session(struct qat_alg_aead_ctx *ctx,
+static int qat_alg_aead_init_dec_session(struct crypto_aead *aead_tfm,
                                         int alg,
                                         struct crypto_authenc_keys *keys)
 {
-       struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm);
-       unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize;
+       struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(aead_tfm);
+       unsigned int digestsize = crypto_aead_authsize(aead_tfm);
        struct qat_dec *dec_ctx = &ctx->dec_cd->qat_dec_cd;
        struct icp_qat_hw_auth_algo_blk *hash = &dec_ctx->hash;
        struct icp_qat_hw_cipher_algo_blk *cipher =
@@ -515,30 +506,27 @@ static int qat_alg_validate_key(int key_len, int *alg)
        return 0;
 }
 
-static int qat_alg_aead_init_sessions(struct qat_alg_aead_ctx *ctx,
+static int qat_alg_aead_init_sessions(struct crypto_aead *tfm,
                                      const uint8_t *key, unsigned int keylen)
 {
        struct crypto_authenc_keys keys;
        int alg;
 
-       if (crypto_rng_get_bytes(crypto_default_rng, ctx->salt, AES_BLOCK_SIZE))
-               return -EFAULT;
-
        if (crypto_authenc_extractkeys(&keys, key, keylen))
                goto bad_key;
 
        if (qat_alg_validate_key(keys.enckeylen, &alg))
                goto bad_key;
 
-       if (qat_alg_aead_init_enc_session(ctx, alg, &keys))
+       if (qat_alg_aead_init_enc_session(tfm, alg, &keys))
                goto error;
 
-       if (qat_alg_aead_init_dec_session(ctx, alg, &keys))
+       if (qat_alg_aead_init_dec_session(tfm, alg, &keys))
                goto error;
 
        return 0;
 bad_key:
-       crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+       crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
        return -EINVAL;
 error:
        return -EFAULT;
@@ -567,7 +555,6 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
        struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm);
        struct device *dev;
 
-       spin_lock(&ctx->lock);
        if (ctx->enc_cd) {
                /* rekeying */
                dev = &GET_DEV(ctx->inst->accel_dev);
@@ -581,7 +568,6 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
                struct qat_crypto_instance *inst =
                                qat_crypto_get_instance_node(node);
                if (!inst) {
-                       spin_unlock(&ctx->lock);
                        return -EINVAL;
                }
 
@@ -591,19 +577,16 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
                                                  &ctx->enc_cd_paddr,
                                                  GFP_ATOMIC);
                if (!ctx->enc_cd) {
-                       spin_unlock(&ctx->lock);
                        return -ENOMEM;
                }
                ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
                                                  &ctx->dec_cd_paddr,
                                                  GFP_ATOMIC);
                if (!ctx->dec_cd) {
-                       spin_unlock(&ctx->lock);
                        goto out_free_enc;
                }
        }
-       spin_unlock(&ctx->lock);
-       if (qat_alg_aead_init_sessions(ctx, key, keylen))
+       if (qat_alg_aead_init_sessions(tfm, key, keylen))
                goto out_free_all;
 
        return 0;
@@ -654,22 +637,20 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst,
 }
 
 static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
-                              struct scatterlist *assoc, int assoclen,
                               struct scatterlist *sgl,
-                              struct scatterlist *sglout, uint8_t *iv,
-                              uint8_t ivlen,
+                              struct scatterlist *sglout,
                               struct qat_crypto_request *qat_req)
 {
        struct device *dev = &GET_DEV(inst->accel_dev);
-       int i, bufs = 0, sg_nctr = 0;
-       int n = sg_nents(sgl), assoc_n = sg_nents(assoc);
+       int i, sg_nctr = 0;
+       int n = sg_nents(sgl);
        struct qat_alg_buf_list *bufl;
        struct qat_alg_buf_list *buflout = NULL;
        dma_addr_t blp;
        dma_addr_t bloutp = 0;
        struct scatterlist *sg;
        size_t sz_out, sz = sizeof(struct qat_alg_buf_list) +
-                       ((1 + n + assoc_n) * sizeof(struct qat_alg_buf));
+                       ((1 + n) * sizeof(struct qat_alg_buf));
 
        if (unlikely(!n))
                return -EINVAL;
@@ -683,35 +664,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
        if (unlikely(dma_mapping_error(dev, blp)))
                goto err;
 
-       for_each_sg(assoc, sg, assoc_n, i) {
-               if (!sg->length)
-                       continue;
-
-               if (!(assoclen > 0))
-                       break;
-
-               bufl->bufers[bufs].addr =
-                       dma_map_single(dev, sg_virt(sg),
-                                      min_t(int, assoclen, sg->length),
-                                      DMA_BIDIRECTIONAL);
-               bufl->bufers[bufs].len = min_t(int, assoclen, sg->length);
-               if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr)))
-                       goto err;
-               bufs++;
-               assoclen -= sg->length;
-       }
-
-       if (ivlen) {
-               bufl->bufers[bufs].addr = dma_map_single(dev, iv, ivlen,
-                                                        DMA_BIDIRECTIONAL);
-               bufl->bufers[bufs].len = ivlen;
-               if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr)))
-                       goto err;
-               bufs++;
-       }
-
        for_each_sg(sgl, sg, n, i) {
-               int y = sg_nctr + bufs;
+               int y = sg_nctr;
 
                if (!sg->length)
                        continue;
@@ -724,7 +678,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
                        goto err;
                sg_nctr++;
        }
-       bufl->num_bufs = sg_nctr + bufs;
+       bufl->num_bufs = sg_nctr;
        qat_req->buf.bl = bufl;
        qat_req->buf.blp = blp;
        qat_req->buf.sz = sz;
@@ -734,7 +688,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
 
                n = sg_nents(sglout);
                sz_out = sizeof(struct qat_alg_buf_list) +
-                       ((1 + n + assoc_n) * sizeof(struct qat_alg_buf));
+                       ((1 + n) * sizeof(struct qat_alg_buf));
                sg_nctr = 0;
                buflout = kzalloc_node(sz_out, GFP_ATOMIC,
                                       dev_to_node(&GET_DEV(inst->accel_dev)));
@@ -744,14 +698,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
                if (unlikely(dma_mapping_error(dev, bloutp)))
                        goto err;
                bufers = buflout->bufers;
-               /* For out of place operation dma map only data and
-                * reuse assoc mapping and iv */
-               for (i = 0; i < bufs; i++) {
-                       bufers[i].len = bufl->bufers[i].len;
-                       bufers[i].addr = bufl->bufers[i].addr;
-               }
                for_each_sg(sglout, sg, n, i) {
-                       int y = sg_nctr + bufs;
+                       int y = sg_nctr;
 
                        if (!sg->length)
                                continue;
@@ -764,7 +712,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
                        bufers[y].len = sg->length;
                        sg_nctr++;
                }
-               buflout->num_bufs = sg_nctr + bufs;
+               buflout->num_bufs = sg_nctr;
                buflout->num_mapped_bufs = sg_nctr;
                qat_req->buf.blout = buflout;
                qat_req->buf.bloutp = bloutp;
@@ -778,7 +726,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
 err:
        dev_err(dev, "Failed to map buf for dma\n");
        sg_nctr = 0;
-       for (i = 0; i < n + bufs; i++)
+       for (i = 0; i < n; i++)
                if (!dma_mapping_error(dev, bufl->bufers[i].addr))
                        dma_unmap_single(dev, bufl->bufers[i].addr,
                                         bufl->bufers[i].len,
@@ -789,7 +737,7 @@ err:
        kfree(bufl);
        if (sgl != sglout && buflout) {
                n = sg_nents(sglout);
-               for (i = bufs; i < n + bufs; i++)
+               for (i = 0; i < n; i++)
                        if (!dma_mapping_error(dev, buflout->bufers[i].addr))
                                dma_unmap_single(dev, buflout->bufers[i].addr,
                                                 buflout->bufers[i].len,
@@ -849,12 +797,10 @@ static int qat_alg_aead_dec(struct aead_request *areq)
        struct icp_qat_fw_la_cipher_req_params *cipher_param;
        struct icp_qat_fw_la_auth_req_params *auth_param;
        struct icp_qat_fw_la_bulk_req *msg;
-       int digst_size = crypto_aead_crt(aead_tfm)->authsize;
+       int digst_size = crypto_aead_authsize(aead_tfm);
        int ret, ctr = 0;
 
-       ret = qat_alg_sgl_to_bufl(ctx->inst, areq->assoc, areq->assoclen,
-                                 areq->src, areq->dst, areq->iv,
-                                 AES_BLOCK_SIZE, qat_req);
+       ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req);
        if (unlikely(ret))
                return ret;
 
@@ -868,12 +814,11 @@ static int qat_alg_aead_dec(struct aead_request *areq)
        qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp;
        cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
        cipher_param->cipher_length = areq->cryptlen - digst_size;
-       cipher_param->cipher_offset = areq->assoclen + AES_BLOCK_SIZE;
+       cipher_param->cipher_offset = areq->assoclen;
        memcpy(cipher_param->u.cipher_IV_array, areq->iv, AES_BLOCK_SIZE);
        auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
        auth_param->auth_off = 0;
-       auth_param->auth_len = areq->assoclen +
-                               cipher_param->cipher_length + AES_BLOCK_SIZE;
+       auth_param->auth_len = areq->assoclen + cipher_param->cipher_length;
        do {
                ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
        } while (ret == -EAGAIN && ctr++ < 10);
@@ -885,8 +830,7 @@ static int qat_alg_aead_dec(struct aead_request *areq)
        return -EINPROGRESS;
 }
 
-static int qat_alg_aead_enc_internal(struct aead_request *areq, uint8_t *iv,
-                                    int enc_iv)
+static int qat_alg_aead_enc(struct aead_request *areq)
 {
        struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq);
        struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
@@ -895,11 +839,10 @@ static int qat_alg_aead_enc_internal(struct aead_request *areq, uint8_t *iv,
        struct icp_qat_fw_la_cipher_req_params *cipher_param;
        struct icp_qat_fw_la_auth_req_params *auth_param;
        struct icp_qat_fw_la_bulk_req *msg;
+       uint8_t *iv = areq->iv;
        int ret, ctr = 0;
 
-       ret = qat_alg_sgl_to_bufl(ctx->inst, areq->assoc, areq->assoclen,
-                                 areq->src, areq->dst, iv, AES_BLOCK_SIZE,
-                                 qat_req);
+       ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req);
        if (unlikely(ret))
                return ret;
 
@@ -914,16 +857,12 @@ static int qat_alg_aead_enc_internal(struct aead_request *areq, uint8_t *iv,
        cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
        auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
 
-       if (enc_iv) {
-               cipher_param->cipher_length = areq->cryptlen + AES_BLOCK_SIZE;
-               cipher_param->cipher_offset = areq->assoclen;
-       } else {
-               memcpy(cipher_param->u.cipher_IV_array, iv, AES_BLOCK_SIZE);
-               cipher_param->cipher_length = areq->cryptlen;
-               cipher_param->cipher_offset = areq->assoclen + AES_BLOCK_SIZE;
-       }
+       memcpy(cipher_param->u.cipher_IV_array, iv, AES_BLOCK_SIZE);
+       cipher_param->cipher_length = areq->cryptlen;
+       cipher_param->cipher_offset = areq->assoclen;
+
        auth_param->auth_off = 0;
-       auth_param->auth_len = areq->assoclen + areq->cryptlen + AES_BLOCK_SIZE;
+       auth_param->auth_len = areq->assoclen + areq->cryptlen;
 
        do {
                ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
@@ -936,25 +875,6 @@ static int qat_alg_aead_enc_internal(struct aead_request *areq, uint8_t *iv,
        return -EINPROGRESS;
 }
 
-static int qat_alg_aead_enc(struct aead_request *areq)
-{
-       return qat_alg_aead_enc_internal(areq, areq->iv, 0);
-}
-
-static int qat_alg_aead_genivenc(struct aead_givcrypt_request *req)
-{
-       struct crypto_aead *aead_tfm = crypto_aead_reqtfm(&req->areq);
-       struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
-       struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm);
-       __be64 seq;
-
-       memcpy(req->giv, ctx->salt, AES_BLOCK_SIZE);
-       seq = cpu_to_be64(req->seq);
-       memcpy(req->giv + AES_BLOCK_SIZE - sizeof(uint64_t),
-              &seq, sizeof(uint64_t));
-       return qat_alg_aead_enc_internal(&req->areq, req->giv, 1);
-}
-
 static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
                                     const uint8_t *key,
                                     unsigned int keylen)
@@ -1026,8 +946,7 @@ static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req)
        struct icp_qat_fw_la_bulk_req *msg;
        int ret, ctr = 0;
 
-       ret = qat_alg_sgl_to_bufl(ctx->inst, NULL, 0, req->src, req->dst,
-                                 NULL, 0, qat_req);
+       ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req);
        if (unlikely(ret))
                return ret;
 
@@ -1064,8 +983,7 @@ static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req)
        struct icp_qat_fw_la_bulk_req *msg;
        int ret, ctr = 0;
 
-       ret = qat_alg_sgl_to_bufl(ctx->inst, NULL, 0, req->src, req->dst,
-                                 NULL, 0, qat_req);
+       ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req);
        if (unlikely(ret))
                return ret;
 
@@ -1092,47 +1010,43 @@ static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req)
        return -EINPROGRESS;
 }
 
-static int qat_alg_aead_init(struct crypto_tfm *tfm,
+static int qat_alg_aead_init(struct crypto_aead *tfm,
                             enum icp_qat_hw_auth_algo hash,
                             const char *hash_name)
 {
-       struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm);
 
        ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
        if (IS_ERR(ctx->hash_tfm))
-               return -EFAULT;
-       spin_lock_init(&ctx->lock);
+               return PTR_ERR(ctx->hash_tfm);
        ctx->qat_hash_alg = hash;
-       crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
-               sizeof(struct aead_request) +
-               sizeof(struct qat_crypto_request));
-       ctx->tfm = tfm;
+       crypto_aead_set_reqsize(tfm, sizeof(struct aead_request) +
+                                    sizeof(struct qat_crypto_request));
        return 0;
 }
 
-static int qat_alg_aead_sha1_init(struct crypto_tfm *tfm)
+static int qat_alg_aead_sha1_init(struct crypto_aead *tfm)
 {
        return qat_alg_aead_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA1, "sha1");
 }
 
-static int qat_alg_aead_sha256_init(struct crypto_tfm *tfm)
+static int qat_alg_aead_sha256_init(struct crypto_aead *tfm)
 {
        return qat_alg_aead_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA256, "sha256");
 }
 
-static int qat_alg_aead_sha512_init(struct crypto_tfm *tfm)
+static int qat_alg_aead_sha512_init(struct crypto_aead *tfm)
 {
        return qat_alg_aead_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA512, "sha512");
 }
 
-static void qat_alg_aead_exit(struct crypto_tfm *tfm)
+static void qat_alg_aead_exit(struct crypto_aead *tfm)
 {
-       struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm);
        struct qat_crypto_instance *inst = ctx->inst;
        struct device *dev;
 
-       if (!IS_ERR(ctx->hash_tfm))
-               crypto_free_shash(ctx->hash_tfm);
+       crypto_free_shash(ctx->hash_tfm);
 
        if (!inst)
                return;
@@ -1189,73 +1103,61 @@ static void qat_alg_ablkcipher_exit(struct crypto_tfm *tfm)
        qat_crypto_put_instance(inst);
 }
 
-static struct crypto_alg qat_algs[] = { {
-       .cra_name = "authenc(hmac(sha1),cbc(aes))",
-       .cra_driver_name = "qat_aes_cbc_hmac_sha1",
-       .cra_priority = 4001,
-       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-       .cra_blocksize = AES_BLOCK_SIZE,
-       .cra_ctxsize = sizeof(struct qat_alg_aead_ctx),
-       .cra_alignmask = 0,
-       .cra_type = &crypto_aead_type,
-       .cra_module = THIS_MODULE,
-       .cra_init = qat_alg_aead_sha1_init,
-       .cra_exit = qat_alg_aead_exit,
-       .cra_u = {
-               .aead = {
-                       .setkey = qat_alg_aead_setkey,
-                       .decrypt = qat_alg_aead_dec,
-                       .encrypt = qat_alg_aead_enc,
-                       .givencrypt = qat_alg_aead_genivenc,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = SHA1_DIGEST_SIZE,
-               },
+
+static struct aead_alg qat_aeads[] = { {
+       .base = {
+               .cra_name = "authenc(hmac(sha1),cbc(aes))",
+               .cra_driver_name = "qat_aes_cbc_hmac_sha1",
+               .cra_priority = 4001,
+               .cra_flags = CRYPTO_ALG_ASYNC,
+               .cra_blocksize = AES_BLOCK_SIZE,
+               .cra_ctxsize = sizeof(struct qat_alg_aead_ctx),
+               .cra_module = THIS_MODULE,
        },
+       .init = qat_alg_aead_sha1_init,
+       .exit = qat_alg_aead_exit,
+       .setkey = qat_alg_aead_setkey,
+       .decrypt = qat_alg_aead_dec,
+       .encrypt = qat_alg_aead_enc,
+       .ivsize = AES_BLOCK_SIZE,
+       .maxauthsize = SHA1_DIGEST_SIZE,
 }, {
-       .cra_name = "authenc(hmac(sha256),cbc(aes))",
-       .cra_driver_name = "qat_aes_cbc_hmac_sha256",
-       .cra_priority = 4001,
-       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-       .cra_blocksize = AES_BLOCK_SIZE,
-       .cra_ctxsize = sizeof(struct qat_alg_aead_ctx),
-       .cra_alignmask = 0,
-       .cra_type = &crypto_aead_type,
-       .cra_module = THIS_MODULE,
-       .cra_init = qat_alg_aead_sha256_init,
-       .cra_exit = qat_alg_aead_exit,
-       .cra_u = {
-               .aead = {
-                       .setkey = qat_alg_aead_setkey,
-                       .decrypt = qat_alg_aead_dec,
-                       .encrypt = qat_alg_aead_enc,
-                       .givencrypt = qat_alg_aead_genivenc,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = SHA256_DIGEST_SIZE,
-               },
+       .base = {
+               .cra_name = "authenc(hmac(sha256),cbc(aes))",
+               .cra_driver_name = "qat_aes_cbc_hmac_sha256",
+               .cra_priority = 4001,
+               .cra_flags = CRYPTO_ALG_ASYNC,
+               .cra_blocksize = AES_BLOCK_SIZE,
+               .cra_ctxsize = sizeof(struct qat_alg_aead_ctx),
+               .cra_module = THIS_MODULE,
        },
+       .init = qat_alg_aead_sha256_init,
+       .exit = qat_alg_aead_exit,
+       .setkey = qat_alg_aead_setkey,
+       .decrypt = qat_alg_aead_dec,
+       .encrypt = qat_alg_aead_enc,
+       .ivsize = AES_BLOCK_SIZE,
+       .maxauthsize = SHA256_DIGEST_SIZE,
 }, {
-       .cra_name = "authenc(hmac(sha512),cbc(aes))",
-       .cra_driver_name = "qat_aes_cbc_hmac_sha512",
-       .cra_priority = 4001,
-       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-       .cra_blocksize = AES_BLOCK_SIZE,
-       .cra_ctxsize = sizeof(struct qat_alg_aead_ctx),
-       .cra_alignmask = 0,
-       .cra_type = &crypto_aead_type,
-       .cra_module = THIS_MODULE,
-       .cra_init = qat_alg_aead_sha512_init,
-       .cra_exit = qat_alg_aead_exit,
-       .cra_u = {
-               .aead = {
-                       .setkey = qat_alg_aead_setkey,
-                       .decrypt = qat_alg_aead_dec,
-                       .encrypt = qat_alg_aead_enc,
-                       .givencrypt = qat_alg_aead_genivenc,
-                       .ivsize = AES_BLOCK_SIZE,
-                       .maxauthsize = SHA512_DIGEST_SIZE,
-               },
+       .base = {
+               .cra_name = "authenc(hmac(sha512),cbc(aes))",
+               .cra_driver_name = "qat_aes_cbc_hmac_sha512",
+               .cra_priority = 4001,
+               .cra_flags = CRYPTO_ALG_ASYNC,
+               .cra_blocksize = AES_BLOCK_SIZE,
+               .cra_ctxsize = sizeof(struct qat_alg_aead_ctx),
+               .cra_module = THIS_MODULE,
        },
-}, {
+       .init = qat_alg_aead_sha512_init,
+       .exit = qat_alg_aead_exit,
+       .setkey = qat_alg_aead_setkey,
+       .decrypt = qat_alg_aead_dec,
+       .encrypt = qat_alg_aead_enc,
+       .ivsize = AES_BLOCK_SIZE,
+       .maxauthsize = SHA512_DIGEST_SIZE,
+} };
+
+static struct crypto_alg qat_algs[] = { {
        .cra_name = "cbc(aes)",
        .cra_driver_name = "qat_aes_cbc",
        .cra_priority = 4001,
@@ -1281,42 +1183,54 @@ static struct crypto_alg qat_algs[] = { {
 
 int qat_algs_register(void)
 {
-       int ret = 0;
+       int ret = 0, i;
 
        mutex_lock(&algs_lock);
-       if (++active_devs == 1) {
-               int i;
+       if (++active_devs != 1)
+               goto unlock;
 
-               for (i = 0; i < ARRAY_SIZE(qat_algs); i++)
-                       qat_algs[i].cra_flags =
-                               (qat_algs[i].cra_type == &crypto_aead_type) ?
-                               CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC :
-                               CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
+       for (i = 0; i < ARRAY_SIZE(qat_algs); i++)
+               qat_algs[i].cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
 
-               ret = crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs));
-       }
+       ret = crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs));
+       if (ret)
+               goto unlock;
+
+       for (i = 0; i < ARRAY_SIZE(qat_aeads); i++)
+               qat_aeads[i].base.cra_flags = CRYPTO_ALG_ASYNC;
+
+       ret = crypto_register_aeads(qat_aeads, ARRAY_SIZE(qat_aeads));
+       if (ret)
+               goto unreg_algs;
+
+unlock:
        mutex_unlock(&algs_lock);
        return ret;
+
+unreg_algs:
+       crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
+       goto unlock;
 }
 
 int qat_algs_unregister(void)
 {
-       int ret = 0;
-
        mutex_lock(&algs_lock);
-       if (--active_devs == 0)
-               ret = crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
+       if (--active_devs != 0)
+               goto unlock;
+
+       crypto_unregister_aeads(qat_aeads, ARRAY_SIZE(qat_aeads));
+       crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
+
+unlock:
        mutex_unlock(&algs_lock);
-       return ret;
+       return 0;
 }
 
 int qat_algs_init(void)
 {
-       crypto_get_default_rng();
        return 0;
 }
 
 void qat_algs_exit(void)
 {
-       crypto_put_default_rng();
 }
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
new file mode 100644 (file)
index 0000000..e87f510
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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 Intel Corporation nor the names of its
+         contributors may be used to endorse or promote products derived
+         from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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/module.h>
+#include <crypto/internal/rsa.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/akcipher.h>
+#include <linux/dma-mapping.h>
+#include <linux/fips.h>
+#include "qat_rsakey-asn1.h"
+#include "icp_qat_fw_pke.h"
+#include "adf_accel_devices.h"
+#include "adf_transport.h"
+#include "adf_common_drv.h"
+#include "qat_crypto.h"
+
+static DEFINE_MUTEX(algs_lock);
+static unsigned int active_devs;
+
+struct qat_rsa_input_params {
+       union {
+               struct {
+                       dma_addr_t m;
+                       dma_addr_t e;
+                       dma_addr_t n;
+               } enc;
+               struct {
+                       dma_addr_t c;
+                       dma_addr_t d;
+                       dma_addr_t n;
+               } dec;
+               u64 in_tab[8];
+       };
+} __packed __aligned(64);
+
+struct qat_rsa_output_params {
+       union {
+               struct {
+                       dma_addr_t c;
+               } enc;
+               struct {
+                       dma_addr_t m;
+               } dec;
+               u64 out_tab[8];
+       };
+} __packed __aligned(64);
+
+struct qat_rsa_ctx {
+       char *n;
+       char *e;
+       char *d;
+       dma_addr_t dma_n;
+       dma_addr_t dma_e;
+       dma_addr_t dma_d;
+       unsigned int key_sz;
+       struct qat_crypto_instance *inst;
+} __packed __aligned(64);
+
+struct qat_rsa_request {
+       struct qat_rsa_input_params in;
+       struct qat_rsa_output_params out;
+       dma_addr_t phy_in;
+       dma_addr_t phy_out;
+       char *src_align;
+       struct icp_qat_fw_pke_request req;
+       struct qat_rsa_ctx *ctx;
+       int err;
+} __aligned(64);
+
+static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
+{
+       struct akcipher_request *areq = (void *)(__force long)resp->opaque;
+       struct qat_rsa_request *req = PTR_ALIGN(akcipher_request_ctx(areq), 64);
+       struct device *dev = &GET_DEV(req->ctx->inst->accel_dev);
+       int err = ICP_QAT_FW_PKE_RESP_PKE_STAT_GET(
+                               resp->pke_resp_hdr.comn_resp_flags);
+       char *ptr = areq->dst;
+
+       err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;
+
+       if (req->src_align)
+               dma_free_coherent(dev, req->ctx->key_sz, req->src_align,
+                                 req->in.enc.m);
+       else
+               dma_unmap_single(dev, req->in.enc.m, req->ctx->key_sz,
+                                DMA_TO_DEVICE);
+
+       dma_unmap_single(dev, req->out.enc.c, req->ctx->key_sz,
+                        DMA_FROM_DEVICE);
+       dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params),
+                        DMA_TO_DEVICE);
+       dma_unmap_single(dev, req->phy_out,
+                        sizeof(struct qat_rsa_output_params),
+                        DMA_TO_DEVICE);
+
+       areq->dst_len = req->ctx->key_sz;
+       /* Need to set the corect length of the output */
+       while (!(*ptr) && areq->dst_len) {
+               areq->dst_len--;
+               ptr++;
+       }
+
+       if (areq->dst_len != req->ctx->key_sz)
+               memmove(areq->dst, ptr, areq->dst_len);
+
+       akcipher_request_complete(areq, err);
+}
+
+void qat_alg_asym_callback(void *_resp)
+{
+       struct icp_qat_fw_pke_resp *resp = _resp;
+
+       qat_rsa_cb(resp);
+}
+
+#define PKE_RSA_EP_512 0x1c161b21
+#define PKE_RSA_EP_1024 0x35111bf7
+#define PKE_RSA_EP_1536 0x4d111cdc
+#define PKE_RSA_EP_2048 0x6e111dba
+#define PKE_RSA_EP_3072 0x7d111ea3
+#define PKE_RSA_EP_4096 0xa5101f7e
+
+static unsigned long qat_rsa_enc_fn_id(unsigned int len)
+{
+       unsigned int bitslen = len << 3;
+
+       switch (bitslen) {
+       case 512:
+               return PKE_RSA_EP_512;
+       case 1024:
+               return PKE_RSA_EP_1024;
+       case 1536:
+               return PKE_RSA_EP_1536;
+       case 2048:
+               return PKE_RSA_EP_2048;
+       case 3072:
+               return PKE_RSA_EP_3072;
+       case 4096:
+               return PKE_RSA_EP_4096;
+       default:
+               return 0;
+       };
+}
+
+#define PKE_RSA_DP1_512 0x1c161b3c
+#define PKE_RSA_DP1_1024 0x35111c12
+#define PKE_RSA_DP1_1536 0x4d111cf7
+#define PKE_RSA_DP1_2048 0x6e111dda
+#define PKE_RSA_DP1_3072 0x7d111ebe
+#define PKE_RSA_DP1_4096 0xa5101f98
+
+static unsigned long qat_rsa_dec_fn_id(unsigned int len)
+{
+       unsigned int bitslen = len << 3;
+
+       switch (bitslen) {
+       case 512:
+               return PKE_RSA_DP1_512;
+       case 1024:
+               return PKE_RSA_DP1_1024;
+       case 1536:
+               return PKE_RSA_DP1_1536;
+       case 2048:
+               return PKE_RSA_DP1_2048;
+       case 3072:
+               return PKE_RSA_DP1_3072;
+       case 4096:
+               return PKE_RSA_DP1_4096;
+       default:
+               return 0;
+       };
+}
+
+static int qat_rsa_enc(struct akcipher_request *req)
+{
+       struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+       struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+       struct qat_crypto_instance *inst = ctx->inst;
+       struct device *dev = &GET_DEV(inst->accel_dev);
+       struct qat_rsa_request *qat_req =
+                       PTR_ALIGN(akcipher_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
+       int ret, ctr = 0;
+
+       if (unlikely(!ctx->n || !ctx->e))
+               return -EINVAL;
+
+       if (req->dst_len < ctx->key_sz) {
+               req->dst_len = ctx->key_sz;
+               return -EOVERFLOW;
+       }
+       memset(msg, '\0', sizeof(*msg));
+       ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
+                                         ICP_QAT_FW_COMN_REQ_FLAG_SET);
+       msg->pke_hdr.cd_pars.func_id = qat_rsa_enc_fn_id(ctx->key_sz);
+       if (unlikely(!msg->pke_hdr.cd_pars.func_id))
+               return -EINVAL;
+
+       qat_req->ctx = ctx;
+       msg->pke_hdr.service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_PKE;
+       msg->pke_hdr.comn_req_flags =
+               ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT,
+                                           QAT_COMN_CD_FLD_TYPE_64BIT_ADR);
+
+       qat_req->in.enc.e = ctx->dma_e;
+       qat_req->in.enc.n = ctx->dma_n;
+       ret = -ENOMEM;
+
+       /*
+        * src can be of any size in valid range, but HW expects it to be the
+        * same as modulo n so in case it is different we need to allocate a
+        * new buf and copy src data.
+        * In other case we just need to map the user provided buffer.
+        */
+       if (req->src_len < ctx->key_sz) {
+               int shift = ctx->key_sz - req->src_len;
+
+               qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
+                                                        &qat_req->in.enc.m,
+                                                        GFP_KERNEL);
+               if (unlikely(!qat_req->src_align))
+                       return ret;
+
+               memcpy(qat_req->src_align + shift, req->src, req->src_len);
+       } else {
+               qat_req->src_align = NULL;
+               qat_req->in.enc.m = dma_map_single(dev, req->src, req->src_len,
+                                          DMA_TO_DEVICE);
+       }
+       qat_req->in.in_tab[3] = 0;
+       qat_req->out.enc.c = dma_map_single(dev, req->dst, req->dst_len,
+                                           DMA_FROM_DEVICE);
+       qat_req->out.out_tab[1] = 0;
+       qat_req->phy_in = dma_map_single(dev, &qat_req->in.enc.m,
+                                        sizeof(struct qat_rsa_input_params),
+                                        DMA_TO_DEVICE);
+       qat_req->phy_out = dma_map_single(dev, &qat_req->out.enc.c,
+                                         sizeof(struct qat_rsa_output_params),
+                                           DMA_TO_DEVICE);
+
+       if (unlikely((!qat_req->src_align &&
+                     dma_mapping_error(dev, qat_req->in.enc.m)) ||
+                    dma_mapping_error(dev, qat_req->out.enc.c) ||
+                    dma_mapping_error(dev, qat_req->phy_in) ||
+                    dma_mapping_error(dev, qat_req->phy_out)))
+               goto unmap;
+
+       msg->pke_mid.src_data_addr = qat_req->phy_in;
+       msg->pke_mid.dest_data_addr = qat_req->phy_out;
+       msg->pke_mid.opaque = (uint64_t)(__force long)req;
+       msg->input_param_count = 3;
+       msg->output_param_count = 1;
+       do {
+               ret = adf_send_message(ctx->inst->pke_tx, (uint32_t *)msg);
+       } while (ret == -EBUSY && ctr++ < 100);
+
+       if (!ret)
+               return -EINPROGRESS;
+unmap:
+       if (qat_req->src_align)
+               dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
+                                 qat_req->in.enc.m);
+       else
+               if (!dma_mapping_error(dev, qat_req->in.enc.m))
+                       dma_unmap_single(dev, qat_req->in.enc.m, ctx->key_sz,
+                                        DMA_TO_DEVICE);
+       if (!dma_mapping_error(dev, qat_req->out.enc.c))
+               dma_unmap_single(dev, qat_req->out.enc.c, ctx->key_sz,
+                                DMA_FROM_DEVICE);
+       if (!dma_mapping_error(dev, qat_req->phy_in))
+               dma_unmap_single(dev, qat_req->phy_in,
+                                sizeof(struct qat_rsa_input_params),
+                                DMA_TO_DEVICE);
+       if (!dma_mapping_error(dev, qat_req->phy_out))
+               dma_unmap_single(dev, qat_req->phy_out,
+                                sizeof(struct qat_rsa_output_params),
+                                DMA_TO_DEVICE);
+       return ret;
+}
+
+static int qat_rsa_dec(struct akcipher_request *req)
+{
+       struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+       struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+       struct qat_crypto_instance *inst = ctx->inst;
+       struct device *dev = &GET_DEV(inst->accel_dev);
+       struct qat_rsa_request *qat_req =
+                       PTR_ALIGN(akcipher_request_ctx(req), 64);
+       struct icp_qat_fw_pke_request *msg = &qat_req->req;
+       int ret, ctr = 0;
+
+       if (unlikely(!ctx->n || !ctx->d))
+               return -EINVAL;
+
+       if (req->dst_len < ctx->key_sz) {
+               req->dst_len = ctx->key_sz;
+               return -EOVERFLOW;
+       }
+       memset(msg, '\0', sizeof(*msg));
+       ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
+                                         ICP_QAT_FW_COMN_REQ_FLAG_SET);
+       msg->pke_hdr.cd_pars.func_id = qat_rsa_dec_fn_id(ctx->key_sz);
+       if (unlikely(!msg->pke_hdr.cd_pars.func_id))
+               return -EINVAL;
+
+       qat_req->ctx = ctx;
+       msg->pke_hdr.service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_PKE;
+       msg->pke_hdr.comn_req_flags =
+               ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT,
+                                           QAT_COMN_CD_FLD_TYPE_64BIT_ADR);
+
+       qat_req->in.dec.d = ctx->dma_d;
+       qat_req->in.dec.n = ctx->dma_n;
+       ret = -ENOMEM;
+
+       /*
+        * src can be of any size in valid range, but HW expects it to be the
+        * same as modulo n so in case it is different we need to allocate a
+        * new buf and copy src data.
+        * In other case we just need to map the user provided buffer.
+        */
+       if (req->src_len < ctx->key_sz) {
+               int shift = ctx->key_sz - req->src_len;
+
+               qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
+                                                        &qat_req->in.dec.c,
+                                                        GFP_KERNEL);
+               if (unlikely(!qat_req->src_align))
+                       return ret;
+
+               memcpy(qat_req->src_align + shift, req->src, req->src_len);
+       } else {
+               qat_req->src_align = NULL;
+               qat_req->in.dec.c = dma_map_single(dev, req->src, req->src_len,
+                                                  DMA_TO_DEVICE);
+       }
+       qat_req->in.in_tab[3] = 0;
+       qat_req->out.dec.m = dma_map_single(dev, req->dst, req->dst_len,
+                                           DMA_FROM_DEVICE);
+       qat_req->out.out_tab[1] = 0;
+       qat_req->phy_in = dma_map_single(dev, &qat_req->in.dec.c,
+                                        sizeof(struct qat_rsa_input_params),
+                                        DMA_TO_DEVICE);
+       qat_req->phy_out = dma_map_single(dev, &qat_req->out.dec.m,
+                                         sizeof(struct qat_rsa_output_params),
+                                           DMA_TO_DEVICE);
+
+       if (unlikely((!qat_req->src_align &&
+                     dma_mapping_error(dev, qat_req->in.dec.c)) ||
+                    dma_mapping_error(dev, qat_req->out.dec.m) ||
+                    dma_mapping_error(dev, qat_req->phy_in) ||
+                    dma_mapping_error(dev, qat_req->phy_out)))
+               goto unmap;
+
+       msg->pke_mid.src_data_addr = qat_req->phy_in;
+       msg->pke_mid.dest_data_addr = qat_req->phy_out;
+       msg->pke_mid.opaque = (uint64_t)(__force long)req;
+       msg->input_param_count = 3;
+       msg->output_param_count = 1;
+       do {
+               ret = adf_send_message(ctx->inst->pke_tx, (uint32_t *)msg);
+       } while (ret == -EBUSY && ctr++ < 100);
+
+       if (!ret)
+               return -EINPROGRESS;
+unmap:
+       if (qat_req->src_align)
+               dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
+                                 qat_req->in.dec.c);
+       else
+               if (!dma_mapping_error(dev, qat_req->in.dec.c))
+                       dma_unmap_single(dev, qat_req->in.dec.c, ctx->key_sz,
+                                        DMA_TO_DEVICE);
+       if (!dma_mapping_error(dev, qat_req->out.dec.m))
+               dma_unmap_single(dev, qat_req->out.dec.m, ctx->key_sz,
+                                DMA_FROM_DEVICE);
+       if (!dma_mapping_error(dev, qat_req->phy_in))
+               dma_unmap_single(dev, qat_req->phy_in,
+                                sizeof(struct qat_rsa_input_params),
+                                DMA_TO_DEVICE);
+       if (!dma_mapping_error(dev, qat_req->phy_out))
+               dma_unmap_single(dev, qat_req->phy_out,
+                                sizeof(struct qat_rsa_output_params),
+                                DMA_TO_DEVICE);
+       return ret;
+}
+
+int qat_rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
+                 const void *value, size_t vlen)
+{
+       struct qat_rsa_ctx *ctx = context;
+       struct qat_crypto_instance *inst = ctx->inst;
+       struct device *dev = &GET_DEV(inst->accel_dev);
+       const char *ptr = value;
+       int ret;
+
+       while (!*ptr && vlen) {
+               ptr++;
+               vlen--;
+       }
+
+       ctx->key_sz = vlen;
+       ret = -EINVAL;
+       /* In FIPS mode only allow key size 2K & 3K */
+       if (fips_enabled && (ctx->key_sz != 256 && ctx->key_sz != 384)) {
+               pr_err("QAT: RSA: key size not allowed in FIPS mode\n");
+               goto err;
+       }
+       /* invalid key size provided */
+       if (!qat_rsa_enc_fn_id(ctx->key_sz))
+               goto err;
+
+       ret = -ENOMEM;
+       ctx->n = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
+       if (!ctx->n)
+               goto err;
+
+       memcpy(ctx->n, ptr, ctx->key_sz);
+       return 0;
+err:
+       ctx->key_sz = 0;
+       ctx->n = NULL;
+       return ret;
+}
+
+int qat_rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
+                 const void *value, size_t vlen)
+{
+       struct qat_rsa_ctx *ctx = context;
+       struct qat_crypto_instance *inst = ctx->inst;
+       struct device *dev = &GET_DEV(inst->accel_dev);
+       const char *ptr = value;
+
+       while (!*ptr && vlen) {
+               ptr++;
+               vlen--;
+       }
+
+       if (!ctx->key_sz || !vlen || vlen > ctx->key_sz) {
+               ctx->e = NULL;
+               return -EINVAL;
+       }
+
+       ctx->e = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
+       if (!ctx->e) {
+               ctx->e = NULL;
+               return -ENOMEM;
+       }
+       memcpy(ctx->e + (ctx->key_sz - vlen), ptr, vlen);
+       return 0;
+}
+
+int qat_rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
+                 const void *value, size_t vlen)
+{
+       struct qat_rsa_ctx *ctx = context;
+       struct qat_crypto_instance *inst = ctx->inst;
+       struct device *dev = &GET_DEV(inst->accel_dev);
+       const char *ptr = value;
+       int ret;
+
+       while (!*ptr && vlen) {
+               ptr++;
+               vlen--;
+       }
+
+       ret = -EINVAL;
+       if (!ctx->key_sz || !vlen || vlen > ctx->key_sz)
+               goto err;
+
+       /* In FIPS mode only allow key size 2K & 3K */
+       if (fips_enabled && (vlen != 256 && vlen != 384)) {
+               pr_err("QAT: RSA: key size not allowed in FIPS mode\n");
+               goto err;
+       }
+
+       ret = -ENOMEM;
+       ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
+       if (!ctx->n)
+               goto err;
+
+       memcpy(ctx->d + (ctx->key_sz - vlen), ptr, vlen);
+       return 0;
+err:
+       ctx->d = NULL;
+       return ret;
+}
+
+static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
+                         unsigned int keylen)
+{
+       struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+       struct device *dev = &GET_DEV(ctx->inst->accel_dev);
+       int ret;
+
+       /* Free the old key if any */
+       if (ctx->n)
+               dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
+       if (ctx->e)
+               dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
+       if (ctx->d) {
+               memset(ctx->d, '\0', ctx->key_sz);
+               dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
+       }
+
+       ctx->n = NULL;
+       ctx->e = NULL;
+       ctx->d = NULL;
+       ret = asn1_ber_decoder(&qat_rsakey_decoder, ctx, key, keylen);
+       if (ret < 0)
+               goto free;
+
+       if (!ctx->n || !ctx->e) {
+               /* invalid key provided */
+               ret = -EINVAL;
+               goto free;
+       }
+
+       return 0;
+free:
+       if (ctx->d) {
+               memset(ctx->d, '\0', ctx->key_sz);
+               dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
+               ctx->d = NULL;
+       }
+       if (ctx->e) {
+               dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
+               ctx->e = NULL;
+       }
+       if (ctx->n) {
+               dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
+               ctx->n = NULL;
+               ctx->key_sz = 0;
+       }
+       return ret;
+}
+
+static int qat_rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+       struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+       struct qat_crypto_instance *inst =
+                       qat_crypto_get_instance_node(get_current_node());
+
+       if (!inst)
+               return -EINVAL;
+
+       ctx->key_sz = 0;
+       ctx->inst = inst;
+       return 0;
+}
+
+static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+       struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+       struct device *dev = &GET_DEV(ctx->inst->accel_dev);
+
+       if (ctx->n)
+               dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
+       if (ctx->e)
+               dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
+       if (ctx->d) {
+               memset(ctx->d, '\0', ctx->key_sz);
+               dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
+       }
+       qat_crypto_put_instance(ctx->inst);
+       ctx->n = NULL;
+       ctx->d = NULL;
+       ctx->d = NULL;
+}
+
+static struct akcipher_alg rsa = {
+       .encrypt = qat_rsa_enc,
+       .decrypt = qat_rsa_dec,
+       .sign = qat_rsa_dec,
+       .verify = qat_rsa_enc,
+       .setkey = qat_rsa_setkey,
+       .init = qat_rsa_init_tfm,
+       .exit = qat_rsa_exit_tfm,
+       .reqsize = sizeof(struct qat_rsa_request) + 64,
+       .base = {
+               .cra_name = "rsa",
+               .cra_driver_name = "qat-rsa",
+               .cra_priority = 1000,
+               .cra_module = THIS_MODULE,
+               .cra_ctxsize = sizeof(struct qat_rsa_ctx),
+       },
+};
+
+int qat_asym_algs_register(void)
+{
+       int ret = 0;
+
+       mutex_lock(&algs_lock);
+       if (++active_devs == 1) {
+               rsa.base.cra_flags = 0;
+               ret = crypto_register_akcipher(&rsa);
+       }
+       mutex_unlock(&algs_lock);
+       return ret;
+}
+
+void qat_asym_algs_unregister(void)
+{
+       mutex_lock(&algs_lock);
+       if (--active_devs == 0)
+               crypto_unregister_akcipher(&rsa);
+       mutex_unlock(&algs_lock);
+}
index 3bd705ca5973c1d02598731d387afb9c12da5caf..07c2f9f9d1fcd8831938e4c10711dd2a6a736acb 100644 (file)
@@ -88,12 +88,6 @@ static int qat_crypto_free_instances(struct adf_accel_dev *accel_dev)
                if (inst->pke_rx)
                        adf_remove_ring(inst->pke_rx);
 
-               if (inst->rnd_tx)
-                       adf_remove_ring(inst->rnd_tx);
-
-               if (inst->rnd_rx)
-                       adf_remove_ring(inst->rnd_rx);
-
                list_del(list_ptr);
                kfree(inst);
        }
@@ -109,9 +103,11 @@ struct qat_crypto_instance *qat_crypto_get_instance_node(int node)
 
        list_for_each(itr, adf_devmgr_get_head()) {
                accel_dev = list_entry(itr, struct adf_accel_dev, list);
+
                if ((node == dev_to_node(&GET_DEV(accel_dev)) ||
                     dev_to_node(&GET_DEV(accel_dev)) < 0) &&
-                   adf_dev_started(accel_dev))
+                   adf_dev_started(accel_dev) &&
+                   !list_empty(&accel_dev->crypto_list))
                        break;
                accel_dev = NULL;
        }
@@ -158,7 +154,6 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
 
        INIT_LIST_HEAD(&accel_dev->crypto_list);
        strlcpy(key, ADF_NUM_CY, sizeof(key));
-
        if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
                return -EFAULT;
 
@@ -187,7 +182,9 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
 
                if (kstrtoul(val, 10, &num_msg_sym))
                        goto err;
+
                num_msg_sym = num_msg_sym >> 1;
+
                snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_SIZE, i);
                if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
                        goto err;
@@ -202,11 +199,6 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
                                    msg_size, key, NULL, 0, &inst->sym_tx))
                        goto err;
 
-               snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_TX, i);
-               if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
-                                   msg_size, key, NULL, 0, &inst->rnd_tx))
-                       goto err;
-
                msg_size = msg_size >> 1;
                snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_TX, i);
                if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
@@ -220,15 +212,9 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
                                    &inst->sym_rx))
                        goto err;
 
-               snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_RX, i);
-               if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
-                                   msg_size, key, qat_alg_callback, 0,
-                                   &inst->rnd_rx))
-                       goto err;
-
                snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, i);
                if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
-                                   msg_size, key, qat_alg_callback, 0,
+                                   msg_size, key, qat_alg_asym_callback, 0,
                                    &inst->pke_rx))
                        goto err;
        }
index d503007b49e6ef3f7499a19836e5f09c1b7de9ae..dc0273fe36206e7faaa9cb0f901d580a4b5f037f 100644 (file)
@@ -57,8 +57,6 @@ struct qat_crypto_instance {
        struct adf_etr_ring_data *sym_rx;
        struct adf_etr_ring_data *pke_tx;
        struct adf_etr_ring_data *pke_rx;
-       struct adf_etr_ring_data *rnd_tx;
-       struct adf_etr_ring_data *rnd_rx;
        struct adf_accel_dev *accel_dev;
        struct list_head list;
        unsigned long state;
index 274ff7e9de6e9cfa165a8c99297cfada512bc794..8e711d1c308402ad35ce87822ed16f572d07fe5b 100644 (file)
@@ -671,7 +671,6 @@ static int qat_hal_clear_gpr(struct icp_qat_fw_loader_handle *handle)
 #define ICP_DH895XCC_CAP_OFFSET     (ICP_DH895XCC_AE_OFFSET + 0x10000)
 #define LOCAL_TO_XFER_REG_OFFSET    0x800
 #define ICP_DH895XCC_EP_OFFSET      0x3a000
-#define ICP_DH895XCC_PMISC_BAR 1
 int qat_hal_init(struct adf_accel_dev *accel_dev)
 {
        unsigned char ae;
@@ -679,21 +678,24 @@ int qat_hal_init(struct adf_accel_dev *accel_dev)
        struct icp_qat_fw_loader_handle *handle;
        struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
-       struct adf_bar *bar =
+       struct adf_bar *misc_bar =
                        &pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)];
+       struct adf_bar *sram_bar =
+                       &pci_info->pci_bars[hw_data->get_sram_bar_id(hw_data)];
 
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (!handle)
                return -ENOMEM;
 
-       handle->hal_cap_g_ctl_csr_addr_v = bar->virt_addr +
+       handle->hal_cap_g_ctl_csr_addr_v = misc_bar->virt_addr +
                                                ICP_DH895XCC_CAP_OFFSET;
-       handle->hal_cap_ae_xfer_csr_addr_v = bar->virt_addr +
+       handle->hal_cap_ae_xfer_csr_addr_v = misc_bar->virt_addr +
                                                ICP_DH895XCC_AE_OFFSET;
-       handle->hal_ep_csr_addr_v = bar->virt_addr + ICP_DH895XCC_EP_OFFSET;
+       handle->hal_ep_csr_addr_v = misc_bar->virt_addr +
+                                   ICP_DH895XCC_EP_OFFSET;
        handle->hal_cap_ae_local_csr_addr_v =
                handle->hal_cap_ae_xfer_csr_addr_v + LOCAL_TO_XFER_REG_OFFSET;
-
+       handle->hal_sram_addr_v = sram_bar->virt_addr;
        handle->hal_handle = kzalloc(sizeof(*handle->hal_handle), GFP_KERNEL);
        if (!handle->hal_handle)
                goto out_hal_handle;
diff --git a/drivers/crypto/qat/qat_common/qat_rsakey.asn1 b/drivers/crypto/qat/qat_common/qat_rsakey.asn1
new file mode 100644 (file)
index 0000000..97b0e02
--- /dev/null
@@ -0,0 +1,5 @@
+RsaKey ::= SEQUENCE {
+       n INTEGER ({ qat_rsa_get_n }),
+       e INTEGER ({ qat_rsa_get_e }),
+       d INTEGER ({ qat_rsa_get_d })
+}
index 1e27f9f7fddf64dbb5ed959305dc93aa7c894fda..c48f181e894157a1c8767d64d4ecf00975bd1ef6 100644 (file)
@@ -359,28 +359,7 @@ static int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
 static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
                                   struct icp_qat_uof_initmem *init_mem)
 {
-       unsigned int i;
-       struct icp_qat_uof_memvar_attr *mem_val_attr;
-
-       mem_val_attr =
-               (struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
-               sizeof(struct icp_qat_uof_initmem));
-
        switch (init_mem->region) {
-       case ICP_QAT_UOF_SRAM_REGION:
-               if ((init_mem->addr + init_mem->num_in_bytes) >
-                   ICP_DH895XCC_PESRAM_BAR_SIZE) {
-                       pr_err("QAT: initmem on SRAM is out of range");
-                       return -EINVAL;
-               }
-               for (i = 0; i < init_mem->val_attr_num; i++) {
-                       qat_uclo_wr_sram_by_words(handle,
-                                                 init_mem->addr +
-                                                 mem_val_attr->offset_in_byte,
-                                                 &mem_val_attr->value, 4);
-                       mem_val_attr++;
-               }
-               break;
        case ICP_QAT_UOF_LMEM_REGION:
                if (qat_uclo_init_lmem_seg(handle, init_mem))
                        return -EINVAL;
@@ -990,6 +969,12 @@ out_err:
        return -EFAULT;
 }
 
+void qat_uclo_wr_mimage(struct icp_qat_fw_loader_handle *handle,
+                       void *addr_ptr, int mem_size)
+{
+       qat_uclo_wr_sram_by_words(handle, 0, addr_ptr, ALIGN(mem_size, 4));
+}
+
 int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
                         void *addr_ptr, int mem_size)
 {
index 25171c557043300d440d74f385bd8a8ad8beec51..8c79c543740f673be990ed5aa5099b5e1eb871cb 100644 (file)
@@ -2,7 +2,4 @@ ccflags-y := -I$(src)/../qat_common
 obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc.o
 qat_dh895xcc-objs := adf_drv.o \
                adf_isr.o \
-               adf_dh895xcc_hw_data.o \
-               adf_hw_arbiter.o \
-               qat_admin.o \
-               adf_admin.o
+               adf_dh895xcc_hw_data.o
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_admin.c b/drivers/crypto/qat/qat_dh895xcc/adf_admin.c
deleted file mode 100644 (file)
index e466606..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-  This file is provided under a dual BSD/GPLv2 license.  When using or
-  redistributing this file, you may do so under either license.
-
-  GPL LICENSE SUMMARY
-  Copyright(c) 2014 Intel Corporation.
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of version 2 of the GNU General Public License 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.
-
-  Contact Information:
-  qat-linux@intel.com
-
-  BSD LICENSE
-  Copyright(c) 2014 Intel Corporation.
-  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 Intel Corporation nor the names of its
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-  "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 COPYRIGHT
-  OWNER 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/types.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <adf_accel_devices.h>
-#include "adf_drv.h"
-#include "adf_dh895xcc_hw_data.h"
-
-#define ADF_ADMINMSG_LEN 32
-
-struct adf_admin_comms {
-       dma_addr_t phy_addr;
-       void *virt_addr;
-       void __iomem *mailbox_addr;
-       struct mutex lock;      /* protects adf_admin_comms struct */
-};
-
-int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
-                          uint32_t ae, void *in, void *out)
-{
-       struct adf_admin_comms *admin = accel_dev->admin;
-       int offset = ae * ADF_ADMINMSG_LEN * 2;
-       void __iomem *mailbox = admin->mailbox_addr;
-       int mb_offset = ae * ADF_DH895XCC_MAILBOX_STRIDE;
-       int times, received;
-
-       mutex_lock(&admin->lock);
-
-       if (ADF_CSR_RD(mailbox, mb_offset) == 1) {
-               mutex_unlock(&admin->lock);
-               return -EAGAIN;
-       }
-
-       memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN);
-       ADF_CSR_WR(mailbox, mb_offset, 1);
-       received = 0;
-       for (times = 0; times < 50; times++) {
-               msleep(20);
-               if (ADF_CSR_RD(mailbox, mb_offset) == 0) {
-                       received = 1;
-                       break;
-               }
-       }
-       if (received)
-               memcpy(out, admin->virt_addr + offset +
-                      ADF_ADMINMSG_LEN, ADF_ADMINMSG_LEN);
-       else
-               dev_err(&GET_DEV(accel_dev),
-                       "Failed to send admin msg to accelerator\n");
-
-       mutex_unlock(&admin->lock);
-       return received ? 0 : -EFAULT;
-}
-
-int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
-{
-       struct adf_admin_comms *admin;
-       struct adf_bar *pmisc = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
-       void __iomem *csr = pmisc->virt_addr;
-       void __iomem *mailbox = csr + ADF_DH895XCC_MAILBOX_BASE_OFFSET;
-       uint64_t reg_val;
-
-       admin = kzalloc_node(sizeof(*accel_dev->admin), GFP_KERNEL,
-                            dev_to_node(&GET_DEV(accel_dev)));
-       if (!admin)
-               return -ENOMEM;
-       admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
-                                              &admin->phy_addr, GFP_KERNEL);
-       if (!admin->virt_addr) {
-               dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
-               kfree(admin);
-               return -ENOMEM;
-       }
-       reg_val = (uint64_t)admin->phy_addr;
-       ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGUR_OFFSET, reg_val >> 32);
-       ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGLR_OFFSET, reg_val);
-       mutex_init(&admin->lock);
-       admin->mailbox_addr = mailbox;
-       accel_dev->admin = admin;
-       return 0;
-}
-
-void adf_exit_admin_comms(struct adf_accel_dev *accel_dev)
-{
-       struct adf_admin_comms *admin = accel_dev->admin;
-
-       if (!admin)
-               return;
-
-       if (admin->virt_addr)
-               dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
-                                 admin->virt_addr, admin->phy_addr);
-
-       mutex_destroy(&admin->lock);
-       kfree(admin);
-       accel_dev->admin = NULL;
-}
index b1386922d7a2a7c0aaf6bf06c52c1a860ffd12bf..ff54257eced47c619d14e3e4275383d3cf186d47 100644 (file)
@@ -45,8 +45,9 @@
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #include <adf_accel_devices.h>
+#include <adf_pf2vf_msg.h>
+#include <adf_common_drv.h>
 #include "adf_dh895xcc_hw_data.h"
-#include "adf_common_drv.h"
 #include "adf_drv.h"
 
 /* Worker thread to service arbiter mappings based on dev SKUs */
@@ -117,6 +118,11 @@ static uint32_t get_etr_bar_id(struct adf_hw_device_data *self)
        return ADF_DH895XCC_ETR_BAR;
 }
 
+static uint32_t get_sram_bar_id(struct adf_hw_device_data *self)
+{
+       return ADF_DH895XCC_SRAM_BAR;
+}
+
 static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
 {
        int sku = (self->fuses & ADF_DH895XCC_FUSECTL_SKU_MASK)
@@ -156,6 +162,16 @@ void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
        }
 }
 
+static uint32_t get_pf2vf_offset(uint32_t i)
+{
+       return ADF_DH895XCC_PF2VF_OFFSET(i);
+}
+
+static uint32_t get_vintmsk_offset(uint32_t i)
+{
+       return ADF_DH895XCC_VINTMSK_OFFSET(i);
+}
+
 static void adf_enable_error_correction(struct adf_accel_dev *accel_dev)
 {
        struct adf_hw_device_data *hw_device = accel_dev->hw_device;
@@ -192,18 +208,23 @@ static void adf_enable_ints(struct adf_accel_dev *accel_dev)
 
        /* Enable bundle and misc interrupts */
        ADF_CSR_WR(addr, ADF_DH895XCC_SMIAPF0_MASK_OFFSET,
-                  ADF_DH895XCC_SMIA0_MASK);
+                  accel_dev->pf.vf_info ? 0 :
+                       GENMASK_ULL(GET_MAX_BANKS(accel_dev) - 1, 0));
        ADF_CSR_WR(addr, ADF_DH895XCC_SMIAPF1_MASK_OFFSET,
                   ADF_DH895XCC_SMIA1_MASK);
 }
 
+static int adf_pf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
+{
+       return 0;
+}
+
 void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
 {
        hw_data->dev_class = &dh895xcc_class;
        hw_data->instance_id = dh895xcc_class.instances++;
        hw_data->num_banks = ADF_DH895XCC_ETR_MAX_BANKS;
        hw_data->num_accel = ADF_DH895XCC_MAX_ACCELERATORS;
-       hw_data->pci_dev_id = ADF_DH895XCC_PCI_DEVICE_ID;
        hw_data->num_logical_accel = 1;
        hw_data->num_engines = ADF_DH895XCC_MAX_ACCELENGINES;
        hw_data->tx_rx_gap = ADF_DH895XCC_RX_RINGS_OFFSET;
@@ -211,21 +232,28 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
        hw_data->alloc_irq = adf_isr_resource_alloc;
        hw_data->free_irq = adf_isr_resource_free;
        hw_data->enable_error_correction = adf_enable_error_correction;
-       hw_data->hw_arb_ring_enable = adf_update_ring_arb_enable;
-       hw_data->hw_arb_ring_disable = adf_update_ring_arb_enable;
        hw_data->get_accel_mask = get_accel_mask;
        hw_data->get_ae_mask = get_ae_mask;
        hw_data->get_num_accels = get_num_accels;
        hw_data->get_num_aes = get_num_aes;
        hw_data->get_etr_bar_id = get_etr_bar_id;
        hw_data->get_misc_bar_id = get_misc_bar_id;
+       hw_data->get_pf2vf_offset = get_pf2vf_offset;
+       hw_data->get_vintmsk_offset = get_vintmsk_offset;
+       hw_data->get_sram_bar_id = get_sram_bar_id;
        hw_data->get_sku = get_sku;
        hw_data->fw_name = ADF_DH895XCC_FW;
+       hw_data->fw_mmp_name = ADF_DH895XCC_MMP;
        hw_data->init_admin_comms = adf_init_admin_comms;
        hw_data->exit_admin_comms = adf_exit_admin_comms;
+       hw_data->disable_iov = adf_disable_sriov;
+       hw_data->send_admin_init = adf_send_admin_init;
        hw_data->init_arb = adf_init_arb;
        hw_data->exit_arb = adf_exit_arb;
+       hw_data->get_arb_mapping = adf_get_arbiter_mapping;
        hw_data->enable_ints = adf_enable_ints;
+       hw_data->enable_vf2pf_comms = adf_pf_enable_vf2pf_comms;
+       hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION;
 }
 
 void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
index 25269a9f24a2bca0cb41e095668589b609a462ff..88dffb29734683efa437d618464e263dfb95ec00 100644 (file)
@@ -48,6 +48,7 @@
 #define ADF_DH895x_HW_DATA_H_
 
 /* PCIe configuration space */
+#define ADF_DH895XCC_SRAM_BAR 0
 #define ADF_DH895XCC_PMISC_BAR 1
 #define ADF_DH895XCC_ETR_BAR 2
 #define ADF_DH895XCC_RX_RINGS_OFFSET 8
 #define ADF_DH895XCC_CERRSSMSH(i) (i * 0x4000 + 0x10)
 #define ADF_DH895XCC_ERRSSMSH_EN BIT(3)
 
-/* Admin Messages Registers */
-#define ADF_DH895XCC_ADMINMSGUR_OFFSET (0x3A000 + 0x574)
-#define ADF_DH895XCC_ADMINMSGLR_OFFSET (0x3A000 + 0x578)
-#define ADF_DH895XCC_MAILBOX_BASE_OFFSET 0x20970
-#define ADF_DH895XCC_MAILBOX_STRIDE 0x1000
+#define ADF_DH895XCC_ERRSOU3   (0x3A000 + 0x00C)
+#define ADF_DH895XCC_ERRSOU5   (0x3A000 + 0x0D8)
+#define ADF_DH895XCC_PF2VF_OFFSET(i)   (0x3A000 + 0x280 + ((i) * 0x04))
+#define ADF_DH895XCC_VINTMSK_OFFSET(i) (0x3A000 + 0x200 + ((i) * 0x04))
+/* FW names */
 #define ADF_DH895XCC_FW "qat_895xcc.bin"
+#define ADF_DH895XCC_MMP "qat_mmp.bin"
 #endif
index 1bde45b7a3c560f5e409c17f45c4bf6bb9eb730e..f8dd14f232c83bffee35a2f096cd13dd88cd15dd 100644 (file)
@@ -82,16 +82,21 @@ static struct pci_driver adf_driver = {
        .id_table = adf_pci_tbl,
        .name = adf_driver_name,
        .probe = adf_probe,
-       .remove = adf_remove
+       .remove = adf_remove,
+       .sriov_configure = adf_sriov_configure,
 };
 
+static void adf_cleanup_pci_dev(struct adf_accel_dev *accel_dev)
+{
+       pci_release_regions(accel_dev->accel_pci_dev.pci_dev);
+       pci_disable_device(accel_dev->accel_pci_dev.pci_dev);
+}
+
 static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
 {
        struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev;
        int i;
 
-       adf_dev_shutdown(accel_dev);
-
        for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
                struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
 
@@ -100,7 +105,7 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
        }
 
        if (accel_dev->hw_device) {
-               switch (accel_dev->hw_device->pci_dev_id) {
+               switch (accel_pci_dev->pci_dev->device) {
                case ADF_DH895XCC_PCI_DEVICE_ID:
                        adf_clean_hw_data_dh895xcc(accel_dev->hw_device);
                        break;
@@ -108,13 +113,11 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
                        break;
                }
                kfree(accel_dev->hw_device);
+               accel_dev->hw_device = NULL;
        }
        adf_cfg_dev_remove(accel_dev);
        debugfs_remove(accel_dev->debugfs_dir);
-       adf_devmgr_rm_dev(accel_dev);
-       pci_release_regions(accel_pci_dev->pci_dev);
-       pci_disable_device(accel_pci_dev->pci_dev);
-       kfree(accel_dev);
+       adf_devmgr_rm_dev(accel_dev, NULL);
 }
 
 static int adf_dev_configure(struct adf_accel_dev *accel_dev)
@@ -167,12 +170,6 @@ static int adf_dev_configure(struct adf_accel_dev *accel_dev)
                                                key, (void *)&val, ADF_DEC))
                        goto err;
 
-               val = 4;
-               snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_TX, i);
-               if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
-                                               key, (void *)&val, ADF_DEC))
-                       goto err;
-
                val = 8;
                snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, i);
                if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
@@ -185,12 +182,6 @@ static int adf_dev_configure(struct adf_accel_dev *accel_dev)
                                                key, (void *)&val, ADF_DEC))
                        goto err;
 
-               val = 12;
-               snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_RX, i);
-               if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
-                                               key, (void *)&val, ADF_DEC))
-                       goto err;
-
                val = ADF_COALESCING_DEF_TIME;
                snprintf(key, sizeof(key), ADF_ETRMGR_COALESCE_TIMER_FORMAT, i);
                if (adf_cfg_add_key_value_param(accel_dev, "Accelerator0",
@@ -217,7 +208,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct adf_hw_device_data *hw_data;
        char name[ADF_DEVICE_NAME_LENGTH];
        unsigned int i, bar_nr;
-       int ret;
+       int ret, bar_mask;
 
        switch (ent->device) {
        case ADF_DH895XCC_PCI_DEVICE_ID:
@@ -241,10 +232,12 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&accel_dev->crypto_list);
+       accel_pci_dev = &accel_dev->accel_pci_dev;
+       accel_pci_dev->pci_dev = pdev;
 
        /* Add accel device to accel table.
         * This should be called before adf_cleanup_accel is called */
-       if (adf_devmgr_add_dev(accel_dev)) {
+       if (adf_devmgr_add_dev(accel_dev, NULL)) {
                dev_err(&pdev->dev, "Failed to add new accelerator device.\n");
                kfree(accel_dev);
                return -EFAULT;
@@ -267,7 +260,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        default:
                return -ENODEV;
        }
-       accel_pci_dev = &accel_dev->accel_pci_dev;
        pci_read_config_byte(pdev, PCI_REVISION_ID, &accel_pci_dev->revid);
        pci_read_config_dword(pdev, ADF_DH895XCC_FUSECTL_OFFSET,
                              &hw_data->fuses);
@@ -276,7 +268,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw_data->accel_mask = hw_data->get_accel_mask(hw_data->fuses);
        hw_data->ae_mask = hw_data->get_ae_mask(hw_data->fuses);
        accel_pci_dev->sku = hw_data->get_sku(hw_data);
-       accel_pci_dev->pci_dev = pdev;
        /* If the device has no acceleration engines then ignore it. */
        if (!hw_data->accel_mask || !hw_data->ae_mask ||
            ((~hw_data->ae_mask) & 0x01)) {
@@ -286,11 +277,14 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        /* Create dev top level debugfs entry */
-       snprintf(name, sizeof(name), "%s%s_dev%d", ADF_DEVICE_NAME_PREFIX,
-                hw_data->dev_class->name, hw_data->instance_id);
+       snprintf(name, sizeof(name), "%s%s_%02x:%02d.%02d",
+                ADF_DEVICE_NAME_PREFIX, hw_data->dev_class->name,
+                pdev->bus->number, PCI_SLOT(pdev->devfn),
+                PCI_FUNC(pdev->devfn));
+
        accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
        if (!accel_dev->debugfs_dir) {
-               dev_err(&pdev->dev, "Could not create debugfs dir\n");
+               dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
                ret = -EINVAL;
                goto out_err;
        }
@@ -313,7 +307,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
                        dev_err(&pdev->dev, "No usable DMA configuration\n");
                        ret = -EFAULT;
-                       goto out_err;
+                       goto out_err_disable;
                } else {
                        pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
                }
@@ -324,7 +318,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (pci_request_regions(pdev, adf_driver_name)) {
                ret = -EFAULT;
-               goto out_err;
+               goto out_err_disable;
        }
 
        /* Read accelerator capabilities mask */
@@ -332,19 +326,21 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                              &hw_data->accel_capabilities_mask);
 
        /* Find and map all the device's BARS */
-       for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
-               struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
+       i = 0;
+       bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
+       for_each_set_bit(bar_nr, (const unsigned long *)&bar_mask,
+                        ADF_PCI_MAX_BARS * 2) {
+               struct adf_bar *bar = &accel_pci_dev->pci_bars[i++];
 
-               bar_nr = i * 2;
                bar->base_addr = pci_resource_start(pdev, bar_nr);
                if (!bar->base_addr)
                        break;
                bar->size = pci_resource_len(pdev, bar_nr);
                bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0);
                if (!bar->virt_addr) {
-                       dev_err(&pdev->dev, "Failed to map BAR %d\n", i);
+                       dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr);
                        ret = -EFAULT;
-                       goto out_err;
+                       goto out_err_free_reg;
                }
        }
        pci_set_master(pdev);
@@ -352,32 +348,40 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (adf_enable_aer(accel_dev, &adf_driver)) {
                dev_err(&pdev->dev, "Failed to enable aer\n");
                ret = -EFAULT;
-               goto out_err;
+               goto out_err_free_reg;
        }
 
        if (pci_save_state(pdev)) {
                dev_err(&pdev->dev, "Failed to save pci state\n");
                ret = -ENOMEM;
-               goto out_err;
+               goto out_err_free_reg;
        }
 
        ret = adf_dev_configure(accel_dev);
        if (ret)
-               goto out_err;
+               goto out_err_free_reg;
 
        ret = adf_dev_init(accel_dev);
        if (ret)
-               goto out_err;
+               goto out_err_dev_shutdown;
 
        ret = adf_dev_start(accel_dev);
-       if (ret) {
-               adf_dev_stop(accel_dev);
-               goto out_err;
-       }
+       if (ret)
+               goto out_err_dev_stop;
 
-       return 0;
+       return ret;
+
+out_err_dev_stop:
+       adf_dev_stop(accel_dev);
+out_err_dev_shutdown:
+       adf_dev_shutdown(accel_dev);
+out_err_free_reg:
+       pci_release_regions(accel_pci_dev->pci_dev);
+out_err_disable:
+       pci_disable_device(accel_pci_dev->pci_dev);
 out_err:
        adf_cleanup_accel(accel_dev);
+       kfree(accel_dev);
        return ret;
 }
 
@@ -391,15 +395,17 @@ static void adf_remove(struct pci_dev *pdev)
        }
        if (adf_dev_stop(accel_dev))
                dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
+
+       adf_dev_shutdown(accel_dev);
        adf_disable_aer(accel_dev);
        adf_cleanup_accel(accel_dev);
+       adf_cleanup_pci_dev(accel_dev);
+       kfree(accel_dev);
 }
 
 static int __init adfdrv_init(void)
 {
        request_module("intel_qat");
-       if (qat_admin_register())
-               return -EFAULT;
 
        if (pci_register_driver(&adf_driver)) {
                pr_err("QAT: Driver initialization failed\n");
@@ -411,7 +417,6 @@ static int __init adfdrv_init(void)
 static void __exit adfdrv_release(void)
 {
        pci_unregister_driver(&adf_driver);
-       qat_admin_unregister();
 }
 
 module_init(adfdrv_init);
index a2fbb6ce75cd8093f49ea22520cf2bca6cd9450e..85ff245bd1d8d982133516d90557fbe4cb28441b 100644 (file)
@@ -53,15 +53,6 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data);
 void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data);
 int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev);
 void adf_isr_resource_free(struct adf_accel_dev *accel_dev);
-void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring);
 void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
                             uint32_t const **arb_map_config);
-int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
-void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
-int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
-                          uint32_t ae, void *in, void *out);
-int qat_admin_register(void);
-int qat_admin_unregister(void);
-int adf_init_arb(struct adf_accel_dev *accel_dev);
-void adf_exit_arb(struct adf_accel_dev *accel_dev);
 #endif
index 0d03c109c2d32f56c80e1d5d3e7f490fe5a0bd55..5570f78795c1840e029f7c560cc4bd6c5b59cc45 100644 (file)
 #include <adf_transport_access_macros.h>
 #include <adf_transport_internal.h>
 #include "adf_drv.h"
+#include "adf_dh895xcc_hw_data.h"
 
 static int adf_enable_msix(struct adf_accel_dev *accel_dev)
 {
        struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
-       uint32_t msix_num_entries = hw_data->num_banks + 1;
-       int i;
-
-       for (i = 0; i < msix_num_entries; i++)
-               pci_dev_info->msix_entries.entries[i].entry = i;
+       u32 msix_num_entries = 1;
+
+       /* If SR-IOV is disabled, add entries for each bank */
+       if (!accel_dev->pf.vf_info) {
+               int i;
+
+               msix_num_entries += hw_data->num_banks;
+               for (i = 0; i < msix_num_entries; i++)
+                       pci_dev_info->msix_entries.entries[i].entry = i;
+       } else {
+               pci_dev_info->msix_entries.entries[0].entry =
+                       hw_data->num_banks;
+       }
 
        if (pci_enable_msix_exact(pci_dev_info->pci_dev,
                                  pci_dev_info->msix_entries.entries,
                                  msix_num_entries)) {
-               dev_err(&GET_DEV(accel_dev), "Failed to enable MSIX IRQ\n");
+               dev_err(&GET_DEV(accel_dev), "Failed to enable MSI-X IRQ(s)\n");
                return -EFAULT;
        }
        return 0;
@@ -97,9 +106,58 @@ static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
 {
        struct adf_accel_dev *accel_dev = dev_ptr;
 
-       dev_info(&GET_DEV(accel_dev), "qat_dev%d spurious AE interrupt\n",
-                accel_dev->accel_id);
-       return IRQ_HANDLED;
+#ifdef CONFIG_PCI_IOV
+       /* If SR-IOV is enabled (vf_info is non-NULL), check for VF->PF ints */
+       if (accel_dev->pf.vf_info) {
+               void __iomem *pmisc_bar_addr =
+                   (&GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR])->virt_addr;
+               u32 vf_mask;
+
+               /* Get the interrupt sources triggered by VFs */
+               vf_mask = ((ADF_CSR_RD(pmisc_bar_addr, ADF_DH895XCC_ERRSOU5) &
+                           0x0000FFFF) << 16) |
+                         ((ADF_CSR_RD(pmisc_bar_addr, ADF_DH895XCC_ERRSOU3) &
+                           0x01FFFE00) >> 9);
+
+               if (vf_mask) {
+                       struct adf_accel_vf_info *vf_info;
+                       bool irq_handled = false;
+                       int i;
+
+                       /* Disable VF2PF interrupts for VFs with pending ints */
+                       adf_disable_vf2pf_interrupts(accel_dev, vf_mask);
+
+                       /*
+                        * Schedule tasklets to handle VF2PF interrupt BHs
+                        * unless the VF is malicious and is attempting to
+                        * flood the host OS with VF2PF interrupts.
+                        */
+                       for_each_set_bit(i, (const unsigned long *)&vf_mask,
+                                        (sizeof(vf_mask) * BITS_PER_BYTE)) {
+                               vf_info = accel_dev->pf.vf_info + i;
+
+                               if (!__ratelimit(&vf_info->vf2pf_ratelimit)) {
+                                       dev_info(&GET_DEV(accel_dev),
+                                                "Too many ints from VF%d\n",
+                                                 vf_info->vf_nr + 1);
+                                       continue;
+                               }
+
+                               /* Tasklet will re-enable ints from this VF */
+                               tasklet_hi_schedule(&vf_info->vf2pf_bh_tasklet);
+                               irq_handled = true;
+                       }
+
+                       if (irq_handled)
+                               return IRQ_HANDLED;
+               }
+       }
+#endif /* CONFIG_PCI_IOV */
+
+       dev_dbg(&GET_DEV(accel_dev), "qat_dev%d spurious AE interrupt\n",
+               accel_dev->accel_id);
+
+       return IRQ_NONE;
 }
 
 static int adf_request_irqs(struct adf_accel_dev *accel_dev)
@@ -108,28 +166,32 @@ static int adf_request_irqs(struct adf_accel_dev *accel_dev)
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
        struct adf_etr_data *etr_data = accel_dev->transport;
-       int ret, i;
+       int ret, i = 0;
        char *name;
 
-       /* Request msix irq for all banks */
-       for (i = 0; i < hw_data->num_banks; i++) {
-               struct adf_etr_bank_data *bank = &etr_data->banks[i];
-               unsigned int cpu, cpus = num_online_cpus();
-
-               name = *(pci_dev_info->msix_entries.names + i);
-               snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
-                        "qat%d-bundle%d", accel_dev->accel_id, i);
-               ret = request_irq(msixe[i].vector,
-                                 adf_msix_isr_bundle, 0, name, bank);
-               if (ret) {
-                       dev_err(&GET_DEV(accel_dev),
-                               "failed to enable irq %d for %s\n",
-                               msixe[i].vector, name);
-                       return ret;
+       /* Request msix irq for all banks unless SR-IOV enabled */
+       if (!accel_dev->pf.vf_info) {
+               for (i = 0; i < hw_data->num_banks; i++) {
+                       struct adf_etr_bank_data *bank = &etr_data->banks[i];
+                       unsigned int cpu, cpus = num_online_cpus();
+
+                       name = *(pci_dev_info->msix_entries.names + i);
+                       snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
+                                "qat%d-bundle%d", accel_dev->accel_id, i);
+                       ret = request_irq(msixe[i].vector,
+                                         adf_msix_isr_bundle, 0, name, bank);
+                       if (ret) {
+                               dev_err(&GET_DEV(accel_dev),
+                                       "failed to enable irq %d for %s\n",
+                                       msixe[i].vector, name);
+                               return ret;
+                       }
+
+                       cpu = ((accel_dev->accel_id * hw_data->num_banks) +
+                              i) % cpus;
+                       irq_set_affinity_hint(msixe[i].vector,
+                                             get_cpu_mask(cpu));
                }
-
-               cpu = ((accel_dev->accel_id * hw_data->num_banks) + i) % cpus;
-               irq_set_affinity_hint(msixe[i].vector, get_cpu_mask(cpu));
        }
 
        /* Request msix irq for AE */
@@ -152,11 +214,13 @@ static void adf_free_irqs(struct adf_accel_dev *accel_dev)
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
        struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
        struct adf_etr_data *etr_data = accel_dev->transport;
-       int i;
+       int i = 0;
 
-       for (i = 0; i < hw_data->num_banks; i++) {
-               irq_set_affinity_hint(msixe[i].vector, NULL);
-               free_irq(msixe[i].vector, &etr_data->banks[i]);
+       if (pci_dev_info->msix_entries.num_entries > 1) {
+               for (i = 0; i < hw_data->num_banks; i++) {
+                       irq_set_affinity_hint(msixe[i].vector, NULL);
+                       free_irq(msixe[i].vector, &etr_data->banks[i]);
+               }
        }
        irq_set_affinity_hint(msixe[i].vector, NULL);
        free_irq(msixe[i].vector, accel_dev);
@@ -168,7 +232,11 @@ static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
        char **names;
        struct msix_entry *entries;
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
-       uint32_t msix_num_entries = hw_data->num_banks + 1;
+       u32 msix_num_entries = 1;
+
+       /* If SR-IOV is disabled (vf_info is NULL), add entries for each bank */
+       if (!accel_dev->pf.vf_info)
+               msix_num_entries += hw_data->num_banks;
 
        entries = kzalloc_node(msix_num_entries * sizeof(*entries),
                               GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev)));
@@ -185,6 +253,7 @@ static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
                if (!(*(names + i)))
                        goto err;
        }
+       accel_dev->accel_pci_dev.msix_entries.num_entries = msix_num_entries;
        accel_dev->accel_pci_dev.msix_entries.entries = entries;
        accel_dev->accel_pci_dev.msix_entries.names = names;
        return 0;
@@ -198,13 +267,11 @@ err:
 
 static void adf_isr_free_msix_entry_table(struct adf_accel_dev *accel_dev)
 {
-       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
-       uint32_t msix_num_entries = hw_data->num_banks + 1;
        char **names = accel_dev->accel_pci_dev.msix_entries.names;
        int i;
 
        kfree(accel_dev->accel_pci_dev.msix_entries.entries);
-       for (i = 0; i < msix_num_entries; i++)
+       for (i = 0; i < accel_dev->accel_pci_dev.msix_entries.num_entries; i++)
                kfree(*(names + i));
        kfree(names);
 }
diff --git a/drivers/crypto/qat/qat_dh895xccvf/Makefile b/drivers/crypto/qat/qat_dh895xccvf/Makefile
new file mode 100644 (file)
index 0000000..85399fc
--- /dev/null
@@ -0,0 +1,5 @@
+ccflags-y := -I$(src)/../qat_common
+obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCCVF) += qat_dh895xccvf.o
+qat_dh895xccvf-objs := adf_drv.o \
+               adf_isr.o \
+               adf_dh895xccvf_hw_data.o
diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c b/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c
new file mode 100644 (file)
index 0000000..a9a27ef
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2015 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2015 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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 <adf_accel_devices.h>
+#include <adf_pf2vf_msg.h>
+#include <adf_common_drv.h>
+#include "adf_dh895xccvf_hw_data.h"
+#include "adf_drv.h"
+
+static struct adf_hw_device_class dh895xcciov_class = {
+       .name = ADF_DH895XCCVF_DEVICE_NAME,
+       .type = DEV_DH895XCCVF,
+       .instances = 0
+};
+
+static u32 get_accel_mask(u32 fuse)
+{
+       return ADF_DH895XCCIOV_ACCELERATORS_MASK;
+}
+
+static u32 get_ae_mask(u32 fuse)
+{
+       return ADF_DH895XCCIOV_ACCELENGINES_MASK;
+}
+
+static u32 get_num_accels(struct adf_hw_device_data *self)
+{
+       return ADF_DH895XCCIOV_MAX_ACCELERATORS;
+}
+
+static u32 get_num_aes(struct adf_hw_device_data *self)
+{
+       return ADF_DH895XCCIOV_MAX_ACCELENGINES;
+}
+
+static u32 get_misc_bar_id(struct adf_hw_device_data *self)
+{
+       return ADF_DH895XCCIOV_PMISC_BAR;
+}
+
+static u32 get_etr_bar_id(struct adf_hw_device_data *self)
+{
+       return ADF_DH895XCCIOV_ETR_BAR;
+}
+
+static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
+{
+       return DEV_SKU_VF;
+}
+
+static u32 get_pf2vf_offset(u32 i)
+{
+       return ADF_DH895XCCIOV_PF2VF_OFFSET;
+}
+
+static u32 get_vintmsk_offset(u32 i)
+{
+       return ADF_DH895XCCIOV_VINTMSK_OFFSET;
+}
+
+static int adf_vf_int_noop(struct adf_accel_dev *accel_dev)
+{
+       return 0;
+}
+
+static void adf_vf_void_noop(struct adf_accel_dev *accel_dev)
+{
+}
+
+static int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
+{
+       u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
+               (ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT));
+
+       if (adf_iov_putmsg(accel_dev, msg, 0)) {
+               dev_err(&GET_DEV(accel_dev),
+                       "Failed to send Init event to PF\n");
+               return -EFAULT;
+       }
+       return 0;
+}
+
+static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
+{
+       u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
+           (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT));
+
+       if (adf_iov_putmsg(accel_dev, msg, 0))
+               dev_err(&GET_DEV(accel_dev),
+                       "Failed to send Shutdown event to PF\n");
+}
+
+void adf_init_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data)
+{
+       hw_data->dev_class = &dh895xcciov_class;
+       hw_data->instance_id = dh895xcciov_class.instances++;
+       hw_data->num_banks = ADF_DH895XCCIOV_ETR_MAX_BANKS;
+       hw_data->num_accel = ADF_DH895XCCIOV_MAX_ACCELERATORS;
+       hw_data->num_logical_accel = 1;
+       hw_data->num_engines = ADF_DH895XCCIOV_MAX_ACCELENGINES;
+       hw_data->tx_rx_gap = ADF_DH895XCCIOV_RX_RINGS_OFFSET;
+       hw_data->tx_rings_mask = ADF_DH895XCCIOV_TX_RINGS_MASK;
+       hw_data->alloc_irq = adf_vf_isr_resource_alloc;
+       hw_data->free_irq = adf_vf_isr_resource_free;
+       hw_data->enable_error_correction = adf_vf_void_noop;
+       hw_data->init_admin_comms = adf_vf_int_noop;
+       hw_data->exit_admin_comms = adf_vf_void_noop;
+       hw_data->send_admin_init = adf_vf2pf_init;
+       hw_data->init_arb = adf_vf_int_noop;
+       hw_data->exit_arb = adf_vf_void_noop;
+       hw_data->disable_iov = adf_vf2pf_shutdown;
+       hw_data->get_accel_mask = get_accel_mask;
+       hw_data->get_ae_mask = get_ae_mask;
+       hw_data->get_num_accels = get_num_accels;
+       hw_data->get_num_aes = get_num_aes;
+       hw_data->get_etr_bar_id = get_etr_bar_id;
+       hw_data->get_misc_bar_id = get_misc_bar_id;
+       hw_data->get_pf2vf_offset = get_pf2vf_offset;
+       hw_data->get_vintmsk_offset = get_vintmsk_offset;
+       hw_data->get_sku = get_sku;
+       hw_data->enable_ints = adf_vf_void_noop;
+       hw_data->enable_vf2pf_comms = adf_enable_vf2pf_comms;
+       hw_data->min_iov_compat_ver = ADF_PFVF_COMPATIBILITY_VERSION;
+}
+
+void adf_clean_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data)
+{
+       hw_data->dev_class->instances--;
+}
diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.h b/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.h
new file mode 100644 (file)
index 0000000..8f6babf
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2015 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2015 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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 ADF_DH895XVF_HW_DATA_H_
+#define ADF_DH895XVF_HW_DATA_H_
+
+#define ADF_DH895XCCIOV_PMISC_BAR 1
+#define ADF_DH895XCCIOV_ACCELERATORS_MASK 0x1
+#define ADF_DH895XCCIOV_ACCELENGINES_MASK 0x1
+#define ADF_DH895XCCIOV_MAX_ACCELERATORS 1
+#define ADF_DH895XCCIOV_MAX_ACCELENGINES 1
+#define ADF_DH895XCCIOV_RX_RINGS_OFFSET 8
+#define ADF_DH895XCCIOV_TX_RINGS_MASK 0xFF
+#define ADF_DH895XCCIOV_ETR_BAR 0
+#define ADF_DH895XCCIOV_ETR_MAX_BANKS 1
+
+#define ADF_DH895XCCIOV_PF2VF_OFFSET   0x200
+#define ADF_DH895XCC_PF2VF_PF2VFINT    BIT(0)
+
+#define ADF_DH895XCCIOV_VINTSOU_OFFSET 0x204
+#define ADF_DH895XCC_VINTSOU_BUN       BIT(0)
+#define ADF_DH895XCC_VINTSOU_PF2VF     BIT(1)
+
+#define ADF_DH895XCCIOV_VINTMSK_OFFSET 0x208
+#endif
diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
new file mode 100644 (file)
index 0000000..789426f
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include <adf_cfg.h>
+#include <adf_transport_access_macros.h>
+#include "adf_dh895xccvf_hw_data.h"
+#include "adf_drv.h"
+
+static const char adf_driver_name[] = ADF_DH895XCCVF_DEVICE_NAME;
+
+#define ADF_SYSTEM_DEVICE(device_id) \
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+
+static const struct pci_device_id adf_pci_tbl[] = {
+       ADF_SYSTEM_DEVICE(ADF_DH895XCCIOV_PCI_DEVICE_ID),
+       {0,}
+};
+MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
+
+static int adf_probe(struct pci_dev *dev, const struct pci_device_id *ent);
+static void adf_remove(struct pci_dev *dev);
+
+static struct pci_driver adf_driver = {
+       .id_table = adf_pci_tbl,
+       .name = adf_driver_name,
+       .probe = adf_probe,
+       .remove = adf_remove,
+};
+
+static void adf_cleanup_pci_dev(struct adf_accel_dev *accel_dev)
+{
+       pci_release_regions(accel_dev->accel_pci_dev.pci_dev);
+       pci_disable_device(accel_dev->accel_pci_dev.pci_dev);
+}
+
+static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
+{
+       struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev;
+       struct adf_accel_dev *pf;
+       int i;
+
+       for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
+               struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
+
+               if (bar->virt_addr)
+                       pci_iounmap(accel_pci_dev->pci_dev, bar->virt_addr);
+       }
+
+       if (accel_dev->hw_device) {
+               switch (accel_pci_dev->pci_dev->device) {
+               case ADF_DH895XCCIOV_PCI_DEVICE_ID:
+                       adf_clean_hw_data_dh895xcciov(accel_dev->hw_device);
+                       break;
+               default:
+                       break;
+               }
+               kfree(accel_dev->hw_device);
+               accel_dev->hw_device = NULL;
+       }
+       adf_cfg_dev_remove(accel_dev);
+       debugfs_remove(accel_dev->debugfs_dir);
+       pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn);
+       adf_devmgr_rm_dev(accel_dev, pf);
+}
+
+static int adf_dev_configure(struct adf_accel_dev *accel_dev)
+{
+       char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+       unsigned long val, bank = 0;
+
+       if (adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC))
+               goto err;
+       if (adf_cfg_section_add(accel_dev, "Accelerator0"))
+               goto err;
+
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, key,
+                                       (void *)&bank, ADF_DEC))
+               goto err;
+
+       val = bank;
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, key,
+                                       (void *)&val, ADF_DEC))
+               goto err;
+
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_SIZE, 0);
+
+       val = 128;
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC, key,
+                                       (void *)&val, ADF_DEC))
+               goto err;
+
+       val = 512;
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_SIZE, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       key, (void *)&val, ADF_DEC))
+               goto err;
+
+       val = 0;
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_TX, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       key, (void *)&val, ADF_DEC))
+               goto err;
+
+       val = 2;
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_TX, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       key, (void *)&val, ADF_DEC))
+               goto err;
+
+       val = 8;
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       key, (void *)&val, ADF_DEC))
+               goto err;
+
+       val = 10;
+       snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_RX, 0);
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       key, (void *)&val, ADF_DEC))
+                       goto err;
+
+       val = ADF_COALESCING_DEF_TIME;
+       snprintf(key, sizeof(key), ADF_ETRMGR_COALESCE_TIMER_FORMAT,
+                (int)bank);
+       if (adf_cfg_add_key_value_param(accel_dev, "Accelerator0",
+                                       key, (void *)&val, ADF_DEC))
+               goto err;
+
+       val = 1;
+       if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+                                       ADF_NUM_CY, (void *)&val, ADF_DEC))
+               goto err;
+
+       set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+       return 0;
+err:
+       dev_err(&GET_DEV(accel_dev), "Failed to configure QAT accel dev\n");
+       return -EINVAL;
+}
+
+static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct adf_accel_dev *accel_dev;
+       struct adf_accel_dev *pf;
+       struct adf_accel_pci *accel_pci_dev;
+       struct adf_hw_device_data *hw_data;
+       char name[ADF_DEVICE_NAME_LENGTH];
+       unsigned int i, bar_nr;
+       int ret, bar_mask;
+
+       switch (ent->device) {
+       case ADF_DH895XCCIOV_PCI_DEVICE_ID:
+               break;
+       default:
+               dev_err(&pdev->dev, "Invalid device 0x%x.\n", ent->device);
+               return -ENODEV;
+       }
+
+       accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL,
+                                dev_to_node(&pdev->dev));
+       if (!accel_dev)
+               return -ENOMEM;
+
+       accel_dev->is_vf = true;
+       pf = adf_devmgr_pci_to_accel_dev(pdev->physfn);
+       accel_pci_dev = &accel_dev->accel_pci_dev;
+       accel_pci_dev->pci_dev = pdev;
+
+       /* Add accel device to accel table */
+       if (adf_devmgr_add_dev(accel_dev, pf)) {
+               dev_err(&pdev->dev, "Failed to add new accelerator device.\n");
+               kfree(accel_dev);
+               return -EFAULT;
+       }
+       INIT_LIST_HEAD(&accel_dev->crypto_list);
+
+       accel_dev->owner = THIS_MODULE;
+       /* Allocate and configure device configuration structure */
+       hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL,
+                              dev_to_node(&pdev->dev));
+       if (!hw_data) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+       accel_dev->hw_device = hw_data;
+       switch (ent->device) {
+       case ADF_DH895XCCIOV_PCI_DEVICE_ID:
+               adf_init_hw_data_dh895xcciov(accel_dev->hw_device);
+               break;
+       default:
+               ret = -ENODEV;
+               goto out_err;
+       }
+
+       /* Get Accelerators and Accelerators Engines masks */
+       hw_data->accel_mask = hw_data->get_accel_mask(hw_data->fuses);
+       hw_data->ae_mask = hw_data->get_ae_mask(hw_data->fuses);
+       accel_pci_dev->sku = hw_data->get_sku(hw_data);
+
+       /* Create dev top level debugfs entry */
+       snprintf(name, sizeof(name), "%s%s_%02x:%02d.%02d",
+                ADF_DEVICE_NAME_PREFIX, hw_data->dev_class->name,
+                pdev->bus->number, PCI_SLOT(pdev->devfn),
+                PCI_FUNC(pdev->devfn));
+
+       accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
+       if (!accel_dev->debugfs_dir) {
+               dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
+               ret = -EINVAL;
+               goto out_err;
+       }
+
+       /* Create device configuration table */
+       ret = adf_cfg_dev_add(accel_dev);
+       if (ret)
+               goto out_err;
+
+       /* enable PCI device */
+       if (pci_enable_device(pdev)) {
+               ret = -EFAULT;
+               goto out_err;
+       }
+
+       /* set dma identifier */
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+               if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
+                       dev_err(&pdev->dev, "No usable DMA configuration\n");
+                       ret = -EFAULT;
+                       goto out_err_disable;
+               } else {
+                       pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+               }
+
+       } else {
+               pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+       }
+
+       if (pci_request_regions(pdev, adf_driver_name)) {
+               ret = -EFAULT;
+               goto out_err_disable;
+       }
+
+       /* Find and map all the device's BARS */
+       i = 0;
+       bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
+       for_each_set_bit(bar_nr, (const unsigned long *)&bar_mask,
+                        ADF_PCI_MAX_BARS * 2) {
+               struct adf_bar *bar = &accel_pci_dev->pci_bars[i++];
+
+               bar->base_addr = pci_resource_start(pdev, bar_nr);
+               if (!bar->base_addr)
+                       break;
+               bar->size = pci_resource_len(pdev, bar_nr);
+               bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0);
+               if (!bar->virt_addr) {
+                       dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr);
+                       ret = -EFAULT;
+                       goto out_err_free_reg;
+               }
+       }
+       pci_set_master(pdev);
+       /* Completion for VF2PF request/response message exchange */
+       init_completion(&accel_dev->vf.iov_msg_completion);
+
+       ret = adf_dev_configure(accel_dev);
+       if (ret)
+               goto out_err_free_reg;
+
+       ret = adf_dev_init(accel_dev);
+       if (ret)
+               goto out_err_dev_shutdown;
+
+       ret = adf_dev_start(accel_dev);
+       if (ret)
+               goto out_err_dev_stop;
+
+       return ret;
+
+out_err_dev_stop:
+       adf_dev_stop(accel_dev);
+out_err_dev_shutdown:
+       adf_dev_shutdown(accel_dev);
+out_err_free_reg:
+       pci_release_regions(accel_pci_dev->pci_dev);
+out_err_disable:
+       pci_disable_device(accel_pci_dev->pci_dev);
+out_err:
+       adf_cleanup_accel(accel_dev);
+       kfree(accel_dev);
+       return ret;
+}
+
+static void adf_remove(struct pci_dev *pdev)
+{
+       struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+       if (!accel_dev) {
+               pr_err("QAT: Driver removal failed\n");
+               return;
+       }
+       if (adf_dev_stop(accel_dev))
+               dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
+
+       adf_dev_shutdown(accel_dev);
+       adf_cleanup_accel(accel_dev);
+       adf_cleanup_pci_dev(accel_dev);
+       kfree(accel_dev);
+}
+
+static int __init adfdrv_init(void)
+{
+       request_module("intel_qat");
+
+       if (pci_register_driver(&adf_driver)) {
+               pr_err("QAT: Driver initialization failed\n");
+               return -EFAULT;
+       }
+       return 0;
+}
+
+static void __exit adfdrv_release(void)
+{
+       pci_unregister_driver(&adf_driver);
+       adf_clean_vf_map(true);
+}
+
+module_init(adfdrv_init);
+module_exit(adfdrv_release);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Intel");
+MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
+MODULE_VERSION(ADF_DRV_VERSION);
similarity index 61%
rename from drivers/crypto/qat/qat_dh895xcc/qat_admin.c
rename to drivers/crypto/qat/qat_dh895xccvf/adf_drv.h
index 55b7a8e48bada2305f38f68877741f04bf377c9c..e270e4a63d1428c388b732c1c9142dda890b016d 100644 (file)
   (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 <icp_qat_fw_init_admin.h>
+#ifndef ADF_DH895xVF_DRV_H_
+#define ADF_DH895xVF_DRV_H_
 #include <adf_accel_devices.h>
-#include <adf_common_drv.h>
-#include "adf_drv.h"
-
-static struct service_hndl qat_admin;
-
-static int qat_send_admin_cmd(struct adf_accel_dev *accel_dev, int cmd)
-{
-       struct adf_hw_device_data *hw_device = accel_dev->hw_device;
-       struct icp_qat_fw_init_admin_req req;
-       struct icp_qat_fw_init_admin_resp resp;
-       int i;
-
-       memset(&req, 0, sizeof(struct icp_qat_fw_init_admin_req));
-       req.init_admin_cmd_id = cmd;
-       for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
-               memset(&resp, 0, sizeof(struct icp_qat_fw_init_admin_resp));
-               if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) ||
-                   resp.init_resp_hdr.status)
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-static int qat_admin_start(struct adf_accel_dev *accel_dev)
-{
-       return qat_send_admin_cmd(accel_dev, ICP_QAT_FW_INIT_ME);
-}
-
-static int qat_admin_event_handler(struct adf_accel_dev *accel_dev,
-                                  enum adf_event event)
-{
-       int ret;
-
-       switch (event) {
-       case ADF_EVENT_START:
-               ret = qat_admin_start(accel_dev);
-               break;
-       case ADF_EVENT_STOP:
-       case ADF_EVENT_INIT:
-       case ADF_EVENT_SHUTDOWN:
-       default:
-               ret = 0;
-       }
-       return ret;
-}
-
-int qat_admin_register(void)
-{
-       memset(&qat_admin, 0, sizeof(struct service_hndl));
-       qat_admin.event_hld = qat_admin_event_handler;
-       qat_admin.name = "qat_admin";
-       qat_admin.admin = 1;
-       return adf_service_register(&qat_admin);
-}
-
-int qat_admin_unregister(void)
-{
-       return adf_service_unregister(&qat_admin);
-}
+#include <adf_transport.h>
+
+void adf_init_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data);
+void adf_clean_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data);
+int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev);
+void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev);
+void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring);
+#endif
diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_isr.c b/drivers/crypto/qat/qat_dh895xccvf/adf_isr.c
new file mode 100644 (file)
index 0000000..87c5d8a
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2014 Intel Corporation.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of version 2 of the GNU General Public License 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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2014 Intel Corporation.
+  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 Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "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 COPYRIGHT
+  OWNER 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/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include <adf_cfg.h>
+#include <adf_cfg_strings.h>
+#include <adf_cfg_common.h>
+#include <adf_transport_access_macros.h>
+#include <adf_transport_internal.h>
+#include <adf_pf2vf_msg.h>
+#include "adf_drv.h"
+#include "adf_dh895xccvf_hw_data.h"
+
+static int adf_enable_msi(struct adf_accel_dev *accel_dev)
+{
+       struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+       int stat = pci_enable_msi(pci_dev_info->pci_dev);
+
+       if (stat) {
+               dev_err(&GET_DEV(accel_dev),
+                       "Failed to enable MSI interrupts\n");
+               return stat;
+       }
+
+       accel_dev->vf.irq_name = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
+       if (!accel_dev->vf.irq_name)
+               return -ENOMEM;
+
+       return stat;
+}
+
+static void adf_disable_msi(struct adf_accel_dev *accel_dev)
+{
+       struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+       kfree(accel_dev->vf.irq_name);
+       pci_disable_msi(pdev);
+}
+
+static void adf_pf2vf_bh_handler(void *data)
+{
+       struct adf_accel_dev *accel_dev = data;
+       void __iomem *pmisc_bar_addr =
+               (&GET_BARS(accel_dev)[ADF_DH895XCCIOV_PMISC_BAR])->virt_addr;
+       u32 msg;
+
+       /* Read the message from PF */
+       msg = ADF_CSR_RD(pmisc_bar_addr, ADF_DH895XCCIOV_PF2VF_OFFSET);
+
+       if (!(msg & ADF_PF2VF_MSGORIGIN_SYSTEM))
+               /* Ignore legacy non-system (non-kernel) PF2VF messages */
+               goto err;
+
+       switch ((msg & ADF_PF2VF_MSGTYPE_MASK) >> ADF_PF2VF_MSGTYPE_SHIFT) {
+       case ADF_PF2VF_MSGTYPE_RESTARTING:
+               dev_dbg(&GET_DEV(accel_dev),
+                       "Restarting msg received from PF 0x%x\n", msg);
+               adf_dev_stop(accel_dev);
+               break;
+       case ADF_PF2VF_MSGTYPE_VERSION_RESP:
+               dev_dbg(&GET_DEV(accel_dev),
+                       "Version resp received from PF 0x%x\n", msg);
+               accel_dev->vf.pf_version =
+                       (msg & ADF_PF2VF_VERSION_RESP_VERS_MASK) >>
+                       ADF_PF2VF_VERSION_RESP_VERS_SHIFT;
+               accel_dev->vf.compatible =
+                       (msg & ADF_PF2VF_VERSION_RESP_RESULT_MASK) >>
+                       ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
+               complete(&accel_dev->vf.iov_msg_completion);
+               break;
+       default:
+               goto err;
+       }
+
+       /* To ack, clear the PF2VFINT bit */
+       msg &= ~ADF_DH895XCC_PF2VF_PF2VFINT;
+       ADF_CSR_WR(pmisc_bar_addr, ADF_DH895XCCIOV_PF2VF_OFFSET, msg);
+
+       /* Re-enable PF2VF interrupts */
+       adf_enable_pf2vf_interrupts(accel_dev);
+       return;
+err:
+       dev_err(&GET_DEV(accel_dev),
+               "Unknown message from PF (0x%x); leaving PF2VF ints disabled\n",
+               msg);
+}
+
+static int adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev)
+{
+       tasklet_init(&accel_dev->vf.pf2vf_bh_tasklet,
+                    (void *)adf_pf2vf_bh_handler, (unsigned long)accel_dev);
+
+       mutex_init(&accel_dev->vf.vf2pf_lock);
+       return 0;
+}
+
+static void adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev)
+{
+       tasklet_disable(&accel_dev->vf.pf2vf_bh_tasklet);
+       tasklet_kill(&accel_dev->vf.pf2vf_bh_tasklet);
+       mutex_destroy(&accel_dev->vf.vf2pf_lock);
+}
+
+static irqreturn_t adf_isr(int irq, void *privdata)
+{
+       struct adf_accel_dev *accel_dev = privdata;
+       void __iomem *pmisc_bar_addr =
+               (&GET_BARS(accel_dev)[ADF_DH895XCCIOV_PMISC_BAR])->virt_addr;
+       u32 v_int;
+
+       /* Read VF INT source CSR to determine the source of VF interrupt */
+       v_int = ADF_CSR_RD(pmisc_bar_addr, ADF_DH895XCCIOV_VINTSOU_OFFSET);
+
+       /* Check for PF2VF interrupt */
+       if (v_int & ADF_DH895XCC_VINTSOU_PF2VF) {
+               /* Disable PF to VF interrupt */
+               adf_disable_pf2vf_interrupts(accel_dev);
+
+               /* Schedule tasklet to handle interrupt BH */
+               tasklet_hi_schedule(&accel_dev->vf.pf2vf_bh_tasklet);
+               return IRQ_HANDLED;
+       }
+
+       /* Check bundle interrupt */
+       if (v_int & ADF_DH895XCC_VINTSOU_BUN) {
+               struct adf_etr_data *etr_data = accel_dev->transport;
+               struct adf_etr_bank_data *bank = &etr_data->banks[0];
+
+               /* Disable Flag and Coalesce Ring Interrupts */
+               WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number,
+                                          0);
+               tasklet_hi_schedule(&bank->resp_handler);
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
+static int adf_request_msi_irq(struct adf_accel_dev *accel_dev)
+{
+       struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+       unsigned int cpu;
+       int ret;
+
+       snprintf(accel_dev->vf.irq_name, ADF_MAX_MSIX_VECTOR_NAME,
+                "qat_%02x:%02d.%02d", pdev->bus->number, PCI_SLOT(pdev->devfn),
+                PCI_FUNC(pdev->devfn));
+       ret = request_irq(pdev->irq, adf_isr, 0, accel_dev->vf.irq_name,
+                         (void *)accel_dev);
+       if (ret) {
+               dev_err(&GET_DEV(accel_dev), "failed to enable irq for %s\n",
+                       accel_dev->vf.irq_name);
+               return ret;
+       }
+       cpu = accel_dev->accel_id % num_online_cpus();
+       irq_set_affinity_hint(pdev->irq, get_cpu_mask(cpu));
+
+       return ret;
+}
+
+static int adf_setup_bh(struct adf_accel_dev *accel_dev)
+{
+       struct adf_etr_data *priv_data = accel_dev->transport;
+
+       tasklet_init(&priv_data->banks[0].resp_handler, adf_response_handler,
+                    (unsigned long)priv_data->banks);
+       return 0;
+}
+
+static void adf_cleanup_bh(struct adf_accel_dev *accel_dev)
+{
+       struct adf_etr_data *priv_data = accel_dev->transport;
+
+       tasklet_disable(&priv_data->banks[0].resp_handler);
+       tasklet_kill(&priv_data->banks[0].resp_handler);
+}
+
+void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev)
+{
+       struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+       irq_set_affinity_hint(pdev->irq, NULL);
+       free_irq(pdev->irq, (void *)accel_dev);
+       adf_cleanup_bh(accel_dev);
+       adf_cleanup_pf2vf_bh(accel_dev);
+       adf_disable_msi(accel_dev);
+}
+
+int adf_vf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
+{
+       if (adf_enable_msi(accel_dev))
+               goto err_out;
+
+       if (adf_setup_pf2vf_bh(accel_dev))
+               goto err_out;
+
+       if (adf_setup_bh(accel_dev))
+               goto err_out;
+
+       if (adf_request_msi_irq(accel_dev))
+               goto err_out;
+
+       return 0;
+err_out:
+       adf_vf_isr_resource_free(accel_dev);
+       return -EFAULT;
+}
index 397a500b3d8a9edbaf214ae28a8cc88e64582eb0..1c19e44c3146ffbc1d69179c2440f6e26c1aa6ea 100644 (file)
@@ -1516,7 +1516,7 @@ static int sahara_probe(struct platform_device *pdev)
        }
 
        /* Allocate HW descriptors */
-       dev->hw_desc[0] = dma_alloc_coherent(&pdev->dev,
+       dev->hw_desc[0] = dmam_alloc_coherent(&pdev->dev,
                        SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc),
                        &dev->hw_phys_desc[0], GFP_KERNEL);
        if (!dev->hw_desc[0]) {
@@ -1528,34 +1528,31 @@ static int sahara_probe(struct platform_device *pdev)
                                sizeof(struct sahara_hw_desc);
 
        /* Allocate space for iv and key */
-       dev->key_base = dma_alloc_coherent(&pdev->dev, 2 * AES_KEYSIZE_128,
+       dev->key_base = dmam_alloc_coherent(&pdev->dev, 2 * AES_KEYSIZE_128,
                                &dev->key_phys_base, GFP_KERNEL);
        if (!dev->key_base) {
                dev_err(&pdev->dev, "Could not allocate memory for key\n");
-               err = -ENOMEM;
-               goto err_key;
+               return -ENOMEM;
        }
        dev->iv_base = dev->key_base + AES_KEYSIZE_128;
        dev->iv_phys_base = dev->key_phys_base + AES_KEYSIZE_128;
 
        /* Allocate space for context: largest digest + message length field */
-       dev->context_base = dma_alloc_coherent(&pdev->dev,
+       dev->context_base = dmam_alloc_coherent(&pdev->dev,
                                        SHA256_DIGEST_SIZE + 4,
                                        &dev->context_phys_base, GFP_KERNEL);
        if (!dev->context_base) {
                dev_err(&pdev->dev, "Could not allocate memory for MDHA context\n");
-               err = -ENOMEM;
-               goto err_key;
+               return -ENOMEM;
        }
 
        /* Allocate space for HW links */
-       dev->hw_link[0] = dma_alloc_coherent(&pdev->dev,
+       dev->hw_link[0] = dmam_alloc_coherent(&pdev->dev,
                        SAHARA_MAX_HW_LINK * sizeof(struct sahara_hw_link),
                        &dev->hw_phys_link[0], GFP_KERNEL);
        if (!dev->hw_link[0]) {
                dev_err(&pdev->dev, "Could not allocate hw links\n");
-               err = -ENOMEM;
-               goto err_link;
+               return -ENOMEM;
        }
        for (i = 1; i < SAHARA_MAX_HW_LINK; i++) {
                dev->hw_phys_link[i] = dev->hw_phys_link[i - 1] +
@@ -1572,15 +1569,14 @@ static int sahara_probe(struct platform_device *pdev)
 
        dev->kthread = kthread_run(sahara_queue_manage, dev, "sahara_crypto");
        if (IS_ERR(dev->kthread)) {
-               err = PTR_ERR(dev->kthread);
-               goto err_link;
+               return PTR_ERR(dev->kthread);
        }
 
        init_completion(&dev->dma_completion);
 
        err = clk_prepare_enable(dev->clk_ipg);
        if (err)
-               goto err_link;
+               return err;
        err = clk_prepare_enable(dev->clk_ahb);
        if (err)
                goto clk_ipg_disable;
@@ -1620,25 +1616,11 @@ static int sahara_probe(struct platform_device *pdev)
        return 0;
 
 err_algs:
-       dma_free_coherent(&pdev->dev,
-                         SAHARA_MAX_HW_LINK * sizeof(struct sahara_hw_link),
-                         dev->hw_link[0], dev->hw_phys_link[0]);
        kthread_stop(dev->kthread);
        dev_ptr = NULL;
        clk_disable_unprepare(dev->clk_ahb);
 clk_ipg_disable:
        clk_disable_unprepare(dev->clk_ipg);
-err_link:
-       dma_free_coherent(&pdev->dev,
-                         2 * AES_KEYSIZE_128,
-                         dev->key_base, dev->key_phys_base);
-       dma_free_coherent(&pdev->dev,
-                         SHA256_DIGEST_SIZE,
-                         dev->context_base, dev->context_phys_base);
-err_key:
-       dma_free_coherent(&pdev->dev,
-                         SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc),
-                         dev->hw_desc[0], dev->hw_phys_desc[0]);
 
        return err;
 }
@@ -1647,16 +1629,6 @@ static int sahara_remove(struct platform_device *pdev)
 {
        struct sahara_dev *dev = platform_get_drvdata(pdev);
 
-       dma_free_coherent(&pdev->dev,
-                         SAHARA_MAX_HW_LINK * sizeof(struct sahara_hw_link),
-                         dev->hw_link[0], dev->hw_phys_link[0]);
-       dma_free_coherent(&pdev->dev,
-                         2 * AES_KEYSIZE_128,
-                         dev->key_base, dev->key_phys_base);
-       dma_free_coherent(&pdev->dev,
-                         SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc),
-                         dev->hw_desc[0], dev->hw_phys_desc[0]);
-
        kthread_stop(dev->kthread);
 
        sahara_unregister_algs(dev);
diff --git a/drivers/crypto/sunxi-ss/Makefile b/drivers/crypto/sunxi-ss/Makefile
new file mode 100644 (file)
index 0000000..8f4c7a2
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o
+sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
new file mode 100644 (file)
index 0000000..e070c31
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * sun4i-ss-cipher.c - hardware cryptographic accelerator for Allwinner A20 SoC
+ *
+ * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
+ *
+ * This file add support for AES cipher with 128,192,256 bits
+ * keysize in CBC and ECB mode.
+ * Add support also for DES and 3DES in CBC and ECB mode.
+ *
+ * You could find the datasheet in Documentation/arm/sunxi/README
+ *
+ * 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 "sun4i-ss.h"
+
+static int sun4i_ss_opti_poll(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_ss_ctx *ss = op->ss;
+       unsigned int ivsize = crypto_ablkcipher_ivsize(tfm);
+       struct sun4i_cipher_req_ctx *ctx = ablkcipher_request_ctx(areq);
+       u32 mode = ctx->mode;
+       /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
+       u32 rx_cnt = SS_RX_DEFAULT;
+       u32 tx_cnt = 0;
+       u32 spaces;
+       u32 v;
+       int i, err = 0;
+       unsigned int ileft = areq->nbytes;
+       unsigned int oleft = areq->nbytes;
+       unsigned int todo;
+       struct sg_mapping_iter mi, mo;
+       unsigned int oi, oo; /* offset for in and out */
+
+       if (areq->nbytes == 0)
+               return 0;
+
+       if (!areq->info) {
+               dev_err_ratelimited(ss->dev, "ERROR: Empty IV\n");
+               return -EINVAL;
+       }
+
+       if (!areq->src || !areq->dst) {
+               dev_err_ratelimited(ss->dev, "ERROR: Some SGs are NULL\n");
+               return -EINVAL;
+       }
+
+       spin_lock_bh(&ss->slock);
+
+       for (i = 0; i < op->keylen; i += 4)
+               writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
+
+       if (areq->info) {
+               for (i = 0; i < 4 && i < ivsize / 4; i++) {
+                       v = *(u32 *)(areq->info + i * 4);
+                       writel(v, ss->base + SS_IV0 + i * 4);
+               }
+       }
+       writel(mode, ss->base + SS_CTL);
+
+       sg_miter_start(&mi, areq->src, sg_nents(areq->src),
+                      SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+       sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
+                      SG_MITER_TO_SG | SG_MITER_ATOMIC);
+       sg_miter_next(&mi);
+       sg_miter_next(&mo);
+       if (!mi.addr || !mo.addr) {
+               dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
+               err = -EINVAL;
+               goto release_ss;
+       }
+
+       ileft = areq->nbytes / 4;
+       oleft = areq->nbytes / 4;
+       oi = 0;
+       oo = 0;
+       do {
+               todo = min3(rx_cnt, ileft, (mi.length - oi) / 4);
+               if (todo > 0) {
+                       ileft -= todo;
+                       writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo);
+                       oi += todo * 4;
+               }
+               if (oi == mi.length) {
+                       sg_miter_next(&mi);
+                       oi = 0;
+               }
+
+               spaces = readl(ss->base + SS_FCSR);
+               rx_cnt = SS_RXFIFO_SPACES(spaces);
+               tx_cnt = SS_TXFIFO_SPACES(spaces);
+
+               todo = min3(tx_cnt, oleft, (mo.length - oo) / 4);
+               if (todo > 0) {
+                       oleft -= todo;
+                       readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo);
+                       oo += todo * 4;
+               }
+               if (oo == mo.length) {
+                       sg_miter_next(&mo);
+                       oo = 0;
+               }
+       } while (mo.length > 0);
+
+       if (areq->info) {
+               for (i = 0; i < 4 && i < ivsize / 4; i++) {
+                       v = readl(ss->base + SS_IV0 + i * 4);
+                       *(u32 *)(areq->info + i * 4) = v;
+               }
+       }
+
+release_ss:
+       sg_miter_stop(&mi);
+       sg_miter_stop(&mo);
+       writel(0, ss->base + SS_CTL);
+       spin_unlock_bh(&ss->slock);
+       return err;
+}
+
+/* Generic function that support SG with size not multiple of 4 */
+static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_ss_ctx *ss = op->ss;
+       int no_chunk = 1;
+       struct scatterlist *in_sg = areq->src;
+       struct scatterlist *out_sg = areq->dst;
+       unsigned int ivsize = crypto_ablkcipher_ivsize(tfm);
+       struct sun4i_cipher_req_ctx *ctx = ablkcipher_request_ctx(areq);
+       u32 mode = ctx->mode;
+       /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
+       u32 rx_cnt = SS_RX_DEFAULT;
+       u32 tx_cnt = 0;
+       u32 v;
+       u32 spaces;
+       int i, err = 0;
+       unsigned int ileft = areq->nbytes;
+       unsigned int oleft = areq->nbytes;
+       unsigned int todo;
+       struct sg_mapping_iter mi, mo;
+       unsigned int oi, oo;    /* offset for in and out */
+       char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */
+       char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */
+       unsigned int ob = 0;    /* offset in buf */
+       unsigned int obo = 0;   /* offset in bufo*/
+       unsigned int obl = 0;   /* length of data in bufo */
+
+       if (areq->nbytes == 0)
+               return 0;
+
+       if (!areq->info) {
+               dev_err_ratelimited(ss->dev, "ERROR: Empty IV\n");
+               return -EINVAL;
+       }
+
+       if (!areq->src || !areq->dst) {
+               dev_err_ratelimited(ss->dev, "ERROR: Some SGs are NULL\n");
+               return -EINVAL;
+       }
+
+       /*
+        * if we have only SGs with size multiple of 4,
+        * we can use the SS optimized function
+        */
+       while (in_sg && no_chunk == 1) {
+               if ((in_sg->length % 4) != 0)
+                       no_chunk = 0;
+               in_sg = sg_next(in_sg);
+       }
+       while (out_sg && no_chunk == 1) {
+               if ((out_sg->length % 4) != 0)
+                       no_chunk = 0;
+               out_sg = sg_next(out_sg);
+       }
+
+       if (no_chunk == 1)
+               return sun4i_ss_opti_poll(areq);
+
+       spin_lock_bh(&ss->slock);
+
+       for (i = 0; i < op->keylen; i += 4)
+               writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
+
+       if (areq->info) {
+               for (i = 0; i < 4 && i < ivsize / 4; i++) {
+                       v = *(u32 *)(areq->info + i * 4);
+                       writel(v, ss->base + SS_IV0 + i * 4);
+               }
+       }
+       writel(mode, ss->base + SS_CTL);
+
+       sg_miter_start(&mi, areq->src, sg_nents(areq->src),
+                      SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+       sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
+                      SG_MITER_TO_SG | SG_MITER_ATOMIC);
+       sg_miter_next(&mi);
+       sg_miter_next(&mo);
+       if (!mi.addr || !mo.addr) {
+               dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
+               err = -EINVAL;
+               goto release_ss;
+       }
+       ileft = areq->nbytes;
+       oleft = areq->nbytes;
+       oi = 0;
+       oo = 0;
+
+       while (oleft > 0) {
+               if (ileft > 0) {
+                       /*
+                        * todo is the number of consecutive 4byte word that we
+                        * can read from current SG
+                        */
+                       todo = min3(rx_cnt, ileft / 4, (mi.length - oi) / 4);
+                       if (todo > 0 && ob == 0) {
+                               writesl(ss->base + SS_RXFIFO, mi.addr + oi,
+                                       todo);
+                               ileft -= todo * 4;
+                               oi += todo * 4;
+                       } else {
+                               /*
+                                * not enough consecutive bytes, so we need to
+                                * linearize in buf. todo is in bytes
+                                * After that copy, if we have a multiple of 4
+                                * we need to be able to write all buf in one
+                                * pass, so it is why we min() with rx_cnt
+                                */
+                               todo = min3(rx_cnt * 4 - ob, ileft,
+                                           mi.length - oi);
+                               memcpy(buf + ob, mi.addr + oi, todo);
+                               ileft -= todo;
+                               oi += todo;
+                               ob += todo;
+                               if (ob % 4 == 0) {
+                                       writesl(ss->base + SS_RXFIFO, buf,
+                                               ob / 4);
+                                       ob = 0;
+                               }
+                       }
+                       if (oi == mi.length) {
+                               sg_miter_next(&mi);
+                               oi = 0;
+                       }
+               }
+
+               spaces = readl(ss->base + SS_FCSR);
+               rx_cnt = SS_RXFIFO_SPACES(spaces);
+               tx_cnt = SS_TXFIFO_SPACES(spaces);
+               dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u %u\n",
+                       mode,
+                       oi, mi.length, ileft, areq->nbytes, rx_cnt,
+                       oo, mo.length, oleft, areq->nbytes, tx_cnt,
+                       todo, ob);
+
+               if (tx_cnt == 0)
+                       continue;
+               /* todo in 4bytes word */
+               todo = min3(tx_cnt, oleft / 4, (mo.length - oo) / 4);
+               if (todo > 0) {
+                       readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo);
+                       oleft -= todo * 4;
+                       oo += todo * 4;
+                       if (oo == mo.length) {
+                               sg_miter_next(&mo);
+                               oo = 0;
+                       }
+               } else {
+                       /*
+                        * read obl bytes in bufo, we read at maximum for
+                        * emptying the device
+                        */
+                       readsl(ss->base + SS_TXFIFO, bufo, tx_cnt);
+                       obl = tx_cnt * 4;
+                       obo = 0;
+                       do {
+                               /*
+                                * how many bytes we can copy ?
+                                * no more than remaining SG size
+                                * no more than remaining buffer
+                                * no need to test against oleft
+                                */
+                               todo = min(mo.length - oo, obl - obo);
+                               memcpy(mo.addr + oo, bufo + obo, todo);
+                               oleft -= todo;
+                               obo += todo;
+                               oo += todo;
+                               if (oo == mo.length) {
+                                       sg_miter_next(&mo);
+                                       oo = 0;
+                               }
+                       } while (obo < obl);
+                       /* bufo must be fully used here */
+               }
+       }
+       if (areq->info) {
+               for (i = 0; i < 4 && i < ivsize / 4; i++) {
+                       v = readl(ss->base + SS_IV0 + i * 4);
+                       *(u32 *)(areq->info + i * 4) = v;
+               }
+       }
+
+release_ss:
+       sg_miter_stop(&mi);
+       sg_miter_stop(&mo);
+       writel(0, ss->base + SS_CTL);
+       spin_unlock_bh(&ss->slock);
+
+       return err;
+}
+
+/* CBC AES */
+int sun4i_ss_cbc_aes_encrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_ENCRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_cbc_aes_decrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_DECRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+/* ECB AES */
+int sun4i_ss_ecb_aes_encrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_ENCRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_ecb_aes_decrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_DECRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+/* CBC DES */
+int sun4i_ss_cbc_des_encrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_cbc_des_decrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_DECRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+/* ECB DES */
+int sun4i_ss_ecb_des_encrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_ecb_des_decrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_DECRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+/* CBC 3DES */
+int sun4i_ss_cbc_des3_encrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_cbc_des3_decrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_DECRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+/* ECB 3DES */
+int sun4i_ss_ecb_des3_encrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_ecb_des3_decrypt(struct ablkcipher_request *areq)
+{
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq);
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq);
+
+       rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_DECRYPTION |
+               op->keymode;
+       return sun4i_ss_cipher_poll(areq);
+}
+
+int sun4i_ss_cipher_init(struct crypto_tfm *tfm)
+{
+       struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm);
+       struct crypto_alg *alg = tfm->__crt_alg;
+       struct sun4i_ss_alg_template *algt;
+
+       memset(op, 0, sizeof(struct sun4i_tfm_ctx));
+
+       algt = container_of(alg, struct sun4i_ss_alg_template, alg.crypto);
+       op->ss = algt->ss;
+
+       tfm->crt_ablkcipher.reqsize = sizeof(struct sun4i_cipher_req_ctx);
+
+       return 0;
+}
+
+/* check and set the AES key, prepare the mode to be used */
+int sun4i_ss_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                       unsigned int keylen)
+{
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_ss_ctx *ss = op->ss;
+
+       switch (keylen) {
+       case 128 / 8:
+               op->keymode = SS_AES_128BITS;
+               break;
+       case 192 / 8:
+               op->keymode = SS_AES_192BITS;
+               break;
+       case 256 / 8:
+               op->keymode = SS_AES_256BITS;
+               break;
+       default:
+               dev_err(ss->dev, "ERROR: Invalid keylen %u\n", keylen);
+               crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+       op->keylen = keylen;
+       memcpy(op->key, key, keylen);
+       return 0;
+}
+
+/* check and set the DES key, prepare the mode to be used */
+int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                       unsigned int keylen)
+{
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_ss_ctx *ss = op->ss;
+       u32 flags;
+       u32 tmp[DES_EXPKEY_WORDS];
+       int ret;
+
+       if (unlikely(keylen != DES_KEY_SIZE)) {
+               dev_err(ss->dev, "Invalid keylen %u\n", keylen);
+               crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+
+       flags = crypto_ablkcipher_get_flags(tfm);
+
+       ret = des_ekey(tmp, key);
+       if (unlikely(ret == 0) && (flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+               crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY);
+               dev_dbg(ss->dev, "Weak key %u\n", keylen);
+               return -EINVAL;
+       }
+
+       op->keylen = keylen;
+       memcpy(op->key, key, keylen);
+       return 0;
+}
+
+/* check and set the 3DES key, prepare the mode to be used */
+int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                        unsigned int keylen)
+{
+       struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm);
+       struct sun4i_ss_ctx *ss = op->ss;
+
+       if (unlikely(keylen != 3 * DES_KEY_SIZE)) {
+               dev_err(ss->dev, "Invalid keylen %u\n", keylen);
+               crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+       op->keylen = keylen;
+       memcpy(op->key, key, keylen);
+       return 0;
+}
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
new file mode 100644 (file)
index 0000000..eab6fe2
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC
+ *
+ * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
+ *
+ * Core file which registers crypto algorithms supported by the SS.
+ *
+ * You could find a link for the datasheet in Documentation/arm/sunxi/README
+ *
+ * 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/clk.h>
+#include <linux/crypto.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <crypto/scatterwalk.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/reset.h>
+
+#include "sun4i-ss.h"
+
+static struct sun4i_ss_alg_template ss_algs[] = {
+{       .type = CRYPTO_ALG_TYPE_AHASH,
+       .mode = SS_OP_MD5,
+       .alg.hash = {
+               .init = sun4i_hash_init,
+               .update = sun4i_hash_update,
+               .final = sun4i_hash_final,
+               .finup = sun4i_hash_finup,
+               .digest = sun4i_hash_digest,
+               .export = sun4i_hash_export_md5,
+               .import = sun4i_hash_import_md5,
+               .halg = {
+                       .digestsize = MD5_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "md5",
+                               .cra_driver_name = "md5-sun4i-ss",
+                               .cra_priority = 300,
+                               .cra_alignmask = 3,
+                               .cra_flags = CRYPTO_ALG_TYPE_AHASH,
+                               .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct sun4i_req_ctx),
+                               .cra_module = THIS_MODULE,
+                               .cra_type = &crypto_ahash_type,
+                               .cra_init = sun4i_hash_crainit
+                       }
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_AHASH,
+       .mode = SS_OP_SHA1,
+       .alg.hash = {
+               .init = sun4i_hash_init,
+               .update = sun4i_hash_update,
+               .final = sun4i_hash_final,
+               .finup = sun4i_hash_finup,
+               .digest = sun4i_hash_digest,
+               .export = sun4i_hash_export_sha1,
+               .import = sun4i_hash_import_sha1,
+               .halg = {
+                       .digestsize = SHA1_DIGEST_SIZE,
+                       .base = {
+                               .cra_name = "sha1",
+                               .cra_driver_name = "sha1-sun4i-ss",
+                               .cra_priority = 300,
+                               .cra_alignmask = 3,
+                               .cra_flags = CRYPTO_ALG_TYPE_AHASH,
+                               .cra_blocksize = SHA1_BLOCK_SIZE,
+                               .cra_ctxsize = sizeof(struct sun4i_req_ctx),
+                               .cra_module = THIS_MODULE,
+                               .cra_type = &crypto_ahash_type,
+                               .cra_init = sun4i_hash_crainit
+                       }
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+       .alg.crypto = {
+               .cra_name = "cbc(aes)",
+               .cra_driver_name = "cbc-aes-sun4i-ss",
+               .cra_priority = 300,
+               .cra_blocksize = AES_BLOCK_SIZE,
+               .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
+               .cra_module = THIS_MODULE,
+               .cra_alignmask = 3,
+               .cra_type = &crypto_ablkcipher_type,
+               .cra_init = sun4i_ss_cipher_init,
+               .cra_ablkcipher = {
+                       .min_keysize    = AES_MIN_KEY_SIZE,
+                       .max_keysize    = AES_MAX_KEY_SIZE,
+                       .ivsize         = AES_BLOCK_SIZE,
+                       .setkey         = sun4i_ss_aes_setkey,
+                       .encrypt        = sun4i_ss_cbc_aes_encrypt,
+                       .decrypt        = sun4i_ss_cbc_aes_decrypt,
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+       .alg.crypto = {
+               .cra_name = "ecb(aes)",
+               .cra_driver_name = "ecb-aes-sun4i-ss",
+               .cra_priority = 300,
+               .cra_blocksize = AES_BLOCK_SIZE,
+               .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
+               .cra_module = THIS_MODULE,
+               .cra_alignmask = 3,
+               .cra_type = &crypto_ablkcipher_type,
+               .cra_init = sun4i_ss_cipher_init,
+               .cra_ablkcipher = {
+                       .min_keysize    = AES_MIN_KEY_SIZE,
+                       .max_keysize    = AES_MAX_KEY_SIZE,
+                       .ivsize         = AES_BLOCK_SIZE,
+                       .setkey         = sun4i_ss_aes_setkey,
+                       .encrypt        = sun4i_ss_ecb_aes_encrypt,
+                       .decrypt        = sun4i_ss_ecb_aes_decrypt,
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+       .alg.crypto = {
+               .cra_name = "cbc(des)",
+               .cra_driver_name = "cbc-des-sun4i-ss",
+               .cra_priority = 300,
+               .cra_blocksize = DES_BLOCK_SIZE,
+               .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .cra_ctxsize = sizeof(struct sun4i_req_ctx),
+               .cra_module = THIS_MODULE,
+               .cra_alignmask = 3,
+               .cra_type = &crypto_ablkcipher_type,
+               .cra_init = sun4i_ss_cipher_init,
+               .cra_u.ablkcipher = {
+                       .min_keysize    = DES_KEY_SIZE,
+                       .max_keysize    = DES_KEY_SIZE,
+                       .ivsize         = DES_BLOCK_SIZE,
+                       .setkey         = sun4i_ss_des_setkey,
+                       .encrypt        = sun4i_ss_cbc_des_encrypt,
+                       .decrypt        = sun4i_ss_cbc_des_decrypt,
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+       .alg.crypto = {
+               .cra_name = "ecb(des)",
+               .cra_driver_name = "ecb-des-sun4i-ss",
+               .cra_priority = 300,
+               .cra_blocksize = DES_BLOCK_SIZE,
+               .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+               .cra_ctxsize = sizeof(struct sun4i_req_ctx),
+               .cra_module = THIS_MODULE,
+               .cra_alignmask = 3,
+               .cra_type = &crypto_ablkcipher_type,
+               .cra_init = sun4i_ss_cipher_init,
+               .cra_u.ablkcipher = {
+                       .min_keysize    = DES_KEY_SIZE,
+                       .max_keysize    = DES_KEY_SIZE,
+                       .setkey         = sun4i_ss_des_setkey,
+                       .encrypt        = sun4i_ss_ecb_des_encrypt,
+                       .decrypt        = sun4i_ss_ecb_des_decrypt,
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+       .alg.crypto = {
+                       .cra_name = "cbc(des3_ede)",
+                       .cra_driver_name = "cbc-des3-sun4i-ss",
+                       .cra_priority = 300,
+                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+                       .cra_ctxsize = sizeof(struct sun4i_req_ctx),
+                       .cra_module = THIS_MODULE,
+                       .cra_alignmask = 3,
+                       .cra_type = &crypto_ablkcipher_type,
+                       .cra_init = sun4i_ss_cipher_init,
+                       .cra_u.ablkcipher = {
+                               .min_keysize    = DES3_EDE_KEY_SIZE,
+                               .max_keysize    = DES3_EDE_KEY_SIZE,
+                               .ivsize         = DES3_EDE_BLOCK_SIZE,
+                               .setkey         = sun4i_ss_des3_setkey,
+                               .encrypt        = sun4i_ss_cbc_des3_encrypt,
+                               .decrypt        = sun4i_ss_cbc_des3_decrypt,
+               }
+       }
+},
+{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+       .alg.crypto = {
+                       .cra_name = "ecb(des3_ede)",
+                       .cra_driver_name = "ecb-des3-sun4i-ss",
+                       .cra_priority = 300,
+                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                       .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+                       .cra_ctxsize = sizeof(struct sun4i_req_ctx),
+                       .cra_module = THIS_MODULE,
+                       .cra_alignmask = 3,
+                       .cra_type = &crypto_ablkcipher_type,
+                       .cra_init = sun4i_ss_cipher_init,
+                       .cra_u.ablkcipher = {
+                               .min_keysize    = DES3_EDE_KEY_SIZE,
+                               .max_keysize    = DES3_EDE_KEY_SIZE,
+                               .ivsize         = DES3_EDE_BLOCK_SIZE,
+                               .setkey         = sun4i_ss_des3_setkey,
+                               .encrypt        = sun4i_ss_ecb_des3_encrypt,
+                               .decrypt        = sun4i_ss_ecb_des3_decrypt,
+               }
+       }
+},
+};
+
+static int sun4i_ss_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       u32 v;
+       int err, i;
+       unsigned long cr;
+       const unsigned long cr_ahb = 24 * 1000 * 1000;
+       const unsigned long cr_mod = 150 * 1000 * 1000;
+       struct sun4i_ss_ctx *ss;
+
+       if (!pdev->dev.of_node)
+               return -ENODEV;
+
+       ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL);
+       if (!ss)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       ss->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(ss->base)) {
+               dev_err(&pdev->dev, "Cannot request MMIO\n");
+               return PTR_ERR(ss->base);
+       }
+
+       ss->ssclk = devm_clk_get(&pdev->dev, "mod");
+       if (IS_ERR(ss->ssclk)) {
+               err = PTR_ERR(ss->ssclk);
+               dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err);
+               return err;
+       }
+       dev_dbg(&pdev->dev, "clock ss acquired\n");
+
+       ss->busclk = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(ss->busclk)) {
+               err = PTR_ERR(ss->busclk);
+               dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err);
+               return err;
+       }
+       dev_dbg(&pdev->dev, "clock ahb_ss acquired\n");
+
+       ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
+       if (IS_ERR(ss->reset)) {
+               if (PTR_ERR(ss->reset) == -EPROBE_DEFER)
+                       return PTR_ERR(ss->reset);
+               dev_info(&pdev->dev, "no reset control found\n");
+               ss->reset = NULL;
+       }
+
+       /* Enable both clocks */
+       err = clk_prepare_enable(ss->busclk);
+       if (err != 0) {
+               dev_err(&pdev->dev, "Cannot prepare_enable busclk\n");
+               return err;
+       }
+       err = clk_prepare_enable(ss->ssclk);
+       if (err != 0) {
+               dev_err(&pdev->dev, "Cannot prepare_enable ssclk\n");
+               goto error_ssclk;
+       }
+
+       /*
+        * Check that clock have the correct rates given in the datasheet
+        * Try to set the clock to the maximum allowed
+        */
+       err = clk_set_rate(ss->ssclk, cr_mod);
+       if (err != 0) {
+               dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n");
+               goto error_clk;
+       }
+
+       /* Deassert reset if we have a reset control */
+       if (ss->reset) {
+               err = reset_control_deassert(ss->reset);
+               if (err) {
+                       dev_err(&pdev->dev, "Cannot deassert reset control\n");
+                       goto error_clk;
+               }
+       }
+
+       /*
+        * The only impact on clocks below requirement are bad performance,
+        * so do not print "errors"
+        * warn on Overclocked clocks
+        */
+       cr = clk_get_rate(ss->busclk);
+       if (cr >= cr_ahb)
+               dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
+                       cr, cr / 1000000, cr_ahb);
+       else
+               dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
+                        cr, cr / 1000000, cr_ahb);
+
+       cr = clk_get_rate(ss->ssclk);
+       if (cr <= cr_mod)
+               if (cr < cr_mod)
+                       dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
+                                cr, cr / 1000000, cr_mod);
+               else
+                       dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
+                               cr, cr / 1000000, cr_mod);
+       else
+               dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
+                        cr, cr / 1000000, cr_mod);
+
+       /*
+        * Datasheet named it "Die Bonding ID"
+        * I expect to be a sort of Security System Revision number.
+        * Since the A80 seems to have an other version of SS
+        * this info could be useful
+        */
+       writel(SS_ENABLED, ss->base + SS_CTL);
+       v = readl(ss->base + SS_CTL);
+       v >>= 16;
+       v &= 0x07;
+       dev_info(&pdev->dev, "Die ID %d\n", v);
+       writel(0, ss->base + SS_CTL);
+
+       ss->dev = &pdev->dev;
+
+       spin_lock_init(&ss->slock);
+
+       for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
+               ss_algs[i].ss = ss;
+               switch (ss_algs[i].type) {
+               case CRYPTO_ALG_TYPE_ABLKCIPHER:
+                       err = crypto_register_alg(&ss_algs[i].alg.crypto);
+                       if (err != 0) {
+                               dev_err(ss->dev, "Fail to register %s\n",
+                                       ss_algs[i].alg.crypto.cra_name);
+                               goto error_alg;
+                       }
+                       break;
+               case CRYPTO_ALG_TYPE_AHASH:
+                       err = crypto_register_ahash(&ss_algs[i].alg.hash);
+                       if (err != 0) {
+                               dev_err(ss->dev, "Fail to register %s\n",
+                                       ss_algs[i].alg.hash.halg.base.cra_name);
+                               goto error_alg;
+                       }
+                       break;
+               }
+       }
+       platform_set_drvdata(pdev, ss);
+       return 0;
+error_alg:
+       i--;
+       for (; i >= 0; i--) {
+               switch (ss_algs[i].type) {
+               case CRYPTO_ALG_TYPE_ABLKCIPHER:
+                       crypto_unregister_alg(&ss_algs[i].alg.crypto);
+                       break;
+               case CRYPTO_ALG_TYPE_AHASH:
+                       crypto_unregister_ahash(&ss_algs[i].alg.hash);
+                       break;
+               }
+       }
+       if (ss->reset)
+               reset_control_assert(ss->reset);
+error_clk:
+       clk_disable_unprepare(ss->ssclk);
+error_ssclk:
+       clk_disable_unprepare(ss->busclk);
+       return err;
+}
+
+static int sun4i_ss_remove(struct platform_device *pdev)
+{
+       int i;
+       struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
+
+       for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
+               switch (ss_algs[i].type) {
+               case CRYPTO_ALG_TYPE_ABLKCIPHER:
+                       crypto_unregister_alg(&ss_algs[i].alg.crypto);
+                       break;
+               case CRYPTO_ALG_TYPE_AHASH:
+                       crypto_unregister_ahash(&ss_algs[i].alg.hash);
+                       break;
+               }
+       }
+
+       writel(0, ss->base + SS_CTL);
+       if (ss->reset)
+               reset_control_assert(ss->reset);
+       clk_disable_unprepare(ss->busclk);
+       clk_disable_unprepare(ss->ssclk);
+       return 0;
+}
+
+static const struct of_device_id a20ss_crypto_of_match_table[] = {
+       { .compatible = "allwinner,sun4i-a10-crypto" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
+
+static struct platform_driver sun4i_ss_driver = {
+       .probe          = sun4i_ss_probe,
+       .remove         = sun4i_ss_remove,
+       .driver         = {
+               .name           = "sun4i-ss",
+               .of_match_table = a20ss_crypto_of_match_table,
+       },
+};
+
+module_platform_driver(sun4i_ss_driver);
+
+MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
new file mode 100644 (file)
index 0000000..ff80314
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * sun4i-ss-hash.c - hardware cryptographic accelerator for Allwinner A20 SoC
+ *
+ * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
+ *
+ * This file add support for MD5 and SHA1.
+ *
+ * You could find the datasheet in Documentation/arm/sunxi/README
+ *
+ * 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 "sun4i-ss.h"
+#include <linux/scatterlist.h>
+
+/* This is a totally arbitrary value */
+#define SS_TIMEOUT 100
+
+int sun4i_hash_crainit(struct crypto_tfm *tfm)
+{
+       crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+                                sizeof(struct sun4i_req_ctx));
+       return 0;
+}
+
+/* sun4i_hash_init: initialize request context */
+int sun4i_hash_init(struct ahash_request *areq)
+{
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+       struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg);
+       struct sun4i_ss_alg_template *algt;
+       struct sun4i_ss_ctx *ss;
+
+       memset(op, 0, sizeof(struct sun4i_req_ctx));
+
+       algt = container_of(alg, struct sun4i_ss_alg_template, alg.hash);
+       ss = algt->ss;
+       op->ss = algt->ss;
+       op->mode = algt->mode;
+
+       return 0;
+}
+
+int sun4i_hash_export_md5(struct ahash_request *areq, void *out)
+{
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       struct md5_state *octx = out;
+       int i;
+
+       octx->byte_count = op->byte_count + op->len;
+
+       memcpy(octx->block, op->buf, op->len);
+
+       if (op->byte_count > 0) {
+               for (i = 0; i < 4; i++)
+                       octx->hash[i] = op->hash[i];
+       } else {
+               octx->hash[0] = SHA1_H0;
+               octx->hash[1] = SHA1_H1;
+               octx->hash[2] = SHA1_H2;
+               octx->hash[3] = SHA1_H3;
+       }
+
+       return 0;
+}
+
+int sun4i_hash_import_md5(struct ahash_request *areq, const void *in)
+{
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       const struct md5_state *ictx = in;
+       int i;
+
+       sun4i_hash_init(areq);
+
+       op->byte_count = ictx->byte_count & ~0x3F;
+       op->len = ictx->byte_count & 0x3F;
+
+       memcpy(op->buf, ictx->block, op->len);
+
+       for (i = 0; i < 4; i++)
+               op->hash[i] = ictx->hash[i];
+
+       return 0;
+}
+
+int sun4i_hash_export_sha1(struct ahash_request *areq, void *out)
+{
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       struct sha1_state *octx = out;
+       int i;
+
+       octx->count = op->byte_count + op->len;
+
+       memcpy(octx->buffer, op->buf, op->len);
+
+       if (op->byte_count > 0) {
+               for (i = 0; i < 5; i++)
+                       octx->state[i] = op->hash[i];
+       } else {
+               octx->state[0] = SHA1_H0;
+               octx->state[1] = SHA1_H1;
+               octx->state[2] = SHA1_H2;
+               octx->state[3] = SHA1_H3;
+               octx->state[4] = SHA1_H4;
+       }
+
+       return 0;
+}
+
+int sun4i_hash_import_sha1(struct ahash_request *areq, const void *in)
+{
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       const struct sha1_state *ictx = in;
+       int i;
+
+       sun4i_hash_init(areq);
+
+       op->byte_count = ictx->count & ~0x3F;
+       op->len = ictx->count & 0x3F;
+
+       memcpy(op->buf, ictx->buffer, op->len);
+
+       for (i = 0; i < 5; i++)
+               op->hash[i] = ictx->state[i];
+
+       return 0;
+}
+
+/*
+ * sun4i_hash_update: update hash engine
+ *
+ * Could be used for both SHA1 and MD5
+ * Write data by step of 32bits and put then in the SS.
+ *
+ * Since we cannot leave partial data and hash state in the engine,
+ * we need to get the hash state at the end of this function.
+ * We can get the hash state every 64 bytes
+ *
+ * So the first work is to get the number of bytes to write to SS modulo 64
+ * The extra bytes will go to a temporary buffer op->buf storing op->len bytes
+ *
+ * So at the begin of update()
+ * if op->len + areq->nbytes < 64
+ * => all data will be written to wait buffer (op->buf) and end=0
+ * if not, write all data from op->buf to the device and position end to
+ * complete to 64bytes
+ *
+ * example 1:
+ * update1 60o => op->len=60
+ * update2 60o => need one more word to have 64 bytes
+ * end=4
+ * so write all data from op->buf and one word of SGs
+ * write remaining data in op->buf
+ * final state op->len=56
+ */
+int sun4i_hash_update(struct ahash_request *areq)
+{
+       u32 v, ivmode = 0;
+       unsigned int i = 0;
+       /*
+        * i is the total bytes read from SGs, to be compared to areq->nbytes
+        * i is important because we cannot rely on SG length since the sum of
+        * SG->length could be greater than areq->nbytes
+        */
+
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       struct sun4i_ss_ctx *ss = op->ss;
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+       unsigned int in_i = 0; /* advancement in the current SG */
+       unsigned int end;
+       /*
+        * end is the position when we need to stop writing to the device,
+        * to be compared to i
+        */
+       int in_r, err = 0;
+       unsigned int todo;
+       u32 spaces, rx_cnt = SS_RX_DEFAULT;
+       size_t copied = 0;
+       struct sg_mapping_iter mi;
+
+       dev_dbg(ss->dev, "%s %s bc=%llu len=%u mode=%x wl=%u h0=%0x",
+               __func__, crypto_tfm_alg_name(areq->base.tfm),
+               op->byte_count, areq->nbytes, op->mode,
+               op->len, op->hash[0]);
+
+       if (areq->nbytes == 0)
+               return 0;
+
+       /* protect against overflow */
+       if (areq->nbytes > UINT_MAX - op->len) {
+               dev_err(ss->dev, "Cannot process too large request\n");
+               return -EINVAL;
+       }
+
+       if (op->len + areq->nbytes < 64) {
+               /* linearize data to op->buf */
+               copied = sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
+                                           op->buf + op->len, areq->nbytes, 0);
+               op->len += copied;
+               return 0;
+       }
+
+       end = ((areq->nbytes + op->len) / 64) * 64 - op->len;
+
+       if (end > areq->nbytes || areq->nbytes - end > 63) {
+               dev_err(ss->dev, "ERROR: Bound error %u %u\n",
+                       end, areq->nbytes);
+               return -EINVAL;
+       }
+
+       spin_lock_bh(&ss->slock);
+
+       /*
+        * if some data have been processed before,
+        * we need to restore the partial hash state
+        */
+       if (op->byte_count > 0) {
+               ivmode = SS_IV_ARBITRARY;
+               for (i = 0; i < 5; i++)
+                       writel(op->hash[i], ss->base + SS_IV0 + i * 4);
+       }
+       /* Enable the device */
+       writel(op->mode | SS_ENABLED | ivmode, ss->base + SS_CTL);
+
+       i = 0;
+       sg_miter_start(&mi, areq->src, sg_nents(areq->src),
+                      SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+       sg_miter_next(&mi);
+       in_i = 0;
+
+       do {
+               /*
+                * we need to linearize in two case:
+                * - the buffer is already used
+                * - the SG does not have enough byte remaining ( < 4)
+                */
+               if (op->len > 0 || (mi.length - in_i) < 4) {
+                       /*
+                        * if we have entered here we have two reason to stop
+                        * - the buffer is full
+                        * - reach the end
+                        */
+                       while (op->len < 64 && i < end) {
+                               /* how many bytes we can read from current SG */
+                               in_r = min3(mi.length - in_i, end - i,
+                                           64 - op->len);
+                               memcpy(op->buf + op->len, mi.addr + in_i, in_r);
+                               op->len += in_r;
+                               i += in_r;
+                               in_i += in_r;
+                               if (in_i == mi.length) {
+                                       sg_miter_next(&mi);
+                                       in_i = 0;
+                               }
+                       }
+                       if (op->len > 3 && (op->len % 4) == 0) {
+                               /* write buf to the device */
+                               writesl(ss->base + SS_RXFIFO, op->buf,
+                                       op->len / 4);
+                               op->byte_count += op->len;
+                               op->len = 0;
+                       }
+               }
+               if (mi.length - in_i > 3 && i < end) {
+                       /* how many bytes we can read from current SG */
+                       in_r = min3(mi.length - in_i, areq->nbytes - i,
+                                   ((mi.length - in_i) / 4) * 4);
+                       /* how many bytes we can write in the device*/
+                       todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4);
+                       writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo);
+                       op->byte_count += todo * 4;
+                       i += todo * 4;
+                       in_i += todo * 4;
+                       rx_cnt -= todo;
+                       if (rx_cnt == 0) {
+                               spaces = readl(ss->base + SS_FCSR);
+                               rx_cnt = SS_RXFIFO_SPACES(spaces);
+                       }
+                       if (in_i == mi.length) {
+                               sg_miter_next(&mi);
+                               in_i = 0;
+                       }
+               }
+       } while (i < end);
+       /* final linear */
+       if ((areq->nbytes - i) < 64) {
+               while (i < areq->nbytes && in_i < mi.length && op->len < 64) {
+                       /* how many bytes we can read from current SG */
+                       in_r = min3(mi.length - in_i, areq->nbytes - i,
+                                   64 - op->len);
+                       memcpy(op->buf + op->len, mi.addr + in_i, in_r);
+                       op->len += in_r;
+                       i += in_r;
+                       in_i += in_r;
+                       if (in_i == mi.length) {
+                               sg_miter_next(&mi);
+                               in_i = 0;
+                       }
+               }
+       }
+
+       sg_miter_stop(&mi);
+
+       writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL);
+       i = 0;
+       do {
+               v = readl(ss->base + SS_CTL);
+               i++;
+       } while (i < SS_TIMEOUT && (v & SS_DATA_END) > 0);
+       if (i >= SS_TIMEOUT) {
+               dev_err_ratelimited(ss->dev,
+                                   "ERROR: hash end timeout %d>%d ctl=%x len=%u\n",
+                                   i, SS_TIMEOUT, v, areq->nbytes);
+               err = -EIO;
+               goto release_ss;
+       }
+
+       /* get the partial hash only if something was written */
+       for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++)
+               op->hash[i] = readl(ss->base + SS_MD0 + i * 4);
+
+release_ss:
+       writel(0, ss->base + SS_CTL);
+       spin_unlock_bh(&ss->slock);
+       return err;
+}
+
+/*
+ * sun4i_hash_final: finalize hashing operation
+ *
+ * If we have some remaining bytes, we write them.
+ * Then ask the SS for finalizing the hashing operation
+ *
+ * I do not check RX FIFO size in this function since the size is 32
+ * after each enabling and this function neither write more than 32 words.
+ */
+int sun4i_hash_final(struct ahash_request *areq)
+{
+       u32 v, ivmode = 0;
+       unsigned int i;
+       unsigned int j = 0;
+       int zeros, err = 0;
+       unsigned int index, padlen;
+       __be64 bits;
+       struct sun4i_req_ctx *op = ahash_request_ctx(areq);
+       struct sun4i_ss_ctx *ss = op->ss;
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+       u32 bf[32];
+       u32 wb = 0;
+       unsigned int nwait, nbw = 0;
+
+       dev_dbg(ss->dev, "%s: byte=%llu len=%u mode=%x wl=%u h=%x",
+               __func__, op->byte_count, areq->nbytes, op->mode,
+               op->len, op->hash[0]);
+
+       spin_lock_bh(&ss->slock);
+
+       /*
+        * if we have already written something,
+        * restore the partial hash state
+        */
+       if (op->byte_count > 0) {
+               ivmode = SS_IV_ARBITRARY;
+               for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++)
+                       writel(op->hash[i], ss->base + SS_IV0 + i * 4);
+       }
+       writel(op->mode | SS_ENABLED | ivmode, ss->base + SS_CTL);
+
+       /* write the remaining words of the wait buffer */
+       if (op->len > 0) {
+               nwait = op->len / 4;
+               if (nwait > 0) {
+                       writesl(ss->base + SS_RXFIFO, op->buf, nwait);
+                       op->byte_count += 4 * nwait;
+               }
+               nbw = op->len - 4 * nwait;
+               wb = *(u32 *)(op->buf + nwait * 4);
+               wb &= (0xFFFFFFFF >> (4 - nbw) * 8);
+       }
+
+       /* write the remaining bytes of the nbw buffer */
+       if (nbw > 0) {
+               wb |= ((1 << 7) << (nbw * 8));
+               bf[j++] = wb;
+       } else {
+               bf[j++] = 1 << 7;
+       }
+
+       /*
+        * number of space to pad to obtain 64o minus 8(size) minus 4 (final 1)
+        * I take the operations from other MD5/SHA1 implementations
+        */
+
+       /* we have already send 4 more byte of which nbw data */
+       if (op->mode == SS_OP_MD5) {
+               index = (op->byte_count + 4) & 0x3f;
+               op->byte_count += nbw;
+               if (index > 56)
+                       zeros = (120 - index) / 4;
+               else
+                       zeros = (56 - index) / 4;
+       } else {
+               op->byte_count += nbw;
+               index = op->byte_count & 0x3f;
+               padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
+               zeros = (padlen - 1) / 4;
+       }
+
+       memset(bf + j, 0, 4 * zeros);
+       j += zeros;
+
+       /* write the length of data */
+       if (op->mode == SS_OP_SHA1) {
+               bits = cpu_to_be64(op->byte_count << 3);
+               bf[j++] = bits & 0xffffffff;
+               bf[j++] = (bits >> 32) & 0xffffffff;
+       } else {
+               bf[j++] = (op->byte_count << 3) & 0xffffffff;
+               bf[j++] = (op->byte_count >> 29) & 0xffffffff;
+       }
+       writesl(ss->base + SS_RXFIFO, bf, j);
+
+       /* Tell the SS to stop the hashing */
+       writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL);
+
+       /*
+        * Wait for SS to finish the hash.
+        * The timeout could happen only in case of bad overcloking
+        * or driver bug.
+        */
+       i = 0;
+       do {
+               v = readl(ss->base + SS_CTL);
+               i++;
+       } while (i < SS_TIMEOUT && (v & SS_DATA_END) > 0);
+       if (i >= SS_TIMEOUT) {
+               dev_err_ratelimited(ss->dev,
+                                   "ERROR: hash end timeout %d>%d ctl=%x len=%u\n",
+                                   i, SS_TIMEOUT, v, areq->nbytes);
+               err = -EIO;
+               goto release_ss;
+       }
+
+       /* Get the hash from the device */
+       if (op->mode == SS_OP_SHA1) {
+               for (i = 0; i < 5; i++) {
+                       v = cpu_to_be32(readl(ss->base + SS_MD0 + i * 4));
+                       memcpy(areq->result + i * 4, &v, 4);
+               }
+       } else {
+               for (i = 0; i < 4; i++) {
+                       v = readl(ss->base + SS_MD0 + i * 4);
+                       memcpy(areq->result + i * 4, &v, 4);
+               }
+       }
+
+release_ss:
+       writel(0, ss->base + SS_CTL);
+       spin_unlock_bh(&ss->slock);
+       return err;
+}
+
+/* sun4i_hash_finup: finalize hashing operation after an update */
+int sun4i_hash_finup(struct ahash_request *areq)
+{
+       int err;
+
+       err = sun4i_hash_update(areq);
+       if (err != 0)
+               return err;
+
+       return sun4i_hash_final(areq);
+}
+
+/* combo of init/update/final functions */
+int sun4i_hash_digest(struct ahash_request *areq)
+{
+       int err;
+
+       err = sun4i_hash_init(areq);
+       if (err != 0)
+               return err;
+
+       err = sun4i_hash_update(areq);
+       if (err != 0)
+               return err;
+
+       return sun4i_hash_final(areq);
+}
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h
new file mode 100644 (file)
index 0000000..8e9c05f
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * sun4i-ss.h - hardware cryptographic accelerator for Allwinner A20 SoC
+ *
+ * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
+ *
+ * Support AES cipher with 128,192,256 bits keysize.
+ * Support MD5 and SHA1 hash algorithms.
+ * Support DES and 3DES
+ *
+ * You could find the datasheet in Documentation/arm/sunxi/README
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <crypto/scatterwalk.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <crypto/md5.h>
+#include <crypto/sha.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+#include <crypto/aes.h>
+#include <crypto/des.h>
+#include <crypto/internal/rng.h>
+
+#define SS_CTL            0x00
+#define SS_KEY0           0x04
+#define SS_KEY1           0x08
+#define SS_KEY2           0x0C
+#define SS_KEY3           0x10
+#define SS_KEY4           0x14
+#define SS_KEY5           0x18
+#define SS_KEY6           0x1C
+#define SS_KEY7           0x20
+
+#define SS_IV0            0x24
+#define SS_IV1            0x28
+#define SS_IV2            0x2C
+#define SS_IV3            0x30
+
+#define SS_FCSR           0x44
+
+#define SS_MD0            0x4C
+#define SS_MD1            0x50
+#define SS_MD2            0x54
+#define SS_MD3            0x58
+#define SS_MD4            0x5C
+
+#define SS_RXFIFO         0x200
+#define SS_TXFIFO         0x204
+
+/* SS_CTL configuration values */
+
+/* PRNG generator mode - bit 15 */
+#define SS_PRNG_ONESHOT                (0 << 15)
+#define SS_PRNG_CONTINUE       (1 << 15)
+
+/* IV mode for hash */
+#define SS_IV_ARBITRARY                (1 << 14)
+
+/* SS operation mode - bits 12-13 */
+#define SS_ECB                 (0 << 12)
+#define SS_CBC                 (1 << 12)
+#define SS_CTS                 (3 << 12)
+
+/* Counter width for CNT mode - bits 10-11 */
+#define SS_CNT_16BITS          (0 << 10)
+#define SS_CNT_32BITS          (1 << 10)
+#define SS_CNT_64BITS          (2 << 10)
+
+/* Key size for AES - bits 8-9 */
+#define SS_AES_128BITS         (0 << 8)
+#define SS_AES_192BITS         (1 << 8)
+#define SS_AES_256BITS         (2 << 8)
+
+/* Operation direction - bit 7 */
+#define SS_ENCRYPTION          (0 << 7)
+#define SS_DECRYPTION          (1 << 7)
+
+/* SS Method - bits 4-6 */
+#define SS_OP_AES              (0 << 4)
+#define SS_OP_DES              (1 << 4)
+#define SS_OP_3DES             (2 << 4)
+#define SS_OP_SHA1             (3 << 4)
+#define SS_OP_MD5              (4 << 4)
+#define SS_OP_PRNG             (5 << 4)
+
+/* Data end bit - bit 2 */
+#define SS_DATA_END            (1 << 2)
+
+/* PRNG start bit - bit 1 */
+#define SS_PRNG_START          (1 << 1)
+
+/* SS Enable bit - bit 0 */
+#define SS_DISABLED            (0 << 0)
+#define SS_ENABLED             (1 << 0)
+
+/* SS_FCSR configuration values */
+/* RX FIFO status - bit 30 */
+#define SS_RXFIFO_FREE         (1 << 30)
+
+/* RX FIFO empty spaces - bits 24-29 */
+#define SS_RXFIFO_SPACES(val)  (((val) >> 24) & 0x3f)
+
+/* TX FIFO status - bit 22 */
+#define SS_TXFIFO_AVAILABLE    (1 << 22)
+
+/* TX FIFO available spaces - bits 16-21 */
+#define SS_TXFIFO_SPACES(val)  (((val) >> 16) & 0x3f)
+
+#define SS_RX_MAX      32
+#define SS_RX_DEFAULT  SS_RX_MAX
+#define SS_TX_MAX      33
+
+#define SS_RXFIFO_EMP_INT_PENDING      (1 << 10)
+#define SS_TXFIFO_AVA_INT_PENDING      (1 << 8)
+#define SS_RXFIFO_EMP_INT_ENABLE       (1 << 2)
+#define SS_TXFIFO_AVA_INT_ENABLE       (1 << 0)
+
+struct sun4i_ss_ctx {
+       void __iomem *base;
+       int irq;
+       struct clk *busclk;
+       struct clk *ssclk;
+       struct reset_control *reset;
+       struct device *dev;
+       struct resource *res;
+       spinlock_t slock; /* control the use of the device */
+};
+
+struct sun4i_ss_alg_template {
+       u32 type;
+       u32 mode;
+       union {
+               struct crypto_alg crypto;
+               struct ahash_alg hash;
+       } alg;
+       struct sun4i_ss_ctx *ss;
+};
+
+struct sun4i_tfm_ctx {
+       u32 key[AES_MAX_KEY_SIZE / 4];/* divided by sizeof(u32) */
+       u32 keylen;
+       u32 keymode;
+       struct sun4i_ss_ctx *ss;
+};
+
+struct sun4i_cipher_req_ctx {
+       u32 mode;
+};
+
+struct sun4i_req_ctx {
+       u32 mode;
+       u64 byte_count; /* number of bytes "uploaded" to the device */
+       u32 hash[5]; /* for storing SS_IVx register */
+       char buf[64];
+       unsigned int len;
+       struct sun4i_ss_ctx *ss;
+};
+
+int sun4i_hash_crainit(struct crypto_tfm *tfm);
+int sun4i_hash_init(struct ahash_request *areq);
+int sun4i_hash_update(struct ahash_request *areq);
+int sun4i_hash_final(struct ahash_request *areq);
+int sun4i_hash_finup(struct ahash_request *areq);
+int sun4i_hash_digest(struct ahash_request *areq);
+int sun4i_hash_export_md5(struct ahash_request *areq, void *out);
+int sun4i_hash_import_md5(struct ahash_request *areq, const void *in);
+int sun4i_hash_export_sha1(struct ahash_request *areq, void *out);
+int sun4i_hash_import_sha1(struct ahash_request *areq, const void *in);
+
+int sun4i_ss_cbc_aes_encrypt(struct ablkcipher_request *areq);
+int sun4i_ss_cbc_aes_decrypt(struct ablkcipher_request *areq);
+int sun4i_ss_ecb_aes_encrypt(struct ablkcipher_request *areq);
+int sun4i_ss_ecb_aes_decrypt(struct ablkcipher_request *areq);
+
+int sun4i_ss_cbc_des_encrypt(struct ablkcipher_request *areq);
+int sun4i_ss_cbc_des_decrypt(struct ablkcipher_request *areq);
+int sun4i_ss_ecb_des_encrypt(struct ablkcipher_request *areq);
+int sun4i_ss_ecb_des_decrypt(struct ablkcipher_request *areq);
+
+int sun4i_ss_cbc_des3_encrypt(struct ablkcipher_request *areq);
+int sun4i_ss_cbc_des3_decrypt(struct ablkcipher_request *areq);
+int sun4i_ss_ecb_des3_encrypt(struct ablkcipher_request *areq);
+int sun4i_ss_ecb_des3_decrypt(struct ablkcipher_request *areq);
+
+int sun4i_ss_cipher_init(struct crypto_tfm *tfm);
+int sun4i_ss_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                       unsigned int keylen);
+int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                       unsigned int keylen);
+int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                        unsigned int keylen);
index 83aca95a95bc226e6b3d1b083c7ba5373660cc6b..cd774534d987756f57fd79f9d6441a51d74af609 100644 (file)
@@ -766,6 +766,7 @@ static int talitos_rng_init(struct hwrng *rng)
 static int talitos_register_rng(struct device *dev)
 {
        struct talitos_private *priv = dev_get_drvdata(dev);
+       int err;
 
        priv->rng.name          = dev_driver_string(dev),
        priv->rng.init          = talitos_rng_init,
@@ -773,14 +774,22 @@ static int talitos_register_rng(struct device *dev)
        priv->rng.data_read     = talitos_rng_data_read,
        priv->rng.priv          = (unsigned long)dev;
 
-       return hwrng_register(&priv->rng);
+       err = hwrng_register(&priv->rng);
+       if (!err)
+               priv->rng_registered = true;
+
+       return err;
 }
 
 static void talitos_unregister_rng(struct device *dev)
 {
        struct talitos_private *priv = dev_get_drvdata(dev);
 
+       if (!priv->rng_registered)
+               return;
+
        hwrng_unregister(&priv->rng);
+       priv->rng_registered = false;
 }
 
 /*
@@ -799,7 +808,6 @@ struct talitos_ctx {
        unsigned int keylen;
        unsigned int enckeylen;
        unsigned int authkeylen;
-       unsigned int authsize;
 };
 
 #define HASH_MAX_BLOCK_SIZE            SHA512_BLOCK_SIZE
@@ -819,16 +827,6 @@ struct talitos_ahash_req_ctx {
        struct scatterlist *psrc;
 };
 
-static int aead_setauthsize(struct crypto_aead *authenc,
-                           unsigned int authsize)
-{
-       struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-
-       ctx->authsize = authsize;
-
-       return 0;
-}
-
 static int aead_setkey(struct crypto_aead *authenc,
                       const u8 *key, unsigned int keylen)
 {
@@ -857,12 +855,11 @@ badkey:
 
 /*
  * talitos_edesc - s/w-extended descriptor
- * @assoc_nents: number of segments in associated data scatterlist
  * @src_nents: number of segments in input scatterlist
  * @dst_nents: number of segments in output scatterlist
- * @assoc_chained: whether assoc is chained or not
  * @src_chained: whether src is chained or not
  * @dst_chained: whether dst is chained or not
+ * @icv_ool: whether ICV is out-of-line
  * @iv_dma: dma address of iv for checking continuity and link table
  * @dma_len: length of dma mapped link_tbl space
  * @dma_link_tbl: bus physical address of link_tbl/buf
@@ -875,12 +872,11 @@ badkey:
  * of link_tbl data
  */
 struct talitos_edesc {
-       int assoc_nents;
        int src_nents;
        int dst_nents;
-       bool assoc_chained;
        bool src_chained;
        bool dst_chained;
+       bool icv_ool;
        dma_addr_t iv_dma;
        int dma_len;
        dma_addr_t dma_link_tbl;
@@ -952,14 +948,6 @@ static void ipsec_esp_unmap(struct device *dev,
        unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
        unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
 
-       if (edesc->assoc_chained)
-               talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
-       else if (areq->assoclen)
-               /* assoc_nents counts also for IV in non-contiguous cases */
-               dma_unmap_sg(dev, areq->assoc,
-                            edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
-                            DMA_TO_DEVICE);
-
        talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
 
        if (edesc->dma_len)
@@ -976,7 +964,7 @@ static void ipsec_esp_encrypt_done(struct device *dev,
 {
        struct aead_request *areq = context;
        struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
-       struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+       unsigned int authsize = crypto_aead_authsize(authenc);
        struct talitos_edesc *edesc;
        struct scatterlist *sg;
        void *icvdata;
@@ -986,13 +974,12 @@ static void ipsec_esp_encrypt_done(struct device *dev,
        ipsec_esp_unmap(dev, edesc, areq);
 
        /* copy the generated ICV to dst */
-       if (edesc->dst_nents) {
+       if (edesc->icv_ool) {
                icvdata = &edesc->link_tbl[edesc->src_nents +
-                                          edesc->dst_nents + 2 +
-                                          edesc->assoc_nents];
+                                          edesc->dst_nents + 2];
                sg = sg_last(areq->dst, edesc->dst_nents);
-               memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize,
-                      icvdata, ctx->authsize);
+               memcpy((char *)sg_virt(sg) + sg->length - authsize,
+                      icvdata, authsize);
        }
 
        kfree(edesc);
@@ -1006,10 +993,10 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
 {
        struct aead_request *req = context;
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-       struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+       unsigned int authsize = crypto_aead_authsize(authenc);
        struct talitos_edesc *edesc;
        struct scatterlist *sg;
-       void *icvdata;
+       char *oicv, *icv;
 
        edesc = container_of(desc, struct talitos_edesc, desc);
 
@@ -1017,16 +1004,18 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
 
        if (!err) {
                /* auth check */
-               if (edesc->dma_len)
-                       icvdata = &edesc->link_tbl[edesc->src_nents +
-                                                  edesc->dst_nents + 2 +
-                                                  edesc->assoc_nents];
-               else
-                       icvdata = &edesc->link_tbl[0];
-
                sg = sg_last(req->dst, edesc->dst_nents ? : 1);
-               err = memcmp(icvdata, (char *)sg_virt(sg) + sg->length -
-                            ctx->authsize, ctx->authsize) ? -EBADMSG : 0;
+               icv = (char *)sg_virt(sg) + sg->length - authsize;
+
+               if (edesc->dma_len) {
+                       oicv = (char *)&edesc->link_tbl[edesc->src_nents +
+                                                       edesc->dst_nents + 2];
+                       if (edesc->icv_ool)
+                               icv = oicv + authsize;
+               } else
+                       oicv = (char *)&edesc->link_tbl[0];
+
+               err = memcmp(oicv, icv, authsize) ? -EBADMSG : 0;
        }
 
        kfree(edesc);
@@ -1059,53 +1048,69 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
  * convert scatterlist to SEC h/w link table format
  * stop at cryptlen bytes
  */
-static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
-                          int cryptlen, struct talitos_ptr *link_tbl_ptr)
+static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
+                                unsigned int offset, int cryptlen,
+                                struct talitos_ptr *link_tbl_ptr)
 {
        int n_sg = sg_count;
+       int count = 0;
 
-       while (sg && n_sg--) {
-               to_talitos_ptr(link_tbl_ptr, sg_dma_address(sg), 0);
-               link_tbl_ptr->len = cpu_to_be16(sg_dma_len(sg));
-               link_tbl_ptr->j_extent = 0;
-               link_tbl_ptr++;
-               cryptlen -= sg_dma_len(sg);
-               sg = sg_next(sg);
-       }
+       while (cryptlen && sg && n_sg--) {
+               unsigned int len = sg_dma_len(sg);
+
+               if (offset >= len) {
+                       offset -= len;
+                       goto next;
+               }
+
+               len -= offset;
+
+               if (len > cryptlen)
+                       len = cryptlen;
 
-       /* adjust (decrease) last one (or two) entry's len to cryptlen */
-       link_tbl_ptr--;
-       while (be16_to_cpu(link_tbl_ptr->len) <= (-cryptlen)) {
-               /* Empty this entry, and move to previous one */
-               cryptlen += be16_to_cpu(link_tbl_ptr->len);
-               link_tbl_ptr->len = 0;
-               sg_count--;
-               link_tbl_ptr--;
+               to_talitos_ptr(link_tbl_ptr + count,
+                              sg_dma_address(sg) + offset, 0);
+               link_tbl_ptr[count].len = cpu_to_be16(len);
+               link_tbl_ptr[count].j_extent = 0;
+               count++;
+               cryptlen -= len;
+               offset = 0;
+
+next:
+               sg = sg_next(sg);
        }
-       link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len)
-                                       + cryptlen);
 
        /* tag end of link table */
-       link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
+       if (count > 0)
+               link_tbl_ptr[count - 1].j_extent = DESC_PTR_LNKTBL_RETURN;
 
-       return sg_count;
+       return count;
+}
+
+static inline int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
+                                int cryptlen,
+                                struct talitos_ptr *link_tbl_ptr)
+{
+       return sg_to_link_tbl_offset(sg, sg_count, 0, cryptlen,
+                                    link_tbl_ptr);
 }
 
 /*
  * fill in and submit ipsec_esp descriptor
  */
 static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
-                    u64 seq, void (*callback) (struct device *dev,
-                                               struct talitos_desc *desc,
-                                               void *context, int error))
+                    void (*callback)(struct device *dev,
+                                     struct talitos_desc *desc,
+                                     void *context, int error))
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(areq);
+       unsigned int authsize = crypto_aead_authsize(aead);
        struct talitos_ctx *ctx = crypto_aead_ctx(aead);
        struct device *dev = ctx->dev;
        struct talitos_desc *desc = &edesc->desc;
        unsigned int cryptlen = areq->cryptlen;
-       unsigned int authsize = ctx->authsize;
        unsigned int ivsize = crypto_aead_ivsize(aead);
+       int tbl_off = 0;
        int sg_count, ret;
        int sg_link_tbl_len;
 
@@ -1113,36 +1118,27 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
        map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
                               DMA_TO_DEVICE);
 
+       sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ?: 1,
+                                 (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
+                                                          : DMA_TO_DEVICE,
+                                 edesc->src_chained);
+
        /* hmac data */
-       desc->ptr[1].len = cpu_to_be16(areq->assoclen + ivsize);
-       if (edesc->assoc_nents) {
-               int tbl_off = edesc->src_nents + edesc->dst_nents + 2;
-               struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
+       desc->ptr[1].len = cpu_to_be16(areq->assoclen);
+       if (sg_count > 1 &&
+           (ret = sg_to_link_tbl_offset(areq->src, sg_count, 0,
+                                        areq->assoclen,
+                                        &edesc->link_tbl[tbl_off])) > 1) {
+               tbl_off += ret;
 
                to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off *
                               sizeof(struct talitos_ptr), 0);
                desc->ptr[1].j_extent = DESC_PTR_LNKTBL_JUMP;
 
-               /* assoc_nents - 1 entries for assoc, 1 for IV */
-               sg_count = sg_to_link_tbl(areq->assoc, edesc->assoc_nents - 1,
-                                         areq->assoclen, tbl_ptr);
-
-               /* add IV to link table */
-               tbl_ptr += sg_count - 1;
-               tbl_ptr->j_extent = 0;
-               tbl_ptr++;
-               to_talitos_ptr(tbl_ptr, edesc->iv_dma, 0);
-               tbl_ptr->len = cpu_to_be16(ivsize);
-               tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
-
                dma_sync_single_for_device(dev, edesc->dma_link_tbl,
                                           edesc->dma_len, DMA_BIDIRECTIONAL);
        } else {
-               if (areq->assoclen)
-                       to_talitos_ptr(&desc->ptr[1],
-                                      sg_dma_address(areq->assoc), 0);
-               else
-                       to_talitos_ptr(&desc->ptr[1], edesc->iv_dma, 0);
+               to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->src), 0);
                desc->ptr[1].j_extent = 0;
        }
 
@@ -1150,8 +1146,6 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
        to_talitos_ptr(&desc->ptr[2], edesc->iv_dma, 0);
        desc->ptr[2].len = cpu_to_be16(ivsize);
        desc->ptr[2].j_extent = 0;
-       /* Sync needed for the aead_givencrypt case */
-       dma_sync_single_for_device(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
 
        /* cipher key */
        map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
@@ -1167,33 +1161,24 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
        desc->ptr[4].len = cpu_to_be16(cryptlen);
        desc->ptr[4].j_extent = authsize;
 
-       sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
-                                 (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
-                                                          : DMA_TO_DEVICE,
-                                 edesc->src_chained);
-
-       if (sg_count == 1) {
+       sg_link_tbl_len = cryptlen;
+       if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
+               sg_link_tbl_len += authsize;
+
+       if (sg_count > 1 &&
+           (ret = sg_to_link_tbl_offset(areq->src, sg_count, areq->assoclen,
+                                        sg_link_tbl_len,
+                                        &edesc->link_tbl[tbl_off])) > 1) {
+               tbl_off += ret;
+               desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
+               to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl +
+                                             tbl_off *
+                                             sizeof(struct talitos_ptr), 0);
+               dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+                                          edesc->dma_len,
+                                          DMA_BIDIRECTIONAL);
+       } else
                to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src), 0);
-       } else {
-               sg_link_tbl_len = cryptlen;
-
-               if (edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV)
-                       sg_link_tbl_len = cryptlen + authsize;
-
-               sg_count = sg_to_link_tbl(areq->src, sg_count, sg_link_tbl_len,
-                                         &edesc->link_tbl[0]);
-               if (sg_count > 1) {
-                       desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
-                       to_talitos_ptr(&desc->ptr[4], edesc->dma_link_tbl, 0);
-                       dma_sync_single_for_device(dev, edesc->dma_link_tbl,
-                                                  edesc->dma_len,
-                                                  DMA_BIDIRECTIONAL);
-               } else {
-                       /* Only one segment now, so no link tbl needed */
-                       to_talitos_ptr(&desc->ptr[4],
-                                      sg_dma_address(areq->src), 0);
-               }
-       }
 
        /* cipher out */
        desc->ptr[5].len = cpu_to_be16(cryptlen);
@@ -1204,16 +1189,17 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
                                          edesc->dst_nents ? : 1,
                                          DMA_FROM_DEVICE, edesc->dst_chained);
 
-       if (sg_count == 1) {
-               to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst), 0);
-       } else {
-               int tbl_off = edesc->src_nents + 1;
+       edesc->icv_ool = false;
+
+       if (sg_count > 1 &&
+           (sg_count = sg_to_link_tbl_offset(areq->dst, sg_count,
+                                             areq->assoclen, cryptlen,
+                                             &edesc->link_tbl[tbl_off])) >
+           1) {
                struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
 
                to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl +
                               tbl_off * sizeof(struct talitos_ptr), 0);
-               sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
-                                         tbl_ptr);
 
                /* Add an entry to the link table for ICV data */
                tbl_ptr += sg_count - 1;
@@ -1224,13 +1210,16 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 
                /* icv data follows link tables */
                to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl +
-                              (tbl_off + edesc->dst_nents + 1 +
-                               edesc->assoc_nents) *
-                              sizeof(struct talitos_ptr), 0);
+                                       (edesc->src_nents + edesc->dst_nents +
+                                        2) * sizeof(struct talitos_ptr) +
+                                       authsize, 0);
                desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
                dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
                                           edesc->dma_len, DMA_BIDIRECTIONAL);
-       }
+
+               edesc->icv_ool = true;
+       } else
+               to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst), 0);
 
        /* iv out */
        map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv,
@@ -1268,7 +1257,6 @@ static int sg_count(struct scatterlist *sg_list, int nbytes, bool *chained)
  * allocate and map the extended descriptor
  */
 static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
-                                                struct scatterlist *assoc,
                                                 struct scatterlist *src,
                                                 struct scatterlist *dst,
                                                 u8 *iv,
@@ -1281,8 +1269,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                 bool encrypt)
 {
        struct talitos_edesc *edesc;
-       int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
-       bool assoc_chained = false, src_chained = false, dst_chained = false;
+       int src_nents, dst_nents, alloc_len, dma_len;
+       bool src_chained = false, dst_chained = false;
        dma_addr_t iv_dma = 0;
        gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
                      GFP_ATOMIC;
@@ -1298,48 +1286,35 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        if (ivsize)
                iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
 
-       if (assoclen) {
-               /*
-                * Currently it is assumed that iv is provided whenever assoc
-                * is.
-                */
-               BUG_ON(!iv);
-
-               assoc_nents = sg_count(assoc, assoclen, &assoc_chained);
-               talitos_map_sg(dev, assoc, assoc_nents, DMA_TO_DEVICE,
-                              assoc_chained);
-               assoc_nents = (assoc_nents == 1) ? 0 : assoc_nents;
-
-               if (assoc_nents || sg_dma_address(assoc) + assoclen != iv_dma)
-                       assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
-       }
-
        if (!dst || dst == src) {
-               src_nents = sg_count(src, cryptlen + authsize, &src_chained);
+               src_nents = sg_count(src, assoclen + cryptlen + authsize,
+                                    &src_chained);
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_nents = dst ? src_nents : 0;
        } else { /* dst && dst != src*/
-               src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
+               src_nents = sg_count(src, assoclen + cryptlen +
+                                         (encrypt ? 0 : authsize),
                                     &src_chained);
                src_nents = (src_nents == 1) ? 0 : src_nents;
-               dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
+               dst_nents = sg_count(dst, assoclen + cryptlen +
+                                         (encrypt ? authsize : 0),
                                     &dst_chained);
                dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
 
        /*
         * allocate space for base edesc plus the link tables,
-        * allowing for two separate entries for ICV and generated ICV (+ 2),
-        * and the ICV data itself
+        * allowing for two separate entries for AD and generated ICV (+ 2),
+        * and space for two sets of ICVs (stashed and generated)
         */
        alloc_len = sizeof(struct talitos_edesc);
-       if (assoc_nents || src_nents || dst_nents) {
+       if (src_nents || dst_nents) {
                if (is_sec1)
                        dma_len = (src_nents ? cryptlen : 0) +
                                  (dst_nents ? cryptlen : 0);
                else
-                       dma_len = (src_nents + dst_nents + 2 + assoc_nents) *
-                                 sizeof(struct talitos_ptr) + authsize;
+                       dma_len = (src_nents + dst_nents + 2) *
+                                 sizeof(struct talitos_ptr) + authsize * 2;
                alloc_len += dma_len;
        } else {
                dma_len = 0;
@@ -1348,13 +1323,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
        if (!edesc) {
-               if (assoc_chained)
-                       talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
-               else if (assoclen)
-                       dma_unmap_sg(dev, assoc,
-                                    assoc_nents ? assoc_nents - 1 : 1,
-                                    DMA_TO_DEVICE);
-
                if (iv_dma)
                        dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
 
@@ -1362,10 +1330,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                return ERR_PTR(-ENOMEM);
        }
 
-       edesc->assoc_nents = assoc_nents;
        edesc->src_nents = src_nents;
        edesc->dst_nents = dst_nents;
-       edesc->assoc_chained = assoc_chained;
        edesc->src_chained = src_chained;
        edesc->dst_chained = dst_chained;
        edesc->iv_dma = iv_dma;
@@ -1382,12 +1348,13 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
                                              int icv_stashing, bool encrypt)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
+       unsigned int authsize = crypto_aead_authsize(authenc);
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
        unsigned int ivsize = crypto_aead_ivsize(authenc);
 
-       return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
+       return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
                                   iv, areq->assoclen, areq->cryptlen,
-                                  ctx->authsize, ivsize, icv_stashing,
+                                  authsize, ivsize, icv_stashing,
                                   areq->base.flags, encrypt);
 }
 
@@ -1405,14 +1372,14 @@ static int aead_encrypt(struct aead_request *req)
        /* set encrypt */
        edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
 
-       return ipsec_esp(edesc, req, 0, ipsec_esp_encrypt_done);
+       return ipsec_esp(edesc, req, ipsec_esp_encrypt_done);
 }
 
 static int aead_decrypt(struct aead_request *req)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+       unsigned int authsize = crypto_aead_authsize(authenc);
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-       unsigned int authsize = ctx->authsize;
        struct talitos_private *priv = dev_get_drvdata(ctx->dev);
        struct talitos_edesc *edesc;
        struct scatterlist *sg;
@@ -1437,7 +1404,7 @@ static int aead_decrypt(struct aead_request *req)
                /* reset integrity check result bits */
                edesc->desc.hdr_lo = 0;
 
-               return ipsec_esp(edesc, req, 0, ipsec_esp_decrypt_hwauth_done);
+               return ipsec_esp(edesc, req, ipsec_esp_decrypt_hwauth_done);
        }
 
        /* Have to check the ICV with software */
@@ -1445,40 +1412,16 @@ static int aead_decrypt(struct aead_request *req)
 
        /* stash incoming ICV for later cmp with ICV generated by the h/w */
        if (edesc->dma_len)
-               icvdata = &edesc->link_tbl[edesc->src_nents +
-                                          edesc->dst_nents + 2 +
-                                          edesc->assoc_nents];
+               icvdata = (char *)&edesc->link_tbl[edesc->src_nents +
+                                                  edesc->dst_nents + 2];
        else
                icvdata = &edesc->link_tbl[0];
 
        sg = sg_last(req->src, edesc->src_nents ? : 1);
 
-       memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
-              ctx->authsize);
+       memcpy(icvdata, (char *)sg_virt(sg) + sg->length - authsize, authsize);
 
-       return ipsec_esp(edesc, req, 0, ipsec_esp_decrypt_swauth_done);
-}
-
-static int aead_givencrypt(struct aead_givcrypt_request *req)
-{
-       struct aead_request *areq = &req->areq;
-       struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
-       struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
-       struct talitos_edesc *edesc;
-
-       /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(areq, req->giv, 0, true);
-       if (IS_ERR(edesc))
-               return PTR_ERR(edesc);
-
-       /* set encrypt */
-       edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
-
-       memcpy(req->giv, ctx->iv, crypto_aead_ivsize(authenc));
-       /* avoid consecutive packets going out with same IV */
-       *(__be64 *)req->giv ^= cpu_to_be64(req->seq);
-
-       return ipsec_esp(edesc, areq, req->seq, ipsec_esp_encrypt_done);
+       return ipsec_esp(edesc, req, ipsec_esp_decrypt_swauth_done);
 }
 
 static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
@@ -1710,7 +1653,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
        struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
        unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
 
-       return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
+       return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst,
                                   areq->info, 0, areq->nbytes, 0, ivsize, 0,
                                   areq->base.flags, encrypt);
 }
@@ -1895,7 +1838,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
        struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
        struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 
-       return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
+       return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, NULL, 0,
                                   nbytes, 0, 0, 0, areq->base.flags, false);
 }
 
@@ -2161,6 +2104,7 @@ struct talitos_alg_template {
        union {
                struct crypto_alg crypto;
                struct ahash_alg hash;
+               struct aead_alg aead;
        } alg;
        __be32 desc_hdr_template;
 };
@@ -2168,15 +2112,16 @@ struct talitos_alg_template {
 static struct talitos_alg_template driver_algs[] = {
        /* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha1),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA1_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-aes-talitos",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_AESU |
@@ -2187,15 +2132,17 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA1_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha1),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha1-"
+                                                  "cbc-3des-talitos",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA1_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_DEU |
@@ -2207,15 +2154,16 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_SHA1_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha224),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha224-cbc-aes-talitos",
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA224_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "cbc-aes-talitos",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_AESU |
@@ -2226,15 +2174,17 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha224),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha224-cbc-3des-talitos",
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA224_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha224),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha224-"
+                                                  "cbc-3des-talitos",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA224_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_DEU |
@@ -2246,15 +2196,16 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_SHA224_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha256),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA256_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-aes-talitos",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_AESU |
@@ -2265,15 +2216,17 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA256_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha256),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha256-"
+                                                  "cbc-3des-talitos",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA256_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_DEU |
@@ -2285,15 +2238,16 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_SHA256_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha384),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha384-cbc-aes-talitos",
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA384_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "cbc-aes-talitos",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_AESU |
@@ -2304,15 +2258,17 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha384),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha384-cbc-3des-talitos",
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA384_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha384),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha384-"
+                                                  "cbc-3des-talitos",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA384_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_DEU |
@@ -2324,15 +2280,16 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEUB_SHA384_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha512),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-sha512-cbc-aes-talitos",
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = SHA512_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha512),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "cbc-aes-talitos",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_AESU |
@@ -2343,15 +2300,17 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(sha512),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-sha512-cbc-3des-talitos",
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = SHA512_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(sha512),"
+                                           "cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-sha512-"
+                                                  "cbc-3des-talitos",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = SHA512_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_DEU |
@@ -2363,15 +2322,16 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEUB_SHA512_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(md5),cbc(aes))",
-                       .cra_driver_name = "authenc-hmac-md5-cbc-aes-talitos",
-                       .cra_blocksize = AES_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = AES_BLOCK_SIZE,
-                               .maxauthsize = MD5_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(aes))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-aes-talitos",
+                               .cra_blocksize = AES_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = AES_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_AESU |
@@ -2382,15 +2342,16 @@ static struct talitos_alg_template driver_algs[] = {
                                     DESC_HDR_MODE1_MDEU_MD5_HMAC,
        },
        {       .type = CRYPTO_ALG_TYPE_AEAD,
-               .alg.crypto = {
-                       .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
-                       .cra_driver_name = "authenc-hmac-md5-cbc-3des-talitos",
-                       .cra_blocksize = DES3_EDE_BLOCK_SIZE,
-                       .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-                       .cra_aead = {
-                               .ivsize = DES3_EDE_BLOCK_SIZE,
-                               .maxauthsize = MD5_DIGEST_SIZE,
-                       }
+               .alg.aead = {
+                       .base = {
+                               .cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+                               .cra_driver_name = "authenc-hmac-md5-"
+                                                  "cbc-3des-talitos",
+                               .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+                               .cra_flags = CRYPTO_ALG_ASYNC,
+                       },
+                       .ivsize = DES3_EDE_BLOCK_SIZE,
+                       .maxauthsize = MD5_DIGEST_SIZE,
                },
                .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
                                     DESC_HDR_SEL0_DEU |
@@ -2658,15 +2619,9 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
        return 0;
 }
 
-static int talitos_cra_init_aead(struct crypto_tfm *tfm)
+static int talitos_cra_init_aead(struct crypto_aead *tfm)
 {
-       struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
-
-       talitos_cra_init(tfm);
-
-       /* random first IV */
-       get_random_bytes(ctx->iv, TALITOS_MAX_IV_LENGTH);
-
+       talitos_cra_init(crypto_aead_tfm(tfm));
        return 0;
 }
 
@@ -2713,9 +2668,9 @@ static int talitos_remove(struct platform_device *ofdev)
        list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
                switch (t_alg->algt.type) {
                case CRYPTO_ALG_TYPE_ABLKCIPHER:
-               case CRYPTO_ALG_TYPE_AEAD:
-                       crypto_unregister_alg(&t_alg->algt.alg.crypto);
                        break;
+               case CRYPTO_ALG_TYPE_AEAD:
+                       crypto_unregister_aead(&t_alg->algt.alg.aead);
                case CRYPTO_ALG_TYPE_AHASH:
                        crypto_unregister_ahash(&t_alg->algt.alg.hash);
                        break;
@@ -2727,7 +2682,7 @@ static int talitos_remove(struct platform_device *ofdev)
        if (hw_supports(dev, DESC_HDR_SEL0_RNG))
                talitos_unregister_rng(dev);
 
-       for (i = 0; i < priv->num_channels; i++)
+       for (i = 0; priv->chan && i < priv->num_channels; i++)
                kfree(priv->chan[i].fifo);
 
        kfree(priv->chan);
@@ -2774,15 +2729,11 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
                alg->cra_ablkcipher.geniv = "eseqiv";
                break;
        case CRYPTO_ALG_TYPE_AEAD:
-               alg = &t_alg->algt.alg.crypto;
-               alg->cra_init = talitos_cra_init_aead;
-               alg->cra_type = &crypto_aead_type;
-               alg->cra_aead.setkey = aead_setkey;
-               alg->cra_aead.setauthsize = aead_setauthsize;
-               alg->cra_aead.encrypt = aead_encrypt;
-               alg->cra_aead.decrypt = aead_decrypt;
-               alg->cra_aead.givencrypt = aead_givencrypt;
-               alg->cra_aead.geniv = "<built-in>";
+               alg = &t_alg->algt.alg.aead.base;
+               t_alg->algt.alg.aead.init = talitos_cra_init_aead;
+               t_alg->algt.alg.aead.setkey = aead_setkey;
+               t_alg->algt.alg.aead.encrypt = aead_encrypt;
+               t_alg->algt.alg.aead.decrypt = aead_decrypt;
                break;
        case CRYPTO_ALG_TYPE_AHASH:
                alg = &t_alg->algt.alg.hash.halg.base;
@@ -3041,7 +2992,7 @@ static int talitos_probe(struct platform_device *ofdev)
        for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
                if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
                        struct talitos_crypto_alg *t_alg;
-                       char *name = NULL;
+                       struct crypto_alg *alg = NULL;
 
                        t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
                        if (IS_ERR(t_alg)) {
@@ -3053,21 +3004,26 @@ static int talitos_probe(struct platform_device *ofdev)
 
                        switch (t_alg->algt.type) {
                        case CRYPTO_ALG_TYPE_ABLKCIPHER:
-                       case CRYPTO_ALG_TYPE_AEAD:
                                err = crypto_register_alg(
                                                &t_alg->algt.alg.crypto);
-                               name = t_alg->algt.alg.crypto.cra_driver_name;
+                               alg = &t_alg->algt.alg.crypto;
                                break;
+
+                       case CRYPTO_ALG_TYPE_AEAD:
+                               err = crypto_register_aead(
+                                       &t_alg->algt.alg.aead);
+                               alg = &t_alg->algt.alg.aead.base;
+                               break;
+
                        case CRYPTO_ALG_TYPE_AHASH:
                                err = crypto_register_ahash(
                                                &t_alg->algt.alg.hash);
-                               name =
-                                t_alg->algt.alg.hash.halg.base.cra_driver_name;
+                               alg = &t_alg->algt.alg.hash.halg.base;
                                break;
                        }
                        if (err) {
                                dev_err(dev, "%s alg registration failed\n",
-                                       name);
+                                       alg->cra_driver_name);
                                kfree(t_alg);
                        } else
                                list_add_tail(&t_alg->entry, &priv->alg_list);
index 314daf55e7f77791d075065a427b531bb361cce1..0090f3211d68bc94af9d4105f51de7c1123ded0b 100644 (file)
@@ -52,12 +52,7 @@ struct talitos_ptr {
        __be32 ptr;     /* address */
 };
 
-static const struct talitos_ptr zero_entry = {
-       .len = 0,
-       .j_extent = 0,
-       .eptr = 0,
-       .ptr = 0
-};
+static const struct talitos_ptr zero_entry;
 
 /* descriptor */
 struct talitos_desc {
@@ -154,6 +149,7 @@ struct talitos_private {
 
        /* hwrng device */
        struct hwrng rng;
+       bool rng_registered;
 };
 
 extern int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
index e79e567e43aacae4584b32c2d7fc9ae1e6c1e300..263af709e53604ee5a049f707d2e9f5795031d1d 100644 (file)
@@ -84,6 +84,7 @@ static int p8_aes_setkey(struct crypto_tfm *tfm, const u8 *key,
        preempt_disable();
        pagefault_disable();
        enable_kernel_altivec();
+       enable_kernel_vsx();
        ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
        ret += aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);
        pagefault_enable();
@@ -103,6 +104,7 @@ static void p8_aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
                preempt_disable();
                pagefault_disable();
                enable_kernel_altivec();
+               enable_kernel_vsx();
                aes_p8_encrypt(src, dst, &ctx->enc_key);
                pagefault_enable();
                preempt_enable();
@@ -119,6 +121,7 @@ static void p8_aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
                preempt_disable();
                pagefault_disable();
                enable_kernel_altivec();
+               enable_kernel_vsx();
                aes_p8_decrypt(src, dst, &ctx->dec_key);
                pagefault_enable();
                preempt_enable();
index 7299995c78ec3b34ea76e289cf84dc877f1175ef..0b8fe2ec5315fc8253431ca533d953b9c72d7243 100644 (file)
@@ -85,6 +85,7 @@ static int p8_aes_cbc_setkey(struct crypto_tfm *tfm, const u8 *key,
        preempt_disable();
        pagefault_disable();
        enable_kernel_altivec();
+       enable_kernel_vsx();
        ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
        ret += aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key);
        pagefault_enable();
@@ -115,6 +116,7 @@ static int p8_aes_cbc_encrypt(struct blkcipher_desc *desc,
                preempt_disable();
                pagefault_disable();
                enable_kernel_altivec();
+               enable_kernel_vsx();
 
                blkcipher_walk_init(&walk, dst, src, nbytes);
                ret = blkcipher_walk_virt(desc, &walk);
@@ -155,6 +157,7 @@ static int p8_aes_cbc_decrypt(struct blkcipher_desc *desc,
                preempt_disable();
                pagefault_disable();
                enable_kernel_altivec();
+               enable_kernel_vsx();
 
                blkcipher_walk_init(&walk, dst, src, nbytes);
                ret = blkcipher_walk_virt(desc, &walk);
index 7adae42a7b79ea81a5bc35ae2db9db9b6a2437e2..ee1306cd8f59bc5fd2d1f8b286ff5f553d53cc85 100644 (file)
@@ -82,6 +82,7 @@ static int p8_aes_ctr_setkey(struct crypto_tfm *tfm, const u8 *key,
 
        pagefault_disable();
        enable_kernel_altivec();
+       enable_kernel_vsx();
        ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key);
        pagefault_enable();
 
@@ -100,6 +101,7 @@ static void p8_aes_ctr_final(struct p8_aes_ctr_ctx *ctx,
 
        pagefault_disable();
        enable_kernel_altivec();
+       enable_kernel_vsx();
        aes_p8_encrypt(ctrblk, keystream, &ctx->enc_key);
        pagefault_enable();
 
@@ -113,6 +115,7 @@ static int p8_aes_ctr_crypt(struct blkcipher_desc *desc,
                            struct scatterlist *src, unsigned int nbytes)
 {
        int ret;
+       u64 inc;
        struct blkcipher_walk walk;
        struct p8_aes_ctr_ctx *ctx =
                crypto_tfm_ctx(crypto_blkcipher_tfm(desc->tfm));
@@ -131,6 +134,7 @@ static int p8_aes_ctr_crypt(struct blkcipher_desc *desc,
                while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
                        pagefault_disable();
                        enable_kernel_altivec();
+                       enable_kernel_vsx();
                        aes_p8_ctr32_encrypt_blocks(walk.src.virt.addr,
                                                    walk.dst.virt.addr,
                                                    (nbytes &
@@ -140,7 +144,12 @@ static int p8_aes_ctr_crypt(struct blkcipher_desc *desc,
                                                    walk.iv);
                        pagefault_enable();
 
-                       crypto_inc(walk.iv, AES_BLOCK_SIZE);
+                       /* We need to update IV mostly for last bytes/round */
+                       inc = (nbytes & AES_BLOCK_MASK) / AES_BLOCK_SIZE;
+                       if (inc > 0)
+                               while (inc--)
+                                       crypto_inc(walk.iv, AES_BLOCK_SIZE);
+
                        nbytes &= AES_BLOCK_SIZE - 1;
                        ret = blkcipher_walk_done(desc, &walk, nbytes);
                }
index 6c5c20c6108e7bd25bd2075a1155d88110832b0b..228053921b3f024f468dbcf720c31bcb3cc58437 100644 (file)
@@ -1437,28 +1437,28 @@ Load_ctr32_enc_key:
        ?vperm          v31,v31,$out0,$keyperm
        lvx             v25,$x10,$key_          # pre-load round[2]
 
-       vadduwm         $two,$one,$one
+       vadduqm         $two,$one,$one
        subi            $inp,$inp,15            # undo "caller"
        $SHL            $len,$len,4
 
-       vadduwm         $out1,$ivec,$one        # counter values ...
-       vadduwm         $out2,$ivec,$two
+       vadduqm         $out1,$ivec,$one        # counter values ...
+       vadduqm         $out2,$ivec,$two
        vxor            $out0,$ivec,$rndkey0    # ... xored with rndkey[0]
         le?li          $idx,8
-       vadduwm         $out3,$out1,$two
+       vadduqm         $out3,$out1,$two
        vxor            $out1,$out1,$rndkey0
         le?lvsl        $inpperm,0,$idx
-       vadduwm         $out4,$out2,$two
+       vadduqm         $out4,$out2,$two
        vxor            $out2,$out2,$rndkey0
         le?vspltisb    $tmp,0x0f
-       vadduwm         $out5,$out3,$two
+       vadduqm         $out5,$out3,$two
        vxor            $out3,$out3,$rndkey0
         le?vxor        $inpperm,$inpperm,$tmp  # transform for lvx_u/stvx_u
-       vadduwm         $out6,$out4,$two
+       vadduqm         $out6,$out4,$two
        vxor            $out4,$out4,$rndkey0
-       vadduwm         $out7,$out5,$two
+       vadduqm         $out7,$out5,$two
        vxor            $out5,$out5,$rndkey0
-       vadduwm         $ivec,$out6,$two        # next counter value
+       vadduqm         $ivec,$out6,$two        # next counter value
        vxor            $out6,$out6,$rndkey0
        vxor            $out7,$out7,$rndkey0
 
@@ -1594,27 +1594,27 @@ Loop_ctr32_enc8x_middle:
 
        vcipherlast     $in0,$out0,$in0
        vcipherlast     $in1,$out1,$in1
-        vadduwm        $out1,$ivec,$one        # counter values ...
+        vadduqm        $out1,$ivec,$one        # counter values ...
        vcipherlast     $in2,$out2,$in2
-        vadduwm        $out2,$ivec,$two
+        vadduqm        $out2,$ivec,$two
         vxor           $out0,$ivec,$rndkey0    # ... xored with rndkey[0]
        vcipherlast     $in3,$out3,$in3
-        vadduwm        $out3,$out1,$two
+        vadduqm        $out3,$out1,$two
         vxor           $out1,$out1,$rndkey0
        vcipherlast     $in4,$out4,$in4
-        vadduwm        $out4,$out2,$two
+        vadduqm        $out4,$out2,$two
         vxor           $out2,$out2,$rndkey0
        vcipherlast     $in5,$out5,$in5
-        vadduwm        $out5,$out3,$two
+        vadduqm        $out5,$out3,$two
         vxor           $out3,$out3,$rndkey0
        vcipherlast     $in6,$out6,$in6
-        vadduwm        $out6,$out4,$two
+        vadduqm        $out6,$out4,$two
         vxor           $out4,$out4,$rndkey0
        vcipherlast     $in7,$out7,$in7
-        vadduwm        $out7,$out5,$two
+        vadduqm        $out7,$out5,$two
         vxor           $out5,$out5,$rndkey0
        le?vperm        $in0,$in0,$in0,$inpperm
-        vadduwm        $ivec,$out6,$two        # next counter value
+        vadduqm        $ivec,$out6,$two        # next counter value
         vxor           $out6,$out6,$rndkey0
        le?vperm        $in1,$in1,$in1,$inpperm
         vxor           $out7,$out7,$rndkey0
index b5e29002b66678337c54ec7858634d43285c4213..2183a2e77641e0682ca113951430765bcbcca4fc 100644 (file)
@@ -119,6 +119,7 @@ static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key,
        preempt_disable();
        pagefault_disable();
        enable_kernel_altivec();
+       enable_kernel_vsx();
        enable_kernel_fp();
        gcm_init_p8(ctx->htable, (const u64 *) key);
        pagefault_enable();
@@ -149,6 +150,7 @@ static int p8_ghash_update(struct shash_desc *desc,
                        preempt_disable();
                        pagefault_disable();
                        enable_kernel_altivec();
+                       enable_kernel_vsx();
                        enable_kernel_fp();
                        gcm_ghash_p8(dctx->shash, ctx->htable,
                                     dctx->buffer, GHASH_DIGEST_SIZE);
@@ -163,6 +165,7 @@ static int p8_ghash_update(struct shash_desc *desc,
                        preempt_disable();
                        pagefault_disable();
                        enable_kernel_altivec();
+                       enable_kernel_vsx();
                        enable_kernel_fp();
                        gcm_ghash_p8(dctx->shash, ctx->htable, src, len);
                        pagefault_enable();
@@ -193,6 +196,7 @@ static int p8_ghash_final(struct shash_desc *desc, u8 *out)
                        preempt_disable();
                        pagefault_disable();
                        enable_kernel_altivec();
+                       enable_kernel_vsx();
                        enable_kernel_fp();
                        gcm_ghash_p8(dctx->shash, ctx->htable,
                                     dctx->buffer, GHASH_DIGEST_SIZE);
index 0a6f899839ddb2ff47044f560a776725b86e5dfc..d8429cb71f02761df72060a7e757c58901681302 100644 (file)
@@ -61,6 +61,12 @@ $code=<<___;
        mtspr           256,r0
        li              r10,0x30
        lvx_u           $H,0,r4                 # load H
+       le?xor          r7,r7,r7
+       le?addi         r7,r7,0x8               # need a vperm start with 08
+       le?lvsr         5,0,r7
+       le?vspltisb     6,0x0f
+       le?vxor         5,5,6                   # set a b-endian mask
+       le?vperm        $H,$H,$H,5
 
        vspltisb        $xC2,-16                # 0xf0
        vspltisb        $t0,1                   # one
index a59188494af872e687dec62a268353f2fde5c8d9..b9997335f1937eb8694321ef0e37c66c8877a6c2 100644 (file)
@@ -169,6 +169,7 @@ my $vpmsumd = sub { vcrypto_op(@_, 1224); };
 my $vpmsubh    = sub { vcrypto_op(@_, 1096); };
 my $vpmsumw    = sub { vcrypto_op(@_, 1160); };
 my $vaddudm    = sub { vcrypto_op(@_, 192);  };
+my $vadduqm    = sub { vcrypto_op(@_, 256);  };
 
 my $mtsle      = sub {
     my ($f, $arg) = @_;
index 4a4cce15f25dd65c6a720d949ed0d9c922ff1cba..3ff284c8e3d5aef72f229017c883c73cbe13403f 100644 (file)
@@ -689,6 +689,10 @@ struct dma_chan *dma_request_slave_channel(struct device *dev,
        struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
        if (IS_ERR(ch))
                return NULL;
+
+       dma_cap_set(DMA_PRIVATE, ch->device->cap_mask);
+       ch->device->privatecnt++;
+
        return ch;
 }
 EXPORT_SYMBOL_GPL(dma_request_slave_channel);
index 3515b381c1312612f56953bc267ee7d5d23b0f84..711d8ad74f116ebdcc7fd3833fbc0672c7a6359b 100644 (file)
@@ -920,7 +920,7 @@ static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
         */
 
        for (row = 0; row < mci->nr_csrows; row++) {
-               struct csrow_info *csi = &mci->csrows[row];
+               struct csrow_info *csi = mci->csrows[row];
 
                /*
                 * Get the configuration settings for this
index ad87f263056f1f4995dba394af244e829afa2f84..4b9f09cc38d879899b18314509d20a7292f81fa6 100644 (file)
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 #include <linux/regulator/consumer.h>
 #include <linux/extcon.h>
 
@@ -46,6 +48,9 @@
 #define HPDET_DEBOUNCE 500
 #define DEFAULT_MICD_TIMEOUT 2000
 
+#define MICD_DBTIME_TWO_READINGS 2
+#define MICD_DBTIME_FOUR_READINGS 4
+
 #define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
                         ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
                         ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
@@ -94,6 +99,8 @@ struct arizona_extcon_info {
        int hpdet_ip_version;
 
        struct extcon_dev *edev;
+
+       struct gpio_desc *micd_pol_gpio;
 };
 
 static const struct arizona_micd_config micd_default_modes[] = {
@@ -204,6 +211,10 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
        if (arizona->pdata.micd_pol_gpio > 0)
                gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
                                        info->micd_modes[mode].gpio);
+       else
+               gpiod_set_value_cansleep(info->micd_pol_gpio,
+                                        info->micd_modes[mode].gpio);
+
        regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
                           ARIZONA_MICD_BIAS_SRC_MASK,
                           info->micd_modes[mode].bias <<
@@ -757,10 +768,11 @@ static void arizona_micd_timeout_work(struct work_struct *work)
        mutex_lock(&info->lock);
 
        dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
-       arizona_identify_headphone(info);
 
        info->detecting = false;
 
+       arizona_identify_headphone(info);
+
        arizona_stop_mic(info);
 
        mutex_unlock(&info->lock);
@@ -820,12 +832,18 @@ static void arizona_micd_detect(struct work_struct *work)
        /* Due to jack detect this should never happen */
        if (!(val & ARIZONA_MICD_STS)) {
                dev_warn(arizona->dev, "Detected open circuit\n");
+               info->mic = false;
+               arizona_stop_mic(info);
                info->detecting = false;
+               arizona_identify_headphone(info);
                goto handled;
        }
 
        /* If we got a high impedence we should have a headset, report it. */
        if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
+               info->mic = true;
+               info->detecting = false;
+
                arizona_identify_headphone(info);
 
                ret = extcon_set_cable_state_(info->edev,
@@ -841,8 +859,6 @@ static void arizona_micd_detect(struct work_struct *work)
                                ret);
                }
 
-               info->mic = true;
-               info->detecting = false;
                goto handled;
        }
 
@@ -855,10 +871,11 @@ static void arizona_micd_detect(struct work_struct *work)
        if (info->detecting && (val & MICD_LVL_1_TO_7)) {
                if (info->jack_flips >= info->micd_num_modes * 10) {
                        dev_dbg(arizona->dev, "Detected HP/line\n");
-                       arizona_identify_headphone(info);
 
                        info->detecting = false;
 
+                       arizona_identify_headphone(info);
+
                        arizona_stop_mic(info);
                } else {
                        info->micd_mode++;
@@ -1110,12 +1127,12 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
        regmap_update_bits(arizona->regmap, reg, mask, level);
 }
 
-static int arizona_extcon_of_get_pdata(struct arizona *arizona)
+static int arizona_extcon_device_get_pdata(struct arizona *arizona)
 {
        struct arizona_pdata *pdata = &arizona->pdata;
        unsigned int val = ARIZONA_ACCDET_MODE_HPL;
 
-       of_property_read_u32(arizona->dev->of_node, "wlf,hpdet-channel", &val);
+       device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
        switch (val) {
        case ARIZONA_ACCDET_MODE_HPL:
        case ARIZONA_ACCDET_MODE_HPR:
@@ -1127,6 +1144,24 @@ static int arizona_extcon_of_get_pdata(struct arizona *arizona)
                pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
        }
 
+       device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
+                                &pdata->micd_detect_debounce);
+
+       device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
+                                &pdata->micd_bias_start_time);
+
+       device_property_read_u32(arizona->dev, "wlf,micd-rate",
+                                &pdata->micd_rate);
+
+       device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
+                                &pdata->micd_dbtime);
+
+       device_property_read_u32(arizona->dev, "wlf,micd-timeout",
+                                &pdata->micd_timeout);
+
+       pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
+                                               "wlf,micd-force-micbias");
+
        return 0;
 }
 
@@ -1147,10 +1182,8 @@ static int arizona_extcon_probe(struct platform_device *pdev)
        if (!info)
                return -ENOMEM;
 
-       if (IS_ENABLED(CONFIG_OF)) {
-               if (!dev_get_platdata(arizona->dev))
-                       arizona_extcon_of_get_pdata(arizona);
-       }
+       if (!dev_get_platdata(arizona->dev))
+               arizona_extcon_device_get_pdata(arizona);
 
        info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
        if (IS_ERR(info->micvdd)) {
@@ -1241,6 +1274,27 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                                arizona->pdata.micd_pol_gpio, ret);
                        goto err_register;
                }
+       } else {
+               if (info->micd_modes[0].gpio)
+                       mode = GPIOD_OUT_HIGH;
+               else
+                       mode = GPIOD_OUT_LOW;
+
+               /* We can't use devm here because we need to do the get
+                * against the MFD device, as that is where the of_node
+                * will reside, but if we devm against that the GPIO
+                * will not be freed if the extcon driver is unloaded.
+                */
+               info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
+                                                        "wlf,micd-pol",
+                                                        GPIOD_OUT_LOW);
+               if (IS_ERR(info->micd_pol_gpio)) {
+                       ret = PTR_ERR(info->micd_pol_gpio);
+                       dev_err(arizona->dev,
+                               "Failed to get microphone polarity GPIO: %d\n",
+                               ret);
+                       goto err_register;
+               }
        }
 
        if (arizona->pdata.hpdet_id_gpio > 0) {
@@ -1251,7 +1305,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
                                arizona->pdata.hpdet_id_gpio, ret);
-                       goto err_register;
+                       goto err_gpio;
                }
        }
 
@@ -1267,11 +1321,19 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                                   arizona->pdata.micd_rate
                                   << ARIZONA_MICD_RATE_SHIFT);
 
-       if (arizona->pdata.micd_dbtime)
+       switch (arizona->pdata.micd_dbtime) {
+       case MICD_DBTIME_FOUR_READINGS:
                regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
                                   ARIZONA_MICD_DBTIME_MASK,
-                                  arizona->pdata.micd_dbtime
-                                  << ARIZONA_MICD_DBTIME_SHIFT);
+                                  ARIZONA_MICD_DBTIME);
+               break;
+       case MICD_DBTIME_TWO_READINGS:
+               regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
+                                  ARIZONA_MICD_DBTIME_MASK, 0);
+               break;
+       default:
+               break;
+       }
 
        BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
 
@@ -1295,7 +1357,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                                dev_err(arizona->dev,
                                        "MICD ranges must be sorted\n");
                                ret = -EINVAL;
-                               goto err_input;
+                               goto err_gpio;
                        }
                }
        }
@@ -1314,7 +1376,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
                        dev_err(arizona->dev, "Unsupported MICD level %d\n",
                                info->micd_ranges[i].max);
                        ret = -EINVAL;
-                       goto err_input;
+                       goto err_gpio;
                }
 
                dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
@@ -1387,7 +1449,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
                        ret);
-               goto err_input;
+               goto err_gpio;
        }
 
        ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
@@ -1458,7 +1520,8 @@ err_rise_wake:
        arizona_set_irq_wake(arizona, jack_irq_rise, 0);
 err_rise:
        arizona_free_irq(arizona, jack_irq_rise, info);
-err_input:
+err_gpio:
+       gpiod_put(info->micd_pol_gpio);
 err_register:
        pm_runtime_disable(&pdev->dev);
        return ret;
@@ -1470,6 +1533,8 @@ static int arizona_extcon_remove(struct platform_device *pdev)
        struct arizona *arizona = info->arizona;
        int jack_irq_rise, jack_irq_fall;
 
+       gpiod_put(info->micd_pol_gpio);
+
        pm_runtime_disable(&pdev->dev);
 
        regmap_update_bits(arizona->regmap,
index 355459a54e8b4fabe8c496fedeae7cef7d66add6..57c24fa52edb8ebf818489851f0425615bdda5f0 100644 (file)
@@ -65,22 +65,6 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
-{
-       struct device *dev = edev->dev.parent;
-       struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev);
-       const char *state;
-
-       if (extcon_get_state(edev))
-               state = extcon_data->state_on;
-       else
-               state = extcon_data->state_off;
-
-       if (state)
-               return sprintf(buf, "%s\n", state);
-       return -EINVAL;
-}
-
 static int gpio_extcon_probe(struct platform_device *pdev)
 {
        struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -110,8 +94,6 @@ static int gpio_extcon_probe(struct platform_device *pdev)
        extcon_data->state_on = pdata->state_on;
        extcon_data->state_off = pdata->state_off;
        extcon_data->check_on_resume = pdata->check_on_resume;
-       if (pdata->state_on && pdata->state_off)
-               extcon_data->edev->print_state = extcon_gpio_print_state;
 
        ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
                                    pdev->name);
index f4f3b3d5392823e145ffa89cf223bd0b45c76892..35b9e118b2fb5b6f47d108033a4ad19b9abccabd 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
 #include <linux/extcon.h>
 #include <linux/regmap.h>
@@ -42,7 +43,7 @@ static struct max77693_reg_data default_init_data[] = {
        {
                /* STATUS2 - [3]ChgDetRun */
                .addr = MAX77693_MUIC_REG_STATUS2,
-               .data = STATUS2_CHGDETRUN_MASK,
+               .data = MAX77693_STATUS2_CHGDETRUN_MASK,
        }, {
                /* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */
                .addr = MAX77693_MUIC_REG_INTMASK1,
@@ -235,7 +236,7 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
                 */
                ret = regmap_write(info->max77693->regmap_muic,
                                  MAX77693_MUIC_REG_CTRL3,
-                                 time << CONTROL3_ADCDBSET_SHIFT);
+                                 time << MAX77693_CONTROL3_ADCDBSET_SHIFT);
                if (ret) {
                        dev_err(info->dev, "failed to set ADC debounce time\n");
                        return ret;
@@ -268,7 +269,7 @@ static int max77693_muic_set_path(struct max77693_muic_info *info,
        if (attached)
                ctrl1 = val;
        else
-               ctrl1 = CONTROL1_SW_OPEN;
+               ctrl1 = MAX77693_CONTROL1_SW_OPEN;
 
        ret = regmap_update_bits(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1);
@@ -278,13 +279,14 @@ static int max77693_muic_set_path(struct max77693_muic_info *info,
        }
 
        if (attached)
-               ctrl2 |= CONTROL2_CPEN_MASK;    /* LowPwr=0, CPEn=1 */
+               ctrl2 |= MAX77693_CONTROL2_CPEN_MASK;   /* LowPwr=0, CPEn=1 */
        else
-               ctrl2 |= CONTROL2_LOWPWR_MASK;  /* LowPwr=1, CPEn=0 */
+               ctrl2 |= MAX77693_CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
 
        ret = regmap_update_bits(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_CTRL2,
-                       CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
+                       MAX77693_CONTROL2_LOWPWR_MASK | MAX77693_CONTROL2_CPEN_MASK,
+                       ctrl2);
        if (ret < 0) {
                dev_err(info->dev, "failed to update MUIC register\n");
                return ret;
@@ -326,8 +328,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
                 * Read ADC value to check cable type and decide cable state
                 * according to cable type
                 */
-               adc = info->status[0] & STATUS1_ADC_MASK;
-               adc >>= STATUS1_ADC_SHIFT;
+               adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;
+               adc >>= MAX77693_STATUS1_ADC_SHIFT;
 
                /*
                 * Check current cable state/cable type and store cable type
@@ -350,8 +352,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
                 * Read ADC value to check cable type and decide cable state
                 * according to cable type
                 */
-               adc = info->status[0] & STATUS1_ADC_MASK;
-               adc >>= STATUS1_ADC_SHIFT;
+               adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;
+               adc >>= MAX77693_STATUS1_ADC_SHIFT;
 
                /*
                 * Check current cable state/cable type and store cable type
@@ -366,13 +368,13 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
                } else {
                        *attached = true;
 
-                       adclow = info->status[0] & STATUS1_ADCLOW_MASK;
-                       adclow >>= STATUS1_ADCLOW_SHIFT;
-                       adc1k = info->status[0] & STATUS1_ADC1K_MASK;
-                       adc1k >>= STATUS1_ADC1K_SHIFT;
+                       adclow = info->status[0] & MAX77693_STATUS1_ADCLOW_MASK;
+                       adclow >>= MAX77693_STATUS1_ADCLOW_SHIFT;
+                       adc1k = info->status[0] & MAX77693_STATUS1_ADC1K_MASK;
+                       adc1k >>= MAX77693_STATUS1_ADC1K_SHIFT;
 
-                       vbvolt = info->status[1] & STATUS2_VBVOLT_MASK;
-                       vbvolt >>= STATUS2_VBVOLT_SHIFT;
+                       vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK;
+                       vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT;
 
                        /**
                         * [0x1|VBVolt|ADCLow|ADC1K]
@@ -397,8 +399,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
                 * Read charger type to check cable type and decide cable state
                 * according to type of charger cable.
                 */
-               chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
-               chg_type >>= STATUS2_CHGTYP_SHIFT;
+               chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK;
+               chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT;
 
                if (chg_type == MAX77693_CHARGER_TYPE_NONE) {
                        *attached = false;
@@ -422,10 +424,10 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
                 * Read ADC value to check cable type and decide cable state
                 * according to cable type
                 */
-               adc = info->status[0] & STATUS1_ADC_MASK;
-               adc >>= STATUS1_ADC_SHIFT;
-               chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
-               chg_type >>= STATUS2_CHGTYP_SHIFT;
+               adc = info->status[0] & MAX77693_STATUS1_ADC_MASK;
+               adc >>= MAX77693_STATUS1_ADC_SHIFT;
+               chg_type = info->status[1] & MAX77693_STATUS2_CHGTYP_MASK;
+               chg_type >>= MAX77693_STATUS2_CHGTYP_SHIFT;
 
                if (adc == MAX77693_MUIC_ADC_OPEN
                                && chg_type == MAX77693_CHARGER_TYPE_NONE)
@@ -437,8 +439,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
                 * Read vbvolt field, if vbvolt is 1,
                 * this cable is used for charging.
                 */
-               vbvolt = info->status[1] & STATUS2_VBVOLT_MASK;
-               vbvolt >>= STATUS2_VBVOLT_SHIFT;
+               vbvolt = info->status[1] & MAX77693_STATUS2_VBVOLT_MASK;
+               vbvolt >>= MAX77693_STATUS2_VBVOLT_SHIFT;
 
                cable_type = vbvolt;
                break;
@@ -520,7 +522,8 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
        }
 
        /* Dock-Car/Desk/Audio, PATH:AUDIO */
-       ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
+       ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO,
+                                       attached);
        if (ret < 0)
                return ret;
        extcon_set_cable_state_(info->edev, dock_id, attached);
@@ -585,14 +588,16 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
        case MAX77693_MUIC_GND_USB_HOST:
        case MAX77693_MUIC_GND_USB_HOST_VB:
                /* USB_HOST, PATH: AP_USB */
-               ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
+               ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_USB,
+                                               attached);
                if (ret < 0)
                        return ret;
                extcon_set_cable_state_(info->edev, EXTCON_USB_HOST, attached);
                break;
        case MAX77693_MUIC_GND_AV_CABLE_LOAD:
                /* Audio Video Cable with load, PATH:AUDIO */
-               ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached);
+               ret = max77693_muic_set_path(info, MAX77693_CONTROL1_SW_AUDIO,
+                                               attached);
                if (ret < 0)
                        return ret;
                extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
@@ -615,7 +620,7 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info,
                int cable_type, bool attached)
 {
        int ret = 0;
-       u8 path = CONTROL1_SW_OPEN;
+       u8 path = MAX77693_CONTROL1_SW_OPEN;
 
        dev_info(info->dev,
                "external connector is %s (adc:0x%02x)\n",
@@ -625,12 +630,12 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info,
        case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:    /* ADC_JIG_USB_OFF */
        case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON:     /* ADC_JIG_USB_ON */
                /* PATH:AP_USB */
-               path = CONTROL1_SW_USB;
+               path = MAX77693_CONTROL1_SW_USB;
                break;
        case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF:   /* ADC_JIG_UART_OFF */
        case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON:    /* ADC_JIG_UART_ON */
                /* PATH:AP_UART */
-               path = CONTROL1_SW_UART;
+               path = MAX77693_CONTROL1_SW_UART;
                break;
        default:
                dev_err(info->dev, "failed to detect %s jig cable\n",
@@ -1077,7 +1082,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
                dev_dbg(&pdev->dev, "allocate register map\n");
        } else {
                info->max77693->regmap_muic = devm_regmap_init_i2c(
-                                               info->max77693->muic,
+                                               info->max77693->i2c_muic,
                                                &max77693_muic_regmap_config);
                if (IS_ERR(info->max77693->regmap_muic)) {
                        ret = PTR_ERR(info->max77693->regmap_muic);
@@ -1164,28 +1169,9 @@ static int max77693_muic_probe(struct platform_device *pdev)
        }
 
        for (i = 0; i < num_init_data; i++) {
-               enum max77693_irq_source irq_src
-                               = MAX77693_IRQ_GROUP_NR;
-
                regmap_write(info->max77693->regmap_muic,
                                init_data[i].addr,
                                init_data[i].data);
-
-               switch (init_data[i].addr) {
-               case MAX77693_MUIC_REG_INTMASK1:
-                       irq_src = MUIC_INT1;
-                       break;
-               case MAX77693_MUIC_REG_INTMASK2:
-                       irq_src = MUIC_INT2;
-                       break;
-               case MAX77693_MUIC_REG_INTMASK3:
-                       irq_src = MUIC_INT3;
-                       break;
-               }
-
-               if (irq_src < MAX77693_IRQ_GROUP_NR)
-                       info->max77693->irq_masks_cur[irq_src]
-                               = init_data[i].data;
        }
 
        if (pdata && pdata->muic_data) {
@@ -1199,12 +1185,12 @@ static int max77693_muic_probe(struct platform_device *pdev)
                if (muic_pdata->path_uart)
                        info->path_uart = muic_pdata->path_uart;
                else
-                       info->path_uart = CONTROL1_SW_UART;
+                       info->path_uart = MAX77693_CONTROL1_SW_UART;
 
                if (muic_pdata->path_usb)
                        info->path_usb = muic_pdata->path_usb;
                else
-                       info->path_usb = CONTROL1_SW_USB;
+                       info->path_usb = MAX77693_CONTROL1_SW_USB;
 
                /*
                 * Default delay time for detecting cable state
@@ -1216,8 +1202,8 @@ static int max77693_muic_probe(struct platform_device *pdev)
                else
                        delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
        } else {
-               info->path_usb = CONTROL1_SW_USB;
-               info->path_uart = CONTROL1_SW_UART;
+               info->path_usb = MAX77693_CONTROL1_SW_USB;
+               info->path_uart = MAX77693_CONTROL1_SW_UART;
                delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
        }
 
index fac2f1417a79ca47752839b79ae7a07522cb1ebb..fdd928542c19dffe06d2ba762b64b4aaf85d7442 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77843-private.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -32,7 +33,7 @@ enum max77843_muic_status {
 
 struct max77843_muic_info {
        struct device *dev;
-       struct max77843 *max77843;
+       struct max77693_dev *max77843;
        struct extcon_dev *edev;
 
        struct mutex mutex;
@@ -198,18 +199,18 @@ static const struct regmap_irq_chip max77843_muic_irq_chip = {
 static int max77843_muic_set_path(struct max77843_muic_info *info,
                u8 val, bool attached)
 {
-       struct max77843 *max77843 = info->max77843;
+       struct max77693_dev *max77843 = info->max77843;
        int ret = 0;
        unsigned int ctrl1, ctrl2;
 
        if (attached)
                ctrl1 = val;
        else
-               ctrl1 = CONTROL1_SW_OPEN;
+               ctrl1 = MAX77843_MUIC_CONTROL1_SW_OPEN;
 
        ret = regmap_update_bits(max77843->regmap_muic,
                        MAX77843_MUIC_REG_CONTROL1,
-                       CONTROL1_COM_SW, ctrl1);
+                       MAX77843_MUIC_CONTROL1_COM_SW, ctrl1);
        if (ret < 0) {
                dev_err(info->dev, "Cannot switch MUIC port\n");
                return ret;
@@ -243,7 +244,7 @@ static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
 
        adc = info->status[MAX77843_MUIC_STATUS1] &
                        MAX77843_MUIC_STATUS1_ADC_MASK;
-       adc >>= STATUS1_ADC_SHIFT;
+       adc >>= MAX77843_MUIC_STATUS1_ADC_SHIFT;
 
        switch (group) {
        case MAX77843_CABLE_GROUP_ADC:
@@ -309,7 +310,7 @@ static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
                        /* Get VBVolt register bit */
                        gnd_type |= (info->status[MAX77843_MUIC_STATUS2] &
                                        MAX77843_MUIC_STATUS2_VBVOLT_MASK);
-                       gnd_type >>= STATUS2_VBVOLT_SHIFT;
+                       gnd_type >>= MAX77843_MUIC_STATUS2_VBVOLT_SHIFT;
 
                        /* Offset of GND cable */
                        gnd_type |= MAX77843_MUIC_GND_USB_HOST;
@@ -338,7 +339,9 @@ static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
        switch (gnd_cable_type) {
        case MAX77843_MUIC_GND_USB_HOST:
        case MAX77843_MUIC_GND_USB_HOST_VB:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_USB,
+                                            attached);
                if (ret < 0)
                        return ret;
 
@@ -346,7 +349,9 @@ static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
                break;
        case MAX77843_MUIC_GND_MHL_VB:
        case MAX77843_MUIC_GND_MHL:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_OPEN,
+                                            attached);
                if (ret < 0)
                        return ret;
 
@@ -365,7 +370,7 @@ static int max77843_muic_jig_handler(struct max77843_muic_info *info,
                int cable_type, bool attached)
 {
        int ret;
-       u8 path = CONTROL1_SW_OPEN;
+       u8 path = MAX77843_MUIC_CONTROL1_SW_OPEN;
 
        dev_dbg(info->dev, "external connector is %s (adc:0x%02x)\n",
                        attached ? "attached" : "detached", cable_type);
@@ -373,10 +378,10 @@ static int max77843_muic_jig_handler(struct max77843_muic_info *info,
        switch (cable_type) {
        case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
        case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
-               path = CONTROL1_SW_USB;
+               path = MAX77843_MUIC_CONTROL1_SW_USB;
                break;
        case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
-               path = CONTROL1_SW_UART;
+               path = MAX77843_MUIC_CONTROL1_SW_UART;
                break;
        default:
                return -EINVAL;
@@ -474,14 +479,18 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 
        switch (chg_type) {
        case MAX77843_MUIC_CHG_USB:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_USB,
+                                            attached);
                if (ret < 0)
                        return ret;
 
                extcon_set_cable_state_(info->edev, EXTCON_USB, attached);
                break;
        case MAX77843_MUIC_CHG_DOWNSTREAM:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_OPEN,
+                                            attached);
                if (ret < 0)
                        return ret;
 
@@ -489,14 +498,18 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
                                        attached);
                break;
        case MAX77843_MUIC_CHG_DEDICATED:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_OPEN,
+                                            attached);
                if (ret < 0)
                        return ret;
 
                extcon_set_cable_state_(info->edev, EXTCON_TA, attached);
                break;
        case MAX77843_MUIC_CHG_SPECIAL_500MA:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_OPEN,
+                                            attached);
                if (ret < 0)
                        return ret;
 
@@ -504,7 +517,9 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
                                        attached);
                break;
        case MAX77843_MUIC_CHG_SPECIAL_1A:
-               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               ret = max77843_muic_set_path(info,
+                                            MAX77843_MUIC_CONTROL1_SW_OPEN,
+                                            attached);
                if (ret < 0)
                        return ret;
 
@@ -528,7 +543,8 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
                        "failed to detect %s accessory (chg_type:0x%x)\n",
                        attached ? "attached" : "detached", chg_type);
 
-               max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_OPEN,
+                                      attached);
                return -EINVAL;
        }
 
@@ -539,7 +555,7 @@ static void max77843_muic_irq_work(struct work_struct *work)
 {
        struct max77843_muic_info *info = container_of(work,
                        struct max77843_muic_info, irq_work);
-       struct max77843 *max77843 = info->max77843;
+       struct max77693_dev *max77843 = info->max77843;
        int ret = 0;
 
        mutex_lock(&info->mutex);
@@ -615,7 +631,7 @@ static void max77843_muic_detect_cable_wq(struct work_struct *work)
 {
        struct max77843_muic_info *info = container_of(to_delayed_work(work),
                        struct max77843_muic_info, wq_detcable);
-       struct max77843 *max77843 = info->max77843;
+       struct max77693_dev *max77843 = info->max77843;
        int chg_type, adc, ret;
        bool attached;
 
@@ -656,7 +672,7 @@ err_cable_wq:
 static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
                enum max77843_muic_adc_debounce_time time)
 {
-       struct max77843 *max77843 = info->max77843;
+       struct max77693_dev *max77843 = info->max77843;
        int ret;
 
        switch (time) {
@@ -667,7 +683,7 @@ static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
                ret = regmap_update_bits(max77843->regmap_muic,
                                MAX77843_MUIC_REG_CONTROL4,
                                MAX77843_MUIC_CONTROL4_ADCDBSET_MASK,
-                               time << CONTROL4_ADCDBSET_SHIFT);
+                               time << MAX77843_MUIC_CONTROL4_ADCDBSET_SHIFT);
                if (ret < 0) {
                        dev_err(info->dev, "Cannot write MUIC regmap\n");
                        return ret;
@@ -681,7 +697,7 @@ static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
        return 0;
 }
 
-static int max77843_init_muic_regmap(struct max77843 *max77843)
+static int max77843_init_muic_regmap(struct max77693_dev *max77843)
 {
        int ret;
 
@@ -720,7 +736,7 @@ err_muic_i2c:
 
 static int max77843_muic_probe(struct platform_device *pdev)
 {
-       struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent);
+       struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent);
        struct max77843_muic_info *info;
        unsigned int id;
        int i, ret;
@@ -768,7 +784,7 @@ static int max77843_muic_probe(struct platform_device *pdev)
        max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
 
        /* Set initial path for UART */
-       max77843_muic_set_path(info, CONTROL1_SW_UART, true);
+       max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_UART, true);
 
        /* Check revision number of MUIC device */
        ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id);
@@ -781,6 +797,15 @@ static int max77843_muic_probe(struct platform_device *pdev)
        /* Support virtual irq domain for max77843 MUIC device */
        INIT_WORK(&info->irq_work, max77843_muic_irq_work);
 
+       /* Clear IRQ bits before request IRQs */
+       ret = regmap_bulk_read(max77843->regmap_muic,
+                       MAX77843_MUIC_REG_INT1, info->status,
+                       MAX77843_MUIC_IRQ_NUM);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to Clear IRQ bits\n");
+               goto err_muic_irq;
+       }
+
        for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
                struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
                unsigned int virq = 0;
@@ -821,7 +846,7 @@ err_muic_irq:
 static int max77843_muic_remove(struct platform_device *pdev)
 {
        struct max77843_muic_info *info = platform_get_drvdata(pdev);
-       struct max77843 *max77843 = info->max77843;
+       struct max77693_dev *max77843 = info->max77843;
 
        cancel_work_sync(&info->irq_work);
        regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
index eebdf2a33bfe4b84e1fc1886e7222641f4a56122..93c30a885740e9bebb08c8f80162118c7e3f2359 100644 (file)
 #include <linux/mfd/palmas.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/workqueue.h>
+
+#define USB_GPIO_DEBOUNCE_MS   20      /* ms */
 
 static const unsigned int palmas_extcon_cable[] = {
        EXTCON_USB,
@@ -35,8 +40,6 @@ static const unsigned int palmas_extcon_cable[] = {
        EXTCON_NONE,
 };
 
-static const int mutually_exclusive[] = {0x3, 0x0};
-
 static void palmas_usb_wakeup(struct palmas *palmas, int enable)
 {
        if (enable)
@@ -120,19 +123,54 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
        return IRQ_HANDLED;
 }
 
+static void palmas_gpio_id_detect(struct work_struct *work)
+{
+       int id;
+       struct palmas_usb *palmas_usb = container_of(to_delayed_work(work),
+                                                    struct palmas_usb,
+                                                    wq_detectid);
+       struct extcon_dev *edev = palmas_usb->edev;
+
+       if (!palmas_usb->id_gpiod)
+               return;
+
+       id = gpiod_get_value_cansleep(palmas_usb->id_gpiod);
+
+       if (id) {
+               extcon_set_cable_state_(edev, EXTCON_USB_HOST, false);
+               dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
+       } else {
+               extcon_set_cable_state_(edev, EXTCON_USB_HOST, true);
+               dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
+       }
+}
+
+static irqreturn_t palmas_gpio_id_irq_handler(int irq, void *_palmas_usb)
+{
+       struct palmas_usb *palmas_usb = _palmas_usb;
+
+       queue_delayed_work(system_power_efficient_wq, &palmas_usb->wq_detectid,
+                          palmas_usb->sw_debounce_jiffies);
+
+       return IRQ_HANDLED;
+}
+
 static void palmas_enable_irq(struct palmas_usb *palmas_usb)
 {
        palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
                PALMAS_USB_VBUS_CTRL_SET,
                PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
 
-       palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
-               PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
+       if (palmas_usb->enable_id_detection) {
+               palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+                            PALMAS_USB_ID_CTRL_SET,
+                            PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
 
-       palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
-               PALMAS_USB_ID_INT_EN_HI_SET,
-               PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
-               PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
+               palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+                            PALMAS_USB_ID_INT_EN_HI_SET,
+                            PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
+                            PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
+       }
 
        if (palmas_usb->enable_vbus_detection)
                palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
@@ -171,20 +209,37 @@ static int palmas_usb_probe(struct platform_device *pdev)
                        palmas_usb->wakeup = pdata->wakeup;
        }
 
+       palmas_usb->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id",
+                                                       GPIOD_IN);
+       if (IS_ERR(palmas_usb->id_gpiod)) {
+               dev_err(&pdev->dev, "failed to get id gpio\n");
+               return PTR_ERR(palmas_usb->id_gpiod);
+       }
+
+       if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) {
+               palmas_usb->enable_id_detection = false;
+               palmas_usb->enable_gpio_id_detection = true;
+       }
+
+       if (palmas_usb->enable_gpio_id_detection) {
+               u32 debounce;
+
+               if (of_property_read_u32(node, "debounce-delay-ms", &debounce))
+                       debounce = USB_GPIO_DEBOUNCE_MS;
+
+               status = gpiod_set_debounce(palmas_usb->id_gpiod,
+                                           debounce * 1000);
+               if (status < 0)
+                       palmas_usb->sw_debounce_jiffies = msecs_to_jiffies(debounce);
+       }
+
+       INIT_DELAYED_WORK(&palmas_usb->wq_detectid, palmas_gpio_id_detect);
+
        palmas->usb = palmas_usb;
        palmas_usb->palmas = palmas;
 
        palmas_usb->dev  = &pdev->dev;
 
-       palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
-                                               PALMAS_ID_OTG_IRQ);
-       palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
-                                               PALMAS_ID_IRQ);
-       palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
-                                               PALMAS_VBUS_OTG_IRQ);
-       palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
-                                               PALMAS_VBUS_IRQ);
-
        palmas_usb_wakeup(palmas, palmas_usb->wakeup);
 
        platform_set_drvdata(pdev, palmas_usb);
@@ -195,7 +250,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to allocate extcon device\n");
                return -ENOMEM;
        }
-       palmas_usb->edev->mutually_exclusive = mutually_exclusive;
 
        status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
        if (status) {
@@ -204,6 +258,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
        }
 
        if (palmas_usb->enable_id_detection) {
+               palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
+                                                            PALMAS_ID_OTG_IRQ);
+               palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
+                                                        PALMAS_ID_IRQ);
                status = devm_request_threaded_irq(palmas_usb->dev,
                                palmas_usb->id_irq,
                                NULL, palmas_id_irq_handler,
@@ -215,9 +273,33 @@ static int palmas_usb_probe(struct platform_device *pdev)
                                        palmas_usb->id_irq, status);
                        return status;
                }
+       } else if (palmas_usb->enable_gpio_id_detection) {
+               palmas_usb->gpio_id_irq = gpiod_to_irq(palmas_usb->id_gpiod);
+               if (palmas_usb->gpio_id_irq < 0) {
+                       dev_err(&pdev->dev, "failed to get id irq\n");
+                       return palmas_usb->gpio_id_irq;
+               }
+               status = devm_request_threaded_irq(&pdev->dev,
+                                                  palmas_usb->gpio_id_irq,
+                                                  NULL,
+                                                  palmas_gpio_id_irq_handler,
+                                                  IRQF_TRIGGER_RISING |
+                                                  IRQF_TRIGGER_FALLING |
+                                                  IRQF_ONESHOT,
+                                                  "palmas_usb_id",
+                                                  palmas_usb);
+               if (status < 0) {
+                       dev_err(&pdev->dev,
+                               "failed to request handler for id irq\n");
+                       return status;
+               }
        }
 
        if (palmas_usb->enable_vbus_detection) {
+               palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
+                                                      PALMAS_VBUS_OTG_IRQ);
+               palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
+                                                          PALMAS_VBUS_IRQ);
                status = devm_request_threaded_irq(palmas_usb->dev,
                                palmas_usb->vbus_irq, NULL,
                                palmas_vbus_irq_handler,
@@ -232,10 +314,21 @@ static int palmas_usb_probe(struct platform_device *pdev)
        }
 
        palmas_enable_irq(palmas_usb);
+       /* perform initial detection */
+       palmas_gpio_id_detect(&palmas_usb->wq_detectid.work);
        device_set_wakeup_capable(&pdev->dev, true);
        return 0;
 }
 
+static int palmas_usb_remove(struct platform_device *pdev)
+{
+       struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
+
+       cancel_delayed_work_sync(&palmas_usb->wq_detectid);
+
+       return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int palmas_usb_suspend(struct device *dev)
 {
@@ -246,6 +339,8 @@ static int palmas_usb_suspend(struct device *dev)
                        enable_irq_wake(palmas_usb->vbus_irq);
                if (palmas_usb->enable_id_detection)
                        enable_irq_wake(palmas_usb->id_irq);
+               if (palmas_usb->enable_gpio_id_detection)
+                       enable_irq_wake(palmas_usb->gpio_id_irq);
        }
        return 0;
 }
@@ -259,6 +354,8 @@ static int palmas_usb_resume(struct device *dev)
                        disable_irq_wake(palmas_usb->vbus_irq);
                if (palmas_usb->enable_id_detection)
                        disable_irq_wake(palmas_usb->id_irq);
+               if (palmas_usb->enable_gpio_id_detection)
+                       disable_irq_wake(palmas_usb->gpio_id_irq);
        }
        return 0;
 };
@@ -276,6 +373,7 @@ static const struct of_device_id of_palmas_match_tbl[] = {
 
 static struct platform_driver palmas_usb_driver = {
        .probe = palmas_usb_probe,
+       .remove = palmas_usb_remove,
        .driver = {
                .name = "palmas-usb",
                .of_match_table = of_palmas_match_tbl,
index 92c939221a41fa1177bc31395f827d8af2b9b5a7..11592e980bc18f2885d91b61720b2b24e943aa0e 100644 (file)
@@ -693,7 +693,6 @@ MODULE_DEVICE_TABLE(i2c, rt8973a_i2c_id);
 static struct i2c_driver rt8973a_muic_i2c_driver = {
        .driver         = {
                .name   = "rt8973a",
-               .owner  = THIS_MODULE,
                .pm     = &rt8973a_muic_pm_ops,
                .of_match_table = rt8973a_dt_match,
        },
index 817dece23b4c2c2048ca190e8b2645de57408dcf..0ffefefa2e260ac9f9a12794befc84b3d1a14d18 100644 (file)
@@ -685,7 +685,6 @@ MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
 static struct i2c_driver sm5502_muic_i2c_driver = {
        .driver         = {
                .name   = "sm5502",
-               .owner  = THIS_MODULE,
                .pm     = &sm5502_muic_pm_ops,
                .of_match_table = sm5502_dt_match,
        },
index a2a44536a608c2c1e300c8c02b40cd1e96bc5f0e..2b2fecffb1ad647ba1b0184da3872fef3a287c23 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/extcon.h>
+#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
index 43b57b02d050d197fe7994ea744231b7a580eb23..a07addde297be4576a9306d170feb5e9b910a6d8 100644 (file)
@@ -126,7 +126,7 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id
 
 static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
 {
-       unsigned int id = -EINVAL;
+       int id = -EINVAL;
        int i = 0;
 
        /* Find the id of extcon cable */
@@ -143,7 +143,7 @@ static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
 
 static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
 {
-       unsigned int id;
+       int id;
 
        if (edev->max_supported == 0)
                return -EINVAL;
@@ -172,14 +172,6 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
        int i, count = 0;
        struct extcon_dev *edev = dev_get_drvdata(dev);
 
-       if (edev->print_state) {
-               int ret = edev->print_state(edev, buf);
-
-               if (ret >= 0)
-                       return ret;
-               /* Use default if failed */
-       }
-
        if (edev->max_supported == 0)
                return sprintf(buf, "%u\n", edev->state);
 
@@ -272,6 +264,9 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
        unsigned long flags;
        bool attached;
 
+       if (!edev)
+               return -EINVAL;
+
        spin_lock_irqsave(&edev->lock, flags);
 
        if (edev->state != ((edev->state & ~mask) | (state & mask))) {
@@ -345,6 +340,9 @@ EXPORT_SYMBOL_GPL(extcon_update_state);
  */
 int extcon_set_state(struct extcon_dev *edev, u32 state)
 {
+       if (!edev)
+               return -EINVAL;
+
        return extcon_update_state(edev, 0xffffffff, state);
 }
 EXPORT_SYMBOL_GPL(extcon_set_state);
@@ -358,6 +356,9 @@ int extcon_get_cable_state_(struct extcon_dev *edev, const unsigned int id)
 {
        int index;
 
+       if (!edev)
+               return -EINVAL;
+
        index = find_cable_index_by_id(edev, id);
        if (index < 0)
                return index;
@@ -378,7 +379,7 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
  */
 int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 {
-       unsigned int id;
+       int id;
 
        id = find_cable_id_by_name(edev, cable_name);
        if (id < 0)
@@ -402,6 +403,9 @@ int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id,
        u32 state;
        int index;
 
+       if (!edev)
+               return -EINVAL;
+
        index = find_cable_index_by_id(edev, id);
        if (index < 0)
                return index;
@@ -426,7 +430,7 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 int extcon_set_cable_state(struct extcon_dev *edev,
                        const char *cable_name, bool cable_state)
 {
-       unsigned int id;
+       int id;
 
        id = find_cable_id_by_name(edev, cable_name);
        if (id < 0)
@@ -444,6 +448,9 @@ struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
 {
        struct extcon_dev *sd;
 
+       if (!extcon_name)
+               return ERR_PTR(-EINVAL);
+
        mutex_lock(&extcon_dev_list_lock);
        list_for_each_entry(sd, &extcon_dev_list, entry) {
                if (!strcmp(sd->name, extcon_name))
@@ -572,6 +579,9 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
        unsigned long flags;
        int ret, idx;
 
+       if (!edev || !nb)
+               return -EINVAL;
+
        idx = find_cable_index_by_id(edev, id);
 
        spin_lock_irqsave(&edev->lock, flags);
@@ -594,6 +604,9 @@ int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
        unsigned long flags;
        int ret, idx;
 
+       if (!edev || !nb)
+               return -EINVAL;
+
        idx = find_cable_index_by_id(edev, id);
 
        spin_lock_irqsave(&edev->lock, flags);
@@ -654,6 +667,9 @@ struct extcon_dev *extcon_dev_allocate(const unsigned int *supported_cable)
 {
        struct extcon_dev *edev;
 
+       if (!supported_cable)
+               return ERR_PTR(-EINVAL);
+
        edev = kzalloc(sizeof(*edev), GFP_KERNEL);
        if (!edev)
                return ERR_PTR(-ENOMEM);
@@ -754,7 +770,7 @@ int extcon_dev_register(struct extcon_dev *edev)
                        return ret;
        }
 
-       if (!edev->supported_cable)
+       if (!edev || !edev->supported_cable)
                return -EINVAL;
 
        for (; edev->supported_cable[index] != EXTCON_NONE; index++);
@@ -960,6 +976,9 @@ void extcon_dev_unregister(struct extcon_dev *edev)
 {
        int index;
 
+       if (!edev)
+               return;
+
        mutex_lock(&extcon_dev_list_lock);
        list_del(&edev->entry);
        mutex_unlock(&extcon_dev_list_lock);
@@ -1066,6 +1085,9 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
        struct device_node *node;
        struct extcon_dev *edev;
 
+       if (!dev)
+               return ERR_PTR(-EINVAL);
+
        if (!dev->of_node) {
                dev_err(dev, "device does not have a device node entry\n");
                return ERR_PTR(-EINVAL);
index 87add3fdce529b1ad6890cb24adb345275e4655c..e41594510b978291de179182c46b0196b3a377e3 100644 (file)
@@ -245,4 +245,4 @@ char *bcm47xx_nvram_get_contents(size_t *nvram_size)
 }
 EXPORT_SYMBOL(bcm47xx_nvram_get_contents);
 
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
index 2f7a5efa21c23ab0fda25ee0ebbb360efae966ea..f5c22556ec2c17ff145c48440dfe5e3563e67606 100644 (file)
@@ -374,7 +374,7 @@ static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
        unsigned height_in_mb = ALIGN(height / 16, 2);
        unsigned fs_in_mb = width_in_mb * height_in_mb;
 
-       unsigned image_size, tmp, min_dpb_size, num_dpb_buffer;
+       unsigned image_size, tmp, min_dpb_size, num_dpb_buffer, min_ctx_size;
 
        image_size = width * height;
        image_size += image_size / 2;
@@ -466,6 +466,8 @@ static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
 
                num_dpb_buffer = (le32_to_cpu(msg[59]) & 0xff) + 2;
                min_dpb_size = image_size * num_dpb_buffer;
+               min_ctx_size = ((width + 255) / 16) * ((height + 255) / 16)
+                                          * 16 * num_dpb_buffer + 52 * 1024;
                break;
 
        default:
@@ -486,6 +488,7 @@ static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
 
        buf_sizes[0x1] = dpb_size;
        buf_sizes[0x2] = image_size;
+       buf_sizes[0x4] = min_ctx_size;
        return 0;
 }
 
@@ -628,6 +631,13 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
                        return -EINVAL;
                }
 
+       } else if (cmd == 0x206) {
+               if ((end - start) < ctx->buf_sizes[4]) {
+                       DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
+                                         (unsigned)(end - start),
+                                         ctx->buf_sizes[4]);
+                       return -EINVAL;
+               }
        } else if ((cmd != 0x100) && (cmd != 0x204)) {
                DRM_ERROR("invalid UVD command %X!\n", cmd);
                return -EINVAL;
@@ -755,9 +765,10 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
        struct amdgpu_uvd_cs_ctx ctx = {};
        unsigned buf_sizes[] = {
                [0x00000000]    =       2048,
-               [0x00000001]    =       32 * 1024 * 1024,
-               [0x00000002]    =       2048 * 1152 * 3,
+               [0x00000001]    =       0xFFFFFFFF,
+               [0x00000002]    =       0xFFFFFFFF,
                [0x00000003]    =       2048,
+               [0x00000004]    =       0xFFFFFFFF,
        };
        struct amdgpu_ib *ib = &parser->ibs[ib_idx];
        int r;
index f5a42ab1f65c070ed55192758793c04c9a2d5f7f..20e2cfd521d5352202070f357de89234175cb800 100644 (file)
@@ -3135,7 +3135,7 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
                                WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
                                       AMDGPU_DOORBELL_KIQ << 2);
                                WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
-                                               0x7FFFF << 2);
+                                      AMDGPU_DOORBELL_MEC_RING7 << 2);
                        }
                        tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
                        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
index 6fad1f9648f38870b2162cb74a6320f50c34aabc..ef6182bc8e5eef229dc990354f6d31c18915f3bc 100644 (file)
@@ -559,7 +559,7 @@ static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
index b0487c9f018cfd09d040ffb08fe4585f68ab6022..eb603f1defc2250ea158864ea4371e24655138e1 100644 (file)
@@ -873,9 +873,10 @@ static void drm_dp_destroy_port(struct kref *kref)
                   from an EDID retrieval */
                if (port->connector) {
                        mutex_lock(&mgr->destroy_connector_lock);
-                       list_add(&port->connector->destroy_list, &mgr->destroy_connector_list);
+                       list_add(&port->next, &mgr->destroy_connector_list);
                        mutex_unlock(&mgr->destroy_connector_lock);
                        schedule_work(&mgr->destroy_connector_work);
+                       return;
                }
                drm_dp_port_teardown_pdt(port, port->pdt);
 
@@ -2659,7 +2660,7 @@ static void drm_dp_tx_work(struct work_struct *work)
 static void drm_dp_destroy_connector_work(struct work_struct *work)
 {
        struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
-       struct drm_connector *connector;
+       struct drm_dp_mst_port *port;
 
        /*
         * Not a regular list traverse as we have to drop the destroy
@@ -2668,15 +2669,21 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
         */
        for (;;) {
                mutex_lock(&mgr->destroy_connector_lock);
-               connector = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_connector, destroy_list);
-               if (!connector) {
+               port = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_dp_mst_port, next);
+               if (!port) {
                        mutex_unlock(&mgr->destroy_connector_lock);
                        break;
                }
-               list_del(&connector->destroy_list);
+               list_del(&port->next);
                mutex_unlock(&mgr->destroy_connector_lock);
 
-               mgr->cbs->destroy_connector(mgr, connector);
+               mgr->cbs->destroy_connector(mgr, port->connector);
+
+               drm_dp_port_teardown_pdt(port, port->pdt);
+
+               if (!port->input && port->vcpi.vcpi > 0)
+                       drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+               kfree(port);
        }
 }
 
index 842d6b8dc3c435ee7d836402d4169847aef75d31..2a652359af644b51f257cde7528d70b6016897da 100644 (file)
@@ -1745,7 +1745,6 @@ static int fimc_probe(struct platform_device *pdev)
        spin_lock_init(&ctx->lock);
        platform_set_drvdata(pdev, ctx);
 
-       pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
 
        ret = exynos_drm_ippdrv_register(ippdrv);
index 8040ed2a831f9a6f226baf8aee3ce00b213be8e6..f1c6b76c127f4db02388267775431fcd25ac7eb8 100644 (file)
@@ -593,8 +593,7 @@ static int gsc_src_set_transf(struct device *dev,
 
        gsc_write(cfg, GSC_IN_CON);
 
-       ctx->rotation = cfg &
-               (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
+       ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
        *swap = ctx->rotation;
 
        return 0;
@@ -857,8 +856,7 @@ static int gsc_dst_set_transf(struct device *dev,
 
        gsc_write(cfg, GSC_IN_CON);
 
-       ctx->rotation = cfg &
-               (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
+       ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
        *swap = ctx->rotation;
 
        return 0;
index 99e286489031c4a2931565823e0158428548aef2..4a00990e4ae4e8459b94a9a007044af1cc11af62 100644 (file)
@@ -1064,6 +1064,7 @@ static int hdmi_get_modes(struct drm_connector *connector)
 {
        struct hdmi_context *hdata = ctx_from_connector(connector);
        struct edid *edid;
+       int ret;
 
        if (!hdata->ddc_adpt)
                return -ENODEV;
@@ -1079,7 +1080,11 @@ static int hdmi_get_modes(struct drm_connector *connector)
 
        drm_mode_connector_update_edid_property(connector, edid);
 
-       return drm_add_edid_modes(connector, edid);
+       ret = drm_add_edid_modes(connector, edid);
+
+       kfree(edid);
+
+       return ret;
 }
 
 static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
index cae98db3306205e2628b2090b731cf6cfdf79d4f..4706b56902b44f5ba205b30d3aa6e53678bbad52 100644 (file)
@@ -718,6 +718,10 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
 
        /* handling VSYNC */
        if (val & MXR_INT_STATUS_VSYNC) {
+               /* vsync interrupt use different bit for read and clear */
+               val |= MXR_INT_CLEAR_VSYNC;
+               val &= ~MXR_INT_STATUS_VSYNC;
+
                /* interlace scan need to check shadow register */
                if (ctx->interlace) {
                        base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
@@ -743,11 +747,6 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
 
 out:
        /* clear interrupts */
-       if (~val & MXR_INT_EN_VSYNC) {
-               /* vsync interrupt use different bit for read and clear */
-               val &= ~MXR_INT_EN_VSYNC;
-               val |= MXR_INT_CLEAR_VSYNC;
-       }
        mixer_reg_write(res, MXR_INT_STATUS, val);
 
        spin_unlock(&res->reg_slock);
@@ -907,8 +906,8 @@ static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
        }
 
        /* enable vsync interrupt */
-       mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
-                       MXR_INT_EN_VSYNC);
+       mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
+       mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
 
        return 0;
 }
@@ -918,7 +917,13 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
        struct mixer_context *mixer_ctx = crtc->ctx;
        struct mixer_resources *res = &mixer_ctx->mixer_res;
 
+       if (!mixer_ctx->powered) {
+               mixer_ctx->int_en &= MXR_INT_EN_VSYNC;
+               return;
+       }
+
        /* disable vsync interrupt */
+       mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
        mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
@@ -1047,6 +1052,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
 
        mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
 
+       if (ctx->int_en & MXR_INT_EN_VSYNC)
+               mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
        mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
        mixer_win_reset(ctx);
 }
index 7ed8033aae6097af69d90e83bb6c97f7dc6f7225..8e35e0d013df556d8ac04fc27f9ba2bd7354fae3 100644 (file)
@@ -129,8 +129,9 @@ int intel_atomic_commit(struct drm_device *dev,
                        struct drm_atomic_state *state,
                        bool async)
 {
-       int ret;
-       int i;
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *crtc;
+       int ret, i;
 
        if (async) {
                DRM_DEBUG_KMS("i915 does not yet support async commit\n");
@@ -142,48 +143,18 @@ int intel_atomic_commit(struct drm_device *dev,
                return ret;
 
        /* Point of no return */
-
-       /*
-        * FIXME:  The proper sequence here will eventually be:
-        *
-        * drm_atomic_helper_swap_state(dev, state)
-        * drm_atomic_helper_commit_modeset_disables(dev, state);
-        * drm_atomic_helper_commit_planes(dev, state);
-        * drm_atomic_helper_commit_modeset_enables(dev, state);
-        * drm_atomic_helper_wait_for_vblanks(dev, state);
-        * drm_atomic_helper_cleanup_planes(dev, state);
-        * drm_atomic_state_free(state);
-        *
-        * once we have full atomic modeset.  For now, just manually update
-        * plane states to avoid clobbering good states with dummy states
-        * while nuclear pageflipping.
-        */
-       for (i = 0; i < dev->mode_config.num_total_plane; i++) {
-               struct drm_plane *plane = state->planes[i];
-
-               if (!plane)
-                       continue;
-
-               plane->state->state = state;
-               swap(state->plane_states[i], plane->state);
-               plane->state->state = NULL;
-       }
+       drm_atomic_helper_swap_state(dev, state);
 
        /* swap crtc_scaler_state */
-       for (i = 0; i < dev->mode_config.num_crtc; i++) {
-               struct drm_crtc *crtc = state->crtcs[i];
-               if (!crtc) {
-                       continue;
-               }
-
-               to_intel_crtc(crtc)->config->scaler_state =
-                       to_intel_crtc_state(state->crtc_states[i])->scaler_state;
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state);
 
                if (INTEL_INFO(dev)->gen >= 9)
                        skl_detach_scalers(to_intel_crtc(crtc));
+
+               drm_atomic_helper_commit_planes_on_crtc(crtc_state);
        }
 
-       drm_atomic_helper_commit_planes(dev, state);
        drm_atomic_helper_wait_for_vblanks(dev, state);
        drm_atomic_helper_cleanup_planes(dev, state);
        drm_atomic_state_free(state);
index 3dcd59e694db9e6f32c8e49ea04cbf21bbdc0ad8..198fc3c3291b2ac05540ea36ef853c9826b23efa 100644 (file)
@@ -1075,34 +1075,15 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
        const union child_device_config *p_child;
        union child_device_config *child_dev_ptr;
        int i, child_device_num, count;
-       u8 expected_size;
-       u16 block_size;
+       u16     block_size;
 
        p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
        if (!p_defs) {
                DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
                return;
        }
-       if (bdb->version < 195) {
-               expected_size = 33;
-       } else if (bdb->version == 195) {
-               expected_size = 37;
-       } else if (bdb->version <= 197) {
-               expected_size = 38;
-       } else {
-               expected_size = 38;
-               DRM_DEBUG_DRIVER("Expected child_device_config size for BDB version %u not known; assuming %u\n",
-                                expected_size, bdb->version);
-       }
-
-       if (expected_size > sizeof(*p_child)) {
-               DRM_ERROR("child_device_config cannot fit in p_child\n");
-               return;
-       }
-
-       if (p_defs->child_dev_size != expected_size) {
-               DRM_ERROR("Size mismatch; child_device_config size=%u (expected %u); bdb->version: %u\n",
-                         p_defs->child_dev_size, expected_size, bdb->version);
+       if (p_defs->child_dev_size < sizeof(*p_child)) {
+               DRM_ERROR("General definiton block child device size is too small.\n");
                return;
        }
        /* get the block size of general definitions */
@@ -1149,7 +1130,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
 
                child_dev_ptr = dev_priv->vbt.child_dev + count;
                count++;
-               memcpy(child_dev_ptr, p_child, p_defs->child_dev_size);
+               memcpy(child_dev_ptr, p_child, sizeof(*p_child));
        }
        return;
 }
index 30e0f54ba19d1284107958bb6e5d49f6309b63de..87476ff181ddbef0967d948c37119cfcbd758315 100644 (file)
@@ -11826,7 +11826,9 @@ encoder_retry:
                goto encoder_retry;
        }
 
-       pipe_config->dither = pipe_config->pipe_bpp != base_bpp;
+       /* Dithering seems to not pass-through bits correctly when it should, so
+        * only enable it on 6bpc panels. */
+       pipe_config->dither = pipe_config->pipe_bpp == 6*3;
        DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
                      base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
 
@@ -12624,17 +12626,17 @@ static int __intel_set_mode(struct drm_crtc *modeset_crtc,
 
        modeset_update_crtc_power_domains(state);
 
-       drm_atomic_helper_commit_planes(dev, state);
-
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               if (!needs_modeset(crtc->state) || !crtc->state->enable)
+               if (!needs_modeset(crtc->state) || !crtc->state->enable) {
+                       drm_atomic_helper_commit_planes_on_crtc(crtc_state);
                        continue;
+               }
 
                update_scanline_offset(to_intel_crtc(crtc));
 
                dev_priv->display.crtc_enable(crtc);
-               intel_crtc_enable_planes(crtc);
+               drm_atomic_helper_commit_planes_on_crtc(crtc_state);
        }
 
        /* FIXME: add subpixel order */
@@ -12891,20 +12893,11 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        return 0;
 }
 
-static bool primary_plane_visible(struct drm_crtc *crtc)
-{
-       struct intel_plane_state *plane_state =
-               to_intel_plane_state(crtc->primary->state);
-
-       return plane_state->visible;
-}
-
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
        struct drm_device *dev;
        struct drm_atomic_state *state = NULL;
        struct intel_crtc_state *pipe_config;
-       bool primary_plane_was_visible;
        int ret;
 
        BUG_ON(!set);
@@ -12943,38 +12936,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
        intel_update_pipe_size(to_intel_crtc(set->crtc));
 
-       primary_plane_was_visible = primary_plane_visible(set->crtc);
-
        ret = intel_set_mode_with_config(set->crtc, pipe_config, true);
 
-       if (ret == 0 &&
-           pipe_config->base.enable &&
-           pipe_config->base.planes_changed &&
-           !needs_modeset(&pipe_config->base)) {
-               struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
-
-               /*
-                * We need to make sure the primary plane is re-enabled if it
-                * has previously been turned off.
-                */
-               if (ret == 0 && !primary_plane_was_visible &&
-                   primary_plane_visible(set->crtc)) {
-                       WARN_ON(!intel_crtc->active);
-                       intel_post_enable_primary(set->crtc);
-               }
-
-               /*
-                * In the fastboot case this may be our only check of the
-                * state after boot.  It would be better to only do it on
-                * the first update, but we don't have a nice way of doing that
-                * (and really, set_config isn't used much for high freq page
-                * flipping, so increasing its cost here shouldn't be a big
-                * deal).
-                */
-               if (i915.fastboot && ret == 0)
-                       intel_modeset_check_state(set->crtc->dev);
-       }
-
        if (ret) {
                DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n",
                              set->crtc->base.id, ret);
@@ -13305,6 +13268,9 @@ intel_check_primary_plane(struct drm_plane *plane,
                         */
                        if (IS_BROADWELL(dev))
                                intel_crtc->atomic.wait_vblank = true;
+
+                       if (crtc_state)
+                               intel_crtc->atomic.post_enable_primary = true;
                }
 
                /*
@@ -13317,6 +13283,10 @@ intel_check_primary_plane(struct drm_plane *plane,
                if (!state->visible || !fb)
                        intel_crtc->atomic.disable_ips = true;
 
+               if (!state->visible && old_state->visible &&
+                   crtc_state && !needs_modeset(&crtc_state->base))
+                       intel_crtc->atomic.pre_disable_primary = true;
+
                intel_crtc->atomic.fb_bits |=
                        INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 
@@ -15034,6 +15004,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                struct intel_plane_state *plane_state;
 
                memset(crtc->config, 0, sizeof(*crtc->config));
+               crtc->config->base.crtc = &crtc->base;
 
                crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
 
index 6e8faa25379240cab60f57631adf42612f28df33..1df0e1fe235f112830a0e82a1004b0e949613c78 100644 (file)
@@ -93,9 +93,6 @@ static const struct dp_link_dpll chv_dpll[] = {
 
 static const int skl_rates[] = { 162000, 216000, 270000,
                                  324000, 432000, 540000 };
-static const int chv_rates[] = { 162000, 202500, 210000, 216000,
-                                243000, 270000, 324000, 405000,
-                                420000, 432000, 540000 };
 static const int default_rates[] = { 162000, 270000, 540000 };
 
 /**
@@ -1169,24 +1166,31 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
        return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
 }
 
+static bool intel_dp_source_supports_hbr2(struct drm_device *dev)
+{
+       /* WaDisableHBR2:skl */
+       if (IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0)
+               return false;
+
+       if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) ||
+           (INTEL_INFO(dev)->gen >= 9))
+               return true;
+       else
+               return false;
+}
+
 static int
 intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
 {
        if (IS_SKYLAKE(dev)) {
                *source_rates = skl_rates;
                return ARRAY_SIZE(skl_rates);
-       } else if (IS_CHERRYVIEW(dev)) {
-               *source_rates = chv_rates;
-               return ARRAY_SIZE(chv_rates);
        }
 
        *source_rates = default_rates;
 
-       if (IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0)
-               /* WaDisableHBR2:skl */
-               return (DP_LINK_BW_2_7 >> 3) + 1;
-       else if (INTEL_INFO(dev)->gen >= 8 ||
-           (IS_HASWELL(dev) && !IS_HSW_ULX(dev)))
+       /* This depends on the fact that 5.4 is last value in the array */
+       if (intel_dp_source_supports_hbr2(dev))
                return (DP_LINK_BW_5_4 >> 3) + 1;
        else
                return (DP_LINK_BW_2_7 >> 3) + 1;
@@ -3941,10 +3945,15 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
                }
        }
 
-       /* Training Pattern 3 support, both source and sink */
+       /* Training Pattern 3 support, Intel platforms that support HBR2 alone
+        * have support for TP3 hence that check is used along with dpcd check
+        * to ensure TP3 can be enabled.
+        * SKL < B0: due it's WaDisableHBR2 is the only exception where TP3 is
+        * supported but still not enabled.
+        */
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 &&
            intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED &&
-           (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)) {
+           intel_dp_source_supports_hbr2(dev)) {
                intel_dp->use_tps3 = true;
                DRM_DEBUG_KMS("Displayport TPS3 supported\n");
        } else
index 9b74ffae5f5a7bab8ef545525d361c29fd4c3bf6..7f2161a1ff5d4d40c7b6dca346c20518b084bf6b 100644 (file)
@@ -1012,6 +1012,8 @@ static int intel_lr_context_pin(struct intel_engine_cs *ring,
                ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
                if (ret)
                        goto unpin_ctx_obj;
+
+               ctx_obj->dirty = true;
        }
 
        return ret;
index eb8ac3097ff501b19bea92c69ed73bf1caa988de..18b7727bdc5785f770bbe1b273a2194084927925 100644 (file)
@@ -455,7 +455,7 @@ static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
        cached_state->postdiv1 =
                        pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
        cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
-       cached_state->vco_rate = __clk_get_rate(pll->clk_hw.clk);
+       cached_state->vco_rate = clk_hw_get_rate(&pll->clk_hw);
 }
 
 static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
@@ -466,7 +466,7 @@ static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
        int ret;
 
        if ((cached_state->vco_rate != 0) &&
-               (cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) {
+               (cached_state->vco_rate == clk_hw_get_rate(&pll->clk_hw))) {
                ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
                                                cached_state->vco_rate, 0);
                if (ret) {
index 52c22b02600598cfa7d18e424d69a99cce4879e7..e10f9644140f5d9fcd6e73446c74634d2b13906a 100644 (file)
@@ -165,31 +165,15 @@ gk104_fifo_context_attach(struct nvkm_object *parent,
        return 0;
 }
 
-static int
-gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
-{
-       struct nvkm_object *obj = (void *)chan;
-       struct gk104_fifo_priv *priv = (void *)obj->engine;
-
-       nv_wr32(priv, 0x002634, chan->base.chid);
-       if (!nv_wait(priv, 0x002634, 0x100000, 0x000000)) {
-               nv_error(priv, "channel %d [%s] kick timeout\n",
-                        chan->base.chid, nvkm_client_name(chan));
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
 static int
 gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
                          struct nvkm_object *object)
 {
        struct nvkm_bar *bar = nvkm_bar(parent);
+       struct gk104_fifo_priv *priv = (void *)parent->engine;
        struct gk104_fifo_base *base = (void *)parent->parent;
        struct gk104_fifo_chan *chan = (void *)parent;
        u32 addr;
-       int ret;
 
        switch (nv_engidx(object->engine)) {
        case NVDEV_ENGINE_SW    : return 0;
@@ -204,9 +188,13 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
                return -EINVAL;
        }
 
-       ret = gk104_fifo_chan_kick(chan);
-       if (ret && suspend)
-               return ret;
+       nv_wr32(priv, 0x002634, chan->base.chid);
+       if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) {
+               nv_error(priv, "channel %d [%s] kick timeout\n",
+                        chan->base.chid, nvkm_client_name(chan));
+               if (suspend)
+                       return -EBUSY;
+       }
 
        if (addr) {
                nv_wo32(base, addr + 0x00, 0x00000000);
@@ -331,7 +319,6 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
                gk104_fifo_runlist_update(priv, chan->engine);
        }
 
-       gk104_fifo_chan_kick(chan);
        nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
        return nvkm_fifo_channel_fini(&chan->base, suspend);
 }
index 1162bfa464f3036192854f4d0f3f363eb1ee8cff..171d3e43c30cc02257df75645c6c77f0a726de33 100644 (file)
@@ -79,6 +79,11 @@ static void radeon_hotplug_work_func(struct work_struct *work)
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct drm_connector *connector;
 
+       /* we can race here at startup, some boards seem to trigger
+        * hotplug irqs when they shouldn't. */
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        mutex_lock(&mode_config->mutex);
        if (mode_config->num_connector) {
                list_for_each_entry(connector, &mode_config->connector_list, head)
index 654c8daeb5ab3d0dd84a2ed1d32af633d6955ac9..97ad3bcb99a75a441a54150f779415dc59236ac7 100644 (file)
@@ -2492,7 +2492,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes,
                                     true, NULL);
        if (unlikely(ret != 0))
-               goto out_err;
+               goto out_err_nores;
 
        ret = vmw_validate_buffers(dev_priv, sw_context);
        if (unlikely(ret != 0))
@@ -2536,6 +2536,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        vmw_resource_relocations_free(&sw_context->res_relocations);
 
        vmw_fifo_commit(dev_priv, command_size);
+       mutex_unlock(&dev_priv->binding_mutex);
 
        vmw_query_bo_switch_commit(dev_priv, sw_context);
        ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
@@ -2551,7 +2552,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                DRM_ERROR("Fence submission error. Syncing.\n");
 
        vmw_resource_list_unreserve(&sw_context->resource_list, false);
-       mutex_unlock(&dev_priv->binding_mutex);
 
        ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
                                    (void *) fence);
index 603ce97e9027283044b5da16ed15436a7ddcd3af..c4dcab048cb8ecbc38b7784408bfd7902d5a40a7 100644 (file)
@@ -601,6 +601,7 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
        u64 aligned_data = 0;
        int ret;
        bool signal = false;
+       int num_vecs = ((bufferlen != 0) ? 3 : 1);
 
 
        /* Setup the descriptor */
@@ -618,7 +619,8 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
        bufferlist[2].iov_base = &aligned_data;
        bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
-       ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
+       ret = hv_ringbuffer_write(&channel->outbound, bufferlist, num_vecs,
+                                 &signal);
 
        /*
         * Signalling the host is conditional on many factors:
index 4506a66236181abe932f4c0358db6ef9a6bf61b3..2f9aead4ecfc0e696d1fe4f3c8d8fdddbe9e49fc 100644 (file)
@@ -347,6 +347,7 @@ enum {
        IDE = 0,
        SCSI,
        NIC,
+       ND_NIC,
        MAX_PERF_CHN,
 };
 
@@ -391,6 +392,7 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
        struct vmbus_channel *primary = channel->primary_channel;
        int next_node;
        struct cpumask available_mask;
+       struct cpumask *alloced_mask;
 
        for (i = IDE; i < MAX_PERF_CHN; i++) {
                if (!memcmp(type_guid->b, hp_devs[i].guid,
@@ -408,7 +410,6 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
                 * channel, bind it to cpu 0.
                 */
                channel->numa_node = 0;
-               cpumask_set_cpu(0, &channel->alloced_cpus_in_node);
                channel->target_cpu = 0;
                channel->target_vp = hv_context.vp_index[0];
                return;
@@ -433,21 +434,38 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
                channel->numa_node = next_node;
                primary = channel;
        }
+       alloced_mask = &hv_context.hv_numa_map[primary->numa_node];
 
-       if (cpumask_weight(&primary->alloced_cpus_in_node) ==
+       if (cpumask_weight(alloced_mask) ==
            cpumask_weight(cpumask_of_node(primary->numa_node))) {
                /*
                 * We have cycled through all the CPUs in the node;
                 * reset the alloced map.
                 */
-               cpumask_clear(&primary->alloced_cpus_in_node);
+               cpumask_clear(alloced_mask);
        }
 
-       cpumask_xor(&available_mask, &primary->alloced_cpus_in_node,
+       cpumask_xor(&available_mask, alloced_mask,
                    cpumask_of_node(primary->numa_node));
 
-       cur_cpu = cpumask_next(-1, &available_mask);
-       cpumask_set_cpu(cur_cpu, &primary->alloced_cpus_in_node);
+       cur_cpu = -1;
+       while (true) {
+               cur_cpu = cpumask_next(cur_cpu, &available_mask);
+               if (cur_cpu >= nr_cpu_ids) {
+                       cur_cpu = -1;
+                       cpumask_copy(&available_mask,
+                                    cpumask_of_node(primary->numa_node));
+                       continue;
+               }
+
+               if (!cpumask_test_cpu(cur_cpu,
+                               &primary->alloced_cpus_in_node)) {
+                       cpumask_set_cpu(cur_cpu,
+                                       &primary->alloced_cpus_in_node);
+                       cpumask_set_cpu(cur_cpu, alloced_mask);
+                       break;
+               }
+       }
 
        channel->target_cpu = cur_cpu;
        channel->target_vp = hv_context.vp_index[cur_cpu];
@@ -469,6 +487,10 @@ void vmbus_initiate_unload(void)
 {
        struct vmbus_channel_message_header hdr;
 
+       /* Pre-Win2012R2 hosts don't support reconnect */
+       if (vmbus_proto_version < VERSION_WIN8_1)
+               return;
+
        init_completion(&vmbus_connection.unload_event);
        memset(&hdr, 0, sizeof(struct vmbus_channel_message_header));
        hdr.msgtype = CHANNELMSG_UNLOAD;
index d3943bceecc367c7b5241de3ba7933aae45f41c4..6341be8739ae6e3a4931912a6fcd3139a0314c4c 100644 (file)
@@ -93,11 +93,14 @@ static int query_hypervisor_info(void)
  */
 static u64 do_hypercall(u64 control, void *input, void *output)
 {
-#ifdef CONFIG_X86_64
-       u64 hv_status = 0;
        u64 input_address = (input) ? virt_to_phys(input) : 0;
        u64 output_address = (output) ? virt_to_phys(output) : 0;
        void *hypercall_page = hv_context.hypercall_page;
+#ifdef CONFIG_X86_64
+       u64 hv_status = 0;
+
+       if (!hypercall_page)
+               return (u64)ULLONG_MAX;
 
        __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
        __asm__ __volatile__("call *%3" : "=a" (hv_status) :
@@ -112,13 +115,13 @@ static u64 do_hypercall(u64 control, void *input, void *output)
        u32 control_lo = control & 0xFFFFFFFF;
        u32 hv_status_hi = 1;
        u32 hv_status_lo = 1;
-       u64 input_address = (input) ? virt_to_phys(input) : 0;
        u32 input_address_hi = input_address >> 32;
        u32 input_address_lo = input_address & 0xFFFFFFFF;
-       u64 output_address = (output) ? virt_to_phys(output) : 0;
        u32 output_address_hi = output_address >> 32;
        u32 output_address_lo = output_address & 0xFFFFFFFF;
-       void *hypercall_page = hv_context.hypercall_page;
+
+       if (!hypercall_page)
+               return (u64)ULLONG_MAX;
 
        __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
                              "=a"(hv_status_lo) : "d" (control_hi),
@@ -130,6 +133,56 @@ static u64 do_hypercall(u64 control, void *input, void *output)
 #endif /* !x86_64 */
 }
 
+#ifdef CONFIG_X86_64
+static cycle_t read_hv_clock_tsc(struct clocksource *arg)
+{
+       cycle_t current_tick;
+       struct ms_hyperv_tsc_page *tsc_pg = hv_context.tsc_page;
+
+       if (tsc_pg->tsc_sequence != -1) {
+               /*
+                * Use the tsc page to compute the value.
+                */
+
+               while (1) {
+                       cycle_t tmp;
+                       u32 sequence = tsc_pg->tsc_sequence;
+                       u64 cur_tsc;
+                       u64 scale = tsc_pg->tsc_scale;
+                       s64 offset = tsc_pg->tsc_offset;
+
+                       rdtscll(cur_tsc);
+                       /* current_tick = ((cur_tsc *scale) >> 64) + offset */
+                       asm("mulq %3"
+                               : "=d" (current_tick), "=a" (tmp)
+                               : "a" (cur_tsc), "r" (scale));
+
+                       current_tick += offset;
+                       if (tsc_pg->tsc_sequence == sequence)
+                               return current_tick;
+
+                       if (tsc_pg->tsc_sequence != -1)
+                               continue;
+                       /*
+                        * Fallback using MSR method.
+                        */
+                       break;
+               }
+       }
+       rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+       return current_tick;
+}
+
+static struct clocksource hyperv_cs_tsc = {
+               .name           = "hyperv_clocksource_tsc_page",
+               .rating         = 425,
+               .read           = read_hv_clock_tsc,
+               .mask           = CLOCKSOURCE_MASK(64),
+               .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+#endif
+
+
 /*
  * hv_init - Main initialization routine.
  *
@@ -139,7 +192,9 @@ int hv_init(void)
 {
        int max_leaf;
        union hv_x64_msr_hypercall_contents hypercall_msr;
+       union hv_x64_msr_hypercall_contents tsc_msr;
        void *virtaddr = NULL;
+       void *va_tsc = NULL;
 
        memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
        memset(hv_context.synic_message_page, 0,
@@ -183,6 +238,22 @@ int hv_init(void)
 
        hv_context.hypercall_page = virtaddr;
 
+#ifdef CONFIG_X86_64
+       if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
+               va_tsc = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
+               if (!va_tsc)
+                       goto cleanup;
+               hv_context.tsc_page = va_tsc;
+
+               rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
+
+               tsc_msr.enable = 1;
+               tsc_msr.guest_physical_address = vmalloc_to_pfn(va_tsc);
+
+               wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
+               clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
+       }
+#endif
        return 0;
 
 cleanup:
@@ -216,6 +287,21 @@ void hv_cleanup(void)
                vfree(hv_context.hypercall_page);
                hv_context.hypercall_page = NULL;
        }
+
+#ifdef CONFIG_X86_64
+       /*
+        * Cleanup the TSC page based CS.
+        */
+       if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
+               clocksource_change_rating(&hyperv_cs_tsc, 10);
+               clocksource_unregister(&hyperv_cs_tsc);
+
+               hypercall_msr.as_uint64 = 0;
+               wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
+               vfree(hv_context.tsc_page);
+               hv_context.tsc_page = NULL;
+       }
+#endif
 }
 
 /*
@@ -271,7 +357,7 @@ static int hv_ce_set_next_event(unsigned long delta,
 {
        cycle_t current_tick;
 
-       WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
+       WARN_ON(!clockevent_state_oneshot(evt));
 
        rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
        current_tick += delta;
@@ -279,31 +365,24 @@ static int hv_ce_set_next_event(unsigned long delta,
        return 0;
 }
 
-static void hv_ce_setmode(enum clock_event_mode mode,
-                         struct clock_event_device *evt)
+static int hv_ce_shutdown(struct clock_event_device *evt)
+{
+       wrmsrl(HV_X64_MSR_STIMER0_COUNT, 0);
+       wrmsrl(HV_X64_MSR_STIMER0_CONFIG, 0);
+
+       return 0;
+}
+
+static int hv_ce_set_oneshot(struct clock_event_device *evt)
 {
        union hv_timer_config timer_cfg;
 
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               /* unsupported */
-               break;
-
-       case CLOCK_EVT_MODE_ONESHOT:
-               timer_cfg.enable = 1;
-               timer_cfg.auto_enable = 1;
-               timer_cfg.sintx = VMBUS_MESSAGE_SINT;
-               wrmsrl(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
-               break;
-
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               wrmsrl(HV_X64_MSR_STIMER0_COUNT, 0);
-               wrmsrl(HV_X64_MSR_STIMER0_CONFIG, 0);
-               break;
-       case CLOCK_EVT_MODE_RESUME:
-               break;
-       }
+       timer_cfg.enable = 1;
+       timer_cfg.auto_enable = 1;
+       timer_cfg.sintx = VMBUS_MESSAGE_SINT;
+       wrmsrl(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
+
+       return 0;
 }
 
 static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
@@ -318,7 +397,8 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
         * references to the hv_vmbus module making it impossible to unload.
         */
 
-       dev->set_mode = hv_ce_setmode;
+       dev->set_state_shutdown = hv_ce_shutdown;
+       dev->set_state_oneshot = hv_ce_set_oneshot;
        dev->set_next_event = hv_ce_set_next_event;
 }
 
@@ -329,6 +409,13 @@ int hv_synic_alloc(void)
        size_t ced_size = sizeof(struct clock_event_device);
        int cpu;
 
+       hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids,
+                                        GFP_ATOMIC);
+       if (hv_context.hv_numa_map == NULL) {
+               pr_err("Unable to allocate NUMA map\n");
+               goto err;
+       }
+
        for_each_online_cpu(cpu) {
                hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
                if (hv_context.event_dpc[cpu] == NULL) {
@@ -342,6 +429,7 @@ int hv_synic_alloc(void)
                        pr_err("Unable to allocate clock event device\n");
                        goto err;
                }
+
                hv_init_clockevent_device(hv_context.clk_evt[cpu], cpu);
 
                hv_context.synic_message_page[cpu] =
@@ -390,6 +478,7 @@ void hv_synic_free(void)
 {
        int cpu;
 
+       kfree(hv_context.hv_numa_map);
        for_each_online_cpu(cpu)
                hv_synic_free_cpu(cpu);
 }
@@ -503,8 +592,7 @@ void hv_synic_cleanup(void *arg)
 
        /* Turn off clockevent device */
        if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
-               hv_ce_setmode(CLOCK_EVT_MODE_SHUTDOWN,
-                             hv_context.clk_evt[cpu]);
+               hv_ce_shutdown(hv_context.clk_evt[cpu]);
 
        rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
@@ -530,6 +618,4 @@ void hv_synic_cleanup(void *arg)
        rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
        sctrl.enable = 0;
        wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
-
-       hv_synic_free_cpu(cpu);
 }
index 8a725cd69ad73601dbbe3153a1ef77e851484798..b853b4b083bde2c402ee4dbacdd25736b4273e58 100644 (file)
 enum {
        DYNMEM_PROTOCOL_VERSION_1 = DYNMEM_MAKE_VERSION(0, 3),
        DYNMEM_PROTOCOL_VERSION_2 = DYNMEM_MAKE_VERSION(1, 0),
+       DYNMEM_PROTOCOL_VERSION_3 = DYNMEM_MAKE_VERSION(2, 0),
 
        DYNMEM_PROTOCOL_VERSION_WIN7 = DYNMEM_PROTOCOL_VERSION_1,
        DYNMEM_PROTOCOL_VERSION_WIN8 = DYNMEM_PROTOCOL_VERSION_2,
+       DYNMEM_PROTOCOL_VERSION_WIN10 = DYNMEM_PROTOCOL_VERSION_3,
 
-       DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN8
+       DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN10
 };
 
 
@@ -1296,13 +1298,25 @@ static void version_resp(struct hv_dynmem_device *dm,
        if (dm->next_version == 0)
                goto version_error;
 
-       dm->next_version = 0;
        memset(&version_req, 0, sizeof(struct dm_version_request));
        version_req.hdr.type = DM_VERSION_REQUEST;
        version_req.hdr.size = sizeof(struct dm_version_request);
        version_req.hdr.trans_id = atomic_inc_return(&trans_id);
-       version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN7;
-       version_req.is_last_attempt = 1;
+       version_req.version.version = dm->next_version;
+
+       /*
+        * Set the next version to try in case current version fails.
+        * Win7 protocol ought to be the last one to try.
+        */
+       switch (version_req.version.version) {
+       case DYNMEM_PROTOCOL_VERSION_WIN8:
+               dm->next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
+               version_req.is_last_attempt = 0;
+               break;
+       default:
+               dm->next_version = 0;
+               version_req.is_last_attempt = 1;
+       }
 
        ret = vmbus_sendpacket(dm->dev->channel, &version_req,
                                sizeof(struct dm_version_request),
@@ -1442,7 +1456,7 @@ static int balloon_probe(struct hv_device *dev,
 
        dm_device.dev = dev;
        dm_device.state = DM_INITIALIZING;
-       dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
+       dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN8;
        init_completion(&dm_device.host_event);
        init_completion(&dm_device.config_event);
        INIT_LIST_HEAD(&dm_device.ha_region_list);
@@ -1474,7 +1488,7 @@ static int balloon_probe(struct hv_device *dev,
        version_req.hdr.type = DM_VERSION_REQUEST;
        version_req.hdr.size = sizeof(struct dm_version_request);
        version_req.hdr.trans_id = atomic_inc_return(&trans_id);
-       version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN8;
+       version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN10;
        version_req.is_last_attempt = 0;
 
        ret = vmbus_sendpacket(dev->channel, &version_req,
index b50dd330cf311ca5d7da7681aa0d818d61a6463b..db4b887b889d268c3e427764e732ce88dc6a008e 100644 (file)
@@ -116,7 +116,7 @@ static int fcopy_handle_handshake(u32 version)
 
 static void fcopy_send_data(struct work_struct *dummy)
 {
-       struct hv_start_fcopy smsg_out;
+       struct hv_start_fcopy *smsg_out = NULL;
        int operation = fcopy_transaction.fcopy_msg->operation;
        struct hv_start_fcopy *smsg_in;
        void *out_src;
@@ -136,21 +136,24 @@ static void fcopy_send_data(struct work_struct *dummy)
        switch (operation) {
        case START_FILE_COPY:
                out_len = sizeof(struct hv_start_fcopy);
-               memset(&smsg_out, 0, out_len);
-               smsg_out.hdr.operation = operation;
+               smsg_out = kzalloc(sizeof(*smsg_out), GFP_KERNEL);
+               if (!smsg_out)
+                       return;
+
+               smsg_out->hdr.operation = operation;
                smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg;
 
                utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH,
                                UTF16_LITTLE_ENDIAN,
-                               (__u8 *)&smsg_out.file_name, W_MAX_PATH - 1);
+                               (__u8 *)&smsg_out->file_name, W_MAX_PATH - 1);
 
                utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH,
                                UTF16_LITTLE_ENDIAN,
-                               (__u8 *)&smsg_out.path_name, W_MAX_PATH - 1);
+                               (__u8 *)&smsg_out->path_name, W_MAX_PATH - 1);
 
-               smsg_out.copy_flags = smsg_in->copy_flags;
-               smsg_out.file_size = smsg_in->file_size;
-               out_src = &smsg_out;
+               smsg_out->copy_flags = smsg_in->copy_flags;
+               smsg_out->file_size = smsg_in->file_size;
+               out_src = smsg_out;
                break;
 
        default:
@@ -168,6 +171,8 @@ static void fcopy_send_data(struct work_struct *dummy)
                        fcopy_transaction.state = HVUTIL_READY;
                }
        }
+       kfree(smsg_out);
+
        return;
 }
 
index d85798d5992c7d6196e3a4ae7671721583639d5b..74c38a9f34a609369fc84b9e0c5ce4a4c7de5931 100644 (file)
@@ -353,6 +353,9 @@ kvp_send_key(struct work_struct *dummy)
                return;
 
        message = kzalloc(sizeof(*message), GFP_KERNEL);
+       if (!message)
+               return;
+
        message->kvp_hdr.operation = operation;
        message->kvp_hdr.pool = pool;
        in_msg = kvp_transaction.kvp_msg;
index ea7ba5ef16a90c2f834378c7675193033309671c..6a9d80a5332d31f264c0ff36ac4464264bfcb40d 100644 (file)
@@ -186,7 +186,7 @@ int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len)
                return -EINVAL;
        } else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) {
                cn_msg = kzalloc(sizeof(*cn_msg) + len, GFP_ATOMIC);
-               if (!msg)
+               if (!cn_msg)
                        return -ENOMEM;
                cn_msg->id.idx = hvt->cn_id.idx;
                cn_msg->id.val = hvt->cn_id.val;
index cddc0c9f6bf9965a8e59bde34011896a762e07ba..3d70e36c918ef3202362daa608eb86bd2fce2281 100644 (file)
@@ -141,7 +141,7 @@ struct hv_port_info {
                struct {
                        u32 target_sint;
                        u32 target_vp;
-                       u16 base_flag_bumber;
+                       u16 base_flag_number;
                        u16 flag_count;
                        u32 rsvdz;
                } event_port_info;
@@ -517,6 +517,7 @@ struct hv_context {
        u64 guestid;
 
        void *hypercall_page;
+       void *tsc_page;
 
        bool synic_initialized;
 
@@ -551,10 +552,23 @@ struct hv_context {
         * Support PV clockevent device.
         */
        struct clock_event_device *clk_evt[NR_CPUS];
+       /*
+        * To manage allocations in a NUMA node.
+        * Array indexed by numa node ID.
+        */
+       struct cpumask *hv_numa_map;
 };
 
 extern struct hv_context hv_context;
 
+struct ms_hyperv_tsc_page {
+       volatile u32 tsc_sequence;
+       u32 reserved1;
+       volatile u64 tsc_scale;
+       volatile s64 tsc_offset;
+       u64 reserved2[509];
+};
+
 struct hv_ring_buffer_debug_info {
        u32 current_interrupt_mask;
        u32 current_read_index;
index 6361d124f67dc71efc5b2e4e020bc208a54acc12..70a1a9a22f872761aceeaaa56032dd5ec044a729 100644 (file)
@@ -103,10 +103,9 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
  *    there is room for the producer to send the pending packet.
  */
 
-static bool hv_need_to_signal_on_read(u32 old_rd,
-                                        struct hv_ring_buffer_info *rbi)
+static bool hv_need_to_signal_on_read(u32 prev_write_sz,
+                                     struct hv_ring_buffer_info *rbi)
 {
-       u32 prev_write_sz;
        u32 cur_write_sz;
        u32 r_size;
        u32 write_loc = rbi->ring_buffer->write_index;
@@ -123,10 +122,6 @@ static bool hv_need_to_signal_on_read(u32 old_rd,
        cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) :
                        read_loc - write_loc;
 
-       prev_write_sz = write_loc >= old_rd ? r_size - (write_loc - old_rd) :
-                       old_rd - write_loc;
-
-
        if ((prev_write_sz < pending_sz) && (cur_write_sz >= pending_sz))
                return true;
 
@@ -517,7 +512,6 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
        u32 next_read_location = 0;
        u64 prev_indices = 0;
        unsigned long flags;
-       u32 old_read;
 
        if (buflen <= 0)
                return -EINVAL;
@@ -528,8 +522,6 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
                                &bytes_avail_toread,
                                &bytes_avail_towrite);
 
-       old_read = bytes_avail_toread;
-
        /* Make sure there is something to read */
        if (bytes_avail_toread < buflen) {
                spin_unlock_irqrestore(&inring_info->ring_lock, flags);
@@ -560,7 +552,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
 
        spin_unlock_irqrestore(&inring_info->ring_lock, flags);
 
-       *signal = hv_need_to_signal_on_read(old_read, inring_info);
+       *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info);
 
        return 0;
 }
index cf204005ee784db8dc7bd3cab85e86c589f67cec..f19b6f7a467a6a8c14988da9a3817e2cea02c433 100644 (file)
@@ -39,6 +39,8 @@
 #include <asm/mshyperv.h>
 #include <linux/notifier.h>
 #include <linux/ptrace.h>
+#include <linux/screen_info.h>
+#include <linux/kdebug.h>
 #include "hyperv_vmbus.h"
 
 static struct acpi_device  *hv_acpi_dev;
@@ -48,12 +50,18 @@ static struct completion probe_event;
 static int irq;
 
 
-static int hyperv_panic_event(struct notifier_block *nb,
-                       unsigned long event, void *ptr)
+static void hyperv_report_panic(struct pt_regs *regs)
 {
-       struct pt_regs *regs;
+       static bool panic_reported;
 
-       regs = current_pt_regs();
+       /*
+        * We prefer to report panic on 'die' chain as we have proper
+        * registers to report, but if we miss it (e.g. on BUG()) we need
+        * to report it on 'panic'.
+        */
+       if (panic_reported)
+               return;
+       panic_reported = true;
 
        wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
        wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
@@ -65,18 +73,37 @@ static int hyperv_panic_event(struct notifier_block *nb,
         * Let Hyper-V know there is crash data available
         */
        wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
+}
+
+static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
+                             void *args)
+{
+       struct pt_regs *regs;
+
+       regs = current_pt_regs();
+
+       hyperv_report_panic(regs);
        return NOTIFY_DONE;
 }
 
+static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
+                           void *args)
+{
+       struct die_args *die = (struct die_args *)args;
+       struct pt_regs *regs = die->regs;
+
+       hyperv_report_panic(regs);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block hyperv_die_block = {
+       .notifier_call = hyperv_die_event,
+};
 static struct notifier_block hyperv_panic_block = {
        .notifier_call = hyperv_panic_event,
 };
 
-struct resource hyperv_mmio = {
-       .name  = "hyperv mmio",
-       .flags = IORESOURCE_MEM,
-};
-EXPORT_SYMBOL_GPL(hyperv_mmio);
+struct resource *hyperv_mmio;
 
 static int vmbus_exists(void)
 {
@@ -414,6 +441,43 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(in_write_bytes_avail);
 
+static ssize_t channel_vp_mapping_show(struct device *dev,
+                                      struct device_attribute *dev_attr,
+                                      char *buf)
+{
+       struct hv_device *hv_dev = device_to_hv_device(dev);
+       struct vmbus_channel *channel = hv_dev->channel, *cur_sc;
+       unsigned long flags;
+       int buf_size = PAGE_SIZE, n_written, tot_written;
+       struct list_head *cur;
+
+       if (!channel)
+               return -ENODEV;
+
+       tot_written = snprintf(buf, buf_size, "%u:%u\n",
+               channel->offermsg.child_relid, channel->target_cpu);
+
+       spin_lock_irqsave(&channel->lock, flags);
+
+       list_for_each(cur, &channel->sc_list) {
+               if (tot_written >= buf_size - 1)
+                       break;
+
+               cur_sc = list_entry(cur, struct vmbus_channel, sc_list);
+               n_written = scnprintf(buf + tot_written,
+                                    buf_size - tot_written,
+                                    "%u:%u\n",
+                                    cur_sc->offermsg.child_relid,
+                                    cur_sc->target_cpu);
+               tot_written += n_written;
+       }
+
+       spin_unlock_irqrestore(&channel->lock, flags);
+
+       return tot_written;
+}
+static DEVICE_ATTR_RO(channel_vp_mapping);
+
 /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
 static struct attribute *vmbus_attrs[] = {
        &dev_attr_id.attr,
@@ -438,6 +502,7 @@ static struct attribute *vmbus_attrs[] = {
        &dev_attr_in_write_index.attr,
        &dev_attr_in_read_bytes_avail.attr,
        &dev_attr_in_write_bytes_avail.attr,
+       &dev_attr_channel_vp_mapping.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(vmbus);
@@ -763,38 +828,6 @@ static void vmbus_isr(void)
        }
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int hyperv_cpu_disable(void)
-{
-       return -ENOSYS;
-}
-
-static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
-{
-       static void *previous_cpu_disable;
-
-       /*
-        * Offlining a CPU when running on newer hypervisors (WS2012R2, Win8,
-        * ...) is not supported at this moment as channel interrupts are
-        * distributed across all of them.
-        */
-
-       if ((vmbus_proto_version == VERSION_WS2008) ||
-           (vmbus_proto_version == VERSION_WIN7))
-               return;
-
-       if (vmbus_loaded) {
-               previous_cpu_disable = smp_ops.cpu_disable;
-               smp_ops.cpu_disable = hyperv_cpu_disable;
-               pr_notice("CPU offlining is not supported by hypervisor\n");
-       } else if (previous_cpu_disable)
-               smp_ops.cpu_disable = previous_cpu_disable;
-}
-#else
-static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
-{
-}
-#endif
 
 /*
  * vmbus_bus_init -Main vmbus driver initialization routine.
@@ -836,12 +869,14 @@ static int vmbus_bus_init(int irq)
        if (ret)
                goto err_alloc;
 
-       hv_cpu_hotplug_quirk(true);
+       if (vmbus_proto_version > VERSION_WIN7)
+               cpu_hotplug_disable();
 
        /*
         * Only register if the crash MSRs are available
         */
-       if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+       if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+               register_die_notifier(&hyperv_die_block);
                atomic_notifier_chain_register(&panic_notifier_list,
                                               &hyperv_panic_block);
        }
@@ -863,8 +898,8 @@ err_cleanup:
 }
 
 /**
- * __vmbus_child_driver_register - Register a vmbus's driver
- * @drv: Pointer to driver structure you want to register
+ * __vmbus_child_driver_register() - Register a vmbus's driver
+ * @hv_driver: Pointer to driver structure you want to register
  * @owner: owner module of the drv
  * @mod_name: module name string
  *
@@ -896,7 +931,8 @@ EXPORT_SYMBOL_GPL(__vmbus_driver_register);
 
 /**
  * vmbus_driver_unregister() - Unregister a vmbus's driver
- * @drv: Pointer to driver structure you want to un-register
+ * @hv_driver: Pointer to driver structure you want to
+ *             un-register
  *
  * Un-register the given driver that was previous registered with a call to
  * vmbus_driver_register()
@@ -982,30 +1018,184 @@ void vmbus_device_unregister(struct hv_device *device_obj)
 
 
 /*
- * VMBUS is an acpi enumerated device. Get the the information we
+ * VMBUS is an acpi enumerated device. Get the information we
  * need from DSDT.
  */
-
+#define VTPM_BASE_ADDRESS 0xfed40000
 static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
 {
+       resource_size_t start = 0;
+       resource_size_t end = 0;
+       struct resource *new_res;
+       struct resource **old_res = &hyperv_mmio;
+       struct resource **prev_res = NULL;
+
        switch (res->type) {
        case ACPI_RESOURCE_TYPE_IRQ:
                irq = res->data.irq.interrupts[0];
+               return AE_OK;
+
+       /*
+        * "Address" descriptors are for bus windows. Ignore
+        * "memory" descriptors, which are for registers on
+        * devices.
+        */
+       case ACPI_RESOURCE_TYPE_ADDRESS32:
+               start = res->data.address32.address.minimum;
+               end = res->data.address32.address.maximum;
                break;
 
        case ACPI_RESOURCE_TYPE_ADDRESS64:
-               hyperv_mmio.start = res->data.address64.address.minimum;
-               hyperv_mmio.end = res->data.address64.address.maximum;
+               start = res->data.address64.address.minimum;
+               end = res->data.address64.address.maximum;
                break;
+
+       default:
+               /* Unused resource type */
+               return AE_OK;
+
        }
+       /*
+        * Ignore ranges that are below 1MB, as they're not
+        * necessary or useful here.
+        */
+       if (end < 0x100000)
+               return AE_OK;
+
+       new_res = kzalloc(sizeof(*new_res), GFP_ATOMIC);
+       if (!new_res)
+               return AE_NO_MEMORY;
+
+       /* If this range overlaps the virtual TPM, truncate it. */
+       if (end > VTPM_BASE_ADDRESS && start < VTPM_BASE_ADDRESS)
+               end = VTPM_BASE_ADDRESS;
+
+       new_res->name = "hyperv mmio";
+       new_res->flags = IORESOURCE_MEM;
+       new_res->start = start;
+       new_res->end = end;
+
+       do {
+               if (!*old_res) {
+                       *old_res = new_res;
+                       break;
+               }
+
+               if ((*old_res)->end < new_res->start) {
+                       new_res->sibling = *old_res;
+                       if (prev_res)
+                               (*prev_res)->sibling = new_res;
+                       *old_res = new_res;
+                       break;
+               }
+
+               prev_res = old_res;
+               old_res = &(*old_res)->sibling;
+
+       } while (1);
 
        return AE_OK;
 }
 
+static int vmbus_acpi_remove(struct acpi_device *device)
+{
+       struct resource *cur_res;
+       struct resource *next_res;
+
+       if (hyperv_mmio) {
+               for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) {
+                       next_res = cur_res->sibling;
+                       kfree(cur_res);
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * vmbus_allocate_mmio() - Pick a memory-mapped I/O range.
+ * @new:               If successful, supplied a pointer to the
+ *                     allocated MMIO space.
+ * @device_obj:                Identifies the caller
+ * @min:               Minimum guest physical address of the
+ *                     allocation
+ * @max:               Maximum guest physical address
+ * @size:              Size of the range to be allocated
+ * @align:             Alignment of the range to be allocated
+ * @fb_overlap_ok:     Whether this allocation can be allowed
+ *                     to overlap the video frame buffer.
+ *
+ * This function walks the resources granted to VMBus by the
+ * _CRS object in the ACPI namespace underneath the parent
+ * "bridge" whether that's a root PCI bus in the Generation 1
+ * case or a Module Device in the Generation 2 case.  It then
+ * attempts to allocate from the global MMIO pool in a way that
+ * matches the constraints supplied in these parameters and by
+ * that _CRS.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
+                       resource_size_t min, resource_size_t max,
+                       resource_size_t size, resource_size_t align,
+                       bool fb_overlap_ok)
+{
+       struct resource *iter;
+       resource_size_t range_min, range_max, start, local_min, local_max;
+       const char *dev_n = dev_name(&device_obj->device);
+       u32 fb_end = screen_info.lfb_base + (screen_info.lfb_size << 1);
+       int i;
+
+       for (iter = hyperv_mmio; iter; iter = iter->sibling) {
+               if ((iter->start >= max) || (iter->end <= min))
+                       continue;
+
+               range_min = iter->start;
+               range_max = iter->end;
+
+               /* If this range overlaps the frame buffer, split it into
+                  two tries. */
+               for (i = 0; i < 2; i++) {
+                       local_min = range_min;
+                       local_max = range_max;
+                       if (fb_overlap_ok || (range_min >= fb_end) ||
+                           (range_max <= screen_info.lfb_base)) {
+                               i++;
+                       } else {
+                               if ((range_min <= screen_info.lfb_base) &&
+                                   (range_max >= screen_info.lfb_base)) {
+                                       /*
+                                        * The frame buffer is in this window,
+                                        * so trim this into the part that
+                                        * preceeds the frame buffer.
+                                        */
+                                       local_max = screen_info.lfb_base - 1;
+                                       range_min = fb_end;
+                               } else {
+                                       range_min = fb_end;
+                                       continue;
+                               }
+                       }
+
+                       start = (local_min + align - 1) & ~(align - 1);
+                       for (; start + size - 1 <= local_max; start += align) {
+                               *new = request_mem_region_exclusive(start, size,
+                                                                   dev_n);
+                               if (*new)
+                                       return 0;
+                       }
+               }
+       }
+
+       return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(vmbus_allocate_mmio);
+
 static int vmbus_acpi_add(struct acpi_device *device)
 {
        acpi_status result;
        int ret_val = -ENODEV;
+       struct acpi_device *ancestor;
 
        hv_acpi_dev = device;
 
@@ -1015,35 +1205,27 @@ static int vmbus_acpi_add(struct acpi_device *device)
        if (ACPI_FAILURE(result))
                goto acpi_walk_err;
        /*
-        * The parent of the vmbus acpi device (Gen2 firmware) is the VMOD that
-        * has the mmio ranges. Get that.
+        * Some ancestor of the vmbus acpi device (Gen1 or Gen2
+        * firmware) is the VMOD that has the mmio ranges. Get that.
         */
-       if (device->parent) {
-               result = acpi_walk_resources(device->parent->handle,
-                                       METHOD_NAME__CRS,
-                                       vmbus_walk_resources, NULL);
+       for (ancestor = device->parent; ancestor; ancestor = ancestor->parent) {
+               result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS,
+                                            vmbus_walk_resources, NULL);
 
                if (ACPI_FAILURE(result))
-                       goto acpi_walk_err;
-               if (hyperv_mmio.start && hyperv_mmio.end)
-                       request_resource(&iomem_resource, &hyperv_mmio);
+                       continue;
+               if (hyperv_mmio)
+                       break;
        }
        ret_val = 0;
 
 acpi_walk_err:
        complete(&probe_event);
+       if (ret_val)
+               vmbus_acpi_remove(device);
        return ret_val;
 }
 
-static int vmbus_acpi_remove(struct acpi_device *device)
-{
-       int ret = 0;
-
-       if (hyperv_mmio.start && hyperv_mmio.end)
-               ret = release_resource(&hyperv_mmio);
-       return ret;
-}
-
 static const struct acpi_device_id vmbus_acpi_device_ids[] = {
        {"VMBUS", 0},
        {"VMBus", 0},
@@ -1060,6 +1242,29 @@ static struct acpi_driver vmbus_acpi_driver = {
        },
 };
 
+static void hv_kexec_handler(void)
+{
+       int cpu;
+
+       hv_synic_clockevents_cleanup();
+       vmbus_initiate_unload();
+       for_each_online_cpu(cpu)
+               smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
+       hv_cleanup();
+};
+
+static void hv_crash_handler(struct pt_regs *regs)
+{
+       vmbus_initiate_unload();
+       /*
+        * In crash handler we can't schedule synic cleanup for all CPUs,
+        * doing the cleanup for current CPU only. This should be sufficient
+        * for kdump.
+        */
+       hv_synic_cleanup(NULL);
+       hv_cleanup();
+};
+
 static int __init hv_acpi_init(void)
 {
        int ret, t;
@@ -1092,6 +1297,9 @@ static int __init hv_acpi_init(void)
        if (ret)
                goto cleanup;
 
+       hv_setup_kexec_handler(hv_kexec_handler);
+       hv_setup_crash_handler(hv_crash_handler);
+
        return 0;
 
 cleanup:
@@ -1104,13 +1312,16 @@ static void __exit vmbus_exit(void)
 {
        int cpu;
 
+       hv_remove_kexec_handler();
+       hv_remove_crash_handler();
        vmbus_connection.conn_state = DISCONNECTED;
        hv_synic_clockevents_cleanup();
        vmbus_disconnect();
        hv_remove_vmbus_irq();
        tasklet_kill(&msg_dpc);
        vmbus_free_channels();
-       if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+       if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+               unregister_die_notifier(&hyperv_die_block);
                atomic_notifier_chain_unregister(&panic_notifier_list,
                                                 &hyperv_panic_block);
        }
@@ -1120,8 +1331,10 @@ static void __exit vmbus_exit(void)
                tasklet_kill(hv_context.event_dpc[cpu]);
                smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
        }
+       hv_synic_free();
        acpi_bus_unregister_driver(&vmbus_acpi_driver);
-       hv_cpu_hotplug_quirk(false);
+       if (vmbus_proto_version > VERSION_WIN7)
+               cpu_hotplug_enable();
 }
 
 
index 7c65b7334738ee1539d0fbc7bbf4d5ad7475166d..500b262b89bb15ee9859caa097fdb2b2f6977849 100644 (file)
@@ -609,8 +609,8 @@ config SENSORS_IT87
        depends on !PPC
        select HWMON_VID
        help
-         If you say yes here you get support for ITE IT8705F, IT8712F,
-         IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
+         If you say yes here you get support for ITE IT8705F, IT8712F, IT8716F,
+         IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, IT8758E,
          IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E,
          IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone.
 
index 2e5c6f46e4422b818ec8d91a33af971213a23074..cb28e4b4fb108567c508914fcf21bfb440c7c4da 100644 (file)
@@ -51,6 +51,7 @@
 #define SIO_F71808A_ID         0x1001  /* Chipset ID */
 #define SIO_F71858_ID          0x0507  /* Chipset ID */
 #define SIO_F71862_ID          0x0601  /* Chipset ID */
+#define SIO_F71868_ID          0x1106  /* Chipset ID */
 #define SIO_F71869_ID          0x0814  /* Chipset ID */
 #define SIO_F71869A_ID         0x1007  /* Chipset ID */
 #define SIO_F71882_ID          0x0541  /* Chipset ID */
@@ -58,7 +59,9 @@
 #define SIO_F71889E_ID         0x0909  /* Chipset ID */
 #define SIO_F71889A_ID         0x1005  /* Chipset ID */
 #define SIO_F8000_ID           0x0581  /* Chipset ID */
+#define SIO_F81768D_ID         0x1210  /* Chipset ID */
 #define SIO_F81865_ID          0x0704  /* Chipset ID */
+#define SIO_F81866_ID          0x1010  /* Chipset ID */
 
 #define REGION_LENGTH          8
 #define ADDR_REG_OFFSET                5
 #define F71882FG_REG_IN(nr)            (0x20  + (nr))
 #define F71882FG_REG_IN1_HIGH          0x32 /* f7188x only */
 
+#define F81866_REG_IN_STATUS           0x16 /* F81866 only */
+#define F81866_REG_IN_BEEP                     0x17 /* F81866 only */
+#define F81866_REG_IN1_HIGH            0x3a /* F81866 only */
+
 #define F71882FG_REG_FAN(nr)           (0xA0 + (16 * (nr)))
 #define F71882FG_REG_FAN_TARGET(nr)    (0xA2 + (16 * (nr)))
 #define F71882FG_REG_FAN_FULL_SPEED(nr)        (0xA4 + (16 * (nr)))
 
 #define        F71882FG_REG_START              0x01
 
-#define F71882FG_MAX_INS               9
+#define F71882FG_MAX_INS               11
 
 #define FAN_MIN_DETECT                 366 /* Lowest detectable fanspeed */
 
@@ -109,14 +116,16 @@ static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg,
-            f71889fg, f71889ed, f71889a, f8000, f81865f };
+enum chips { f71808e, f71808a, f71858fg, f71862fg, f71868a, f71869, f71869a,
+       f71882fg, f71889fg, f71889ed, f71889a, f8000, f81768d, f81865f,
+       f81866a};
 
 static const char *const f71882fg_names[] = {
        "f71808e",
        "f71808a",
        "f71858fg",
        "f71862fg",
+       "f71868a",
        "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
        "f71869a",
        "f71882fg",
@@ -124,22 +133,27 @@ static const char *const f71882fg_names[] = {
        "f71889ed",
        "f71889a",
        "f8000",
+       "f81768d",
        "f81865f",
+       "f81866a",
 };
 
 static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
-       [f71808e]       = { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
-       [f71808a]       = { 1, 1, 1, 1, 0, 0, 0, 1, 1 },
-       [f71858fg]      = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
-       [f71862fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71869]        = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71869a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71882fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71889fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71889ed]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f71889a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
-       [f8000]         = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
-       [f81865f]       = { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71808e]       = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 },
+       [f71808a]       = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0 },
+       [f71858fg]      = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+       [f71862fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71868a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
+       [f71869]        = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71869a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71882fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71889fg]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71889ed]      = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f71889a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+       [f8000]         = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+       [f81768d]       = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+       [f81865f]       = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+       [f81866a]       = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
 };
 
 static const char f71882fg_has_in1_alarm[] = {
@@ -147,6 +161,7 @@ static const char f71882fg_has_in1_alarm[] = {
        [f71808a]       = 0,
        [f71858fg]      = 0,
        [f71862fg]      = 0,
+       [f71868a]       = 0,
        [f71869]        = 0,
        [f71869a]       = 0,
        [f71882fg]      = 1,
@@ -154,7 +169,9 @@ static const char f71882fg_has_in1_alarm[] = {
        [f71889ed]      = 1,
        [f71889a]       = 1,
        [f8000]         = 0,
+       [f81768d]       = 1,
        [f81865f]       = 1,
+       [f81866a]       = 1,
 };
 
 static const char f71882fg_fan_has_beep[] = {
@@ -162,6 +179,7 @@ static const char f71882fg_fan_has_beep[] = {
        [f71808a]       = 0,
        [f71858fg]      = 0,
        [f71862fg]      = 1,
+       [f71868a]       = 1,
        [f71869]        = 1,
        [f71869a]       = 1,
        [f71882fg]      = 1,
@@ -169,7 +187,9 @@ static const char f71882fg_fan_has_beep[] = {
        [f71889ed]      = 1,
        [f71889a]       = 1,
        [f8000]         = 0,
+       [f81768d]       = 1,
        [f81865f]       = 1,
+       [f81866a]       = 1,
 };
 
 static const char f71882fg_nr_fans[] = {
@@ -177,6 +197,7 @@ static const char f71882fg_nr_fans[] = {
        [f71808a]       = 2, /* +1 fan which is monitor + simple pwm only */
        [f71858fg]      = 3,
        [f71862fg]      = 3,
+       [f71868a]       = 3,
        [f71869]        = 3,
        [f71869a]       = 3,
        [f71882fg]      = 4,
@@ -184,7 +205,9 @@ static const char f71882fg_nr_fans[] = {
        [f71889ed]      = 3,
        [f71889a]       = 3,
        [f8000]         = 3, /* +1 fan which is monitor only */
+       [f81768d]       = 3,
        [f81865f]       = 2,
+       [f81866a]       = 3,
 };
 
 static const char f71882fg_temp_has_beep[] = {
@@ -192,6 +215,7 @@ static const char f71882fg_temp_has_beep[] = {
        [f71808a]       = 1,
        [f71858fg]      = 0,
        [f71862fg]      = 1,
+       [f71868a]       = 1,
        [f71869]        = 1,
        [f71869a]       = 1,
        [f71882fg]      = 1,
@@ -199,7 +223,9 @@ static const char f71882fg_temp_has_beep[] = {
        [f71889ed]      = 1,
        [f71889a]       = 1,
        [f8000]         = 0,
+       [f81768d]       = 1,
        [f81865f]       = 1,
+       [f81866a]       = 1,
 };
 
 static const char f71882fg_nr_temps[] = {
@@ -207,6 +233,7 @@ static const char f71882fg_nr_temps[] = {
        [f71808a]       = 2,
        [f71858fg]      = 3,
        [f71862fg]      = 3,
+       [f71868a]       = 3,
        [f71869]        = 3,
        [f71869a]       = 3,
        [f71882fg]      = 3,
@@ -214,7 +241,9 @@ static const char f71882fg_nr_temps[] = {
        [f71889ed]      = 3,
        [f71889a]       = 3,
        [f8000]         = 3,
+       [f81768d]       = 3,
        [f81865f]       = 2,
+       [f81866a]       = 3,
 };
 
 static struct platform_device *f71882fg_pdev;
@@ -490,6 +519,23 @@ static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
                store_temp_beep, 0, 7),
 } };
 
+static struct sensor_device_attribute_2 f81866_temp_beep_attr[3][2] = { {
+       SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 0),
+       SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 4),
+}, {
+       SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 1),
+       SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 5),
+}, {
+       SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 2),
+       SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+               store_temp_beep, 0, 6),
+} };
+
 /*
  * Temp attr for the f8000
  * Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
@@ -531,6 +577,8 @@ static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
        SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
        SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
        SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+       SENSOR_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 0, 9),
+       SENSOR_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 0, 10),
 };
 
 /* For models with in1 alarm capability */
@@ -1170,10 +1218,21 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
        if (time_after(jiffies, data->last_limits + 60 * HZ) ||
                        !data->valid) {
                if (f71882fg_has_in1_alarm[data->type]) {
-                       data->in1_max =
-                               f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
-                       data->in_beep =
-                               f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+                       if (data->type == f81866a) {
+                               data->in1_max =
+                                       f71882fg_read8(data,
+                                                      F81866_REG_IN1_HIGH);
+                               data->in_beep =
+                                       f71882fg_read8(data,
+                                                      F81866_REG_IN_BEEP);
+                       } else {
+                               data->in1_max =
+                                       f71882fg_read8(data,
+                                                      F71882FG_REG_IN1_HIGH);
+                               data->in_beep =
+                                       f71882fg_read8(data,
+                                                      F71882FG_REG_IN_BEEP);
+                       }
                }
 
                /* Get High & boundary temps*/
@@ -1297,9 +1356,16 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
                        data->fan[3] = f71882fg_read16(data,
                                                F71882FG_REG_FAN(3));
 
-               if (f71882fg_has_in1_alarm[data->type])
-                       data->in_status = f71882fg_read8(data,
+               if (f71882fg_has_in1_alarm[data->type]) {
+                       if (data->type == f81866a)
+                               data->in_status = f71882fg_read8(data,
+                                               F81866_REG_IN_STATUS);
+
+                       else
+                               data->in_status = f71882fg_read8(data,
                                                F71882FG_REG_IN_STATUS);
+               }
+
                for (nr = 0; nr < F71882FG_MAX_INS; nr++)
                        if (f71882fg_has_in[data->type][nr])
                                data->in[nr] = f71882fg_read8(data,
@@ -1440,7 +1506,10 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
        val = clamp_val(val, 0, 255);
 
        mutex_lock(&data->update_lock);
-       f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
+       if (data->type == f81866a)
+               f71882fg_write8(data, F81866_REG_IN1_HIGH, val);
+       else
+               f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
        data->in1_max = val;
        mutex_unlock(&data->update_lock);
 
@@ -1471,13 +1540,20 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute
                return err;
 
        mutex_lock(&data->update_lock);
-       data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+       if (data->type == f81866a)
+               data->in_beep = f71882fg_read8(data, F81866_REG_IN_BEEP);
+       else
+               data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+
        if (val)
                data->in_beep |= 1 << nr;
        else
                data->in_beep &= ~(1 << nr);
 
-       f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
+       if (data->type == f81866a)
+               f71882fg_write8(data, F81866_REG_IN_BEEP, data->in_beep);
+       else
+               f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
        mutex_unlock(&data->update_lock);
 
        return count;
@@ -2270,6 +2346,7 @@ static int f71882fg_probe(struct platform_device *pdev)
        int nr_fans = f71882fg_nr_fans[sio_data->type];
        int nr_temps = f71882fg_nr_temps[sio_data->type];
        int err, i;
+       int size;
        u8 start_reg, reg;
 
        data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),
@@ -2280,7 +2357,8 @@ static int f71882fg_probe(struct platform_device *pdev)
        data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
        data->type = sio_data->type;
        data->temp_start =
-           (data->type == f71858fg || data->type == f8000) ? 0 : 1;
+           (data->type == f71858fg || data->type == f8000 ||
+               data->type == f81866a) ? 0 : 1;
        mutex_init(&data->update_lock);
        platform_set_drvdata(pdev, data);
 
@@ -2322,6 +2400,11 @@ static int f71882fg_probe(struct platform_device *pdev)
                                        f8000_temp_attr,
                                        ARRAY_SIZE(f8000_temp_attr));
                        break;
+               case f81866a:
+                       err = f71882fg_create_sysfs_files(pdev,
+                                       f71858fg_temp_attr,
+                                       ARRAY_SIZE(f71858fg_temp_attr));
+                       break;
                default:
                        err = f71882fg_create_sysfs_files(pdev,
                                &fxxxx_temp_attr[0][0],
@@ -2331,10 +2414,18 @@ static int f71882fg_probe(struct platform_device *pdev)
                        goto exit_unregister_sysfs;
 
                if (f71882fg_temp_has_beep[data->type]) {
-                       err = f71882fg_create_sysfs_files(pdev,
-                                       &fxxxx_temp_beep_attr[0][0],
-                                       ARRAY_SIZE(fxxxx_temp_beep_attr[0])
-                                               * nr_temps);
+                       if (data->type == f81866a) {
+                               size = ARRAY_SIZE(f81866_temp_beep_attr[0]);
+                               err = f71882fg_create_sysfs_files(pdev,
+                                               &f81866_temp_beep_attr[0][0],
+                                               size * nr_temps);
+
+                       } else {
+                               size = ARRAY_SIZE(fxxxx_temp_beep_attr[0]);
+                               err = f71882fg_create_sysfs_files(pdev,
+                                               &fxxxx_temp_beep_attr[0][0],
+                                               size * nr_temps);
+                       }
                        if (err)
                                goto exit_unregister_sysfs;
                }
@@ -2451,15 +2542,27 @@ static int f71882fg_remove(struct platform_device *pdev)
                                        f8000_temp_attr,
                                        ARRAY_SIZE(f8000_temp_attr));
                        break;
+               case f81866a:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       f71858fg_temp_attr,
+                                       ARRAY_SIZE(f71858fg_temp_attr));
+                       break;
                default:
                        f71882fg_remove_sysfs_files(pdev,
                                &fxxxx_temp_attr[0][0],
                                ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
                }
                if (f71882fg_temp_has_beep[data->type]) {
-                       f71882fg_remove_sysfs_files(pdev,
-                              &fxxxx_temp_beep_attr[0][0],
-                              ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
+                       if (data->type == f81866a)
+                               f71882fg_remove_sysfs_files(pdev,
+                                       &f81866_temp_beep_attr[0][0],
+                                       ARRAY_SIZE(f81866_temp_beep_attr[0])
+                                               * nr_temps);
+                       else
+                               f71882fg_remove_sysfs_files(pdev,
+                                       &fxxxx_temp_beep_attr[0][0],
+                                       ARRAY_SIZE(fxxxx_temp_beep_attr[0])
+                                               * nr_temps);
                }
 
                for (i = 0; i < F71882FG_MAX_INS; i++) {
@@ -2551,6 +2654,9 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
        case SIO_F71862_ID:
                sio_data->type = f71862fg;
                break;
+       case SIO_F71868_ID:
+               sio_data->type = f71868a;
+               break;
        case SIO_F71869_ID:
                sio_data->type = f71869;
                break;
@@ -2572,9 +2678,15 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
        case SIO_F8000_ID:
                sio_data->type = f8000;
                break;
+       case SIO_F81768D_ID:
+               sio_data->type = f81768d;
+               break;
        case SIO_F81865_ID:
                sio_data->type = f81865f;
                break;
+       case SIO_F81866_ID:
+               sio_data->type = f81866a;
+               break;
        default:
                pr_info("Unsupported Fintek device: %04x\n",
                        (unsigned int)devid);
index 3057dfc7e3bc6cde853660579b01b4cab3530344..e80ee23b62d317c007d2445d69917b2e65b35559 100644 (file)
@@ -46,6 +46,7 @@ struct fam15h_power_data {
        unsigned int tdp_to_watts;
        unsigned int base_tdp;
        unsigned int processor_pwr_watts;
+       unsigned int cpu_pwr_sample_ratio;
 };
 
 static ssize_t show_power(struct device *dev,
@@ -59,8 +60,19 @@ static ssize_t show_power(struct device *dev,
 
        pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
                                  REG_TDP_RUNNING_AVERAGE, &val);
-       running_avg_capture = (val >> 4) & 0x3fffff;
-       running_avg_capture = sign_extend32(running_avg_capture, 21);
+
+       /*
+        * On Carrizo and later platforms, TdpRunAvgAccCap bit field
+        * is extended to 4:31 from 4:25.
+        */
+       if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) {
+               running_avg_capture = val >> 4;
+               running_avg_capture = sign_extend32(running_avg_capture, 27);
+       } else {
+               running_avg_capture = (val >> 4) & 0x3fffff;
+               running_avg_capture = sign_extend32(running_avg_capture, 21);
+       }
+
        running_avg_range = (val & 0xf) + 1;
 
        pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
@@ -117,7 +129,7 @@ static const struct attribute_group fam15h_power_group = {
 };
 __ATTRIBUTE_GROUPS(fam15h_power);
 
-static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
+static bool should_load_on_this_node(struct pci_dev *f4)
 {
        u32 val;
 
@@ -177,7 +189,7 @@ static int fam15h_power_resume(struct pci_dev *pdev)
 static void fam15h_power_init_data(struct pci_dev *f4,
                                             struct fam15h_power_data *data)
 {
-       u32 val;
+       u32 val, eax, ebx, ecx, edx;
        u64 tmp;
 
        pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val);
@@ -198,6 +210,19 @@ static void fam15h_power_init_data(struct pci_dev *f4,
 
        /* convert to microWatt */
        data->processor_pwr_watts = (tmp * 15625) >> 10;
+
+       cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
+
+       /* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */
+       if (!(edx & BIT(12)))
+               return;
+
+       /*
+        * determine the ratio of the compute unit power accumulator
+        * sample period to the PTSC counter period by executing CPUID
+        * Fn8000_0007:ECX
+        */
+       data->cpu_pwr_sample_ratio = ecx;
 }
 
 static int fam15h_power_probe(struct pci_dev *pdev,
@@ -214,7 +239,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
         */
        tweak_runavg_range(pdev);
 
-       if (!fam15h_power_is_internal_node0(pdev))
+       if (!should_load_on_this_node(pdev))
                return -ENODEV;
 
        data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL);
@@ -233,6 +258,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
 static const struct pci_device_id fam15h_power_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
        {}
index 85d106fe3ce8628061901b53240e546a884cbea0..b96a2a9e4df7d5af127ad42fa5ee5a00fa840b8e 100644 (file)
@@ -1113,7 +1113,6 @@ static int g762_remove(struct i2c_client *client)
 static struct i2c_driver g762_driver = {
        .driver = {
                .name = DRVNAME,
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(g762_dt_match),
        },
        .probe    = g762_probe,
index d0ee556e8ce00447d9d16d8c3adb81de4160bfae..1896e26df6347c7b3290fecc1bcd28b51466d754 100644 (file)
@@ -21,6 +21,7 @@
  *            IT8721F  Super I/O chip w/LPC interface
  *            IT8726F  Super I/O chip w/LPC interface
  *            IT8728F  Super I/O chip w/LPC interface
+ *            IT8732F  Super I/O chip w/LPC interface
  *            IT8758E  Super I/O chip w/LPC interface
  *            IT8771E  Super I/O chip w/LPC interface
  *            IT8772E  Super I/O chip w/LPC interface
@@ -69,8 +70,9 @@
 
 #define DRVNAME "it87"
 
-enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
-            it8772, it8781, it8782, it8783, it8786, it8790, it8603, it8620 };
+enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
+            it8771, it8772, it8781, it8782, it8783, it8786, it8790, it8603,
+            it8620 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -148,6 +150,7 @@ static inline void superio_exit(void)
 #define IT8721F_DEVID 0x8721
 #define IT8726F_DEVID 0x8726
 #define IT8728F_DEVID 0x8728
+#define IT8732F_DEVID 0x8732
 #define IT8771E_DEVID 0x8771
 #define IT8772E_DEVID 0x8772
 #define IT8781F_DEVID 0x8781
@@ -265,6 +268,7 @@ struct it87_devices {
 #define FEAT_VID               (1 << 9)        /* Set if chip supports VID */
 #define FEAT_IN7_INTERNAL      (1 << 10)       /* Set if in7 is internal */
 #define FEAT_SIX_FANS          (1 << 11)       /* Supports six fans */
+#define FEAT_10_9MV_ADC                (1 << 12)
 
 static const struct it87_devices it87_devices[] = {
        [it87] = {
@@ -315,6 +319,15 @@ static const struct it87_devices it87_devices[] = {
                  | FEAT_IN7_INTERNAL,
                .peci_mask = 0x07,
        },
+       [it8732] = {
+               .name = "it8732",
+               .suffix = "F",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
+                 | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL,
+               .peci_mask = 0x07,
+               .old_peci_mask = 0x02,  /* Actually reports PCH */
+       },
        [it8771] = {
                .name = "it8771",
                .suffix = "E",
@@ -391,6 +404,7 @@ static const struct it87_devices it87_devices[] = {
 
 #define has_16bit_fans(data)   ((data)->features & FEAT_16BIT_FANS)
 #define has_12mv_adc(data)     ((data)->features & FEAT_12MV_ADC)
+#define has_10_9mv_adc(data)   ((data)->features & FEAT_10_9MV_ADC)
 #define has_newer_autopwm(data)        ((data)->features & FEAT_NEWER_AUTOPWM)
 #define has_old_autopwm(data)  ((data)->features & FEAT_OLD_AUTOPWM)
 #define has_temp_offset(data)  ((data)->features & FEAT_TEMP_OFFSET)
@@ -475,7 +489,14 @@ struct it87_data {
 
 static int adc_lsb(const struct it87_data *data, int nr)
 {
-       int lsb = has_12mv_adc(data) ? 12 : 16;
+       int lsb;
+
+       if (has_12mv_adc(data))
+               lsb = 120;
+       else if (has_10_9mv_adc(data))
+               lsb = 109;
+       else
+               lsb = 160;
        if (data->in_scaled & (1 << nr))
                lsb <<= 1;
        return lsb;
@@ -483,13 +504,13 @@ static int adc_lsb(const struct it87_data *data, int nr)
 
 static u8 in_to_reg(const struct it87_data *data, int nr, long val)
 {
-       val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
+       val = DIV_ROUND_CLOSEST(val * 10, adc_lsb(data, nr));
        return clamp_val(val, 0, 255);
 }
 
 static int in_from_reg(const struct it87_data *data, int nr, int val)
 {
-       return val * adc_lsb(data, nr);
+       return DIV_ROUND_CLOSEST(val * adc_lsb(data, nr), 10);
 }
 
 static inline u8 FAN_TO_REG(long rpm, int div)
@@ -1515,9 +1536,14 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
        };
        struct it87_data *data = dev_get_drvdata(dev);
        int nr = to_sensor_dev_attr(attr)->index;
+       const char *label;
 
-       return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
-                                                      : labels[nr]);
+       if (has_12mv_adc(data) || has_10_9mv_adc(data))
+               label = labels_it8721[nr];
+       else
+               label = labels[nr];
+
+       return sprintf(buf, "%s\n", label);
 }
 static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
 static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
@@ -1853,6 +1879,9 @@ static int __init it87_find(unsigned short *address,
        case IT8728F_DEVID:
                sio_data->type = it8728;
                break;
+       case IT8732F_DEVID:
+               sio_data->type = it8732;
+               break;
        case IT8771E_DEVID:
                sio_data->type = it8771;
                break;
index 97204dce162db6a5d3ff4ae703e58b6164683aff..9296e9daf774474654d3fa7037e579ef01be5566 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 
 #define DRVNAME                "lm70"
@@ -130,11 +131,41 @@ ATTRIBUTE_GROUPS(lm70);
 
 /*----------------------------------------------------------------------*/
 
+#ifdef CONFIG_OF
+static const struct of_device_id lm70_of_ids[] = {
+       {
+               .compatible = "ti,lm70",
+               .data = (void *) LM70_CHIP_LM70,
+       },
+       {
+               .compatible = "ti,tmp121",
+               .data = (void *) LM70_CHIP_TMP121,
+       },
+       {
+               .compatible = "ti,lm71",
+               .data = (void *) LM70_CHIP_LM71,
+       },
+       {
+               .compatible = "ti,lm74",
+               .data = (void *) LM70_CHIP_LM74,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, lm70_of_ids);
+#endif
+
 static int lm70_probe(struct spi_device *spi)
 {
-       int chip = spi_get_device_id(spi)->driver_data;
+       const struct of_device_id *match;
        struct device *hwmon_dev;
        struct lm70 *p_lm70;
+       int chip;
+
+       match = of_match_device(lm70_of_ids, &spi->dev);
+       if (match)
+               chip = (int)(uintptr_t)match->data;
+       else
+               chip = spi_get_device_id(spi)->driver_data;
 
        /* signaling is SPI_MODE_0 */
        if (spi->mode & (SPI_CPOL | SPI_CPHA))
@@ -169,6 +200,7 @@ static struct spi_driver lm70_driver = {
        .driver = {
                .name   = "lm70",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(lm70_of_ids),
        },
        .id_table = lm70_ids,
        .probe  = lm70_probe,
index fbfc02bb2cfa13c5bc22ece3a47a3cac1af07005..3ce33d244cc0f7a0a31f2f1af4b7cdf92f5341e2 100644 (file)
@@ -49,10 +49,13 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
 #define REG_VOLTAGE_LOW                0x0f
 #define REG_FANCOUNT_LOW       0x13
 #define REG_START              0x21
-#define REG_MODE               0x22
+#define REG_MODE               0x22 /* 7.2.32 Mode Selection Register */
 #define REG_PECI_ENABLE                0x23
 #define REG_FAN_ENABLE         0x24
 #define REG_VMON_ENABLE                0x25
+#define REG_PWM(x)             (0x60 + (x))
+#define REG_SMARTFAN_EN(x)      (0x64 + (x) / 2)
+#define SMARTFAN_EN_SHIFT(x)    ((x) % 2 * 4)
 #define REG_VENDOR_ID          0xfd
 #define REG_CHIP_ID            0xfe
 #define REG_VERSION_ID         0xff
@@ -66,6 +69,129 @@ struct nct7802_data {
        struct mutex access_lock; /* for multi-byte read and write operations */
 };
 
+static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
+                             char *buf)
+{
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       unsigned int mode;
+       int ret;
+
+       ret = regmap_read(data->regmap, REG_MODE, &mode);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", (mode >> (2 * sattr->index) & 3) + 2);
+}
+
+static ssize_t store_temp_type(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
+{
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       unsigned int type;
+       int err;
+
+       err = kstrtouint(buf, 0, &type);
+       if (err < 0)
+               return err;
+       if (sattr->index == 2 && type != 4) /* RD3 */
+               return -EINVAL;
+       if (type < 3 || type > 4)
+               return -EINVAL;
+       err = regmap_update_bits(data->regmap, REG_MODE,
+                       3 << 2 * sattr->index, (type - 2) << 2 * sattr->index);
+       return err ? : count;
+}
+
+static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned int regval;
+       int ret;
+
+       if (sattr->index > 1)
+               return sprintf(buf, "1\n");
+
+       ret = regmap_read(data->regmap, 0x5E, &regval);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", !(regval & (1 << sattr->index)));
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+                       char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned int val;
+       int ret;
+
+       if (!attr->index)
+               return sprintf(buf, "255\n");
+
+       ret = regmap_read(data->regmap, attr->index, &val);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
+                        const char *buf, size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int err;
+       u8 val;
+
+       err = kstrtou8(buf, 0, &val);
+       if (err < 0)
+               return err;
+
+       err = regmap_write(data->regmap, attr->index, val);
+       return err ? : count;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       unsigned int reg, enabled;
+       int ret;
+
+       ret = regmap_read(data->regmap, REG_SMARTFAN_EN(sattr->index), &reg);
+       if (ret < 0)
+               return ret;
+       enabled = reg >> SMARTFAN_EN_SHIFT(sattr->index) & 1;
+       return sprintf(buf, "%u\n", enabled + 1);
+}
+
+static ssize_t store_pwm_enable(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       u8 val;
+       int ret;
+
+       ret = kstrtou8(buf, 0, &val);
+       if (ret < 0)
+               return ret;
+       if (val < 1 || val > 2)
+               return -EINVAL;
+       ret = regmap_update_bits(data->regmap, REG_SMARTFAN_EN(sattr->index),
+                                1 << SMARTFAN_EN_SHIFT(sattr->index),
+                                (val - 1) << SMARTFAN_EN_SHIFT(sattr->index));
+       return ret ? : count;
+}
+
 static int nct7802_read_temp(struct nct7802_data *data,
                             u8 reg_temp, u8 reg_temp_low, int *temp)
 {
@@ -377,6 +503,8 @@ store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
        return err ? : count;
 }
 
+static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
+                         show_temp_type, store_temp_type, 0);
 static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0x01,
                            REG_TEMP_LSB);
 static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp,
@@ -386,6 +514,8 @@ static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp,
 static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp,
                            store_temp, 0x3a, 0);
 
+static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
+                         show_temp_type, store_temp_type, 1);
 static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0x02,
                            REG_TEMP_LSB);
 static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp,
@@ -395,6 +525,8 @@ static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp,
 static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp,
                            store_temp, 0x3b, 0);
 
+static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
+                         show_temp_type, store_temp_type, 2);
 static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0x03,
                            REG_TEMP_LSB);
 static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp,
@@ -475,6 +607,7 @@ static SENSOR_DEVICE_ATTR_2(temp6_beep, S_IRUGO | S_IWUSR, show_beep,
                            store_beep, 0x5c, 5);
 
 static struct attribute *nct7802_temp_attrs[] = {
+       &sensor_dev_attr_temp1_type.dev_attr.attr,
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_min.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -485,7 +618,8 @@ static struct attribute *nct7802_temp_attrs[] = {
        &sensor_dev_attr_temp1_fault.dev_attr.attr,
        &sensor_dev_attr_temp1_beep.dev_attr.attr,
 
-       &sensor_dev_attr_temp2_input.dev_attr.attr,             /* 9 */
+       &sensor_dev_attr_temp2_type.dev_attr.attr,              /* 10 */
+       &sensor_dev_attr_temp2_input.dev_attr.attr,
        &sensor_dev_attr_temp2_min.dev_attr.attr,
        &sensor_dev_attr_temp2_max.dev_attr.attr,
        &sensor_dev_attr_temp2_crit.dev_attr.attr,
@@ -495,7 +629,8 @@ static struct attribute *nct7802_temp_attrs[] = {
        &sensor_dev_attr_temp2_fault.dev_attr.attr,
        &sensor_dev_attr_temp2_beep.dev_attr.attr,
 
-       &sensor_dev_attr_temp3_input.dev_attr.attr,             /* 18 */
+       &sensor_dev_attr_temp3_type.dev_attr.attr,              /* 20 */
+       &sensor_dev_attr_temp3_input.dev_attr.attr,
        &sensor_dev_attr_temp3_min.dev_attr.attr,
        &sensor_dev_attr_temp3_max.dev_attr.attr,
        &sensor_dev_attr_temp3_crit.dev_attr.attr,
@@ -505,7 +640,7 @@ static struct attribute *nct7802_temp_attrs[] = {
        &sensor_dev_attr_temp3_fault.dev_attr.attr,
        &sensor_dev_attr_temp3_beep.dev_attr.attr,
 
-       &sensor_dev_attr_temp4_input.dev_attr.attr,             /* 27 */
+       &sensor_dev_attr_temp4_input.dev_attr.attr,             /* 30 */
        &sensor_dev_attr_temp4_min.dev_attr.attr,
        &sensor_dev_attr_temp4_max.dev_attr.attr,
        &sensor_dev_attr_temp4_crit.dev_attr.attr,
@@ -514,7 +649,7 @@ static struct attribute *nct7802_temp_attrs[] = {
        &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
        &sensor_dev_attr_temp4_beep.dev_attr.attr,
 
-       &sensor_dev_attr_temp5_input.dev_attr.attr,             /* 35 */
+       &sensor_dev_attr_temp5_input.dev_attr.attr,             /* 38 */
        &sensor_dev_attr_temp5_min.dev_attr.attr,
        &sensor_dev_attr_temp5_max.dev_attr.attr,
        &sensor_dev_attr_temp5_crit.dev_attr.attr,
@@ -523,7 +658,7 @@ static struct attribute *nct7802_temp_attrs[] = {
        &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
        &sensor_dev_attr_temp5_beep.dev_attr.attr,
 
-       &sensor_dev_attr_temp6_input.dev_attr.attr,             /* 43 */
+       &sensor_dev_attr_temp6_input.dev_attr.attr,             /* 46 */
        &sensor_dev_attr_temp6_beep.dev_attr.attr,
 
        NULL
@@ -541,25 +676,27 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj,
        if (err < 0)
                return 0;
 
-       if (index < 9 &&
+       if (index < 10 &&
            (reg & 03) != 0x01 && (reg & 0x03) != 0x02)         /* RD1 */
                return 0;
-       if (index >= 9 && index < 18 &&
+
+       if (index >= 10 && index < 20 &&
            (reg & 0x0c) != 0x04 && (reg & 0x0c) != 0x08)       /* RD2 */
                return 0;
-       if (index >= 18 && index < 27 && (reg & 0x30) != 0x20)  /* RD3 */
+       if (index >= 20 && index < 30 && (reg & 0x30) != 0x20)  /* RD3 */
                return 0;
-       if (index >= 27 && index < 35)                          /* local */
+
+       if (index >= 30 && index < 38)                          /* local */
                return attr->mode;
 
        err = regmap_read(data->regmap, REG_PECI_ENABLE, &reg);
        if (err < 0)
                return 0;
 
-       if (index >= 35 && index < 43 && !(reg & 0x01))         /* PECI 0 */
+       if (index >= 38 && index < 46 && !(reg & 0x01))         /* PECI 0 */
                return 0;
 
-       if (index >= 0x43 && (!(reg & 0x02)))                   /* PECI 1 */
+       if (index >= 0x46 && (!(reg & 0x02)))                   /* PECI 1 */
                return 0;
 
        return attr->mode;
@@ -687,6 +824,27 @@ static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 2);
 static SENSOR_DEVICE_ATTR_2(fan3_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
                            0x5b, 2);
 
+/* 7.2.89 Fan Control Output Type */
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
+
+/* 7.2.91... Fan Control Output Value */
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm,
+                         REG_PWM(0));
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm,
+                         REG_PWM(1));
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm,
+                         REG_PWM(2));
+
+/* 7.2.95... Temperature to Fan mapping Relationships Register */
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
+                         store_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
+                         store_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
+                         store_pwm_enable, 2);
+
 static struct attribute *nct7802_fan_attrs[] = {
        &sensor_dev_attr_fan1_input.dev_attr.attr,
        &sensor_dev_attr_fan1_min.dev_attr.attr,
@@ -725,10 +883,142 @@ static struct attribute_group nct7802_fan_group = {
        .is_visible = nct7802_fan_is_visible,
 };
 
+static struct attribute *nct7802_pwm_attrs[] = {
+       &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+       &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+       &sensor_dev_attr_pwm2.dev_attr.attr,
+       &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm3_mode.dev_attr.attr,
+       &sensor_dev_attr_pwm3.dev_attr.attr,
+       NULL
+};
+
+static struct attribute_group nct7802_pwm_group = {
+       .attrs = nct7802_pwm_attrs,
+};
+
+/* 7.2.115... 0x80-0x83, 0x84 Temperature (X-axis) transition */
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x80, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x81, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x82, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x83, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point5_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x84, 0);
+
+/* 7.2.120... 0x85-0x88 PWM (Y-axis) transition */
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x85);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x86);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x87);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x88);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0);
+
+/* 7.2.124 Table 2 X-axis Transition Point 1 Register */
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x90, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x91, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x92, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x93, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point5_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0x94, 0);
+
+/* 7.2.129 Table 2 Y-axis Transition Point 1 Register */
+static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x95);
+static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x96);
+static SENSOR_DEVICE_ATTR(pwm2_auto_point3_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x97);
+static SENSOR_DEVICE_ATTR(pwm2_auto_point4_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0x98);
+static SENSOR_DEVICE_ATTR(pwm2_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0);
+
+/* 7.2.133 Table 3 X-axis Transition Point 1 Register */
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0xA0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0xA1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0xA2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0xA3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point5_temp, S_IRUGO | S_IWUSR,
+                           show_temp, store_temp, 0xA4, 0);
+
+/* 7.2.138 Table 3 Y-axis Transition Point 1 Register */
+static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0xA5);
+static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0xA6);
+static SENSOR_DEVICE_ATTR(pwm3_auto_point3_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0xA7);
+static SENSOR_DEVICE_ATTR(pwm3_auto_point4_pwm, S_IRUGO | S_IWUSR,
+                         show_pwm, store_pwm, 0xA8);
+static SENSOR_DEVICE_ATTR(pwm3_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0);
+
+static struct attribute *nct7802_auto_point_attrs[] = {
+       &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
+
+       &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
+
+       &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point5_temp.dev_attr.attr,
+
+       &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point5_pwm.dev_attr.attr,
+
+       &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point5_temp.dev_attr.attr,
+
+       &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm3_auto_point5_pwm.dev_attr.attr,
+
+       NULL
+};
+
+static struct attribute_group nct7802_auto_point_group = {
+       .attrs = nct7802_auto_point_attrs,
+};
+
 static const struct attribute_group *nct7802_groups[] = {
        &nct7802_temp_group,
        &nct7802_in_group,
        &nct7802_fan_group,
+       &nct7802_pwm_group,
+       &nct7802_auto_point_group,
        NULL
 };
 
@@ -776,7 +1066,8 @@ static int nct7802_detect(struct i2c_client *client,
 
 static bool nct7802_regmap_is_volatile(struct device *dev, unsigned int reg)
 {
-       return reg != REG_BANK && reg <= 0x20;
+       return (reg != REG_BANK && reg <= 0x20) ||
+               (reg >= REG_PWM(0) && reg <= REG_PWM(2));
 }
 
 static const struct regmap_config nct7802_regmap_config = {
index 9f7dbd189c97420acfcbdef68e79137bb6b32015..df6ebb2b8f0f94e3eb82ccdb6b380674f50d3b20 100644 (file)
@@ -20,7 +20,8 @@ config SENSORS_PMBUS
        help
          If you say yes here you get hardware monitoring support for generic
          PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
-         MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, and TPS40400.
+         MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, TPS40400, TPS544B20,
+         TPS544B25, TPS544C20, TPS544C25, and UDT020.
 
          This driver can also be built as a module. If so, the module will
          be called pmbus.
@@ -30,8 +31,8 @@ config SENSORS_ADM1275
        default n
        help
          If you say yes here you get hardware monitoring support for Analog
-         Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital
-         Power Monitors.
+         Devices ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 Hot-Swap
+         Controller and Digital Power Monitors.
 
          This driver can also be built as a module. If so, the module will
          be called adm1275.
@@ -51,7 +52,8 @@ config SENSORS_LTC2978
        default n
        help
          If you say yes here you get hardware monitoring support for Linear
-         Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
+         Technology LTC2974, LTC2975, LTC2977, LTC2978, LTC2980, LTC3880,
+         LTC3883, LTC3886, LTC3887, LTCM2987, LTM4675, and LTM4676.
 
          This driver can also be built as a module. If so, the module will
          be called ltc2978.
@@ -73,6 +75,16 @@ config SENSORS_MAX16064
          This driver can also be built as a module. If so, the module will
          be called max16064.
 
+config SENSORS_MAX20751
+       tristate "Maxim MAX20751"
+       default n
+       help
+         If you say yes here you get hardware monitoring support for Maxim
+         MAX20751.
+
+         This driver can also be built as a module. If so, the module will
+         be called max20751.
+
 config SENSORS_MAX34440
        tristate "Maxim MAX34440 and compatibles"
        default n
index 1454293e985c024cc0cba0b0051c6c1ca2da1a6c..bce046d37f0264eff48a44010ceb1cd8994f65d1 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_SENSORS_ADM1275)   += adm1275.o
 obj-$(CONFIG_SENSORS_LM25066)  += lm25066.o
 obj-$(CONFIG_SENSORS_LTC2978)  += ltc2978.o
 obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
+obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
 obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
 obj-$(CONFIG_SENSORS_MAX8688)  += max8688.o
 obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
index 60aad9570f016987d82acd6d7f6104e94de3c12c..188af4c89f40fe1d2dee176e024d73cae0d1d46c 100644 (file)
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/bitops.h>
 #include "pmbus.h"
 
-enum chips { adm1075, adm1275, adm1276 };
+enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
+
+#define ADM1275_MFR_STATUS_IOUT_WARN2  BIT(0)
+#define ADM1293_MFR_STATUS_VAUX_UV_WARN        BIT(5)
+#define ADM1293_MFR_STATUS_VAUX_OV_WARN        BIT(6)
 
 #define ADM1275_PEAK_IOUT              0xd0
 #define ADM1275_PEAK_VIN               0xd1
 #define ADM1275_PEAK_VOUT              0xd2
 #define ADM1275_PMON_CONFIG            0xd4
 
-#define ADM1275_VIN_VOUT_SELECT                (1 << 6)
-#define ADM1275_VRANGE                 (1 << 5)
-#define ADM1075_IRANGE_50              (1 << 4)
-#define ADM1075_IRANGE_25              (1 << 3)
-#define ADM1075_IRANGE_MASK            ((1 << 3) | (1 << 4))
+#define ADM1275_VIN_VOUT_SELECT                BIT(6)
+#define ADM1275_VRANGE                 BIT(5)
+#define ADM1075_IRANGE_50              BIT(4)
+#define ADM1075_IRANGE_25              BIT(3)
+#define ADM1075_IRANGE_MASK            (BIT(3) | BIT(4))
+
+#define ADM1293_IRANGE_25              0
+#define ADM1293_IRANGE_50              BIT(6)
+#define ADM1293_IRANGE_100             BIT(7)
+#define ADM1293_IRANGE_200             (BIT(6) | BIT(7))
+#define ADM1293_IRANGE_MASK            (BIT(6) | BIT(7))
+
+#define ADM1293_VIN_SEL_012            BIT(2)
+#define ADM1293_VIN_SEL_074            BIT(3)
+#define ADM1293_VIN_SEL_210            (BIT(2) | BIT(3))
+#define ADM1293_VIN_SEL_MASK           (BIT(2) | BIT(3))
+
+#define ADM1293_VAUX_EN                        BIT(1)
 
 #define ADM1275_IOUT_WARN2_LIMIT       0xd7
 #define ADM1275_DEVICE_CONFIG          0xd8
 
-#define ADM1275_IOUT_WARN2_SELECT      (1 << 4)
+#define ADM1275_IOUT_WARN2_SELECT      BIT(4)
 
 #define ADM1276_PEAK_PIN               0xda
-
-#define ADM1275_MFR_STATUS_IOUT_WARN2  (1 << 0)
-
 #define ADM1075_READ_VAUX              0xdd
 #define ADM1075_VAUX_OV_WARN_LIMIT     0xde
 #define ADM1075_VAUX_UV_WARN_LIMIT     0xdf
+#define ADM1293_IOUT_MIN               0xe3
+#define ADM1293_PIN_MIN                        0xe4
 #define ADM1075_VAUX_STATUS            0xf6
 
-#define ADM1075_VAUX_OV_WARN           (1<<7)
-#define ADM1075_VAUX_UV_WARN           (1<<6)
+#define ADM1075_VAUX_OV_WARN           BIT(7)
+#define ADM1075_VAUX_UV_WARN           BIT(6)
 
 struct adm1275_data {
        int id;
        bool have_oc_fault;
+       bool have_uc_fault;
+       bool have_vout;
+       bool have_vaux_status;
+       bool have_mfr_vaux_status;
+       bool have_iout_min;
+       bool have_pin_min;
+       bool have_pin_max;
        struct pmbus_driver_info info;
 };
 
 #define to_adm1275_data(x)  container_of(x, struct adm1275_data, info)
 
+struct coefficients {
+       s16 m;
+       s16 b;
+       s16 R;
+};
+
+static const struct coefficients adm1075_coefficients[] = {
+       [0] = { 27169, 0, -1 },         /* voltage */
+       [1] = { 806, 20475, -1 },       /* current, irange25 */
+       [2] = { 404, 20475, -1 },       /* current, irange50 */
+       [3] = { 0, -1, 8549 },          /* power, irange25 */
+       [4] = { 0, -1, 4279 },          /* power, irange50 */
+};
+
+static const struct coefficients adm1275_coefficients[] = {
+       [0] = { 19199, 0, -2 },         /* voltage, vrange set */
+       [1] = { 6720, 0, -1 },          /* voltage, vrange not set */
+       [2] = { 807, 20475, -1 },       /* current */
+};
+
+static const struct coefficients adm1276_coefficients[] = {
+       [0] = { 19199, 0, -2 },         /* voltage, vrange set */
+       [1] = { 6720, 0, -1 },          /* voltage, vrange not set */
+       [2] = { 807, 20475, -1 },       /* current */
+       [3] = { 6043, 0, -2 },          /* power, vrange set */
+       [4] = { 2115, 0, -1 },          /* power, vrange not set */
+};
+
+static const struct coefficients adm1293_coefficients[] = {
+       [0] = { 3333, -1, 0 },          /* voltage, vrange 1.2V */
+       [1] = { 5552, -5, -1 },         /* voltage, vrange 7.4V */
+       [2] = { 19604, -50, -2 },       /* voltage, vrange 21V */
+       [3] = { 8000, -100, -2 },       /* current, irange25 */
+       [4] = { 4000, -100, -2 },       /* current, irange50 */
+       [5] = { 20000, -1000, -3 },     /* current, irange100 */
+       [6] = { 10000, -1000, -3 },     /* current, irange200 */
+       [7] = { 10417, 0, -1 },         /* power, 1.2V, irange25 */
+       [8] = { 5208, 0, -1 },          /* power, 1.2V, irange50 */
+       [9] = { 26042, 0, -2 },         /* power, 1.2V, irange100 */
+       [10] = { 13021, 0, -2 },        /* power, 1.2V, irange200 */
+       [11] = { 17351, 0, -2 },        /* power, 7.4V, irange25 */
+       [12] = { 8676, 0, -2 },         /* power, 7.4V, irange50 */
+       [13] = { 4338, 0, -2 },         /* power, 7.4V, irange100 */
+       [14] = { 21689, 0, -3 },        /* power, 7.4V, irange200 */
+       [15] = { 6126, 0, -2 },         /* power, 21V, irange25 */
+       [16] = { 30631, 0, -3 },        /* power, 21V, irange50 */
+       [17] = { 15316, 0, -3 },        /* power, 21V, irange100 */
+       [18] = { 7658, 0, -3 },         /* power, 21V, irange200 */
+};
+
 static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
 {
        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -72,42 +146,37 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
 
        switch (reg) {
        case PMBUS_IOUT_UC_FAULT_LIMIT:
-               if (data->have_oc_fault) {
-                       ret = -ENXIO;
-                       break;
-               }
+               if (!data->have_uc_fault)
+                       return -ENXIO;
                ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
                break;
        case PMBUS_IOUT_OC_FAULT_LIMIT:
-               if (!data->have_oc_fault) {
-                       ret = -ENXIO;
-                       break;
-               }
+               if (!data->have_oc_fault)
+                       return -ENXIO;
                ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
                break;
        case PMBUS_VOUT_OV_WARN_LIMIT:
-               if (data->id != adm1075) {
-                       ret = -ENODATA;
-                       break;
-               }
+               if (data->have_vout)
+                       return -ENODATA;
                ret = pmbus_read_word_data(client, 0,
                                           ADM1075_VAUX_OV_WARN_LIMIT);
                break;
        case PMBUS_VOUT_UV_WARN_LIMIT:
-               if (data->id != adm1075) {
-                       ret = -ENODATA;
-                       break;
-               }
+               if (data->have_vout)
+                       return -ENODATA;
                ret = pmbus_read_word_data(client, 0,
                                           ADM1075_VAUX_UV_WARN_LIMIT);
                break;
        case PMBUS_READ_VOUT:
-               if (data->id != adm1075) {
-                       ret = -ENODATA;
-                       break;
-               }
+               if (data->have_vout)
+                       return -ENODATA;
                ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
                break;
+       case PMBUS_VIRT_READ_IOUT_MIN:
+               if (!data->have_iout_min)
+                       return -ENXIO;
+               ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN);
+               break;
        case PMBUS_VIRT_READ_IOUT_MAX:
                ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
                break;
@@ -117,11 +186,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
        case PMBUS_VIRT_READ_VIN_MAX:
                ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
                break;
+       case PMBUS_VIRT_READ_PIN_MIN:
+               if (!data->have_pin_min)
+                       return -ENXIO;
+               ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN);
+               break;
        case PMBUS_VIRT_READ_PIN_MAX:
-               if (data->id == adm1275) {
-                       ret = -ENXIO;
-                       break;
-               }
+               if (!data->have_pin_max)
+                       return -ENXIO;
                ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
                break;
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
@@ -129,8 +201,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
        case PMBUS_VIRT_RESET_VIN_HISTORY:
                break;
        case PMBUS_VIRT_RESET_PIN_HISTORY:
-               if (data->id == adm1275)
-                       ret = -ENXIO;
+               if (!data->have_pin_max)
+                       return -ENXIO;
                break;
        default:
                ret = -ENODATA;
@@ -142,6 +214,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
 static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
                                   u16 word)
 {
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       const struct adm1275_data *data = to_adm1275_data(info);
        int ret;
 
        if (page)
@@ -155,6 +229,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
                break;
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
                ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
+               if (!ret && data->have_iout_min)
+                       ret = pmbus_write_word_data(client, 0,
+                                                   ADM1293_IOUT_MIN, 0);
                break;
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
                ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0);
@@ -164,6 +241,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
                break;
        case PMBUS_VIRT_RESET_PIN_HISTORY:
                ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
+               if (!ret && data->have_pin_min)
+                       ret = pmbus_write_word_data(client, 0,
+                                                   ADM1293_PIN_MIN, 0);
                break;
        default:
                ret = -ENODATA;
@@ -186,29 +266,40 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
                ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
                if (ret < 0)
                        break;
+               if (!data->have_oc_fault && !data->have_uc_fault)
+                       break;
                mfr_status = pmbus_read_byte_data(client, page,
                                                  PMBUS_STATUS_MFR_SPECIFIC);
-               if (mfr_status < 0) {
-                       ret = mfr_status;
-                       break;
-               }
+               if (mfr_status < 0)
+                       return mfr_status;
                if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
                        ret |= data->have_oc_fault ?
                          PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
                }
                break;
        case PMBUS_STATUS_VOUT:
-               if (data->id != adm1075) {
-                       ret = -ENODATA;
-                       break;
-               }
+               if (data->have_vout)
+                       return -ENODATA;
                ret = 0;
-               mfr_status = pmbus_read_byte_data(client, 0,
-                                                 ADM1075_VAUX_STATUS);
-               if (mfr_status & ADM1075_VAUX_OV_WARN)
-                       ret |= PB_VOLTAGE_OV_WARNING;
-               if (mfr_status & ADM1075_VAUX_UV_WARN)
-                       ret |= PB_VOLTAGE_UV_WARNING;
+               if (data->have_vaux_status) {
+                       mfr_status = pmbus_read_byte_data(client, 0,
+                                                         ADM1075_VAUX_STATUS);
+                       if (mfr_status < 0)
+                               return mfr_status;
+                       if (mfr_status & ADM1075_VAUX_OV_WARN)
+                               ret |= PB_VOLTAGE_OV_WARNING;
+                       if (mfr_status & ADM1075_VAUX_UV_WARN)
+                               ret |= PB_VOLTAGE_UV_WARNING;
+               } else if (data->have_mfr_vaux_status) {
+                       mfr_status = pmbus_read_byte_data(client, page,
+                                               PMBUS_STATUS_MFR_SPECIFIC);
+                       if (mfr_status < 0)
+                               return mfr_status;
+                       if (mfr_status & ADM1293_MFR_STATUS_VAUX_OV_WARN)
+                               ret |= PB_VOLTAGE_OV_WARNING;
+                       if (mfr_status & ADM1293_MFR_STATUS_VAUX_UV_WARN)
+                               ret |= PB_VOLTAGE_UV_WARNING;
+               }
                break;
        default:
                ret = -ENODATA;
@@ -221,6 +312,8 @@ static const struct i2c_device_id adm1275_id[] = {
        { "adm1075", adm1075 },
        { "adm1275", adm1275 },
        { "adm1276", adm1276 },
+       { "adm1293", adm1293 },
+       { "adm1294", adm1294 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, adm1275_id);
@@ -234,6 +327,8 @@ static int adm1275_probe(struct i2c_client *client,
        struct pmbus_driver_info *info;
        struct adm1275_data *data;
        const struct i2c_device_id *mid;
+       const struct coefficients *coefficients;
+       int vindex = -1, voindex = -1, cindex = -1, pindex = -1;
 
        if (!i2c_check_functionality(client->adapter,
                                     I2C_FUNC_SMBUS_READ_BYTE_DATA
@@ -290,61 +385,38 @@ static int adm1275_probe(struct i2c_client *client,
        info->format[PSC_VOLTAGE_IN] = direct;
        info->format[PSC_VOLTAGE_OUT] = direct;
        info->format[PSC_CURRENT_OUT] = direct;
-       info->m[PSC_CURRENT_OUT] = 807;
-       info->b[PSC_CURRENT_OUT] = 20475;
-       info->R[PSC_CURRENT_OUT] = -1;
+       info->format[PSC_POWER] = direct;
        info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
 
        info->read_word_data = adm1275_read_word_data;
        info->read_byte_data = adm1275_read_byte_data;
        info->write_word_data = adm1275_write_word_data;
 
-       if (data->id == adm1075) {
-               info->m[PSC_VOLTAGE_IN] = 27169;
-               info->b[PSC_VOLTAGE_IN] = 0;
-               info->R[PSC_VOLTAGE_IN] = -1;
-               info->m[PSC_VOLTAGE_OUT] = 27169;
-               info->b[PSC_VOLTAGE_OUT] = 0;
-               info->R[PSC_VOLTAGE_OUT] = -1;
-       } else if (config & ADM1275_VRANGE) {
-               info->m[PSC_VOLTAGE_IN] = 19199;
-               info->b[PSC_VOLTAGE_IN] = 0;
-               info->R[PSC_VOLTAGE_IN] = -2;
-               info->m[PSC_VOLTAGE_OUT] = 19199;
-               info->b[PSC_VOLTAGE_OUT] = 0;
-               info->R[PSC_VOLTAGE_OUT] = -2;
-       } else {
-               info->m[PSC_VOLTAGE_IN] = 6720;
-               info->b[PSC_VOLTAGE_IN] = 0;
-               info->R[PSC_VOLTAGE_IN] = -1;
-               info->m[PSC_VOLTAGE_OUT] = 6720;
-               info->b[PSC_VOLTAGE_OUT] = 0;
-               info->R[PSC_VOLTAGE_OUT] = -1;
-       }
-
-       if (device_config & ADM1275_IOUT_WARN2_SELECT)
-               data->have_oc_fault = true;
-
        switch (data->id) {
        case adm1075:
-               info->format[PSC_POWER] = direct;
-               info->b[PSC_POWER] = 0;
-               info->R[PSC_POWER] = -1;
+               if (device_config & ADM1275_IOUT_WARN2_SELECT)
+                       data->have_oc_fault = true;
+               else
+                       data->have_uc_fault = true;
+               data->have_pin_max = true;
+               data->have_vaux_status = true;
+
+               coefficients = adm1075_coefficients;
+               vindex = 0;
                switch (config & ADM1075_IRANGE_MASK) {
                case ADM1075_IRANGE_25:
-                       info->m[PSC_POWER] = 8549;
-                       info->m[PSC_CURRENT_OUT] = 806;
+                       cindex = 1;
+                       pindex = 3;
                        break;
                case ADM1075_IRANGE_50:
-                       info->m[PSC_POWER] = 4279;
-                       info->m[PSC_CURRENT_OUT] = 404;
+                       cindex = 2;
+                       pindex = 4;
                        break;
                default:
                        dev_err(&client->dev, "Invalid input current range");
-                       info->m[PSC_POWER] = 0;
-                       info->m[PSC_CURRENT_OUT] = 0;
                        break;
                }
+
                info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
                  | PMBUS_HAVE_STATUS_INPUT;
                if (config & ADM1275_VIN_VOUT_SELECT)
@@ -352,6 +424,16 @@ static int adm1275_probe(struct i2c_client *client,
                          PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
                break;
        case adm1275:
+               if (device_config & ADM1275_IOUT_WARN2_SELECT)
+                       data->have_oc_fault = true;
+               else
+                       data->have_uc_fault = true;
+               data->have_vout = true;
+
+               coefficients = adm1275_coefficients;
+               vindex = (config & ADM1275_VRANGE) ? 0 : 1;
+               cindex = 2;
+
                if (config & ADM1275_VIN_VOUT_SELECT)
                        info->func[0] |=
                          PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
@@ -360,22 +442,100 @@ static int adm1275_probe(struct i2c_client *client,
                          PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
                break;
        case adm1276:
-               info->format[PSC_POWER] = direct;
+               if (device_config & ADM1275_IOUT_WARN2_SELECT)
+                       data->have_oc_fault = true;
+               else
+                       data->have_uc_fault = true;
+               data->have_vout = true;
+               data->have_pin_max = true;
+
+               coefficients = adm1276_coefficients;
+               vindex = (config & ADM1275_VRANGE) ? 0 : 1;
+               cindex = 2;
+               pindex = (config & ADM1275_VRANGE) ? 3 : 4;
+
                info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
                  | PMBUS_HAVE_STATUS_INPUT;
                if (config & ADM1275_VIN_VOUT_SELECT)
                        info->func[0] |=
                          PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
-               if (config & ADM1275_VRANGE) {
-                       info->m[PSC_POWER] = 6043;
-                       info->b[PSC_POWER] = 0;
-                       info->R[PSC_POWER] = -2;
-               } else {
-                       info->m[PSC_POWER] = 2115;
-                       info->b[PSC_POWER] = 0;
-                       info->R[PSC_POWER] = -1;
+               break;
+       case adm1293:
+       case adm1294:
+               data->have_iout_min = true;
+               data->have_pin_min = true;
+               data->have_pin_max = true;
+               data->have_mfr_vaux_status = true;
+
+               coefficients = adm1293_coefficients;
+
+               voindex = 0;
+               switch (config & ADM1293_VIN_SEL_MASK) {
+               case ADM1293_VIN_SEL_012:       /* 1.2V */
+                       vindex = 0;
+                       break;
+               case ADM1293_VIN_SEL_074:       /* 7.4V */
+                       vindex = 1;
+                       break;
+               case ADM1293_VIN_SEL_210:       /* 21V */
+                       vindex = 2;
+                       break;
+               default:                        /* disabled */
+                       break;
                }
+
+               switch (config & ADM1293_IRANGE_MASK) {
+               case ADM1293_IRANGE_25:
+                       cindex = 3;
+                       break;
+               case ADM1293_IRANGE_50:
+                       cindex = 4;
+                       break;
+               case ADM1293_IRANGE_100:
+                       cindex = 5;
+                       break;
+               case ADM1293_IRANGE_200:
+                       cindex = 6;
+                       break;
+               }
+
+               if (vindex >= 0)
+                       pindex = 7 + vindex * 4 + (cindex - 3);
+
+               if (config & ADM1293_VAUX_EN)
+                       info->func[0] |=
+                               PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+
+               info->func[0] |= PMBUS_HAVE_PIN |
+                       PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+
                break;
+       default:
+               dev_err(&client->dev, "Unsupported device\n");
+               return -ENODEV;
+       }
+
+       if (voindex < 0)
+               voindex = vindex;
+       if (vindex >= 0) {
+               info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m;
+               info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b;
+               info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R;
+       }
+       if (voindex >= 0) {
+               info->m[PSC_VOLTAGE_OUT] = coefficients[voindex].m;
+               info->b[PSC_VOLTAGE_OUT] = coefficients[voindex].b;
+               info->R[PSC_VOLTAGE_OUT] = coefficients[voindex].R;
+       }
+       if (cindex >= 0) {
+               info->m[PSC_CURRENT_OUT] = coefficients[cindex].m;
+               info->b[PSC_CURRENT_OUT] = coefficients[cindex].b;
+               info->R[PSC_CURRENT_OUT] = coefficients[cindex].R;
+       }
+       if (pindex >= 0) {
+               info->m[PSC_POWER] = coefficients[pindex].m;
+               info->b[PSC_POWER] = coefficients[pindex].b;
+               info->R[PSC_POWER] = coefficients[pindex].R;
        }
 
        return pmbus_do_probe(client, id, info);
index a26b1d1d95146b5fd82a39b5b0ffe6f40910f4af..a3d912cd3b8d7605692ce00618776516e41b01ff 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -42,15 +43,15 @@ enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 };
 #define LM25066_READ_AVG_IIN           0xde
 #define LM25066_READ_AVG_PIN           0xdf
 
-#define LM25066_DEV_SETUP_CL           (1 << 4)        /* Current limit */
+#define LM25066_DEV_SETUP_CL           BIT(4)  /* Current limit */
 
 /* LM25056 only */
 
 #define LM25056_VAUX_OV_WARN_LIMIT     0xe3
 #define LM25056_VAUX_UV_WARN_LIMIT     0xe4
 
-#define LM25056_MFR_STS_VAUX_OV_WARN   (1 << 1)
-#define LM25056_MFR_STS_VAUX_UV_WARN   (1 << 0)
+#define LM25056_MFR_STS_VAUX_OV_WARN   BIT(1)
+#define LM25056_MFR_STS_VAUX_UV_WARN   BIT(0)
 
 /* LM25063 only */
 
index 0835050ec245ba67c65bd59f341b0f7eef2c3032..58b789c28b483f062b17822a32487be6bdba14ee 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880,
- * LTC3883, and LTM4676
+ * Hardware monitoring driver for LTC2978 and compatible chips.
  *
  * Copyright (c) 2011 Ericsson AB.
- * Copyright (c) 2013, 2014 Guenter Roeck
+ * Copyright (c) 2013, 2014, 2015 Guenter Roeck
+ * Copyright (c) 2015 Linear Technology
  *
  * 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
@@ -16,6 +16,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/regulator/driver.h>
 #include "pmbus.h"
 
-enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
+enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
+       ltc3883, ltc3886, ltc3887, ltm2987, ltm4675, ltm4676 };
 
 /* Common for all chips */
 #define LTC2978_MFR_VOUT_PEAK          0xdd
 #define LTC2978_MFR_VIN_PEAK           0xde
 #define LTC2978_MFR_TEMPERATURE_PEAK   0xdf
-#define LTC2978_MFR_SPECIAL_ID         0xe7
+#define LTC2978_MFR_SPECIAL_ID         0xe7    /* Undocumented on LTC3882 */
+#define LTC2978_MFR_COMMON             0xef
 
-/* LTC2974, LCT2977, and LTC2978 */
+/* LTC2974, LTC2975, LCT2977, LTC2980, LTC2978, and LTM2987 */
 #define LTC2978_MFR_VOUT_MIN           0xfb
 #define LTC2978_MFR_VIN_MIN            0xfc
 #define LTC2978_MFR_TEMPERATURE_MIN    0xfd
 
-/* LTC2974 only */
+/* LTC2974, LTC2975 */
 #define LTC2974_MFR_IOUT_PEAK          0xd7
 #define LTC2974_MFR_IOUT_MIN           0xd8
 
-/* LTC3880, LTC3883, and LTM4676 */
+/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, and LTM4676 */
 #define LTC3880_MFR_IOUT_PEAK          0xd7
 #define LTC3880_MFR_CLEAR_PEAKS                0xe3
 #define LTC3880_MFR_TEMPERATURE2_PEAK  0xf4
 
-/* LTC3883 only */
+/* LTC3883 and LTC3886 only */
 #define LTC3883_MFR_IIN_PEAK           0xe1
 
-#define LTC2974_ID_REV1                        0x0212
-#define LTC2974_ID_REV2                        0x0213
+/* LTC2975 only */
+#define LTC2975_MFR_IIN_PEAK           0xc4
+#define LTC2975_MFR_IIN_MIN            0xc5
+#define LTC2975_MFR_PIN_PEAK           0xc6
+#define LTC2975_MFR_PIN_MIN            0xc7
+
+#define LTC2978_ID_MASK                        0xfff0
+
+#define LTC2974_ID                     0x0210
+#define LTC2975_ID                     0x0220
 #define LTC2977_ID                     0x0130
-#define LTC2978_ID_REV1                        0x0121
-#define LTC2978_ID_REV2                        0x0122
-#define LTC2978A_ID                    0x0124
-#define LTC3880_ID                     0x4000
-#define LTC3880_ID_MASK                        0xff00
+#define LTC2978_ID_REV1                        0x0110  /* Early revision */
+#define LTC2978_ID_REV2                        0x0120
+#define LTC2980_ID_A                   0x8030  /* A/B for two die IDs */
+#define LTC2980_ID_B                   0x8040
+#define LTC3880_ID                     0x4020
+#define LTC3882_ID                     0x4200
+#define LTC3882_ID_D1                  0x4240  /* Dash 1 */
 #define LTC3883_ID                     0x4300
-#define LTC3883_ID_MASK                        0xff00
-#define LTM4676_ID                     0x4480  /* datasheet claims 0x440X */
-#define LTM4676_ID_MASK                        0xfff0
+#define LTC3886_ID                     0x4600
+#define LTC3887_ID                     0x4700
+#define LTM2987_ID_A                   0x8010  /* A/B for two die IDs */
+#define LTM2987_ID_B                   0x8020
+#define LTM4675_ID                     0x47a0
+#define LTM4676_ID_REV1                        0x4400
+#define LTM4676_ID_REV2                        0x4480
+#define LTM4676A_ID                    0x47e0
 
 #define LTC2974_NUM_PAGES              4
 #define LTC2978_NUM_PAGES              8
 #define LTC3880_NUM_PAGES              2
 #define LTC3883_NUM_PAGES              1
 
+#define LTC_POLL_TIMEOUT               100     /* in milli-seconds */
+
+#define LTC_NOT_BUSY                   BIT(5)
+#define LTC_NOT_PENDING                        BIT(4)
+
 /*
  * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
  * happens pretty much each time chip data is updated. Raw peak data therefore
@@ -82,13 +106,91 @@ struct ltc2978_data {
        u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
        u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
        u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES];
-       u16 iin_max;
+       u16 iin_min, iin_max;
+       u16 pin_min, pin_max;
        u16 temp2_max;
        struct pmbus_driver_info info;
+       u32 features;
 };
-
 #define to_ltc2978_data(x)  container_of(x, struct ltc2978_data, info)
 
+#define FEAT_CLEAR_PEAKS       BIT(0)
+#define FEAT_NEEDS_POLLING     BIT(1)
+
+#define has_clear_peaks(d)     ((d)->features & FEAT_CLEAR_PEAKS)
+#define needs_polling(d)       ((d)->features & FEAT_NEEDS_POLLING)
+
+static int ltc_wait_ready(struct i2c_client *client)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(LTC_POLL_TIMEOUT);
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct ltc2978_data *data = to_ltc2978_data(info);
+       int status;
+       u8 mask;
+
+       if (!needs_polling(data))
+               return 0;
+
+       /*
+        * LTC3883 does not support LTC_NOT_PENDING, even though
+        * the datasheet claims that it does.
+        */
+       mask = LTC_NOT_BUSY;
+       if (data->id != ltc3883)
+               mask |= LTC_NOT_PENDING;
+
+       do {
+               status = pmbus_read_byte_data(client, 0, LTC2978_MFR_COMMON);
+               if (status == -EBADMSG || status == -ENXIO) {
+                       /* PEC error or NACK: chip may be busy, try again */
+                       usleep_range(50, 100);
+                       continue;
+               }
+               if (status < 0)
+                       return status;
+
+               if ((status & mask) == mask)
+                       return 0;
+
+               usleep_range(50, 100);
+       } while (time_before(jiffies, timeout));
+
+       return -ETIMEDOUT;
+}
+
+static int ltc_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       int ret;
+
+       ret = ltc_wait_ready(client);
+       if (ret < 0)
+               return ret;
+
+       return pmbus_read_word_data(client, page, reg);
+}
+
+static int ltc_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+       int ret;
+
+       ret = ltc_wait_ready(client);
+       if (ret < 0)
+               return ret;
+
+       return pmbus_read_byte_data(client, page, reg);
+}
+
+static int ltc_write_byte(struct i2c_client *client, int page, u8 byte)
+{
+       int ret;
+
+       ret = ltc_wait_ready(client);
+       if (ret < 0)
+               return ret;
+
+       return pmbus_write_byte(client, page, byte);
+}
+
 static inline int lin11_to_val(int data)
 {
        s16 e = ((s16)data) >> 11;
@@ -102,6 +204,34 @@ static inline int lin11_to_val(int data)
        return (e < 0 ? m >> -e : m << e);
 }
 
+static int ltc_get_max(struct ltc2978_data *data, struct i2c_client *client,
+                      int page, int reg, u16 *pmax)
+{
+       int ret;
+
+       ret = ltc_read_word_data(client, page, reg);
+       if (ret >= 0) {
+               if (lin11_to_val(ret) > lin11_to_val(*pmax))
+                       *pmax = ret;
+               ret = *pmax;
+       }
+       return ret;
+}
+
+static int ltc_get_min(struct ltc2978_data *data, struct i2c_client *client,
+                      int page, int reg, u16 *pmin)
+{
+       int ret;
+
+       ret = ltc_read_word_data(client, page, reg);
+       if (ret >= 0) {
+               if (lin11_to_val(ret) < lin11_to_val(*pmin))
+                       *pmin = ret;
+               ret = *pmin;
+       }
+       return ret;
+}
+
 static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
                                         int reg)
 {
@@ -111,15 +241,11 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
 
        switch (reg) {
        case PMBUS_VIRT_READ_VIN_MAX:
-               ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
-                               data->vin_max = ret;
-                       ret = data->vin_max;
-               }
+               ret = ltc_get_max(data, client, page, LTC2978_MFR_VIN_PEAK,
+                                 &data->vin_max);
                break;
        case PMBUS_VIRT_READ_VOUT_MAX:
-               ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
+               ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
                if (ret >= 0) {
                        /*
                         * VOUT is 16 bit unsigned with fixed exponent,
@@ -131,14 +257,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
                }
                break;
        case PMBUS_VIRT_READ_TEMP_MAX:
-               ret = pmbus_read_word_data(client, page,
-                                          LTC2978_MFR_TEMPERATURE_PEAK);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           > lin11_to_val(data->temp_max[page]))
-                               data->temp_max[page] = ret;
-                       ret = data->temp_max[page];
-               }
+               ret = ltc_get_max(data, client, page,
+                                 LTC2978_MFR_TEMPERATURE_PEAK,
+                                 &data->temp_max[page]);
                break;
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
        case PMBUS_VIRT_RESET_VIN_HISTORY:
@@ -146,6 +267,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
                ret = 0;
                break;
        default:
+               ret = ltc_wait_ready(client);
+               if (ret < 0)
+                       return ret;
                ret = -ENODATA;
                break;
        }
@@ -160,15 +284,11 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
 
        switch (reg) {
        case PMBUS_VIRT_READ_VIN_MIN:
-               ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
-                               data->vin_min = ret;
-                       ret = data->vin_min;
-               }
+               ret = ltc_get_min(data, client, page, LTC2978_MFR_VIN_MIN,
+                                 &data->vin_min);
                break;
        case PMBUS_VIRT_READ_VOUT_MIN:
-               ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
+               ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
                if (ret >= 0) {
                        /*
                         * VOUT_MIN is known to not be supported on some lots
@@ -184,14 +304,9 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
                }
                break;
        case PMBUS_VIRT_READ_TEMP_MIN:
-               ret = pmbus_read_word_data(client, page,
-                                          LTC2978_MFR_TEMPERATURE_MIN);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           < lin11_to_val(data->temp_min[page]))
-                               data->temp_min[page] = ret;
-                       ret = data->temp_min[page];
-               }
+               ret = ltc_get_min(data, client, page,
+                                 LTC2978_MFR_TEMPERATURE_MIN,
+                                 &data->temp_min[page]);
                break;
        case PMBUS_VIRT_READ_IOUT_MAX:
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
@@ -214,22 +329,12 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
 
        switch (reg) {
        case PMBUS_VIRT_READ_IOUT_MAX:
-               ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           > lin11_to_val(data->iout_max[page]))
-                               data->iout_max[page] = ret;
-                       ret = data->iout_max[page];
-               }
+               ret = ltc_get_max(data, client, page, LTC2974_MFR_IOUT_PEAK,
+                                 &data->iout_max[page]);
                break;
        case PMBUS_VIRT_READ_IOUT_MIN:
-               ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           < lin11_to_val(data->iout_min[page]))
-                               data->iout_min[page] = ret;
-                       ret = data->iout_min[page];
-               }
+               ret = ltc_get_min(data, client, page, LTC2974_MFR_IOUT_MIN,
+                                 &data->iout_min[page]);
                break;
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
                ret = 0;
@@ -241,6 +346,40 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
        return ret;
 }
 
+static int ltc2975_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct ltc2978_data *data = to_ltc2978_data(info);
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VIRT_READ_IIN_MAX:
+               ret = ltc_get_max(data, client, page, LTC2975_MFR_IIN_PEAK,
+                                 &data->iin_max);
+               break;
+       case PMBUS_VIRT_READ_IIN_MIN:
+               ret = ltc_get_min(data, client, page, LTC2975_MFR_IIN_MIN,
+                                 &data->iin_min);
+               break;
+       case PMBUS_VIRT_READ_PIN_MAX:
+               ret = ltc_get_max(data, client, page, LTC2975_MFR_PIN_PEAK,
+                                 &data->pin_max);
+               break;
+       case PMBUS_VIRT_READ_PIN_MIN:
+               ret = ltc_get_min(data, client, page, LTC2975_MFR_PIN_MIN,
+                                 &data->pin_min);
+               break;
+       case PMBUS_VIRT_RESET_IIN_HISTORY:
+       case PMBUS_VIRT_RESET_PIN_HISTORY:
+               ret = 0;
+               break;
+       default:
+               ret = ltc2978_read_word_data(client, page, reg);
+               break;
+       }
+       return ret;
+}
+
 static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
 {
        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -249,22 +388,13 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
 
        switch (reg) {
        case PMBUS_VIRT_READ_IOUT_MAX:
-               ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           > lin11_to_val(data->iout_max[page]))
-                               data->iout_max[page] = ret;
-                       ret = data->iout_max[page];
-               }
+               ret = ltc_get_max(data, client, page, LTC3880_MFR_IOUT_PEAK,
+                                 &data->iout_max[page]);
                break;
        case PMBUS_VIRT_READ_TEMP2_MAX:
-               ret = pmbus_read_word_data(client, page,
-                                          LTC3880_MFR_TEMPERATURE2_PEAK);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
-                               data->temp2_max = ret;
-                       ret = data->temp2_max;
-               }
+               ret = ltc_get_max(data, client, page,
+                                 LTC3880_MFR_TEMPERATURE2_PEAK,
+                                 &data->temp2_max);
                break;
        case PMBUS_VIRT_READ_VIN_MIN:
        case PMBUS_VIRT_READ_VOUT_MIN:
@@ -290,13 +420,8 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
 
        switch (reg) {
        case PMBUS_VIRT_READ_IIN_MAX:
-               ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK);
-               if (ret >= 0) {
-                       if (lin11_to_val(ret)
-                           > lin11_to_val(data->iin_max))
-                               data->iin_max = ret;
-                       ret = data->iin_max;
-               }
+               ret = ltc_get_max(data, client, page, LTC3883_MFR_IIN_PEAK,
+                                 &data->iin_max);
                break;
        case PMBUS_VIRT_RESET_IIN_HISTORY:
                ret = 0;
@@ -308,15 +433,15 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
        return ret;
 }
 
-static int ltc2978_clear_peaks(struct i2c_client *client, int page,
-                              enum chips id)
+static int ltc2978_clear_peaks(struct ltc2978_data *data,
+                              struct i2c_client *client, int page)
 {
        int ret;
 
-       if (id == ltc3880 || id == ltc3883)
-               ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
+       if (has_clear_peaks(data))
+               ret = ltc_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
        else
-               ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+               ret = ltc_write_byte(client, page, PMBUS_CLEAR_FAULTS);
 
        return ret;
 }
@@ -331,33 +456,42 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
        switch (reg) {
        case PMBUS_VIRT_RESET_IIN_HISTORY:
                data->iin_max = 0x7c00;
-               ret = ltc2978_clear_peaks(client, page, data->id);
+               data->iin_min = 0x7bff;
+               ret = ltc2978_clear_peaks(data, client, 0);
+               break;
+       case PMBUS_VIRT_RESET_PIN_HISTORY:
+               data->pin_max = 0x7c00;
+               data->pin_min = 0x7bff;
+               ret = ltc2978_clear_peaks(data, client, 0);
                break;
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
                data->iout_max[page] = 0x7c00;
                data->iout_min[page] = 0xfbff;
-               ret = ltc2978_clear_peaks(client, page, data->id);
+               ret = ltc2978_clear_peaks(data, client, page);
                break;
        case PMBUS_VIRT_RESET_TEMP2_HISTORY:
                data->temp2_max = 0x7c00;
-               ret = ltc2978_clear_peaks(client, page, data->id);
+               ret = ltc2978_clear_peaks(data, client, page);
                break;
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
                data->vout_min[page] = 0xffff;
                data->vout_max[page] = 0;
-               ret = ltc2978_clear_peaks(client, page, data->id);
+               ret = ltc2978_clear_peaks(data, client, page);
                break;
        case PMBUS_VIRT_RESET_VIN_HISTORY:
                data->vin_min = 0x7bff;
                data->vin_max = 0x7c00;
-               ret = ltc2978_clear_peaks(client, page, data->id);
+               ret = ltc2978_clear_peaks(data, client, page);
                break;
        case PMBUS_VIRT_RESET_TEMP_HISTORY:
                data->temp_min[page] = 0x7bff;
                data->temp_max[page] = 0x7c00;
-               ret = ltc2978_clear_peaks(client, page, data->id);
+               ret = ltc2978_clear_peaks(data, client, page);
                break;
        default:
+               ret = ltc_wait_ready(client);
+               if (ret < 0)
+                       return ret;
                ret = -ENODATA;
                break;
        }
@@ -366,10 +500,17 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
 
 static const struct i2c_device_id ltc2978_id[] = {
        {"ltc2974", ltc2974},
+       {"ltc2975", ltc2975},
        {"ltc2977", ltc2977},
        {"ltc2978", ltc2978},
+       {"ltc2980", ltc2980},
        {"ltc3880", ltc3880},
+       {"ltc3882", ltc3882},
        {"ltc3883", ltc3883},
+       {"ltc3886", ltc3886},
+       {"ltc3887", ltc3887},
+       {"ltm2987", ltm2987},
+       {"ltm4675", ltm4675},
        {"ltm4676", ltm4676},
        {}
 };
@@ -388,10 +529,74 @@ static const struct regulator_desc ltc2978_reg_desc[] = {
 };
 #endif /* CONFIG_SENSORS_LTC2978_REGULATOR */
 
+static int ltc2978_get_id(struct i2c_client *client)
+{
+       int chip_id;
+
+       chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+       if (chip_id < 0) {
+               const struct i2c_device_id *id;
+               u8 buf[I2C_SMBUS_BLOCK_MAX];
+               int ret;
+
+               if (!i2c_check_functionality(client->adapter,
+                                            I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+                       return -ENODEV;
+
+               ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
+               if (ret < 0)
+                       return ret;
+               if (ret < 3 || strncmp(buf, "LTC", 3))
+                       return -ENODEV;
+
+               ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
+               if (ret < 0)
+                       return ret;
+               for (id = &ltc2978_id[0]; strlen(id->name); id++) {
+                       if (!strncasecmp(id->name, buf, strlen(id->name)))
+                               return (int)id->driver_data;
+               }
+               return -ENODEV;
+       }
+
+       chip_id &= LTC2978_ID_MASK;
+
+       if (chip_id == LTC2974_ID)
+               return ltc2974;
+       else if (chip_id == LTC2975_ID)
+               return ltc2975;
+       else if (chip_id == LTC2977_ID)
+               return ltc2977;
+       else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2)
+               return ltc2978;
+       else if (chip_id == LTC2980_ID_A || chip_id == LTC2980_ID_B)
+               return ltc2980;
+       else if (chip_id == LTC3880_ID)
+               return ltc3880;
+       else if (chip_id == LTC3882_ID || chip_id == LTC3882_ID_D1)
+               return ltc3882;
+       else if (chip_id == LTC3883_ID)
+               return ltc3883;
+       else if (chip_id == LTC3886_ID)
+               return ltc3886;
+       else if (chip_id == LTC3887_ID)
+               return ltc3887;
+       else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
+               return ltm2987;
+       else if (chip_id == LTM4675_ID)
+               return ltm4675;
+       else if (chip_id == LTM4676_ID_REV1 || chip_id == LTM4676_ID_REV2 ||
+                chip_id == LTM4676A_ID)
+               return ltm4676;
+
+       dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
+       return -ENODEV;
+}
+
 static int ltc2978_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
-       int chip_id, i;
+       int i, chip_id;
        struct ltc2978_data *data;
        struct pmbus_driver_info *info;
 
@@ -404,27 +609,11 @@ static int ltc2978_probe(struct i2c_client *client,
        if (!data)
                return -ENOMEM;
 
-       chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
+       chip_id = ltc2978_get_id(client);
        if (chip_id < 0)
                return chip_id;
 
-       if (chip_id == LTC2974_ID_REV1 || chip_id == LTC2974_ID_REV2) {
-               data->id = ltc2974;
-       } else if (chip_id == LTC2977_ID) {
-               data->id = ltc2977;
-       } else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2 ||
-                  chip_id == LTC2978A_ID) {
-               data->id = ltc2978;
-       } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
-               data->id = ltc3880;
-       } else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) {
-               data->id = ltc3883;
-       } else if ((chip_id & LTM4676_ID_MASK) == LTM4676_ID) {
-               data->id = ltm4676;
-       } else {
-               dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
-               return -ENODEV;
-       }
+       data->id = chip_id;
        if (data->id != id->driver_data)
                dev_warn(&client->dev,
                         "Device mismatch: Configured %s, detected %s\n",
@@ -433,6 +622,9 @@ static int ltc2978_probe(struct i2c_client *client,
 
        info = &data->info;
        info->write_word_data = ltc2978_write_word_data;
+       info->write_byte = ltc_write_byte;
+       info->read_word_data = ltc_read_word_data;
+       info->read_byte_data = ltc_read_byte_data;
 
        data->vin_min = 0x7bff;
        data->vin_max = 0x7c00;
@@ -461,8 +653,23 @@ static int ltc2978_probe(struct i2c_client *client,
                          | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
                }
                break;
+       case ltc2975:
+               info->read_word_data = ltc2975_read_word_data;
+               info->pages = LTC2974_NUM_PAGES;
+               info->func[0] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN
+                 | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+                 | PMBUS_HAVE_TEMP2;
+               for (i = 0; i < info->pages; i++) {
+                       info->func[i] |= PMBUS_HAVE_VOUT
+                         | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
+                         | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+                         | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
+               }
+               break;
        case ltc2977:
        case ltc2978:
+       case ltc2980:
+       case ltm2987:
                info->read_word_data = ltc2978_read_word_data;
                info->pages = LTC2978_NUM_PAGES;
                info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
@@ -474,7 +681,10 @@ static int ltc2978_probe(struct i2c_client *client,
                }
                break;
        case ltc3880:
+       case ltc3887:
+       case ltm4675:
        case ltm4676:
+               data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
                info->read_word_data = ltc3880_read_word_data;
                info->pages = LTC3880_NUM_PAGES;
                info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
@@ -488,7 +698,23 @@ static int ltc2978_probe(struct i2c_client *client,
                  | PMBUS_HAVE_POUT
                  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
                break;
+       case ltc3882:
+               data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
+               info->read_word_data = ltc3880_read_word_data;
+               info->pages = LTC3880_NUM_PAGES;
+               info->func[0] = PMBUS_HAVE_VIN
+                 | PMBUS_HAVE_STATUS_INPUT
+                 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+                 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+                 | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+                 | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+               info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+                 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+                 | PMBUS_HAVE_POUT
+                 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+               break;
        case ltc3883:
+               data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
                info->read_word_data = ltc3883_read_word_data;
                info->pages = LTC3883_NUM_PAGES;
                info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
@@ -498,6 +724,21 @@ static int ltc2978_probe(struct i2c_client *client,
                  | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
                  | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
                break;
+       case ltc3886:
+               data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
+               info->read_word_data = ltc3883_read_word_data;
+               info->pages = LTC3880_NUM_PAGES;
+               info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+                 | PMBUS_HAVE_STATUS_INPUT
+                 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+                 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+                 | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+                 | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
+               info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+                 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+                 | PMBUS_HAVE_POUT
+                 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+               break;
        default:
                return -ENODEV;
        }
@@ -517,10 +758,17 @@ static int ltc2978_probe(struct i2c_client *client,
 #ifdef CONFIG_OF
 static const struct of_device_id ltc2978_of_match[] = {
        { .compatible = "lltc,ltc2974" },
+       { .compatible = "lltc,ltc2975" },
        { .compatible = "lltc,ltc2977" },
        { .compatible = "lltc,ltc2978" },
+       { .compatible = "lltc,ltc2980" },
        { .compatible = "lltc,ltc3880" },
+       { .compatible = "lltc,ltc3882" },
        { .compatible = "lltc,ltc3883" },
+       { .compatible = "lltc,ltc3886" },
+       { .compatible = "lltc,ltc3887" },
+       { .compatible = "lltc,ltm2987" },
+       { .compatible = "lltc,ltm4675" },
        { .compatible = "lltc,ltm4676" },
        { }
 };
@@ -540,5 +788,5 @@ static struct i2c_driver ltc2978_driver = {
 module_i2c_driver(ltc2978_driver);
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, LTC3883, and LTM4676");
+MODULE_DESCRIPTION("PMBus driver for LTC2978 and comppatible chips");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c
new file mode 100644 (file)
index 0000000..ab74aea
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Hardware monitoring driver for Maxim MAX20751
+ *
+ * Copyright (c) 2015 Guenter Roeck
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info max20751_info = {
+       .pages = 1,
+       .format[PSC_VOLTAGE_IN] = linear,
+       .format[PSC_VOLTAGE_OUT] = vid,
+       .vrm_version = vr12,
+       .format[PSC_TEMPERATURE] = linear,
+       .format[PSC_CURRENT_OUT] = linear,
+       .format[PSC_POWER] = linear,
+       .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+               PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+               PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
+               PMBUS_HAVE_POUT,
+};
+
+static int max20751_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
+{
+       return pmbus_do_probe(client, id, &max20751_info);
+}
+
+static const struct i2c_device_id max20751_id[] = {
+       {"max20751", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, max20751_id);
+
+static struct i2c_driver max20751_driver = {
+       .driver = {
+                  .name = "max20751",
+                  },
+       .probe = max20751_probe,
+       .remove = pmbus_do_remove,
+       .id_table = max20751_id,
+};
+
+module_i2c_driver(max20751_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX20751");
+MODULE_LICENSE("GPL");
index 7e930c3ce1abf011621669e1f054fcdf991c8e13..74a1f6f68fb384fc02c530aa27bce7f243107969 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -38,10 +39,10 @@ enum chips { max34440, max34441, max34446, max34460, max34461 };
 #define MAX34446_MFR_IOUT_AVG          0xe2
 #define MAX34446_MFR_TEMPERATURE_AVG   0xe3
 
-#define MAX34440_STATUS_OC_WARN                (1 << 0)
-#define MAX34440_STATUS_OC_FAULT       (1 << 1)
-#define MAX34440_STATUS_OT_FAULT       (1 << 5)
-#define MAX34440_STATUS_OT_WARN                (1 << 6)
+#define MAX34440_STATUS_OC_WARN                BIT(0)
+#define MAX34440_STATUS_OC_FAULT       BIT(1)
+#define MAX34440_STATUS_OT_FAULT       BIT(5)
+#define MAX34440_STATUS_OT_WARN                BIT(6)
 
 struct max34440_data {
        int id;
index f04454a42fdd2ec68395535ae3553e86e849bc3e..dd4883a19045601fcccac2cebea02d987a728e02 100644 (file)
@@ -18,6 +18,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #define MAX8688_MFR_TEMPERATURE_PEAK   0xd6
 #define MAX8688_MFG_STATUS             0xd8
 
-#define MAX8688_STATUS_OC_FAULT                (1 << 4)
-#define MAX8688_STATUS_OV_FAULT                (1 << 5)
-#define MAX8688_STATUS_OV_WARNING      (1 << 8)
-#define MAX8688_STATUS_UV_FAULT                (1 << 9)
-#define MAX8688_STATUS_UV_WARNING      (1 << 10)
-#define MAX8688_STATUS_UC_FAULT                (1 << 11)
-#define MAX8688_STATUS_OC_WARNING      (1 << 12)
-#define MAX8688_STATUS_OT_FAULT                (1 << 13)
-#define MAX8688_STATUS_OT_WARNING      (1 << 14)
+#define MAX8688_STATUS_OC_FAULT                BIT(4)
+#define MAX8688_STATUS_OV_FAULT                BIT(5)
+#define MAX8688_STATUS_OV_WARNING      BIT(8)
+#define MAX8688_STATUS_UV_FAULT                BIT(9)
+#define MAX8688_STATUS_UV_WARNING      BIT(10)
+#define MAX8688_STATUS_UC_FAULT                BIT(11)
+#define MAX8688_STATUS_OC_WARNING      BIT(12)
+#define MAX8688_STATUS_OT_FAULT                BIT(13)
+#define MAX8688_STATUS_OT_WARNING      BIT(14)
 
 static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
 {
index 554d0249dcde13c8fe915104acb112bdc4f4c3a6..0a74991a60f0dfca92b88747c0dd85bf3c01d226 100644 (file)
@@ -129,6 +129,7 @@ static int pmbus_identify(struct i2c_client *client,
                                break;
                        case 1:
                                info->format[PSC_VOLTAGE_OUT] = vid;
+                               info->vrm_version = vr11;
                                break;
                        case 2:
                                info->format[PSC_VOLTAGE_OUT] = direct;
@@ -193,6 +194,10 @@ static const struct i2c_device_id pmbus_id[] = {
        {"pdt012", 1},
        {"pmbus", 0},
        {"tps40400", 1},
+       {"tps544b20", 1},
+       {"tps544b25", 1},
+       {"tps544c20", 1},
+       {"tps544c25", 1},
        {"udt020", 1},
        {}
 };
index 89a23ff836e71752bf113ad4f0c48da35af5e89a..bfcb13bae34bd67338e363d8b76849572d39f7d6 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/regulator/driver.h>
-
 #ifndef PMBUS_H
 #define PMBUS_H
 
+#include <linux/bitops.h>
+#include <linux/regulator/driver.h>
+
 /*
  * Registers
  */
-#define PMBUS_PAGE                     0x00
-#define PMBUS_OPERATION                        0x01
-#define PMBUS_ON_OFF_CONFIG            0x02
-#define PMBUS_CLEAR_FAULTS             0x03
-#define PMBUS_PHASE                    0x04
-
-#define PMBUS_CAPABILITY               0x19
-#define PMBUS_QUERY                    0x1A
-
-#define PMBUS_VOUT_MODE                        0x20
-#define PMBUS_VOUT_COMMAND             0x21
-#define PMBUS_VOUT_TRIM                        0x22
-#define PMBUS_VOUT_CAL_OFFSET          0x23
-#define PMBUS_VOUT_MAX                 0x24
-#define PMBUS_VOUT_MARGIN_HIGH         0x25
-#define PMBUS_VOUT_MARGIN_LOW          0x26
-#define PMBUS_VOUT_TRANSITION_RATE     0x27
-#define PMBUS_VOUT_DROOP               0x28
-#define PMBUS_VOUT_SCALE_LOOP          0x29
-#define PMBUS_VOUT_SCALE_MONITOR       0x2A
-
-#define PMBUS_COEFFICIENTS             0x30
-#define PMBUS_POUT_MAX                 0x31
-
-#define PMBUS_FAN_CONFIG_12            0x3A
-#define PMBUS_FAN_COMMAND_1            0x3B
-#define PMBUS_FAN_COMMAND_2            0x3C
-#define PMBUS_FAN_CONFIG_34            0x3D
-#define PMBUS_FAN_COMMAND_3            0x3E
-#define PMBUS_FAN_COMMAND_4            0x3F
-
-#define PMBUS_VOUT_OV_FAULT_LIMIT      0x40
-#define PMBUS_VOUT_OV_FAULT_RESPONSE   0x41
-#define PMBUS_VOUT_OV_WARN_LIMIT       0x42
-#define PMBUS_VOUT_UV_WARN_LIMIT       0x43
-#define PMBUS_VOUT_UV_FAULT_LIMIT      0x44
-#define PMBUS_VOUT_UV_FAULT_RESPONSE   0x45
-#define PMBUS_IOUT_OC_FAULT_LIMIT      0x46
-#define PMBUS_IOUT_OC_FAULT_RESPONSE   0x47
-#define PMBUS_IOUT_OC_LV_FAULT_LIMIT   0x48
-#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE        0x49
-#define PMBUS_IOUT_OC_WARN_LIMIT       0x4A
-#define PMBUS_IOUT_UC_FAULT_LIMIT      0x4B
-#define PMBUS_IOUT_UC_FAULT_RESPONSE   0x4C
-
-#define PMBUS_OT_FAULT_LIMIT           0x4F
-#define PMBUS_OT_FAULT_RESPONSE                0x50
-#define PMBUS_OT_WARN_LIMIT            0x51
-#define PMBUS_UT_WARN_LIMIT            0x52
-#define PMBUS_UT_FAULT_LIMIT           0x53
-#define PMBUS_UT_FAULT_RESPONSE                0x54
-#define PMBUS_VIN_OV_FAULT_LIMIT       0x55
-#define PMBUS_VIN_OV_FAULT_RESPONSE    0x56
-#define PMBUS_VIN_OV_WARN_LIMIT                0x57
-#define PMBUS_VIN_UV_WARN_LIMIT                0x58
-#define PMBUS_VIN_UV_FAULT_LIMIT       0x59
-
-#define PMBUS_IIN_OC_FAULT_LIMIT       0x5B
-#define PMBUS_IIN_OC_WARN_LIMIT                0x5D
-
-#define PMBUS_POUT_OP_FAULT_LIMIT      0x68
-#define PMBUS_POUT_OP_WARN_LIMIT       0x6A
-#define PMBUS_PIN_OP_WARN_LIMIT                0x6B
-
-#define PMBUS_STATUS_BYTE              0x78
-#define PMBUS_STATUS_WORD              0x79
-#define PMBUS_STATUS_VOUT              0x7A
-#define PMBUS_STATUS_IOUT              0x7B
-#define PMBUS_STATUS_INPUT             0x7C
-#define PMBUS_STATUS_TEMPERATURE       0x7D
-#define PMBUS_STATUS_CML               0x7E
-#define PMBUS_STATUS_OTHER             0x7F
-#define PMBUS_STATUS_MFR_SPECIFIC      0x80
-#define PMBUS_STATUS_FAN_12            0x81
-#define PMBUS_STATUS_FAN_34            0x82
-
-#define PMBUS_READ_VIN                 0x88
-#define PMBUS_READ_IIN                 0x89
-#define PMBUS_READ_VCAP                        0x8A
-#define PMBUS_READ_VOUT                        0x8B
-#define PMBUS_READ_IOUT                        0x8C
-#define PMBUS_READ_TEMPERATURE_1       0x8D
-#define PMBUS_READ_TEMPERATURE_2       0x8E
-#define PMBUS_READ_TEMPERATURE_3       0x8F
-#define PMBUS_READ_FAN_SPEED_1         0x90
-#define PMBUS_READ_FAN_SPEED_2         0x91
-#define PMBUS_READ_FAN_SPEED_3         0x92
-#define PMBUS_READ_FAN_SPEED_4         0x93
-#define PMBUS_READ_DUTY_CYCLE          0x94
-#define PMBUS_READ_FREQUENCY           0x95
-#define PMBUS_READ_POUT                        0x96
-#define PMBUS_READ_PIN                 0x97
-
-#define PMBUS_REVISION                 0x98
-#define PMBUS_MFR_ID                   0x99
-#define PMBUS_MFR_MODEL                        0x9A
-#define PMBUS_MFR_REVISION             0x9B
-#define PMBUS_MFR_LOCATION             0x9C
-#define PMBUS_MFR_DATE                 0x9D
-#define PMBUS_MFR_SERIAL               0x9E
+enum pmbus_regs {
+       PMBUS_PAGE                      = 0x00,
+       PMBUS_OPERATION                 = 0x01,
+       PMBUS_ON_OFF_CONFIG             = 0x02,
+       PMBUS_CLEAR_FAULTS              = 0x03,
+       PMBUS_PHASE                     = 0x04,
+
+       PMBUS_CAPABILITY                = 0x19,
+       PMBUS_QUERY                     = 0x1A,
+
+       PMBUS_VOUT_MODE                 = 0x20,
+       PMBUS_VOUT_COMMAND              = 0x21,
+       PMBUS_VOUT_TRIM                 = 0x22,
+       PMBUS_VOUT_CAL_OFFSET           = 0x23,
+       PMBUS_VOUT_MAX                  = 0x24,
+       PMBUS_VOUT_MARGIN_HIGH          = 0x25,
+       PMBUS_VOUT_MARGIN_LOW           = 0x26,
+       PMBUS_VOUT_TRANSITION_RATE      = 0x27,
+       PMBUS_VOUT_DROOP                = 0x28,
+       PMBUS_VOUT_SCALE_LOOP           = 0x29,
+       PMBUS_VOUT_SCALE_MONITOR        = 0x2A,
+
+       PMBUS_COEFFICIENTS              = 0x30,
+       PMBUS_POUT_MAX                  = 0x31,
+
+       PMBUS_FAN_CONFIG_12             = 0x3A,
+       PMBUS_FAN_COMMAND_1             = 0x3B,
+       PMBUS_FAN_COMMAND_2             = 0x3C,
+       PMBUS_FAN_CONFIG_34             = 0x3D,
+       PMBUS_FAN_COMMAND_3             = 0x3E,
+       PMBUS_FAN_COMMAND_4             = 0x3F,
+
+       PMBUS_VOUT_OV_FAULT_LIMIT       = 0x40,
+       PMBUS_VOUT_OV_FAULT_RESPONSE    = 0x41,
+       PMBUS_VOUT_OV_WARN_LIMIT        = 0x42,
+       PMBUS_VOUT_UV_WARN_LIMIT        = 0x43,
+       PMBUS_VOUT_UV_FAULT_LIMIT       = 0x44,
+       PMBUS_VOUT_UV_FAULT_RESPONSE    = 0x45,
+       PMBUS_IOUT_OC_FAULT_LIMIT       = 0x46,
+       PMBUS_IOUT_OC_FAULT_RESPONSE    = 0x47,
+       PMBUS_IOUT_OC_LV_FAULT_LIMIT    = 0x48,
+       PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
+       PMBUS_IOUT_OC_WARN_LIMIT        = 0x4A,
+       PMBUS_IOUT_UC_FAULT_LIMIT       = 0x4B,
+       PMBUS_IOUT_UC_FAULT_RESPONSE    = 0x4C,
+
+       PMBUS_OT_FAULT_LIMIT            = 0x4F,
+       PMBUS_OT_FAULT_RESPONSE         = 0x50,
+       PMBUS_OT_WARN_LIMIT             = 0x51,
+       PMBUS_UT_WARN_LIMIT             = 0x52,
+       PMBUS_UT_FAULT_LIMIT            = 0x53,
+       PMBUS_UT_FAULT_RESPONSE         = 0x54,
+       PMBUS_VIN_OV_FAULT_LIMIT        = 0x55,
+       PMBUS_VIN_OV_FAULT_RESPONSE     = 0x56,
+       PMBUS_VIN_OV_WARN_LIMIT         = 0x57,
+       PMBUS_VIN_UV_WARN_LIMIT         = 0x58,
+       PMBUS_VIN_UV_FAULT_LIMIT        = 0x59,
+
+       PMBUS_IIN_OC_FAULT_LIMIT        = 0x5B,
+       PMBUS_IIN_OC_WARN_LIMIT         = 0x5D,
+
+       PMBUS_POUT_OP_FAULT_LIMIT       = 0x68,
+       PMBUS_POUT_OP_WARN_LIMIT        = 0x6A,
+       PMBUS_PIN_OP_WARN_LIMIT         = 0x6B,
+
+       PMBUS_STATUS_BYTE               = 0x78,
+       PMBUS_STATUS_WORD               = 0x79,
+       PMBUS_STATUS_VOUT               = 0x7A,
+       PMBUS_STATUS_IOUT               = 0x7B,
+       PMBUS_STATUS_INPUT              = 0x7C,
+       PMBUS_STATUS_TEMPERATURE        = 0x7D,
+       PMBUS_STATUS_CML                = 0x7E,
+       PMBUS_STATUS_OTHER              = 0x7F,
+       PMBUS_STATUS_MFR_SPECIFIC       = 0x80,
+       PMBUS_STATUS_FAN_12             = 0x81,
+       PMBUS_STATUS_FAN_34             = 0x82,
+
+       PMBUS_READ_VIN                  = 0x88,
+       PMBUS_READ_IIN                  = 0x89,
+       PMBUS_READ_VCAP                 = 0x8A,
+       PMBUS_READ_VOUT                 = 0x8B,
+       PMBUS_READ_IOUT                 = 0x8C,
+       PMBUS_READ_TEMPERATURE_1        = 0x8D,
+       PMBUS_READ_TEMPERATURE_2        = 0x8E,
+       PMBUS_READ_TEMPERATURE_3        = 0x8F,
+       PMBUS_READ_FAN_SPEED_1          = 0x90,
+       PMBUS_READ_FAN_SPEED_2          = 0x91,
+       PMBUS_READ_FAN_SPEED_3          = 0x92,
+       PMBUS_READ_FAN_SPEED_4          = 0x93,
+       PMBUS_READ_DUTY_CYCLE           = 0x94,
+       PMBUS_READ_FREQUENCY            = 0x95,
+       PMBUS_READ_POUT                 = 0x96,
+       PMBUS_READ_PIN                  = 0x97,
+
+       PMBUS_REVISION                  = 0x98,
+       PMBUS_MFR_ID                    = 0x99,
+       PMBUS_MFR_MODEL                 = 0x9A,
+       PMBUS_MFR_REVISION              = 0x9B,
+       PMBUS_MFR_LOCATION              = 0x9C,
+       PMBUS_MFR_DATE                  = 0x9D,
+       PMBUS_MFR_SERIAL                = 0x9E,
 
 /*
  * Virtual registers.
  * the calling PMBus core code will abort if the chip driver returns an error
  * code when reading or writing virtual registers.
  */
-#define PMBUS_VIRT_BASE                        0x100
-#define PMBUS_VIRT_READ_TEMP_AVG       (PMBUS_VIRT_BASE + 0)
-#define PMBUS_VIRT_READ_TEMP_MIN       (PMBUS_VIRT_BASE + 1)
-#define PMBUS_VIRT_READ_TEMP_MAX       (PMBUS_VIRT_BASE + 2)
-#define PMBUS_VIRT_RESET_TEMP_HISTORY  (PMBUS_VIRT_BASE + 3)
-#define PMBUS_VIRT_READ_VIN_AVG                (PMBUS_VIRT_BASE + 4)
-#define PMBUS_VIRT_READ_VIN_MIN                (PMBUS_VIRT_BASE + 5)
-#define PMBUS_VIRT_READ_VIN_MAX                (PMBUS_VIRT_BASE + 6)
-#define PMBUS_VIRT_RESET_VIN_HISTORY   (PMBUS_VIRT_BASE + 7)
-#define PMBUS_VIRT_READ_IIN_AVG                (PMBUS_VIRT_BASE + 8)
-#define PMBUS_VIRT_READ_IIN_MIN                (PMBUS_VIRT_BASE + 9)
-#define PMBUS_VIRT_READ_IIN_MAX                (PMBUS_VIRT_BASE + 10)
-#define PMBUS_VIRT_RESET_IIN_HISTORY   (PMBUS_VIRT_BASE + 11)
-#define PMBUS_VIRT_READ_PIN_AVG                (PMBUS_VIRT_BASE + 12)
-#define PMBUS_VIRT_READ_PIN_MAX                (PMBUS_VIRT_BASE + 13)
-#define PMBUS_VIRT_RESET_PIN_HISTORY   (PMBUS_VIRT_BASE + 14)
-#define PMBUS_VIRT_READ_POUT_AVG       (PMBUS_VIRT_BASE + 15)
-#define PMBUS_VIRT_READ_POUT_MAX       (PMBUS_VIRT_BASE + 16)
-#define PMBUS_VIRT_RESET_POUT_HISTORY  (PMBUS_VIRT_BASE + 17)
-#define PMBUS_VIRT_READ_VOUT_AVG       (PMBUS_VIRT_BASE + 18)
-#define PMBUS_VIRT_READ_VOUT_MIN       (PMBUS_VIRT_BASE + 19)
-#define PMBUS_VIRT_READ_VOUT_MAX       (PMBUS_VIRT_BASE + 20)
-#define PMBUS_VIRT_RESET_VOUT_HISTORY  (PMBUS_VIRT_BASE + 21)
-#define PMBUS_VIRT_READ_IOUT_AVG       (PMBUS_VIRT_BASE + 22)
-#define PMBUS_VIRT_READ_IOUT_MIN       (PMBUS_VIRT_BASE + 23)
-#define PMBUS_VIRT_READ_IOUT_MAX       (PMBUS_VIRT_BASE + 24)
-#define PMBUS_VIRT_RESET_IOUT_HISTORY  (PMBUS_VIRT_BASE + 25)
-#define PMBUS_VIRT_READ_TEMP2_AVG      (PMBUS_VIRT_BASE + 26)
-#define PMBUS_VIRT_READ_TEMP2_MIN      (PMBUS_VIRT_BASE + 27)
-#define PMBUS_VIRT_READ_TEMP2_MAX      (PMBUS_VIRT_BASE + 28)
-#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29)
-
-#define PMBUS_VIRT_READ_VMON           (PMBUS_VIRT_BASE + 30)
-#define PMBUS_VIRT_VMON_UV_WARN_LIMIT  (PMBUS_VIRT_BASE + 31)
-#define PMBUS_VIRT_VMON_OV_WARN_LIMIT  (PMBUS_VIRT_BASE + 32)
-#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33)
-#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
-#define PMBUS_VIRT_STATUS_VMON         (PMBUS_VIRT_BASE + 35)
+       PMBUS_VIRT_BASE                 = 0x100,
+       PMBUS_VIRT_READ_TEMP_AVG,
+       PMBUS_VIRT_READ_TEMP_MIN,
+       PMBUS_VIRT_READ_TEMP_MAX,
+       PMBUS_VIRT_RESET_TEMP_HISTORY,
+       PMBUS_VIRT_READ_VIN_AVG,
+       PMBUS_VIRT_READ_VIN_MIN,
+       PMBUS_VIRT_READ_VIN_MAX,
+       PMBUS_VIRT_RESET_VIN_HISTORY,
+       PMBUS_VIRT_READ_IIN_AVG,
+       PMBUS_VIRT_READ_IIN_MIN,
+       PMBUS_VIRT_READ_IIN_MAX,
+       PMBUS_VIRT_RESET_IIN_HISTORY,
+       PMBUS_VIRT_READ_PIN_AVG,
+       PMBUS_VIRT_READ_PIN_MIN,
+       PMBUS_VIRT_READ_PIN_MAX,
+       PMBUS_VIRT_RESET_PIN_HISTORY,
+       PMBUS_VIRT_READ_POUT_AVG,
+       PMBUS_VIRT_READ_POUT_MIN,
+       PMBUS_VIRT_READ_POUT_MAX,
+       PMBUS_VIRT_RESET_POUT_HISTORY,
+       PMBUS_VIRT_READ_VOUT_AVG,
+       PMBUS_VIRT_READ_VOUT_MIN,
+       PMBUS_VIRT_READ_VOUT_MAX,
+       PMBUS_VIRT_RESET_VOUT_HISTORY,
+       PMBUS_VIRT_READ_IOUT_AVG,
+       PMBUS_VIRT_READ_IOUT_MIN,
+       PMBUS_VIRT_READ_IOUT_MAX,
+       PMBUS_VIRT_RESET_IOUT_HISTORY,
+       PMBUS_VIRT_READ_TEMP2_AVG,
+       PMBUS_VIRT_READ_TEMP2_MIN,
+       PMBUS_VIRT_READ_TEMP2_MAX,
+       PMBUS_VIRT_RESET_TEMP2_HISTORY,
+
+       PMBUS_VIRT_READ_VMON,
+       PMBUS_VIRT_VMON_UV_WARN_LIMIT,
+       PMBUS_VIRT_VMON_OV_WARN_LIMIT,
+       PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
+       PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
+       PMBUS_VIRT_STATUS_VMON,
+};
 
 /*
  * OPERATION
  */
-#define PB_OPERATION_CONTROL_ON                (1<<7)
+#define PB_OPERATION_CONTROL_ON                BIT(7)
 
 /*
  * CAPABILITY
  */
-#define PB_CAPABILITY_SMBALERT         (1<<4)
-#define PB_CAPABILITY_ERROR_CHECK      (1<<7)
+#define PB_CAPABILITY_SMBALERT         BIT(4)
+#define PB_CAPABILITY_ERROR_CHECK      BIT(7)
 
 /*
  * VOUT_MODE
 /*
  * Fan configuration
  */
-#define PB_FAN_2_PULSE_MASK            ((1 << 0) | (1 << 1))
-#define PB_FAN_2_RPM                   (1 << 2)
-#define PB_FAN_2_INSTALLED             (1 << 3)
-#define PB_FAN_1_PULSE_MASK            ((1 << 4) | (1 << 5))
-#define PB_FAN_1_RPM                   (1 << 6)
-#define PB_FAN_1_INSTALLED             (1 << 7)
+#define PB_FAN_2_PULSE_MASK            (BIT(0) | BIT(1))
+#define PB_FAN_2_RPM                   BIT(2)
+#define PB_FAN_2_INSTALLED             BIT(3)
+#define PB_FAN_1_PULSE_MASK            (BIT(4) | BIT(5))
+#define PB_FAN_1_RPM                   BIT(6)
+#define PB_FAN_1_INSTALLED             BIT(7)
 
 /*
  * STATUS_BYTE, STATUS_WORD (lower)
  */
-#define PB_STATUS_NONE_ABOVE           (1<<0)
-#define PB_STATUS_CML                  (1<<1)
-#define PB_STATUS_TEMPERATURE          (1<<2)
-#define PB_STATUS_VIN_UV               (1<<3)
-#define PB_STATUS_IOUT_OC              (1<<4)
-#define PB_STATUS_VOUT_OV              (1<<5)
-#define PB_STATUS_OFF                  (1<<6)
-#define PB_STATUS_BUSY                 (1<<7)
+#define PB_STATUS_NONE_ABOVE           BIT(0)
+#define PB_STATUS_CML                  BIT(1)
+#define PB_STATUS_TEMPERATURE          BIT(2)
+#define PB_STATUS_VIN_UV               BIT(3)
+#define PB_STATUS_IOUT_OC              BIT(4)
+#define PB_STATUS_VOUT_OV              BIT(5)
+#define PB_STATUS_OFF                  BIT(6)
+#define PB_STATUS_BUSY                 BIT(7)
 
 /*
  * STATUS_WORD (upper)
  */
-#define PB_STATUS_UNKNOWN              (1<<8)
-#define PB_STATUS_OTHER                        (1<<9)
-#define PB_STATUS_FANS                 (1<<10)
-#define PB_STATUS_POWER_GOOD_N         (1<<11)
-#define PB_STATUS_WORD_MFR             (1<<12)
-#define PB_STATUS_INPUT                        (1<<13)
-#define PB_STATUS_IOUT_POUT            (1<<14)
-#define PB_STATUS_VOUT                 (1<<15)
+#define PB_STATUS_UNKNOWN              BIT(8)
+#define PB_STATUS_OTHER                        BIT(9)
+#define PB_STATUS_FANS                 BIT(10)
+#define PB_STATUS_POWER_GOOD_N         BIT(11)
+#define PB_STATUS_WORD_MFR             BIT(12)
+#define PB_STATUS_INPUT                        BIT(13)
+#define PB_STATUS_IOUT_POUT            BIT(14)
+#define PB_STATUS_VOUT                 BIT(15)
 
 /*
  * STATUS_IOUT
  */
-#define PB_POUT_OP_WARNING             (1<<0)
-#define PB_POUT_OP_FAULT               (1<<1)
-#define PB_POWER_LIMITING              (1<<2)
-#define PB_CURRENT_SHARE_FAULT         (1<<3)
-#define PB_IOUT_UC_FAULT               (1<<4)
-#define PB_IOUT_OC_WARNING             (1<<5)
-#define PB_IOUT_OC_LV_FAULT            (1<<6)
-#define PB_IOUT_OC_FAULT               (1<<7)
+#define PB_POUT_OP_WARNING             BIT(0)
+#define PB_POUT_OP_FAULT               BIT(1)
+#define PB_POWER_LIMITING              BIT(2)
+#define PB_CURRENT_SHARE_FAULT         BIT(3)
+#define PB_IOUT_UC_FAULT               BIT(4)
+#define PB_IOUT_OC_WARNING             BIT(5)
+#define PB_IOUT_OC_LV_FAULT            BIT(6)
+#define PB_IOUT_OC_FAULT               BIT(7)
 
 /*
  * STATUS_VOUT, STATUS_INPUT
  */
-#define PB_VOLTAGE_UV_FAULT            (1<<4)
-#define PB_VOLTAGE_UV_WARNING          (1<<5)
-#define PB_VOLTAGE_OV_WARNING          (1<<6)
-#define PB_VOLTAGE_OV_FAULT            (1<<7)
+#define PB_VOLTAGE_UV_FAULT            BIT(4)
+#define PB_VOLTAGE_UV_WARNING          BIT(5)
+#define PB_VOLTAGE_OV_WARNING          BIT(6)
+#define PB_VOLTAGE_OV_FAULT            BIT(7)
 
 /*
  * STATUS_INPUT
  */
-#define PB_PIN_OP_WARNING              (1<<0)
-#define PB_IIN_OC_WARNING              (1<<1)
-#define PB_IIN_OC_FAULT                        (1<<2)
+#define PB_PIN_OP_WARNING              BIT(0)
+#define PB_IIN_OC_WARNING              BIT(1)
+#define PB_IIN_OC_FAULT                        BIT(2)
 
 /*
  * STATUS_TEMPERATURE
  */
-#define PB_TEMP_UT_FAULT               (1<<4)
-#define PB_TEMP_UT_WARNING             (1<<5)
-#define PB_TEMP_OT_WARNING             (1<<6)
-#define PB_TEMP_OT_FAULT               (1<<7)
+#define PB_TEMP_UT_FAULT               BIT(4)
+#define PB_TEMP_UT_WARNING             BIT(5)
+#define PB_TEMP_OT_WARNING             BIT(6)
+#define PB_TEMP_OT_FAULT               BIT(7)
 
 /*
  * STATUS_FAN
  */
-#define PB_FAN_AIRFLOW_WARNING         (1<<0)
-#define PB_FAN_AIRFLOW_FAULT           (1<<1)
-#define PB_FAN_FAN2_SPEED_OVERRIDE     (1<<2)
-#define PB_FAN_FAN1_SPEED_OVERRIDE     (1<<3)
-#define PB_FAN_FAN2_WARNING            (1<<4)
-#define PB_FAN_FAN1_WARNING            (1<<5)
-#define PB_FAN_FAN2_FAULT              (1<<6)
-#define PB_FAN_FAN1_FAULT              (1<<7)
+#define PB_FAN_AIRFLOW_WARNING         BIT(0)
+#define PB_FAN_AIRFLOW_FAULT           BIT(1)
+#define PB_FAN_FAN2_SPEED_OVERRIDE     BIT(2)
+#define PB_FAN_FAN1_SPEED_OVERRIDE     BIT(3)
+#define PB_FAN_FAN2_WARNING            BIT(4)
+#define PB_FAN_FAN1_WARNING            BIT(5)
+#define PB_FAN_FAN2_FAULT              BIT(6)
+#define PB_FAN_FAN1_FAULT              BIT(7)
 
 /*
  * CML_FAULT_STATUS
  */
-#define PB_CML_FAULT_OTHER_MEM_LOGIC   (1<<0)
-#define PB_CML_FAULT_OTHER_COMM                (1<<1)
-#define PB_CML_FAULT_PROCESSOR         (1<<3)
-#define PB_CML_FAULT_MEMORY            (1<<4)
-#define PB_CML_FAULT_PACKET_ERROR      (1<<5)
-#define PB_CML_FAULT_INVALID_DATA      (1<<6)
-#define PB_CML_FAULT_INVALID_COMMAND   (1<<7)
+#define PB_CML_FAULT_OTHER_MEM_LOGIC   BIT(0)
+#define PB_CML_FAULT_OTHER_COMM                BIT(1)
+#define PB_CML_FAULT_PROCESSOR         BIT(3)
+#define PB_CML_FAULT_MEMORY            BIT(4)
+#define PB_CML_FAULT_PACKET_ERROR      BIT(5)
+#define PB_CML_FAULT_INVALID_DATA      BIT(6)
+#define PB_CML_FAULT_INVALID_COMMAND   BIT(7)
 
 enum pmbus_sensor_classes {
        PSC_VOLTAGE_IN = 0,
@@ -314,32 +319,34 @@ enum pmbus_sensor_classes {
 #define PMBUS_PAGES    32      /* Per PMBus specification */
 
 /* Functionality bit mask */
-#define PMBUS_HAVE_VIN         (1 << 0)
-#define PMBUS_HAVE_VCAP                (1 << 1)
-#define PMBUS_HAVE_VOUT                (1 << 2)
-#define PMBUS_HAVE_IIN         (1 << 3)
-#define PMBUS_HAVE_IOUT                (1 << 4)
-#define PMBUS_HAVE_PIN         (1 << 5)
-#define PMBUS_HAVE_POUT                (1 << 6)
-#define PMBUS_HAVE_FAN12       (1 << 7)
-#define PMBUS_HAVE_FAN34       (1 << 8)
-#define PMBUS_HAVE_TEMP                (1 << 9)
-#define PMBUS_HAVE_TEMP2       (1 << 10)
-#define PMBUS_HAVE_TEMP3       (1 << 11)
-#define PMBUS_HAVE_STATUS_VOUT (1 << 12)
-#define PMBUS_HAVE_STATUS_IOUT (1 << 13)
-#define PMBUS_HAVE_STATUS_INPUT        (1 << 14)
-#define PMBUS_HAVE_STATUS_TEMP (1 << 15)
-#define PMBUS_HAVE_STATUS_FAN12        (1 << 16)
-#define PMBUS_HAVE_STATUS_FAN34        (1 << 17)
-#define PMBUS_HAVE_VMON                (1 << 18)
-#define PMBUS_HAVE_STATUS_VMON (1 << 19)
+#define PMBUS_HAVE_VIN         BIT(0)
+#define PMBUS_HAVE_VCAP                BIT(1)
+#define PMBUS_HAVE_VOUT                BIT(2)
+#define PMBUS_HAVE_IIN         BIT(3)
+#define PMBUS_HAVE_IOUT                BIT(4)
+#define PMBUS_HAVE_PIN         BIT(5)
+#define PMBUS_HAVE_POUT                BIT(6)
+#define PMBUS_HAVE_FAN12       BIT(7)
+#define PMBUS_HAVE_FAN34       BIT(8)
+#define PMBUS_HAVE_TEMP                BIT(9)
+#define PMBUS_HAVE_TEMP2       BIT(10)
+#define PMBUS_HAVE_TEMP3       BIT(11)
+#define PMBUS_HAVE_STATUS_VOUT BIT(12)
+#define PMBUS_HAVE_STATUS_IOUT BIT(13)
+#define PMBUS_HAVE_STATUS_INPUT        BIT(14)
+#define PMBUS_HAVE_STATUS_TEMP BIT(15)
+#define PMBUS_HAVE_STATUS_FAN12        BIT(16)
+#define PMBUS_HAVE_STATUS_FAN34        BIT(17)
+#define PMBUS_HAVE_VMON                BIT(18)
+#define PMBUS_HAVE_STATUS_VMON BIT(19)
 
 enum pmbus_data_format { linear = 0, direct, vid };
+enum vrm_version { vr11 = 0, vr12 };
 
 struct pmbus_driver_info {
        int pages;              /* Total number of pages */
        enum pmbus_data_format format[PSC_NUM_CLASSES];
+       enum vrm_version vrm_version;
        /*
         * Support one set of coefficients for each sensor type
         * Used for chips providing data in direct mode.
@@ -380,7 +387,7 @@ struct pmbus_driver_info {
 
 /* Regulator ops */
 
-extern struct regulator_ops pmbus_regulator_ops;
+extern const struct regulator_ops pmbus_regulator_ops;
 
 /* Macro for filling in array of struct regulator_desc */
 #define PMBUS_REGULATOR(_name, _id)                            \
@@ -390,6 +397,7 @@ extern struct regulator_ops pmbus_regulator_ops;
                .of_match = of_match_ptr(_name # _id),          \
                .regulators_node = of_match_ptr("regulators"),  \
                .ops = &pmbus_regulator_ops,                    \
+               .type = REGULATOR_VOLTAGE,                      \
                .owner = THIS_MODULE,                           \
        }
 
index f2e47c7dd808becd444512c74dc5738c9e544955..ba59eaef2e075a74cb15940fdc095673c15346a4 100644 (file)
@@ -515,16 +515,24 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
 /*
  * Convert VID sensor values to milli- or micro-units
  * depending on sensor type.
- * We currently only support VR11.
  */
 static long pmbus_reg2data_vid(struct pmbus_data *data,
                               struct pmbus_sensor *sensor)
 {
        long val = sensor->data;
+       long rv = 0;
 
-       if (val < 0x02 || val > 0xb2)
-               return 0;
-       return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
+       switch (data->info->vrm_version) {
+       case vr11:
+               if (val >= 0x02 && val <= 0xb2)
+                       rv = DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
+               break;
+       case vr12:
+               if (val >= 0x01)
+                       rv = 250 + (val - 1) * 5;
+               break;
+       }
+       return rv;
 }
 
 static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
@@ -1328,6 +1336,10 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
                .reg = PMBUS_VIRT_READ_PIN_AVG,
                .update = true,
                .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_PIN_MIN,
+               .update = true,
+               .attr = "input_lowest",
        }, {
                .reg = PMBUS_VIRT_READ_PIN_MAX,
                .update = true,
@@ -1358,6 +1370,10 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
                .reg = PMBUS_VIRT_READ_POUT_AVG,
                .update = true,
                .attr = "average",
+       }, {
+               .reg = PMBUS_VIRT_READ_POUT_MIN,
+               .update = true,
+               .attr = "input_lowest",
        }, {
                .reg = PMBUS_VIRT_READ_POUT_MAX,
                .update = true,
@@ -1735,6 +1751,11 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
                }
        }
 
+       /* Enable PEC if the controller supports it */
+       ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
+       if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
+               client->flags |= I2C_CLIENT_PEC;
+
        pmbus_clear_faults(client);
 
        if (info->identify) {
@@ -1796,7 +1817,7 @@ static int pmbus_regulator_disable(struct regulator_dev *rdev)
        return _pmbus_regulator_on_off(rdev, 0);
 }
 
-struct regulator_ops pmbus_regulator_ops = {
+const struct regulator_ops pmbus_regulator_ops = {
        .enable = pmbus_regulator_enable,
        .disable = pmbus_regulator_disable,
        .is_enabled = pmbus_regulator_is_enabled,
index 8196441212592d14a6cd49cacc041443918321c9..771802d7e20dba19d62e9ebe2299c4ce5d02ba4c 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -44,16 +45,16 @@ struct zl6100_data {
 #define ZL6100_MFR_CONFIG              0xd0
 #define ZL6100_DEVICE_ID               0xe4
 
-#define ZL6100_MFR_XTEMP_ENABLE                (1 << 7)
+#define ZL6100_MFR_XTEMP_ENABLE                BIT(7)
 
 #define MFR_VMON_OV_FAULT_LIMIT                0xf5
 #define MFR_VMON_UV_FAULT_LIMIT                0xf6
 #define MFR_READ_VMON                  0xf7
 
-#define VMON_UV_WARNING                        (1 << 5)
-#define VMON_OV_WARNING                        (1 << 4)
-#define VMON_UV_FAULT                  (1 << 1)
-#define VMON_OV_FAULT                  (1 << 0)
+#define VMON_UV_WARNING                        BIT(5)
+#define VMON_OV_WARNING                        BIT(4)
+#define VMON_UV_FAULT                  BIT(1)
+#define VMON_OV_FAULT                  BIT(0)
 
 #define ZL6100_WAIT_TIME               1000    /* uS   */
 
index 497a7f822a12c661aeaac71790ec3bd33f2cef54..a2fdbb7d20edcc92f9a1307f4f7105475b41e7ca 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
+#include <linux/bitrev.h>
 
 /* Commands */
 #define SHT15_MEASURE_TEMP             0x03
@@ -172,19 +173,6 @@ struct sht15_data {
        atomic_t                        interrupt_handled;
 };
 
-/**
- * sht15_reverse() - reverse a byte
- * @byte:    byte to reverse.
- */
-static u8 sht15_reverse(u8 byte)
-{
-       u8 i, c;
-
-       for (c = 0, i = 0; i < 8; i++)
-               c |= (!!(byte & (1 << i))) << (7 - i);
-       return c;
-}
-
 /**
  * sht15_crc8() - compute crc8
  * @data:      sht15 specific data.
@@ -196,7 +184,7 @@ static u8 sht15_crc8(struct sht15_data *data,
                const u8 *value,
                int len)
 {
-       u8 crc = sht15_reverse(data->val_status & 0x0F);
+       u8 crc = bitrev8(data->val_status & 0x0F);
 
        while (len--) {
                crc = sht15_crc8_table[*value ^ crc];
@@ -477,7 +465,7 @@ static int sht15_update_status(struct sht15_data *data)
 
                if (data->checksumming) {
                        sht15_ack(data);
-                       dev_checksum = sht15_reverse(sht15_read_byte(data));
+                       dev_checksum = bitrev8(sht15_read_byte(data));
                        checksum_vals[0] = SHT15_READ_STATUS;
                        checksum_vals[1] = status;
                        data->checksum_ok = (sht15_crc8(data, checksum_vals, 2)
@@ -864,7 +852,7 @@ static void sht15_bh_read_data(struct work_struct *work_s)
                 */
                if (sht15_ack(data))
                        goto wakeup;
-               dev_checksum = sht15_reverse(sht15_read_byte(data));
+               dev_checksum = bitrev8(sht15_read_byte(data));
                checksum_vals[0] = (data->state == SHT15_READING_TEMP) ?
                        SHT15_MEASURE_TEMP : SHT15_MEASURE_RH;
                checksum_vals[1] = (u8) (val >> 8);
index 098ffbec0a44229c976f2cbfb86377c4a15245ea..b4481eb29304a1ddf4a2b5a86d9244daa3c05f14 100644 (file)
  * @seq_13_event: event causing the transition from 1 to 3.
  * @seq_curr_state: current value of the sequencer register.
  * @ctxid_idx: index for the context ID registers.
- * @ctxid_val: value for the context ID to trigger on.
+ * @ctxid_pid: value for the context ID to trigger on.
+ * @ctxid_vpid:        Virtual PID seen by users if PID namespace is enabled, otherwise
+ *             the same value of ctxid_pid.
  * @ctxid_mask: mask applicable to all the context IDs.
  * @sync_freq: Synchronisation frequency.
  * @timestamp_event: Defines an event that requests the insertion
@@ -235,7 +237,8 @@ struct etm_drvdata {
        u32                             seq_13_event;
        u32                             seq_curr_state;
        u8                              ctxid_idx;
-       u32                             ctxid_val[ETM_MAX_CTXID_CMP];
+       u32                             ctxid_pid[ETM_MAX_CTXID_CMP];
+       u32                             ctxid_vpid[ETM_MAX_CTXID_CMP];
        u32                             ctxid_mask;
        u32                             sync_freq;
        u32                             timestamp_event;
index 018a00fda611b391699b9c6c334cfa4b3094b0ac..bf2476ed9356a7a2ec0b31a4a36e08a427aa121e 100644 (file)
@@ -237,8 +237,11 @@ static void etm_set_default(struct etm_drvdata *drvdata)
 
        drvdata->seq_curr_state = 0x0;
        drvdata->ctxid_idx = 0x0;
-       for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
-               drvdata->ctxid_val[i] = 0x0;
+       for (i = 0; i < drvdata->nr_ctxid_cmp; i++) {
+               drvdata->ctxid_pid[i] = 0x0;
+               drvdata->ctxid_vpid[i] = 0x0;
+       }
+
        drvdata->ctxid_mask = 0x0;
 }
 
@@ -289,7 +292,7 @@ static void etm_enable_hw(void *info)
        for (i = 0; i < drvdata->nr_ext_out; i++)
                etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i));
        for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
-               etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
+               etm_writel(drvdata, drvdata->ctxid_pid[i], ETMCIDCVRn(i));
        etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
        etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
        /* No external input selected */
@@ -1386,38 +1389,41 @@ static ssize_t ctxid_idx_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(ctxid_idx);
 
-static ssize_t ctxid_val_show(struct device *dev,
+static ssize_t ctxid_pid_show(struct device *dev,
                              struct device_attribute *attr, char *buf)
 {
        unsigned long val;
        struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
        spin_lock(&drvdata->spinlock);
-       val = drvdata->ctxid_val[drvdata->ctxid_idx];
+       val = drvdata->ctxid_vpid[drvdata->ctxid_idx];
        spin_unlock(&drvdata->spinlock);
 
        return sprintf(buf, "%#lx\n", val);
 }
 
-static ssize_t ctxid_val_store(struct device *dev,
+static ssize_t ctxid_pid_store(struct device *dev,
                               struct device_attribute *attr,
                               const char *buf, size_t size)
 {
        int ret;
-       unsigned long val;
+       unsigned long vpid, pid;
        struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
-       ret = kstrtoul(buf, 16, &val);
+       ret = kstrtoul(buf, 16, &vpid);
        if (ret)
                return ret;
 
+       pid = coresight_vpid_to_pid(vpid);
+
        spin_lock(&drvdata->spinlock);
-       drvdata->ctxid_val[drvdata->ctxid_idx] = val;
+       drvdata->ctxid_pid[drvdata->ctxid_idx] = pid;
+       drvdata->ctxid_vpid[drvdata->ctxid_idx] = vpid;
        spin_unlock(&drvdata->spinlock);
 
        return size;
 }
-static DEVICE_ATTR_RW(ctxid_val);
+static DEVICE_ATTR_RW(ctxid_pid);
 
 static ssize_t ctxid_mask_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
@@ -1609,7 +1615,7 @@ static struct attribute *coresight_etm_attrs[] = {
        &dev_attr_seq_13_event.attr,
        &dev_attr_seq_curr_state.attr,
        &dev_attr_ctxid_idx.attr,
-       &dev_attr_ctxid_val.attr,
+       &dev_attr_ctxid_pid.attr,
        &dev_attr_ctxid_mask.attr,
        &dev_attr_sync_freq.attr,
        &dev_attr_timestamp_event.attr,
@@ -1912,6 +1918,11 @@ static struct amba_id etm_ids[] = {
                .mask   = 0x0003ffff,
                .data   = "PTM 1.1",
        },
+       {       /* PTM 1.1 Qualcomm */
+               .id     = 0x0003006f,
+               .mask   = 0x0003ffff,
+               .data   = "PTM 1.1",
+       },
        { 0, 0},
 };
 
index 1312e993c5017b6f28d87197f9201479af1eb877..254a81a4e6f4e5293b6b97891c070a39b0ff09ae 100644 (file)
@@ -155,7 +155,7 @@ static void etm4_enable_hw(void *info)
                               drvdata->base + TRCACATRn(i));
        }
        for (i = 0; i < drvdata->numcidc; i++)
-               writeq_relaxed(drvdata->ctxid_val[i],
+               writeq_relaxed(drvdata->ctxid_pid[i],
                               drvdata->base + TRCCIDCVRn(i));
        writel_relaxed(drvdata->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
        writel_relaxed(drvdata->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
@@ -506,8 +506,11 @@ static ssize_t reset_store(struct device *dev,
        }
 
        drvdata->ctxid_idx = 0x0;
-       for (i = 0; i < drvdata->numcidc; i++)
-               drvdata->ctxid_val[i] = 0x0;
+       for (i = 0; i < drvdata->numcidc; i++) {
+               drvdata->ctxid_pid[i] = 0x0;
+               drvdata->ctxid_vpid[i] = 0x0;
+       }
+
        drvdata->ctxid_mask0 = 0x0;
        drvdata->ctxid_mask1 = 0x0;
 
@@ -1815,7 +1818,7 @@ static ssize_t ctxid_idx_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(ctxid_idx);
 
-static ssize_t ctxid_val_show(struct device *dev,
+static ssize_t ctxid_pid_show(struct device *dev,
                              struct device_attribute *attr,
                              char *buf)
 {
@@ -1825,17 +1828,17 @@ static ssize_t ctxid_val_show(struct device *dev,
 
        spin_lock(&drvdata->spinlock);
        idx = drvdata->ctxid_idx;
-       val = (unsigned long)drvdata->ctxid_val[idx];
+       val = (unsigned long)drvdata->ctxid_vpid[idx];
        spin_unlock(&drvdata->spinlock);
        return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
-static ssize_t ctxid_val_store(struct device *dev,
+static ssize_t ctxid_pid_store(struct device *dev,
                               struct device_attribute *attr,
                               const char *buf, size_t size)
 {
        u8 idx;
-       unsigned long val;
+       unsigned long vpid, pid;
        struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
        /*
@@ -1845,16 +1848,19 @@ static ssize_t ctxid_val_store(struct device *dev,
         */
        if (!drvdata->ctxid_size || !drvdata->numcidc)
                return -EINVAL;
-       if (kstrtoul(buf, 16, &val))
+       if (kstrtoul(buf, 16, &vpid))
                return -EINVAL;
 
+       pid = coresight_vpid_to_pid(vpid);
+
        spin_lock(&drvdata->spinlock);
        idx = drvdata->ctxid_idx;
-       drvdata->ctxid_val[idx] = (u64)val;
+       drvdata->ctxid_pid[idx] = (u64)pid;
+       drvdata->ctxid_vpid[idx] = (u64)vpid;
        spin_unlock(&drvdata->spinlock);
        return size;
 }
-static DEVICE_ATTR_RW(ctxid_val);
+static DEVICE_ATTR_RW(ctxid_pid);
 
 static ssize_t ctxid_masks_show(struct device *dev,
                                struct device_attribute *attr,
@@ -1949,7 +1955,7 @@ static ssize_t ctxid_masks_store(struct device *dev,
                 */
                for (j = 0; j < 8; j++) {
                        if (maskbyte & 1)
-                               drvdata->ctxid_val[i] &= ~(0xFF << (j * 8));
+                               drvdata->ctxid_pid[i] &= ~(0xFF << (j * 8));
                        maskbyte >>= 1;
                }
                /* Select the next ctxid comparator mask value */
@@ -2193,7 +2199,7 @@ static struct attribute *coresight_etmv4_attrs[] = {
        &dev_attr_res_idx.attr,
        &dev_attr_res_ctrl.attr,
        &dev_attr_ctxid_idx.attr,
-       &dev_attr_ctxid_val.attr,
+       &dev_attr_ctxid_pid.attr,
        &dev_attr_ctxid_masks.attr,
        &dev_attr_vmid_idx.attr,
        &dev_attr_vmid_val.attr,
@@ -2513,8 +2519,11 @@ static void etm4_init_default_data(struct etmv4_drvdata *drvdata)
                drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
        }
 
-       for (i = 0; i < drvdata->numcidc; i++)
-               drvdata->ctxid_val[i] = 0x0;
+       for (i = 0; i < drvdata->numcidc; i++) {
+               drvdata->ctxid_pid[i] = 0x0;
+               drvdata->ctxid_vpid[i] = 0x0;
+       }
+
        drvdata->ctxid_mask0 = 0x0;
        drvdata->ctxid_mask1 = 0x0;
 
index e08e983dd2d9968bcec20ef4e806bfd9d4fd6f2e..c34100205ca948681c62cd45411623f8c5cba4a6 100644 (file)
  * @addr_type: Current status of the comparator register.
  * @ctxid_idx: Context ID index selector.
  * @ctxid_size:        Size of the context ID field to consider.
- * @ctxid_val: Value of the context ID comparator.
+ * @ctxid_pid: Value of the context ID comparator.
+ * @ctxid_vpid:        Virtual PID seen by users if PID namespace is enabled, otherwise
+ *             the same value of ctxid_pid.
  * @ctxid_mask0:Context ID comparator mask for comparator 0-3.
  * @ctxid_mask1:Context ID comparator mask for comparator 4-7.
  * @vmid_idx:  VM ID index selector.
@@ -352,7 +354,8 @@ struct etmv4_drvdata {
        u8                              addr_type[ETM_MAX_SINGLE_ADDR_CMP];
        u8                              ctxid_idx;
        u8                              ctxid_size;
-       u64                             ctxid_val[ETMv4_MAX_CTXID_CMP];
+       u64                             ctxid_pid[ETMv4_MAX_CTXID_CMP];
+       u64                             ctxid_vpid[ETMv4_MAX_CTXID_CMP];
        u32                             ctxid_mask0;
        u32                             ctxid_mask1;
        u8                              vmid_idx;
index 7974b7c3da6b6c790b2c94b98159880c32b59fd3..963ac197c2535caf202960af34490e6abd02d4cb 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -184,17 +183,7 @@ static struct platform_driver replicator_driver = {
        },
 };
 
-static int __init replicator_init(void)
-{
-       return platform_driver_register(&replicator_driver);
-}
-module_init(replicator_init);
-
-static void __exit replicator_exit(void)
-{
-       platform_driver_unregister(&replicator_driver);
-}
-module_exit(replicator_exit);
+builtin_platform_driver(replicator_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("CoreSight Replicator driver");
index 00e7bcbdbe2474948b9c5ccbdbd9edca7b09fcc6..a59047d7657eb414999d1f9081d914073a645f19 100644 (file)
@@ -86,18 +86,6 @@ config KXSD9
          To compile this driver as a module, choose M here: the module
          will be called kxsd9.
 
-config MMA8452
-       tristate "Freescale MMA8452Q Accelerometer Driver"
-       depends on I2C
-       select IIO_BUFFER
-       select IIO_TRIGGERED_BUFFER
-       help
-         Say yes here to build support for the Freescale MMA8452Q 3-axis
-         accelerometer.
-
-         To compile this driver as a module, choose M here: the module
-         will be called mma8452.
-
 config KXCJK1013
        tristate "Kionix 3-Axis Accelerometer Driver"
        depends on I2C
@@ -111,6 +99,18 @@ config KXCJK1013
          To compile this driver as a module, choose M here: the module will
          be called kxcjk-1013.
 
+config MMA8452
+       tristate "Freescale MMA8452Q Accelerometer Driver"
+       depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         Say yes here to build support for the Freescale MMA8452Q 3-axis
+         accelerometer.
+
+         To compile this driver as a module, choose M here: the module
+         will be called mma8452.
+
 config MMA9551_CORE
        tristate
 
@@ -140,6 +140,8 @@ config MMA9553
 config STK8312
        tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
        depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          Say yes here to get support for the Sensortek STK8312 3-axis
          accelerometer.
index 75c6d2103e07adad3b11919687e81f8dd7a8fca3..f04b88406995175bc5159a8f300295e33ec3df80 100644 (file)
@@ -846,7 +846,6 @@ MODULE_DEVICE_TABLE(i2c, bma180_ids);
 static struct i2c_driver bma180_driver = {
        .driver = {
                .name   = "bma180",
-               .owner  = THIS_MODULE,
                .pm     = BMA180_PM_OPS,
        },
        .probe          = bma180_probe,
index cc5a35750b507359f6496c980d30bdb7027ded76..0104cdef8709b0dd05be6a337f2396a80629816a 100644 (file)
@@ -151,6 +151,7 @@ struct bmc150_scale_info {
 };
 
 struct bmc150_accel_chip_info {
+       const char *name;
        u8 chip_id;
        const struct iio_chan_spec *channels;
        int num_channels;
@@ -241,7 +242,6 @@ static const struct {
                                       {500000, BMC150_ACCEL_SLEEP_500_MS},
                                       {1000000, BMC150_ACCEL_SLEEP_1_SEC} };
 
-
 static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
                                 enum bmc150_power_modes mode,
                                 int dur_us)
@@ -259,8 +259,9 @@ static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
                                dur_val =
                                bmc150_accel_sleep_value_table[i].reg_value;
                }
-       } else
+       } else {
                dur_val = 0;
+       }
 
        if (dur_val < 0)
                return -EINVAL;
@@ -288,7 +289,7 @@ static int bmc150_accel_set_bw(struct bmc150_accel_data *data, int val,
 
        for (i = 0; i < ARRAY_SIZE(bmc150_accel_samp_freq_table); ++i) {
                if (bmc150_accel_samp_freq_table[i].val == val &&
-                               bmc150_accel_samp_freq_table[i].val2 == val2) {
+                   bmc150_accel_samp_freq_table[i].val2 == val2) {
                        ret = i2c_smbus_write_byte_data(
                                data->client,
                                BMC150_ACCEL_REG_PMU_BW,
@@ -345,65 +346,6 @@ static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
        return 0;
 }
 
-static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
-{
-       int ret;
-
-       ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
-       if (ret < 0) {
-               dev_err(&data->client->dev,
-                       "Error: Reading chip id\n");
-               return ret;
-       }
-
-       dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
-       if (ret != data->chip_info->chip_id) {
-               dev_err(&data->client->dev, "Invalid chip %x\n", ret);
-               return -ENODEV;
-       }
-
-       ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
-       if (ret < 0)
-               return ret;
-
-       /* Set Bandwidth */
-       ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
-       if (ret < 0)
-               return ret;
-
-       /* Set Default Range */
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_PMU_RANGE,
-                                       BMC150_ACCEL_DEF_RANGE_4G);
-       if (ret < 0) {
-               dev_err(&data->client->dev,
-                                       "Error writing reg_pmu_range\n");
-               return ret;
-       }
-
-       data->range = BMC150_ACCEL_DEF_RANGE_4G;
-
-       /* Set default slope duration and thresholds */
-       data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
-       data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
-       ret = bmc150_accel_update_slope(data);
-       if (ret < 0)
-               return ret;
-
-       /* Set default as latched interrupts */
-       ret = i2c_smbus_write_byte_data(data->client,
-                                       BMC150_ACCEL_REG_INT_RST_LATCH,
-                                       BMC150_ACCEL_INT_MODE_LATCH_INT |
-                                       BMC150_ACCEL_INT_MODE_LATCH_RESET);
-       if (ret < 0) {
-               dev_err(&data->client->dev,
-                       "Error writing reg_int_rst_latch\n");
-               return ret;
-       }
-
-       return 0;
-}
-
 static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
                               int *val2)
 {
@@ -437,12 +379,13 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
 {
        int ret;
 
-       if (on)
+       if (on) {
                ret = pm_runtime_get_sync(&data->client->dev);
-       else {
+       else {
                pm_runtime_mark_last_busy(&data->client->dev);
                ret = pm_runtime_put_autosuspend(&data->client->dev);
        }
+
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "Failed: bmc150_accel_set_power_state for %d\n", on);
@@ -514,13 +457,13 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
        }
 
        /*
-        * We will expect the enable and disable to do operation in
-        * in reverse order. This will happen here anyway as our
-        * resume operation uses sync mode runtime pm calls, the
-        * suspend operation will be delayed by autosuspend delay
-        * So the disable operation will still happen in reverse of
-        * enable operation. When runtime pm is disabled the mode
-        * is always on so sequence doesn't matter
+        * We will expect the enable and disable to do operation in reverse
+        * order. This will happen here anyway, as our resume operation uses
+        * sync mode runtime pm calls. The suspend operation will be delayed
+        * by autosuspend delay.
+        * So the disable operation will still happen in reverse order of
+        * enable operation. When runtime pm is disabled the mode is always on,
+        * so sequence doesn't matter.
         */
        ret = bmc150_accel_set_power_state(data, state);
        if (ret < 0)
@@ -574,7 +517,6 @@ out_fix_power_state:
        return ret;
 }
 
-
 static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
 {
        int ret, i;
@@ -674,8 +616,9 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
                if (chan->type == IIO_TEMP) {
                        *val = BMC150_ACCEL_TEMP_CENTER_VAL;
                        return IIO_VAL_INT;
-               } else
+               } else {
                        return -EINVAL;
+               }
        case IIO_CHAN_INFO_SCALE:
                *val = 0;
                switch (chan->type) {
@@ -776,7 +719,7 @@ static int bmc150_accel_write_event(struct iio_dev *indio_dev,
 
        switch (info) {
        case IIO_EV_INFO_VALUE:
-               data->slope_thres = val & 0xFF;
+               data->slope_thres = val & BMC150_ACCEL_SLOPE_THRES_MASK;
                break;
        case IIO_EV_INFO_PERIOD:
                data->slope_dur = val & BMC150_ACCEL_SLOPE_DUR_MASK;
@@ -793,7 +736,6 @@ static int bmc150_accel_read_event_config(struct iio_dev *indio_dev,
                                          enum iio_event_type type,
                                          enum iio_event_direction dir)
 {
-
        struct bmc150_accel_data *data = iio_priv(indio_dev);
 
        return data->ev_enable_state;
@@ -827,7 +769,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
 }
 
 static int bmc150_accel_validate_trigger(struct iio_dev *indio_dev,
-                                  struct iio_trigger *trig)
+                                        struct iio_trigger *trig)
 {
        struct bmc150_accel_data *data = iio_priv(indio_dev);
        int i;
@@ -963,6 +905,7 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
        u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
        int64_t tstamp;
        uint64_t sample_period;
+
        ret = i2c_smbus_read_byte_data(data->client,
                                       BMC150_ACCEL_REG_FIFO_STATUS);
        if (ret < 0) {
@@ -1120,6 +1063,7 @@ enum {
 
 static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
        [bmc150] = {
+               .name = "BMC150A",
                .chip_id = 0xFA,
                .channels = bmc150_accel_channels,
                .num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1129,6 +1073,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
                                 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
        },
        [bmi055] = {
+               .name = "BMI055A",
                .chip_id = 0xFA,
                .channels = bmc150_accel_channels,
                .num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1138,6 +1083,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
                                 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
        },
        [bma255] = {
+               .name = "BMA0255",
                .chip_id = 0xFA,
                .channels = bmc150_accel_channels,
                .num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1147,6 +1093,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
                                 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
        },
        [bma250e] = {
+               .name = "BMA250E",
                .chip_id = 0xF9,
                .channels = bma250e_accel_channels,
                .num_channels = ARRAY_SIZE(bma250e_accel_channels),
@@ -1156,6 +1103,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
                                 {306457, BMC150_ACCEL_DEF_RANGE_16G} },
        },
        [bma222e] = {
+               .name = "BMA222E",
                .chip_id = 0xF8,
                .channels = bma222e_accel_channels,
                .num_channels = ARRAY_SIZE(bma222e_accel_channels),
@@ -1165,6 +1113,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
                                 {1225831, BMC150_ACCEL_DEF_RANGE_16G} },
        },
        [bma280] = {
+               .name = "BMA0280",
                .chip_id = 0xFB,
                .channels = bma280_accel_channels,
                .num_channels = ARRAY_SIZE(bma280_accel_channels),
@@ -1255,7 +1204,7 @@ static int bmc150_accel_trig_try_reen(struct iio_trigger *trig)
 }
 
 static int bmc150_accel_trigger_set_state(struct iio_trigger *trig,
-                                                  bool state)
+                                         bool state)
 {
        struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig);
        struct bmc150_accel_data *data = t->data;
@@ -1314,26 +1263,32 @@ static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
                dir = IIO_EV_DIR_RISING;
 
        if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
-               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
-                                                       0,
-                                                       IIO_MOD_X,
-                                                       IIO_EV_TYPE_ROC,
-                                                       dir),
-                                                       data->timestamp);
+               iio_push_event(indio_dev,
+                              IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                 0,
+                                                 IIO_MOD_X,
+                                                 IIO_EV_TYPE_ROC,
+                                                 dir),
+                              data->timestamp);
+
        if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
-               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
-                                                       0,
-                                                       IIO_MOD_Y,
-                                                       IIO_EV_TYPE_ROC,
-                                                       dir),
-                                                       data->timestamp);
+               iio_push_event(indio_dev,
+                              IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                 0,
+                                                 IIO_MOD_Y,
+                                                 IIO_EV_TYPE_ROC,
+                                                 dir),
+                              data->timestamp);
+
        if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
-               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
-                                                       0,
-                                                       IIO_MOD_Z,
-                                                       IIO_EV_TYPE_ROC,
-                                                       dir),
-                                                       data->timestamp);
+               iio_push_event(indio_dev,
+                              IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                 0,
+                                                 IIO_MOD_Z,
+                                                 IIO_EV_TYPE_ROC,
+                                                 dir),
+                              data->timestamp);
+
        return ret;
 }
 
@@ -1365,7 +1320,9 @@ static irqreturn_t bmc150_accel_irq_thread_handler(int irq, void *private)
                                        BMC150_ACCEL_INT_MODE_LATCH_INT |
                                        BMC150_ACCEL_INT_MODE_LATCH_RESET);
                if (ret)
-                       dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
+                       dev_err(&data->client->dev,
+                               "Error writing reg_int_rst_latch\n");
+
                ret = IRQ_HANDLED;
        } else {
                ret = IRQ_NONE;
@@ -1403,22 +1360,8 @@ static irqreturn_t bmc150_accel_irq_handler(int irq, void *private)
        return IRQ_NONE;
 }
 
-static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
-{
-       const struct acpi_device_id *id;
-
-       id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
-       if (!id)
-               return NULL;
-
-       *data = (int) id->driver_data;
-
-       return dev_name(dev);
-}
-
 static int bmc150_accel_gpio_probe(struct i2c_client *client,
-                                       struct bmc150_accel_data *data)
+                                  struct bmc150_accel_data *data)
 {
        struct device *dev;
        struct gpio_desc *gpio;
@@ -1611,6 +1554,70 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
        .postdisable = bmc150_accel_buffer_postdisable,
 };
 
+static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
+{
+       int ret, i;
+
+       ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error: Reading chip id\n");
+               return ret;
+       }
+
+       dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
+       for (i = 0; i < ARRAY_SIZE(bmc150_accel_chip_info_tbl); i++) {
+               if (bmc150_accel_chip_info_tbl[i].chip_id == ret) {
+                       data->chip_info = &bmc150_accel_chip_info_tbl[i];
+                       break;
+               }
+       }
+
+       if (!data->chip_info) {
+               dev_err(&data->client->dev, "Unsupported chip %x\n", ret);
+               return -ENODEV;
+       }
+
+       ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Set Bandwidth */
+       ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Set Default Range */
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       BMC150_ACCEL_REG_PMU_RANGE,
+                                       BMC150_ACCEL_DEF_RANGE_4G);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_pmu_range\n");
+               return ret;
+       }
+
+       data->range = BMC150_ACCEL_DEF_RANGE_4G;
+
+       /* Set default slope duration and thresholds */
+       data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
+       data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
+       ret = bmc150_accel_update_slope(data);
+       if (ret < 0)
+               return ret;
+
+       /* Set default as latched interrupts */
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       BMC150_ACCEL_REG_INT_RST_LATCH,
+                                       BMC150_ACCEL_INT_MODE_LATCH_INT |
+                                       BMC150_ACCEL_INT_MODE_LATCH_RESET);
+       if (ret < 0) {
+               dev_err(&data->client->dev,
+                       "Error writing reg_int_rst_latch\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static int bmc150_accel_probe(struct i2c_client *client,
                              const struct i2c_device_id *id)
 {
@@ -1618,7 +1625,6 @@ static int bmc150_accel_probe(struct i2c_client *client,
        struct iio_dev *indio_dev;
        int ret;
        const char *name = NULL;
-       int chip_id = 0;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
@@ -1628,15 +1634,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       if (id) {
+       if (id)
                name = id->name;
-               chip_id = id->driver_data;
-       }
-
-       if (ACPI_HANDLE(&client->dev))
-               name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
-
-       data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
 
        ret = bmc150_accel_chip_init(data);
        if (ret < 0)
@@ -1647,7 +1646,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
        indio_dev->dev.parent = &client->dev;
        indio_dev->channels = data->chip_info->channels;
        indio_dev->num_channels = data->chip_info->num_channels;
-       indio_dev->name = name;
+       indio_dev->name = name ? name : data->chip_info->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &bmc150_accel_info;
 
@@ -1663,7 +1662,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
        if (client->irq < 0)
                client->irq = bmc150_accel_gpio_probe(client, data);
 
-       if (client->irq >= 0) {
+       if (client->irq > 0) {
                ret = devm_request_threaded_irq(
                                                &client->dev, client->irq,
                                                bmc150_accel_irq_handler,
index 0d9bd35ff2586bfe4c5d8c776e7196d62a85c474..3292bc0c1d0ef9ea7595c1a4e02effa2dc5c3248 100644 (file)
@@ -658,10 +658,8 @@ static int kxcjk1013_set_scale(struct kxcjk1013_data *data, int val)
        int ret, i;
        enum kxcjk1013_mode store_mode;
 
-
        for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) {
                if (KXCJK1013_scale_table[i].scale == val) {
-
                        ret = kxcjk1013_get_mode(data, &store_mode);
                        if (ret < 0)
                                return ret;
@@ -820,7 +818,6 @@ static int kxcjk1013_read_event_config(struct iio_dev *indio_dev,
                                          enum iio_event_type type,
                                          enum iio_event_direction dir)
 {
-
        struct kxcjk1013_data *data = iio_priv(indio_dev);
 
        return data->ev_enable_state;
@@ -1243,7 +1240,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
        if (client->irq < 0)
                client->irq = kxcjk1013_gpio_probe(client, data);
 
-       if (client->irq >= 0) {
+       if (client->irq > 0) {
                ret = devm_request_threaded_irq(&client->dev, client->irq,
                                                kxcjk1013_data_rdy_trig_poll,
                                                kxcjk1013_event_handler,
index 13ea1ea23328501f4969c5453e603cf67e5b81b2..b921d84c1be6214097c80e91ccdaacc54963034c 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
-#include <linux/iio/trigger_consumer.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/events.h>
 #include <linux/delay.h>
 
-#define MMA8452_STATUS 0x00
-#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit  */
-#define MMA8452_OUT_Y 0x03
-#define MMA8452_OUT_Z 0x05
-#define MMA8452_INT_SRC 0x0c
-#define MMA8452_WHO_AM_I 0x0d
-#define MMA8452_DATA_CFG 0x0e
-#define MMA8452_HP_FILTER_CUTOFF 0x0f
-#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK      (BIT(0) | BIT(1))
-#define MMA8452_TRANSIENT_CFG 0x1d
-#define MMA8452_TRANSIENT_CFG_ELE              BIT(4)
-#define MMA8452_TRANSIENT_CFG_CHAN(chan)       BIT(chan + 1)
-#define MMA8452_TRANSIENT_CFG_HPF_BYP          BIT(0)
-#define MMA8452_TRANSIENT_SRC 0x1e
-#define MMA8452_TRANSIENT_SRC_XTRANSE          BIT(1)
-#define MMA8452_TRANSIENT_SRC_YTRANSE          BIT(3)
-#define MMA8452_TRANSIENT_SRC_ZTRANSE          BIT(5)
-#define MMA8452_TRANSIENT_THS 0x1f
-#define MMA8452_TRANSIENT_THS_MASK     0x7f
-#define MMA8452_TRANSIENT_COUNT 0x20
-#define MMA8452_OFF_X 0x2f
-#define MMA8452_OFF_Y 0x30
-#define MMA8452_OFF_Z 0x31
-#define MMA8452_CTRL_REG1 0x2a
-#define MMA8452_CTRL_REG2 0x2b
-#define MMA8452_CTRL_REG2_RST          BIT(6)
-#define MMA8452_CTRL_REG4 0x2d
-#define MMA8452_CTRL_REG5 0x2e
-
-#define MMA8452_MAX_REG 0x31
-
-#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
-
-#define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3))
-#define MMA8452_CTRL_DR_SHIFT 3
-#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
-#define MMA8452_CTRL_ACTIVE BIT(0)
-
-#define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0))
-#define MMA8452_DATA_CFG_FS_2G 0
-#define MMA8452_DATA_CFG_FS_4G 1
-#define MMA8452_DATA_CFG_FS_8G 2
-#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
-
-#define MMA8452_INT_DRDY       BIT(0)
-#define MMA8452_INT_TRANS      BIT(5)
-
-#define MMA8452_DEVICE_ID 0x2a
+#define MMA8452_STATUS                         0x00
+#define  MMA8452_STATUS_DRDY                   (BIT(2) | BIT(1) | BIT(0))
+#define MMA8452_OUT_X                          0x01 /* MSB first, 12-bit  */
+#define MMA8452_OUT_Y                          0x03
+#define MMA8452_OUT_Z                          0x05
+#define MMA8452_INT_SRC                                0x0c
+#define MMA8452_WHO_AM_I                       0x0d
+#define MMA8452_DATA_CFG                       0x0e
+#define  MMA8452_DATA_CFG_FS_MASK              GENMASK(1, 0)
+#define  MMA8452_DATA_CFG_FS_2G                        0
+#define  MMA8452_DATA_CFG_FS_4G                        1
+#define  MMA8452_DATA_CFG_FS_8G                        2
+#define  MMA8452_DATA_CFG_HPF_MASK             BIT(4)
+#define MMA8452_HP_FILTER_CUTOFF               0x0f
+#define  MMA8452_HP_FILTER_CUTOFF_SEL_MASK     GENMASK(1, 0)
+#define MMA8452_TRANSIENT_CFG                  0x1d
+#define  MMA8452_TRANSIENT_CFG_HPF_BYP         BIT(0)
+#define  MMA8452_TRANSIENT_CFG_CHAN(chan)      BIT(chan + 1)
+#define  MMA8452_TRANSIENT_CFG_ELE             BIT(4)
+#define MMA8452_TRANSIENT_SRC                  0x1e
+#define  MMA8452_TRANSIENT_SRC_XTRANSE         BIT(1)
+#define  MMA8452_TRANSIENT_SRC_YTRANSE         BIT(3)
+#define  MMA8452_TRANSIENT_SRC_ZTRANSE         BIT(5)
+#define MMA8452_TRANSIENT_THS                  0x1f
+#define  MMA8452_TRANSIENT_THS_MASK            GENMASK(6, 0)
+#define MMA8452_TRANSIENT_COUNT                        0x20
+#define MMA8452_CTRL_REG1                      0x2a
+#define  MMA8452_CTRL_ACTIVE                   BIT(0)
+#define  MMA8452_CTRL_DR_MASK                  GENMASK(5, 3)
+#define  MMA8452_CTRL_DR_SHIFT                 3
+#define  MMA8452_CTRL_DR_DEFAULT               0x4 /* 50 Hz sample frequency */
+#define MMA8452_CTRL_REG2                      0x2b
+#define  MMA8452_CTRL_REG2_RST                 BIT(6)
+#define MMA8452_CTRL_REG4                      0x2d
+#define MMA8452_CTRL_REG5                      0x2e
+#define MMA8452_OFF_X                          0x2f
+#define MMA8452_OFF_Y                          0x30
+#define MMA8452_OFF_Z                          0x31
+
+#define MMA8452_MAX_REG                                0x31
+
+#define  MMA8452_INT_DRDY                      BIT(0)
+#define  MMA8452_INT_TRANS                     BIT(5)
+
+#define  MMA8452_DEVICE_ID                     0x2a
 
 struct mma8452_data {
        struct i2c_client *client;
@@ -91,30 +87,34 @@ static int mma8452_drdy(struct mma8452_data *data)
                        return ret;
                if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY)
                        return 0;
+
                msleep(20);
        }
 
        dev_err(&data->client->dev, "data not ready\n");
+
        return -EIO;
 }
 
 static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
 {
        int ret = mma8452_drdy(data);
+
        if (ret < 0)
                return ret;
-       return i2c_smbus_read_i2c_block_data(data->client,
-               MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
+
+       return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
+                                            3 * sizeof(__be16), (u8 *)buf);
 }
 
-static ssize_t mma8452_show_int_plus_micros(char *buf,
-       const int (*vals)[2], int n)
+static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
+                                           int n)
 {
        size_t len = 0;
 
        while (n-- > 0)
-               len += scnprintf(buf + len, PAGE_SIZE - len,
-                       "%d.%06d ", vals[n][0], vals[n][1]);
+               len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ",
+                                vals[n][0], vals[n][1]);
 
        /* replace trailing space by newline */
        buf[len - 1] = '\n';
@@ -123,7 +123,7 @@ static ssize_t mma8452_show_int_plus_micros(char *buf,
 }
 
 static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n,
-                                       int val, int val2)
+                                            int val, int val2)
 {
        while (n-- > 0)
                if (val == vals[n][0] && val2 == vals[n][1])
@@ -147,7 +147,7 @@ static const int mma8452_samp_freq[8][2] = {
  * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
  * The userspace interface uses m/s^2 and we declare micro units
  * So scale factor is given by:
- *     g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
+ *     g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665
  */
 static const int mma8452_scales[3][2] = {
        {0, 9577}, {0, 19154}, {0, 38307}
@@ -178,17 +178,19 @@ static const int mma8452_hp_filter_cutoff[8][4][2] = {
 };
 
 static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+                                           struct device_attribute *attr,
+                                           char *buf)
 {
        return mma8452_show_int_plus_micros(buf, mma8452_samp_freq,
-               ARRAY_SIZE(mma8452_samp_freq));
+                                           ARRAY_SIZE(mma8452_samp_freq));
 }
 
 static ssize_t mma8452_show_scale_avail(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+                                       struct device_attribute *attr,
+                                       char *buf)
 {
        return mma8452_show_int_plus_micros(buf, mma8452_scales,
-               ARRAY_SIZE(mma8452_scales));
+                                           ARRAY_SIZE(mma8452_scales));
 }
 
 static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
@@ -205,22 +207,23 @@ static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
 
 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
 static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
-       mma8452_show_scale_avail, NULL, 0);
+                      mma8452_show_scale_avail, NULL, 0);
 static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available,
-                       S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
+                      S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
 
 static int mma8452_get_samp_freq_index(struct mma8452_data *data,
-       int val, int val2)
+                                      int val, int val2)
 {
        return mma8452_get_int_plus_micros_index(mma8452_samp_freq,
-               ARRAY_SIZE(mma8452_samp_freq), val, val2);
+                                                ARRAY_SIZE(mma8452_samp_freq),
+                                                val, val2);
 }
 
-static int mma8452_get_scale_index(struct mma8452_data *data,
-       int val, int val2)
+static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
 {
        return mma8452_get_int_plus_micros_index(mma8452_scales,
-               ARRAY_SIZE(mma8452_scales), val, val2);
+                                                ARRAY_SIZE(mma8452_scales),
+                                                val, val2);
 }
 
 static int mma8452_get_hp_filter_index(struct mma8452_data *data,
@@ -229,7 +232,7 @@ static int mma8452_get_hp_filter_index(struct mma8452_data *data,
        int i = mma8452_get_odr_index(data);
 
        return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i],
-               ARRAY_SIZE(mma8452_scales[0]), val, val2);
+               ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2);
 }
 
 static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz)
@@ -266,25 +269,31 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
                mutex_unlock(&data->lock);
                if (ret < 0)
                        return ret;
-               *val = sign_extend32(
-                       be16_to_cpu(buffer[chan->scan_index]) >> 4, 11);
+
+               *val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
+                                    11);
+
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
                i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
                *val = mma8452_scales[i][0];
                *val2 = mma8452_scales[i][1];
+
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_SAMP_FREQ:
                i = mma8452_get_odr_index(data);
                *val = mma8452_samp_freq[i][0];
                *val2 = mma8452_samp_freq[i][1];
+
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_CALIBBIAS:
-               ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X +
-                       chan->scan_index);
+               ret = i2c_smbus_read_byte_data(data->client,
+                                             MMA8452_OFF_X + chan->scan_index);
                if (ret < 0)
                        return ret;
+
                *val = sign_extend32(ret, 7);
+
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
                if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) {
@@ -295,21 +304,23 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
                        *val = 0;
                        *val2 = 0;
                }
+
                return IIO_VAL_INT_PLUS_MICRO;
        }
+
        return -EINVAL;
 }
 
 static int mma8452_standby(struct mma8452_data *data)
 {
        return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
-               data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
+                                       data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
 }
 
 static int mma8452_active(struct mma8452_data *data)
 {
        return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
-               data->ctrl_reg1);
+                                        data->ctrl_reg1);
 }
 
 static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
@@ -334,6 +345,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
        ret = 0;
 fail:
        mutex_unlock(&data->lock);
+
        return ret;
 }
 
@@ -344,12 +356,13 @@ static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
 
        i = mma8452_get_hp_filter_index(data, val, val2);
        if (i < 0)
-               return -EINVAL;
+               return i;
 
        reg = i2c_smbus_read_byte_data(data->client,
                                       MMA8452_HP_FILTER_CUTOFF);
        if (reg < 0)
                return reg;
+
        reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK;
        reg |= i;
 
@@ -370,25 +383,30 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SAMP_FREQ:
                i = mma8452_get_samp_freq_index(data, val, val2);
                if (i < 0)
-                       return -EINVAL;
+                       return i;
 
                data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
                data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
+
                return mma8452_change_config(data, MMA8452_CTRL_REG1,
-                       data->ctrl_reg1);
+                                            data->ctrl_reg1);
        case IIO_CHAN_INFO_SCALE:
                i = mma8452_get_scale_index(data, val, val2);
                if (i < 0)
-                       return -EINVAL;
+                       return i;
+
                data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
                data->data_cfg |= i;
+
                return mma8452_change_config(data, MMA8452_DATA_CFG,
-                       data->data_cfg);
+                                            data->data_cfg);
        case IIO_CHAN_INFO_CALIBBIAS:
                if (val < -128 || val > 127)
                        return -EINVAL;
-               return mma8452_change_config(data, MMA8452_OFF_X +
-                       chan->scan_index, val);
+
+               return mma8452_change_config(data,
+                                            MMA8452_OFF_X + chan->scan_index,
+                                            val);
 
        case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
                if (val == 0 && val2 == 0) {
@@ -399,8 +417,9 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
                        if (ret < 0)
                                return ret;
                }
+
                return mma8452_change_config(data, MMA8452_DATA_CFG,
-                                               data->data_cfg);
+                                            data->data_cfg);
 
        default:
                return -EINVAL;
@@ -425,6 +444,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
                        return ret;
 
                *val = ret & MMA8452_TRANSIENT_THS_MASK;
+
                return IIO_VAL_INT;
 
        case IIO_EV_INFO_PERIOD:
@@ -437,6 +457,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
                                mma8452_get_odr_index(data)];
                *val = us / USEC_PER_SEC;
                *val2 = us % USEC_PER_SEC;
+
                return IIO_VAL_INT_PLUS_MICRO;
 
        case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
@@ -453,6 +474,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
                        if (ret < 0)
                                return ret;
                }
+
                return IIO_VAL_INT_PLUS_MICRO;
 
        default:
@@ -472,19 +494,22 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
 
        switch (info) {
        case IIO_EV_INFO_VALUE:
-               return mma8452_change_config(data, MMA8452_TRANSIENT_THS,
-                                            val & MMA8452_TRANSIENT_THS_MASK);
+               if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
+                       return -EINVAL;
+
+               return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
 
        case IIO_EV_INFO_PERIOD:
                steps = (val * USEC_PER_SEC + val2) /
                                mma8452_transient_time_step_us[
                                        mma8452_get_odr_index(data)];
 
-               if (steps > 0xff)
+               if (steps < 0 || steps > 0xff)
                        return -EINVAL;
 
                return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
                                             steps);
+
        case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
                reg = i2c_smbus_read_byte_data(data->client,
                                               MMA8452_TRANSIENT_CFG);
@@ -499,6 +524,7 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
                        if (ret < 0)
                                return ret;
                }
+
                return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg);
 
        default:
@@ -608,15 +634,16 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
        u8 buffer[16]; /* 3 16-bit channels + padding + ts */
        int ret;
 
-       ret = mma8452_read(data, (__be16 *) buffer);
+       ret = mma8452_read(data, (__be16 *)buffer);
        if (ret < 0)
                goto done;
 
        iio_push_to_buffers_with_timestamp(indio_dev, buffer,
-               iio_get_time_ns());
+                                          iio_get_time_ns());
 
 done:
        iio_trigger_notify_done(indio_dev->trig);
+
        return IRQ_HANDLED;
 }
 
@@ -674,10 +701,10 @@ static struct attribute_group mma8452_event_attribute_group = {
        .modified = 1, \
        .channel2 = IIO_MOD_##axis, \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
-               BIT(IIO_CHAN_INFO_CALIBBIAS), \
+                             BIT(IIO_CHAN_INFO_CALIBBIAS), \
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-               BIT(IIO_CHAN_INFO_SCALE) | \
-               BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
+                       BIT(IIO_CHAN_INFO_SCALE) | \
+                       BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
        .scan_index = idx, \
        .scan_type = { \
                .sign = 's', \
@@ -780,6 +807,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev)
                return ret;
 
        indio_dev->trig = trig;
+
        return 0;
 }
 
@@ -849,7 +877,7 @@ static int mma8452_probe(struct i2c_client *client,
 
        data->data_cfg = MMA8452_DATA_CFG_FS_2G;
        ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
-               data->data_cfg);
+                                       data->data_cfg);
        if (ret < 0)
                return ret;
 
@@ -891,14 +919,14 @@ static int mma8452_probe(struct i2c_client *client,
        }
 
        data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
-               (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
+                         (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
        ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
                                        data->ctrl_reg1);
        if (ret < 0)
                goto trigger_cleanup;
 
        ret = iio_triggered_buffer_setup(indio_dev, NULL,
-               mma8452_trigger_handler, NULL);
+                                        mma8452_trigger_handler, NULL);
        if (ret < 0)
                goto trigger_cleanup;
 
@@ -968,6 +996,7 @@ static const struct of_device_id mma8452_dt_ids[] = {
        { .compatible = "fsl,mma8452" },
        { }
 };
+MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
 
 static struct i2c_driver mma8452_driver = {
        .driver = {
index 2fd2a995686b273dae815f2bdb344c6a10284ea0..c34c5ce8123b0938f14c255a21c636dc09e4c513 100644 (file)
@@ -297,7 +297,7 @@ EXPORT_SYMBOL(mma9551_read_status_byte);
  * Returns: 0 on success, negative value on failure.
  */
 int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
-                           u16 reg, u16 *val)
+                            u16 reg, u16 *val)
 {
        int ret;
        __be16 v;
@@ -328,12 +328,12 @@ EXPORT_SYMBOL(mma9551_read_config_word);
  * Returns: 0 on success, negative value on failure.
  */
 int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
-                            u16 reg, u16 val)
+                             u16 reg, u16 val)
 {
        __be16 v = cpu_to_be16(val);
 
        return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
-                               (u8 *) &v, 2, NULL, 0);
+                               (u8 *)&v, 2, NULL, 0);
 }
 EXPORT_SYMBOL(mma9551_write_config_word);
 
@@ -373,7 +373,7 @@ EXPORT_SYMBOL(mma9551_read_status_word);
  * @client:    I2C client
  * @app_id:    Application ID
  * @reg:       Application register
- * @len:       Length of array to read in bytes
+ * @len:       Length of array to read (in words)
  * @buf:       Array of words to read
  *
  * Read multiple configuration registers (word-sized registers).
@@ -385,23 +385,22 @@ EXPORT_SYMBOL(mma9551_read_status_word);
  * Returns: 0 on success, negative value on failure.
  */
 int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
-                            u16 reg, u8 len, u16 *buf)
+                             u16 reg, u8 len, u16 *buf)
 {
        int ret, i;
-       int len_words = len / sizeof(u16);
        __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
 
-       if (len_words > ARRAY_SIZE(be_buf)) {
+       if (len > ARRAY_SIZE(be_buf)) {
                dev_err(&client->dev, "Invalid buffer size %d\n", len);
                return -EINVAL;
        }
 
        ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
-                              reg, NULL, 0, (u8 *) be_buf, len);
+                              reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < len_words; i++)
+       for (i = 0; i < len; i++)
                buf[i] = be16_to_cpu(be_buf[i]);
 
        return 0;
@@ -413,7 +412,7 @@ EXPORT_SYMBOL(mma9551_read_config_words);
  * @client:    I2C client
  * @app_id:    Application ID
  * @reg:       Application register
- * @len:       Length of array to read in bytes
+ * @len:       Length of array to read (in words)
  * @buf:       Array of words to read
  *
  * Read multiple status registers (word-sized registers).
@@ -428,20 +427,19 @@ int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
                              u16 reg, u8 len, u16 *buf)
 {
        int ret, i;
-       int len_words = len / sizeof(u16);
        __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
 
-       if (len_words > ARRAY_SIZE(be_buf)) {
+       if (len > ARRAY_SIZE(be_buf)) {
                dev_err(&client->dev, "Invalid buffer size %d\n", len);
                return -EINVAL;
        }
 
        ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
-                              reg, NULL, 0, (u8 *) be_buf, len);
+                              reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < len_words; i++)
+       for (i = 0; i < len; i++)
                buf[i] = be16_to_cpu(be_buf[i]);
 
        return 0;
@@ -453,7 +451,7 @@ EXPORT_SYMBOL(mma9551_read_status_words);
  * @client:    I2C client
  * @app_id:    Application ID
  * @reg:       Application register
- * @len:       Length of array to write in bytes
+ * @len:       Length of array to write (in words)
  * @buf:       Array of words to write
  *
  * Write multiple configuration registers (word-sized registers).
@@ -468,19 +466,18 @@ int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
                               u16 reg, u8 len, u16 *buf)
 {
        int i;
-       int len_words = len / sizeof(u16);
        __be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2];
 
-       if (len_words > ARRAY_SIZE(be_buf)) {
+       if (len > ARRAY_SIZE(be_buf)) {
                dev_err(&client->dev, "Invalid buffer size %d\n", len);
                return -EINVAL;
        }
 
-       for (i = 0; i < len_words; i++)
+       for (i = 0; i < len; i++)
                be_buf[i] = cpu_to_be16(buf[i]);
 
        return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG,
-                               reg, (u8 *) be_buf, len, NULL, 0);
+                               reg, (u8 *)be_buf, len * sizeof(u16), NULL, 0);
 }
 EXPORT_SYMBOL(mma9551_write_config_words);
 
index 79939e40805a00ead1b15809653d5e9d24756edc..5e88e6454dfd927c7d49e0307614a1a85c4ec3d3 100644 (file)
@@ -53,13 +53,13 @@ int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
 int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
                             u16 reg, u8 *val);
 int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
-                           u16 reg, u16 *val);
+                            u16 reg, u16 *val);
 int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
-                            u16 reg, u16 val);
+                             u16 reg, u16 val);
 int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
                             u16 reg, u16 *val);
 int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
-                            u16 reg, u8 len, u16 *buf);
+                             u16 reg, u8 len, u16 *buf);
 int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
                              u16 reg, u8 len, u16 *buf);
 int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
index 8bfc61824fb2378ab8554777bc1d0842c2bdb7a0..771858cb67a1b57db5472576ecb0656b7d282884 100644 (file)
@@ -182,6 +182,10 @@ struct mma9553_conf_regs {
 
 struct mma9553_data {
        struct i2c_client *client;
+       /*
+        * 1. Serialize access to HW (requested by mma9551_core API).
+        * 2. Serialize sequences that power on/off the device and access HW.
+        */
        struct mutex mutex;
        struct mma9553_conf_regs conf;
        struct mma9553_event events[MMA9553_EVENTS_INFO_SIZE];
@@ -322,7 +326,8 @@ static int mma9553_read_activity_stepcnt(struct mma9553_data *data,
        int ret;
 
        ret = mma9551_read_status_words(data->client, MMA9551_APPID_PEDOMETER,
-                                       MMA9553_REG_STATUS, sizeof(u32), buf);
+                                       MMA9553_REG_STATUS, ARRAY_SIZE(buf),
+                                       buf);
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "error reading status and stepcnt\n");
@@ -342,10 +347,10 @@ static int mma9553_conf_gpio(struct mma9553_data *data)
        struct mma9553_event *ev_step_detect;
        bool activity_enabled;
 
-       activity_enabled =
-           mma9553_is_any_event_enabled(data, true, IIO_ACTIVITY);
-       ev_step_detect =
-           mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE);
+       activity_enabled = mma9553_is_any_event_enabled(data, true,
+                                                       IIO_ACTIVITY);
+       ev_step_detect = mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD,
+                                          IIO_EV_DIR_NONE);
 
        /*
         * If both step detector and activity are enabled, use the MRGFL bit.
@@ -371,9 +376,8 @@ static int mma9553_conf_gpio(struct mma9553_data *data)
                        return ret;
        }
 
-       ret = mma9551_gpio_config(data->client,
-                                 MMA9553_DEFAULT_GPIO_PIN,
-                                 appid, bitnum, MMA9553_DEFAULT_GPIO_POLARITY);
+       ret = mma9551_gpio_config(data->client, MMA9553_DEFAULT_GPIO_PIN, appid,
+                                 bitnum, MMA9553_DEFAULT_GPIO_POLARITY);
        if (ret < 0)
                return ret;
        data->gpio_bitnum = bitnum;
@@ -394,17 +398,16 @@ static int mma9553_init(struct mma9553_data *data)
         * a device identification command to differentiate the MMA9553L
         * from the MMA9550L.
         */
-       ret =
-           mma9551_read_config_words(data->client, MMA9551_APPID_PEDOMETER,
-                                     MMA9553_REG_CONF_SLEEPMIN,
-                                     sizeof(data->conf), (u16 *) &data->conf);
+       ret = mma9551_read_config_words(data->client, MMA9551_APPID_PEDOMETER,
+                                       MMA9553_REG_CONF_SLEEPMIN,
+                                       sizeof(data->conf) / sizeof(u16),
+                                       (u16 *)&data->conf);
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "failed to read configuration registers\n");
                return ret;
        }
 
-
        /* Reset GPIO */
        data->gpio_bitnum = MMA9553_MAX_BITNUM;
        ret = mma9553_conf_gpio(data);
@@ -419,18 +422,18 @@ static int mma9553_init(struct mma9553_data *data)
        data->conf.sleepmin = MMA9553_DEFAULT_SLEEPMIN;
        data->conf.sleepmax = MMA9553_DEFAULT_SLEEPMAX;
        data->conf.sleepthd = MMA9553_DEFAULT_SLEEPTHD;
-       data->conf.config =
-           mma9553_set_bits(data->conf.config, 1, MMA9553_MASK_CONF_CONFIG);
+       data->conf.config = mma9553_set_bits(data->conf.config, 1,
+                                            MMA9553_MASK_CONF_CONFIG);
        /*
         * Clear the activity debounce counter when the activity level changes,
         * so that the confidence level applies for any activity level.
         */
        data->conf.config = mma9553_set_bits(data->conf.config, 1,
                                             MMA9553_MASK_CONF_ACT_DBCNTM);
-       ret =
-           mma9551_write_config_words(data->client, MMA9551_APPID_PEDOMETER,
-                                      MMA9553_REG_CONF_SLEEPMIN,
-                                      sizeof(data->conf), (u16 *) &data->conf);
+       ret = mma9551_write_config_words(data->client, MMA9551_APPID_PEDOMETER,
+                                        MMA9553_REG_CONF_SLEEPMIN,
+                                        sizeof(data->conf) / sizeof(u16),
+                                        (u16 *)&data->conf);
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "failed to write configuration registers\n");
@@ -567,7 +570,7 @@ static int mma9553_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBHEIGHT:
                tmp = mma9553_get_bits(data->conf.height_weight,
-                                       MMA9553_MASK_CONF_HEIGHT);
+                                      MMA9553_MASK_CONF_HEIGHT);
                *val = tmp / 100;       /* cm to m */
                *val2 = (tmp % 100) * 10000;
                return IIO_VAL_INT_PLUS_MICRO;
@@ -719,7 +722,6 @@ static int mma9553_read_event_config(struct iio_dev *indio_dev,
                                     enum iio_event_type type,
                                     enum iio_event_direction dir)
 {
-
        struct mma9553_data *data = iio_priv(indio_dev);
        struct mma9553_event *event;
 
@@ -1026,22 +1028,22 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
                return IRQ_HANDLED;
        }
 
-       ev_prev_activity =
-           mma9553_get_event(data, IIO_ACTIVITY,
-                             mma9553_activity_to_mod(data->activity),
-                             IIO_EV_DIR_FALLING);
-       ev_activity =
-           mma9553_get_event(data, IIO_ACTIVITY,
-                             mma9553_activity_to_mod(activity),
-                             IIO_EV_DIR_RISING);
-       ev_step_detect =
-           mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE);
+       ev_prev_activity = mma9553_get_event(data, IIO_ACTIVITY,
+                                            mma9553_activity_to_mod(
+                                            data->activity),
+                                            IIO_EV_DIR_FALLING);
+       ev_activity = mma9553_get_event(data, IIO_ACTIVITY,
+                                       mma9553_activity_to_mod(activity),
+                                       IIO_EV_DIR_RISING);
+       ev_step_detect = mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD,
+                                          IIO_EV_DIR_NONE);
 
        if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) {
                data->stepcnt = stepcnt;
                iio_push_event(indio_dev,
                               IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
-                              IIO_EV_DIR_NONE, IIO_EV_TYPE_CHANGE, 0, 0, 0),
+                                             IIO_EV_DIR_NONE,
+                                             IIO_EV_TYPE_CHANGE, 0, 0, 0),
                               data->timestamp);
        }
 
@@ -1051,17 +1053,19 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
                if (ev_prev_activity && ev_prev_activity->enabled)
                        iio_push_event(indio_dev,
                                       IIO_EVENT_CODE(IIO_ACTIVITY, 0,
-                                      ev_prev_activity->info->mod,
-                                      IIO_EV_DIR_FALLING,
-                                      IIO_EV_TYPE_THRESH, 0, 0, 0),
+                                                   ev_prev_activity->info->mod,
+                                                   IIO_EV_DIR_FALLING,
+                                                   IIO_EV_TYPE_THRESH, 0, 0,
+                                                   0),
                                       data->timestamp);
 
                if (ev_activity && ev_activity->enabled)
                        iio_push_event(indio_dev,
                                       IIO_EVENT_CODE(IIO_ACTIVITY, 0,
-                                      ev_activity->info->mod,
-                                      IIO_EV_DIR_RISING,
-                                      IIO_EV_TYPE_THRESH, 0, 0, 0),
+                                                     ev_activity->info->mod,
+                                                     IIO_EV_DIR_RISING,
+                                                     IIO_EV_TYPE_THRESH, 0, 0,
+                                                     0),
                                       data->timestamp);
        }
        mutex_unlock(&data->mutex);
@@ -1145,7 +1149,7 @@ static int mma9553_probe(struct i2c_client *client,
        if (client->irq < 0)
                client->irq = mma9553_gpio_probe(client);
 
-       if (client->irq >= 0) {
+       if (client->irq > 0) {
                ret = devm_request_threaded_irq(&client->dev, client->irq,
                                                mma9553_irq_handler,
                                                mma9553_event_handler,
@@ -1156,7 +1160,6 @@ static int mma9553_probe(struct i2c_client *client,
                                client->irq);
                        goto out_poweroff;
                }
-
        }
 
        ret = iio_device_register(indio_dev);
index aa1001931d0c418705dd968c154ce7b149c5324b..468f21fa2950bd2bd59c226919b7b22be1407398 100644 (file)
@@ -26,6 +26,7 @@
 #define LSM303DLH_ACCEL_DEV_NAME       "lsm303dlh_accel"
 #define LSM303DLM_ACCEL_DEV_NAME       "lsm303dlm_accel"
 #define LSM330_ACCEL_DEV_NAME          "lsm330_accel"
+#define LSM303AGR_ACCEL_DEV_NAME       "lsm303agr_accel"
 
 /**
 * struct st_sensors_platform_data - default accel platform data
index 4002e6410444e780f5258813ceb600cd5a9b04c2..ff30f880688019fa099d79d7fce3f53b28cfb828 100644 (file)
@@ -226,12 +226,14 @@ static const struct iio_chan_spec st_accel_16bit_channels[] = {
 static const struct st_sensor_settings st_accel_sensors_settings[] = {
        {
                .wai = ST_ACCEL_1_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LIS3DH_ACCEL_DEV_NAME,
                        [1] = LSM303DLHC_ACCEL_DEV_NAME,
                        [2] = LSM330D_ACCEL_DEV_NAME,
                        [3] = LSM330DL_ACCEL_DEV_NAME,
                        [4] = LSM330DLC_ACCEL_DEV_NAME,
+                       [5] = LSM303AGR_ACCEL_DEV_NAME,
                },
                .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
                .odr = {
@@ -297,6 +299,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
        },
        {
                .wai = ST_ACCEL_2_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LIS331DLH_ACCEL_DEV_NAME,
                        [1] = LSM303DL_ACCEL_DEV_NAME,
@@ -359,6 +362,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
        },
        {
                .wai = ST_ACCEL_3_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LSM330_ACCEL_DEV_NAME,
                },
@@ -437,6 +441,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
        },
        {
                .wai = ST_ACCEL_4_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LIS3LV02DL_ACCEL_DEV_NAME,
                },
@@ -494,6 +499,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
        },
        {
                .wai = ST_ACCEL_5_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LIS331DL_ACCEL_DEV_NAME,
                },
index d4ad72ca4a3de258ef1772492fae50901d6f34a8..8b9cc84fd44f96be22186fb7364a5cf6259de701 100644 (file)
@@ -68,6 +68,10 @@ static const struct of_device_id st_accel_of_match[] = {
                .compatible = "st,lsm330-accel",
                .data = LSM330_ACCEL_DEV_NAME,
        },
+       {
+               .compatible = "st,lsm303agr-accel",
+               .data = LSM303AGR_ACCEL_DEV_NAME,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
@@ -116,13 +120,13 @@ static const struct i2c_device_id st_accel_id_table[] = {
        { LSM303DL_ACCEL_DEV_NAME },
        { LSM303DLM_ACCEL_DEV_NAME },
        { LSM330_ACCEL_DEV_NAME },
+       { LSM303AGR_ACCEL_DEV_NAME },
        {},
 };
 MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
 
 static struct i2c_driver st_accel_driver = {
        .driver = {
-               .owner = THIS_MODULE,
                .name = "st-accel-i2c",
                .of_match_table = of_match_ptr(st_accel_of_match),
        },
index 12ec29389e4ba15c794d3aaa74df3c5c917d3cee..54b61a3961c305e60222de437e4355103ae67029 100644 (file)
@@ -57,6 +57,7 @@ static const struct spi_device_id st_accel_id_table[] = {
        { LSM303DL_ACCEL_DEV_NAME },
        { LSM303DLM_ACCEL_DEV_NAME },
        { LSM330_ACCEL_DEV_NAME },
+       { LSM303AGR_ACCEL_DEV_NAME },
        {},
 };
 MODULE_DEVICE_TABLE(spi, st_accel_id_table);
index d211d9f3975b823e3026cfec2b4871c2ca924bd3..c764af284c947ed103c08ce0e3ecf365e6f80077 100644 (file)
  */
 
 #include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 
 #define STK8312_REG_XOUT               0x00
 #define STK8312_REG_YOUT               0x01
 #define STK8312_REG_ZOUT               0x02
+#define STK8312_REG_INTSU              0x06
 #define STK8312_REG_MODE               0x07
+#define STK8312_REG_SR                 0x08
 #define STK8312_REG_STH                        0x13
 #define STK8312_REG_RESET              0x20
 #define STK8312_REG_AFECTRL            0x24
 #define STK8312_REG_OTPDATA            0x3E
 #define STK8312_REG_OTPCTRL            0x3F
 
-#define STK8312_MODE_ACTIVE            1
-#define STK8312_MODE_STANDBY           0
-#define STK8312_MODE_MASK              0x01
-#define STK8312_RNG_MASK               0xC0
+#define STK8312_MODE_ACTIVE            BIT(0)
+#define STK8312_MODE_STANDBY           0x00
+#define STK8312_MODE_INT_AH_PP         0xC0    /* active-high, push-pull */
+#define STK8312_DREADY_BIT             BIT(4)
+#define STK8312_RNG_6G                 1
 #define STK8312_RNG_SHIFT              6
-#define STK8312_READ_RETRIES           16
+#define STK8312_RNG_MASK               GENMASK(7, 6)
+#define STK8312_SR_MASK                        GENMASK(2, 0)
+#define STK8312_SR_400HZ_IDX           0
+#define STK8312_ALL_CHANNEL_MASK       GENMASK(2, 0)
+#define STK8312_ALL_CHANNEL_SIZE       3
 
 #define STK8312_DRIVER_NAME            "stk8312"
+#define STK8312_GPIO                   "stk8312_gpio"
+#define STK8312_IRQ_NAME               "stk8312_event"
 
 /*
  * The accelerometer has two measurement ranges:
@@ -53,32 +68,56 @@ static const int stk8312_scale_table[][2] = {
        {0, 461600}, {1, 231100}
 };
 
-#define STK8312_ACCEL_CHANNEL(reg, axis) {                     \
-       .type = IIO_ACCEL,                                      \
-       .address = reg,                                         \
-       .modified = 1,                                          \
-       .channel2 = IIO_MOD_##axis,                             \
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
-       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+static const struct {
+       int val;
+       int val2;
+} stk8312_samp_freq_table[] = {
+       {400, 0}, {200, 0}, {100, 0}, {50, 0}, {25, 0},
+       {12, 500000}, {6, 250000}, {3, 125000}
+};
+
+#define STK8312_ACCEL_CHANNEL(index, reg, axis) {                      \
+       .type = IIO_ACCEL,                                              \
+       .address = reg,                                                 \
+       .modified = 1,                                                  \
+       .channel2 = IIO_MOD_##axis,                                     \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |          \
+                                   BIT(IIO_CHAN_INFO_SAMP_FREQ),       \
+       .scan_index = index,                                            \
+       .scan_type = {                                                  \
+               .sign = 's',                                            \
+               .realbits = 8,                                          \
+               .storagebits = 8,                                       \
+               .endianness = IIO_CPU,                                  \
+       },                                                              \
 }
 
 static const struct iio_chan_spec stk8312_channels[] = {
-       STK8312_ACCEL_CHANNEL(STK8312_REG_XOUT, X),
-       STK8312_ACCEL_CHANNEL(STK8312_REG_YOUT, Y),
-       STK8312_ACCEL_CHANNEL(STK8312_REG_ZOUT, Z),
+       STK8312_ACCEL_CHANNEL(0, STK8312_REG_XOUT, X),
+       STK8312_ACCEL_CHANNEL(1, STK8312_REG_YOUT, Y),
+       STK8312_ACCEL_CHANNEL(2, STK8312_REG_ZOUT, Z),
+       IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
 struct stk8312_data {
        struct i2c_client *client;
        struct mutex lock;
-       int range;
+       u8 range;
+       u8 sample_rate_idx;
        u8 mode;
+       struct iio_trigger *dready_trig;
+       bool dready_trigger_on;
+       s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */
 };
 
 static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL);
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("3.125 6.25 12.5 25 50 100 200 400");
+
 static struct attribute *stk8312_attributes[] = {
        &iio_const_attr_in_accel_scale_available.dev_attr.attr,
+       &iio_const_attr_sampling_frequency_available.dev_attr.attr,
        NULL,
 };
 
@@ -105,22 +144,25 @@ static int stk8312_otp_init(struct stk8312_data *data)
                if (ret < 0)
                        goto exit_err;
                count--;
-       } while (!(ret & 0x80) && count > 0);
+       } while (!(ret & BIT(7)) && count > 0);
 
-       if (count == 0)
+       if (count == 0) {
+               ret = -ETIMEDOUT;
                goto exit_err;
+       }
 
        ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA);
+       if (ret == 0)
+               ret = -EINVAL;
        if (ret < 0)
                goto exit_err;
 
-       ret = i2c_smbus_write_byte_data(data->client,
-                       STK8312_REG_AFECTRL, ret);
+       ret = i2c_smbus_write_byte_data(data->client, STK8312_REG_AFECTRL, ret);
        if (ret < 0)
                goto exit_err;
        msleep(150);
 
-       return ret;
+       return 0;
 
 exit_err:
        dev_err(&client->dev, "failed to initialize sensor\n");
@@ -130,31 +172,19 @@ exit_err:
 static int stk8312_set_mode(struct stk8312_data *data, u8 mode)
 {
        int ret;
-       u8 masked_reg;
        struct i2c_client *client = data->client;
 
-       if (mode > 1)
-               return -EINVAL;
-       else if (mode == data->mode)
+       if (mode == data->mode)
                return 0;
 
-       ret = i2c_smbus_read_byte_data(client, STK8312_REG_MODE);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed to change sensor mode\n");
-               return ret;
-       }
-       masked_reg = ret & (~STK8312_MODE_MASK);
-       masked_reg |= mode;
-
-       ret = i2c_smbus_write_byte_data(client,
-                       STK8312_REG_MODE, masked_reg);
+       ret = i2c_smbus_write_byte_data(client, STK8312_REG_MODE, mode);
        if (ret < 0) {
                dev_err(&client->dev, "failed to change sensor mode\n");
                return ret;
        }
 
        data->mode = mode;
-       if (mode == STK8312_MODE_ACTIVE) {
+       if (mode & STK8312_MODE_ACTIVE) {
                /* Need to run OTP sequence before entering active mode */
                usleep_range(1000, 5000);
                ret = stk8312_otp_init(data);
@@ -163,6 +193,92 @@ static int stk8312_set_mode(struct stk8312_data *data, u8 mode)
        return ret;
 }
 
+static int stk8312_set_interrupts(struct stk8312_data *data, u8 int_mask)
+{
+       int ret;
+       u8 mode;
+       struct i2c_client *client = data->client;
+
+       mode = data->mode;
+       /* We need to go in standby mode to modify registers */
+       ret = stk8312_set_mode(data, STK8312_MODE_STANDBY);
+       if (ret < 0)
+               return ret;
+
+       ret = i2c_smbus_write_byte_data(client, STK8312_REG_INTSU, int_mask);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed to set interrupts\n");
+               stk8312_set_mode(data, mode);
+               return ret;
+       }
+
+       return stk8312_set_mode(data, mode);
+}
+
+static int stk8312_data_rdy_trigger_set_state(struct iio_trigger *trig,
+                                             bool state)
+{
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       struct stk8312_data *data = iio_priv(indio_dev);
+       int ret;
+
+       if (state)
+               ret = stk8312_set_interrupts(data, STK8312_DREADY_BIT);
+       else
+               ret = stk8312_set_interrupts(data, 0x00);
+
+       if (ret < 0) {
+               dev_err(&data->client->dev, "failed to set trigger state\n");
+               return ret;
+       }
+
+       data->dready_trigger_on = state;
+
+       return 0;
+}
+
+static const struct iio_trigger_ops stk8312_trigger_ops = {
+       .set_trigger_state = stk8312_data_rdy_trigger_set_state,
+       .owner = THIS_MODULE,
+};
+
+static int stk8312_set_sample_rate(struct stk8312_data *data, u8 rate)
+{
+       int ret;
+       u8 masked_reg;
+       u8 mode;
+       struct i2c_client *client = data->client;
+
+       if (rate == data->sample_rate_idx)
+               return 0;
+
+       mode = data->mode;
+       /* We need to go in standby mode to modify registers */
+       ret = stk8312_set_mode(data, STK8312_MODE_STANDBY);
+       if (ret < 0)
+               return ret;
+
+       ret = i2c_smbus_read_byte_data(client, STK8312_REG_SR);
+       if (ret < 0)
+               goto err_activate;
+
+       masked_reg = (ret & (~STK8312_SR_MASK)) | rate;
+
+       ret = i2c_smbus_write_byte_data(client, STK8312_REG_SR, masked_reg);
+       if (ret < 0)
+               goto err_activate;
+
+       data->sample_rate_idx = rate;
+
+       return stk8312_set_mode(data, mode);
+
+err_activate:
+       dev_err(&client->dev, "failed to set sampling rate\n");
+       stk8312_set_mode(data, mode);
+
+       return ret;
+}
+
 static int stk8312_set_range(struct stk8312_data *data, u8 range)
 {
        int ret;
@@ -182,21 +298,25 @@ static int stk8312_set_range(struct stk8312_data *data, u8 range)
                return ret;
 
        ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed to change sensor range\n");
-               return ret;
-       }
+       if (ret < 0)
+               goto err_activate;
 
        masked_reg = ret & (~STK8312_RNG_MASK);
        masked_reg |= range << STK8312_RNG_SHIFT;
 
        ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg);
        if (ret < 0)
-               dev_err(&client->dev, "failed to change sensor range\n");
-       else
-               data->range = range;
+               goto err_activate;
+
+       data->range = range;
 
        return stk8312_set_mode(data, mode);
+
+err_activate:
+       dev_err(&client->dev, "failed to change sensor range\n");
+       stk8312_set_mode(data, mode);
+
+       return ret;
 }
 
 static int stk8312_read_accel(struct stk8312_data *data, u8 address)
@@ -208,12 +328,10 @@ static int stk8312_read_accel(struct stk8312_data *data, u8 address)
                return -EINVAL;
 
        ret = i2c_smbus_read_byte_data(client, address);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&client->dev, "register read failed\n");
-               return ret;
-       }
 
-       return sign_extend32(ret, 7);
+       return ret;
 }
 
 static int stk8312_read_raw(struct iio_dev *indio_dev,
@@ -221,20 +339,40 @@ static int stk8312_read_raw(struct iio_dev *indio_dev,
                            int *val, int *val2, long mask)
 {
        struct stk8312_data *data = iio_priv(indio_dev);
-
-       if (chan->type != IIO_ACCEL)
-               return -EINVAL;
+       int ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
+               if (iio_buffer_enabled(indio_dev))
+                       return -EBUSY;
                mutex_lock(&data->lock);
-               *val = stk8312_read_accel(data, chan->address);
+               ret = stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
+               if (ret < 0) {
+                       mutex_unlock(&data->lock);
+                       return ret;
+               }
+               ret = stk8312_read_accel(data, chan->address);
+               if (ret < 0) {
+                       stk8312_set_mode(data,
+                                        data->mode & (~STK8312_MODE_ACTIVE));
+                       mutex_unlock(&data->lock);
+                       return ret;
+               }
+               *val = sign_extend32(ret, 7);
+               ret = stk8312_set_mode(data,
+                                      data->mode & (~STK8312_MODE_ACTIVE));
                mutex_unlock(&data->lock);
+               if (ret < 0)
+                       return ret;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
                *val = stk8312_scale_table[data->range - 1][0];
                *val2 = stk8312_scale_table[data->range - 1][1];
                return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *val = stk8312_samp_freq_table[data->sample_rate_idx].val;
+               *val2 = stk8312_samp_freq_table[data->sample_rate_idx].val2;
+               return IIO_VAL_INT_PLUS_MICRO;
        }
 
        return -EINVAL;
@@ -264,6 +402,20 @@ static int stk8312_write_raw(struct iio_dev *indio_dev,
                ret = stk8312_set_range(data, index);
                mutex_unlock(&data->lock);
 
+               return ret;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               for (i = 0; i < ARRAY_SIZE(stk8312_samp_freq_table); i++)
+                       if (val == stk8312_samp_freq_table[i].val &&
+                           val2 == stk8312_samp_freq_table[i].val2) {
+                               index = i;
+                               break;
+                       }
+               if (index < 0)
+                       return -EINVAL;
+               mutex_lock(&data->lock);
+               ret = stk8312_set_sample_rate(data, index);
+               mutex_unlock(&data->lock);
+
                return ret;
        }
 
@@ -277,6 +429,105 @@ static const struct iio_info stk8312_info = {
        .attrs                  = &stk8312_attribute_group,
 };
 
+static irqreturn_t stk8312_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct stk8312_data *data = iio_priv(indio_dev);
+       int bit, ret, i = 0;
+
+       mutex_lock(&data->lock);
+       /*
+        * Do a bulk read if all channels are requested,
+        * from 0x00 (XOUT) to 0x02 (ZOUT)
+        */
+       if (*(indio_dev->active_scan_mask) == STK8312_ALL_CHANNEL_MASK) {
+               ret = i2c_smbus_read_i2c_block_data(data->client,
+                                                   STK8312_REG_XOUT,
+                                                   STK8312_ALL_CHANNEL_SIZE,
+                                                   data->buffer);
+               if (ret < STK8312_ALL_CHANNEL_SIZE) {
+                       dev_err(&data->client->dev, "register read failed\n");
+                       mutex_unlock(&data->lock);
+                       goto err;
+               }
+       } else {
+               for_each_set_bit(bit, indio_dev->active_scan_mask,
+                                indio_dev->masklength) {
+                       ret = stk8312_read_accel(data, bit);
+                       if (ret < 0) {
+                               mutex_unlock(&data->lock);
+                               goto err;
+                       }
+                       data->buffer[i++] = ret;
+               }
+       }
+       mutex_unlock(&data->lock);
+
+       iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+                                          pf->timestamp);
+err:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t stk8312_data_rdy_trig_poll(int irq, void *private)
+{
+       struct iio_dev *indio_dev = private;
+       struct stk8312_data *data = iio_priv(indio_dev);
+
+       if (data->dready_trigger_on)
+               iio_trigger_poll(data->dready_trig);
+
+       return IRQ_HANDLED;
+}
+
+static int stk8312_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct stk8312_data *data = iio_priv(indio_dev);
+
+       return stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
+}
+
+static int stk8312_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct stk8312_data *data = iio_priv(indio_dev);
+
+       return stk8312_set_mode(data, data->mode & (~STK8312_MODE_ACTIVE));
+}
+
+static const struct iio_buffer_setup_ops stk8312_buffer_setup_ops = {
+       .preenable   = stk8312_buffer_preenable,
+       .postenable  = iio_triggered_buffer_postenable,
+       .predisable  = iio_triggered_buffer_predisable,
+       .postdisable = stk8312_buffer_postdisable,
+};
+
+static int stk8312_gpio_probe(struct i2c_client *client)
+{
+       struct device *dev;
+       struct gpio_desc *gpio;
+       int ret;
+
+       if (!client)
+               return -EINVAL;
+
+       dev = &client->dev;
+
+       /* data ready gpio interrupt pin */
+       gpio = devm_gpiod_get_index(dev, STK8312_GPIO, 0, GPIOD_IN);
+       if (IS_ERR(gpio)) {
+               dev_err(dev, "acpi gpio get index failed\n");
+               return PTR_ERR(gpio);
+       }
+
+       ret = gpiod_to_irq(gpio);
+       dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+       return ret;
+}
+
 static int stk8312_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -308,30 +559,91 @@ static int stk8312_probe(struct i2c_client *client,
                dev_err(&client->dev, "failed to reset sensor\n");
                return ret;
        }
-       ret = stk8312_set_range(data, 1);
+       data->sample_rate_idx = STK8312_SR_400HZ_IDX;
+       ret = stk8312_set_range(data, STK8312_RNG_6G);
        if (ret < 0)
                return ret;
 
-       ret = stk8312_set_mode(data, STK8312_MODE_ACTIVE);
+       ret = stk8312_set_mode(data,
+                              STK8312_MODE_INT_AH_PP | STK8312_MODE_ACTIVE);
        if (ret < 0)
                return ret;
 
+       if (client->irq < 0)
+               client->irq = stk8312_gpio_probe(client);
+
+       if (client->irq >= 0) {
+               ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                               stk8312_data_rdy_trig_poll,
+                                               NULL,
+                                               IRQF_TRIGGER_RISING |
+                                               IRQF_ONESHOT,
+                                               STK8312_IRQ_NAME,
+                                               indio_dev);
+               if (ret < 0) {
+                       dev_err(&client->dev, "request irq %d failed\n",
+                               client->irq);
+                       goto err_power_off;
+               }
+
+               data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+                                                          "%s-dev%d",
+                                                          indio_dev->name,
+                                                          indio_dev->id);
+               if (!data->dready_trig) {
+                       ret = -ENOMEM;
+                       goto err_power_off;
+               }
+
+               data->dready_trig->dev.parent = &client->dev;
+               data->dready_trig->ops = &stk8312_trigger_ops;
+               iio_trigger_set_drvdata(data->dready_trig, indio_dev);
+               ret = iio_trigger_register(data->dready_trig);
+               if (ret) {
+                       dev_err(&client->dev, "iio trigger register failed\n");
+                       goto err_power_off;
+               }
+       }
+
+       ret = iio_triggered_buffer_setup(indio_dev,
+                                        iio_pollfunc_store_time,
+                                        stk8312_trigger_handler,
+                                        &stk8312_buffer_setup_ops);
+       if (ret < 0) {
+               dev_err(&client->dev, "iio triggered buffer setup failed\n");
+               goto err_trigger_unregister;
+       }
+
        ret = iio_device_register(indio_dev);
        if (ret < 0) {
                dev_err(&client->dev, "device_register failed\n");
-               stk8312_set_mode(data, STK8312_MODE_STANDBY);
+               goto err_buffer_cleanup;
        }
 
+       return 0;
+
+err_buffer_cleanup:
+       iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+       if (data->dready_trig)
+               iio_trigger_unregister(data->dready_trig);
+err_power_off:
+       stk8312_set_mode(data, STK8312_MODE_STANDBY);
        return ret;
 }
 
 static int stk8312_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct stk8312_data *data = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
+
+       if (data->dready_trig)
+               iio_trigger_unregister(data->dready_trig);
 
-       return stk8312_set_mode(iio_priv(indio_dev), STK8312_MODE_STANDBY);
+       return stk8312_set_mode(data, STK8312_MODE_STANDBY);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -341,7 +653,7 @@ static int stk8312_suspend(struct device *dev)
 
        data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
 
-       return stk8312_set_mode(data, STK8312_MODE_STANDBY);
+       return stk8312_set_mode(data, data->mode & (~STK8312_MODE_ACTIVE));
 }
 
 static int stk8312_resume(struct device *dev)
@@ -350,7 +662,7 @@ static int stk8312_resume(struct device *dev)
 
        data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
 
-       return stk8312_set_mode(data, STK8312_MODE_ACTIVE);
+       return stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
 }
 
 static SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, stk8312_resume);
@@ -364,6 +676,7 @@ static const struct i2c_device_id stk8312_i2c_id[] = {
        {"STK8312", 0},
        {}
 };
+MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id);
 
 static const struct acpi_device_id stk8312_acpi_id[] = {
        {"STK8312", 0},
@@ -374,7 +687,7 @@ MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id);
 
 static struct i2c_driver stk8312_driver = {
        .driver = {
-               .name = "stk8312",
+               .name = STK8312_DRIVER_NAME,
                .pm = STK8312_PM_OPS,
                .acpi_match_table = ACPI_PTR(stk8312_acpi_id),
        },
index 30950c6b36de1f36ac709c4a3548d0a804cb2ccf..80f77d8704b5bf29fdc857a8b5f548a9a24a9f47 100644 (file)
  */
 
 #include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 
 #define STK8BA50_REG_XOUT                      0x02
 #define STK8BA50_REG_YOUT                      0x04
 #define STK8BA50_REG_ZOUT                      0x06
 #define STK8BA50_REG_RANGE                     0x0F
+#define STK8BA50_REG_BWSEL                     0x10
 #define STK8BA50_REG_POWMODE                   0x11
 #define STK8BA50_REG_SWRST                     0x14
+#define STK8BA50_REG_INTEN2                    0x17
+#define STK8BA50_REG_INTMAP2                   0x1A
 
 #define STK8BA50_MODE_NORMAL                   0
 #define STK8BA50_MODE_SUSPEND                  1
 #define STK8BA50_MODE_POWERBIT                 BIT(7)
 #define STK8BA50_DATA_SHIFT                    6
 #define STK8BA50_RESET_CMD                     0xB6
+#define STK8BA50_SR_1792HZ_IDX                 7
+#define STK8BA50_DREADY_INT_MASK               0x10
+#define STK8BA50_DREADY_INT_MAP                        0x81
+#define STK8BA50_ALL_CHANNEL_MASK              7
+#define STK8BA50_ALL_CHANNEL_SIZE              6
 
 #define STK8BA50_DRIVER_NAME                   "stk8ba50"
+#define STK8BA50_GPIO                          "stk8ba50_gpio"
+#define STK8BA50_IRQ_NAME                      "stk8ba50_event"
 
 #define STK8BA50_SCALE_AVAIL                   "0.0384 0.0767 0.1534 0.3069"
 
  *
  * Locally, the range is stored as a table index.
  */
-static const int stk8ba50_scale_table[][2] = {
+static const struct {
+       u8 reg_val;
+       u32 scale_val;
+} stk8ba50_scale_table[] = {
        {3, 38400}, {5, 76700}, {8, 153400}, {12, 306900}
 };
 
+/* Sample rates are stored as { <register value>, <Hz value> } */
+static const struct {
+       u8 reg_val;
+       u16 samp_freq;
+} stk8ba50_samp_freq_table[] = {
+       {0x08, 14},  {0x09, 25},  {0x0A, 56},  {0x0B, 112},
+       {0x0C, 224}, {0x0D, 448}, {0x0E, 896}, {0x0F, 1792}
+};
+
+/* Used to map scan mask bits to their corresponding channel register. */
+static const int stk8ba50_channel_table[] = {
+       STK8BA50_REG_XOUT,
+       STK8BA50_REG_YOUT,
+       STK8BA50_REG_ZOUT
+};
+
 struct stk8ba50_data {
        struct i2c_client *client;
        struct mutex lock;
        int range;
+       u8 sample_rate_idx;
+       struct iio_trigger *dready_trig;
+       bool dready_trigger_on;
+       /*
+        * 3 x 16-bit channels (10-bit data, 6-bit padding) +
+        * 1 x 16 padding +
+        * 4 x 16 64-bit timestamp
+        */
+       s16 buffer[8];
 };
 
-#define STK8BA50_ACCEL_CHANNEL(reg, axis) {                    \
-       .type = IIO_ACCEL,                                      \
-       .address = reg,                                         \
-       .modified = 1,                                          \
-       .channel2 = IIO_MOD_##axis,                             \
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
-       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+#define STK8BA50_ACCEL_CHANNEL(index, reg, axis) {                     \
+       .type = IIO_ACCEL,                                              \
+       .address = reg,                                                 \
+       .modified = 1,                                                  \
+       .channel2 = IIO_MOD_##axis,                                     \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
+                                   BIT(IIO_CHAN_INFO_SAMP_FREQ),       \
+       .scan_index = index,                                            \
+       .scan_type = {                                                  \
+               .sign = 's',                                            \
+               .realbits = 10,                                         \
+               .storagebits = 16,                                      \
+               .shift = STK8BA50_DATA_SHIFT,                           \
+               .endianness = IIO_CPU,                                  \
+       },                                                              \
 }
 
 static const struct iio_chan_spec stk8ba50_channels[] = {
-       STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_XOUT, X),
-       STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_YOUT, Y),
-       STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_ZOUT, Z),
+       STK8BA50_ACCEL_CHANNEL(0, STK8BA50_REG_XOUT, X),
+       STK8BA50_ACCEL_CHANNEL(1, STK8BA50_REG_YOUT, Y),
+       STK8BA50_ACCEL_CHANNEL(2, STK8BA50_REG_ZOUT, Z),
+       IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
 static IIO_CONST_ATTR(in_accel_scale_available, STK8BA50_SCALE_AVAIL);
 
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("14 25 56 112 224 448 896 1792");
+
 static struct attribute *stk8ba50_attributes[] = {
        &iio_const_attr_in_accel_scale_available.dev_attr.attr,
+       &iio_const_attr_sampling_frequency_available.dev_attr.attr,
        NULL,
 };
 
@@ -97,7 +154,61 @@ static int stk8ba50_read_accel(struct stk8ba50_data *data, u8 reg)
                return ret;
        }
 
-       return sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9);
+       return ret;
+}
+
+static int stk8ba50_data_rdy_trigger_set_state(struct iio_trigger *trig,
+                                              bool state)
+{
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       struct stk8ba50_data *data = iio_priv(indio_dev);
+       int ret;
+
+       if (state)
+               ret = i2c_smbus_write_byte_data(data->client,
+                       STK8BA50_REG_INTEN2, STK8BA50_DREADY_INT_MASK);
+       else
+               ret = i2c_smbus_write_byte_data(data->client,
+                       STK8BA50_REG_INTEN2, 0x00);
+
+       if (ret < 0)
+               dev_err(&data->client->dev, "failed to set trigger state\n");
+       else
+               data->dready_trigger_on = state;
+
+       return ret;
+}
+
+static const struct iio_trigger_ops stk8ba50_trigger_ops = {
+       .set_trigger_state = stk8ba50_data_rdy_trigger_set_state,
+       .owner = THIS_MODULE,
+};
+
+static int stk8ba50_set_power(struct stk8ba50_data *data, bool mode)
+{
+       int ret;
+       u8 masked_reg;
+       struct i2c_client *client = data->client;
+
+       ret = i2c_smbus_read_byte_data(client, STK8BA50_REG_POWMODE);
+       if (ret < 0)
+               goto exit_err;
+
+       if (mode)
+               masked_reg = ret | STK8BA50_MODE_POWERBIT;
+       else
+               masked_reg = ret & (~STK8BA50_MODE_POWERBIT);
+
+       ret = i2c_smbus_write_byte_data(client, STK8BA50_REG_POWMODE,
+                                       masked_reg);
+       if (ret < 0)
+               goto exit_err;
+
+       return ret;
+
+exit_err:
+       dev_err(&client->dev, "failed to change sensor mode\n");
+       return ret;
 }
 
 static int stk8ba50_read_raw(struct iio_dev *indio_dev,
@@ -105,17 +216,37 @@ static int stk8ba50_read_raw(struct iio_dev *indio_dev,
                             int *val, int *val2, long mask)
 {
        struct stk8ba50_data *data = iio_priv(indio_dev);
+       int ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
+               if (iio_buffer_enabled(indio_dev))
+                       return -EBUSY;
                mutex_lock(&data->lock);
-               *val = stk8ba50_read_accel(data, chan->address);
+               ret = stk8ba50_set_power(data, STK8BA50_MODE_NORMAL);
+               if (ret < 0) {
+                       mutex_unlock(&data->lock);
+                       return -EINVAL;
+               }
+               ret = stk8ba50_read_accel(data, chan->address);
+               if (ret < 0) {
+                       stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+                       mutex_unlock(&data->lock);
+                       return -EINVAL;
+               }
+               *val = sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9);
+               stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
                mutex_unlock(&data->lock);
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
                *val = 0;
-               *val2 = stk8ba50_scale_table[data->range][1];
+               *val2 = stk8ba50_scale_table[data->range].scale_val;
                return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *val = stk8ba50_samp_freq_table
+                               [data->sample_rate_idx].samp_freq;
+               *val2 = 0;
+               return IIO_VAL_INT;
        }
 
        return -EINVAL;
@@ -136,7 +267,7 @@ static int stk8ba50_write_raw(struct iio_dev *indio_dev,
                        return -EINVAL;
 
                for (i = 0; i < ARRAY_SIZE(stk8ba50_scale_table); i++)
-                       if (val2 == stk8ba50_scale_table[i][1]) {
+                       if (val2 == stk8ba50_scale_table[i].scale_val) {
                                index = i;
                                break;
                        }
@@ -145,13 +276,32 @@ static int stk8ba50_write_raw(struct iio_dev *indio_dev,
 
                ret = i2c_smbus_write_byte_data(data->client,
                                STK8BA50_REG_RANGE,
-                               stk8ba50_scale_table[index][0]);
+                               stk8ba50_scale_table[index].reg_val);
                if (ret < 0)
                        dev_err(&data->client->dev,
                                        "failed to set measurement range\n");
                else
                        data->range = index;
 
+               return ret;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               for (i = 0; i < ARRAY_SIZE(stk8ba50_samp_freq_table); i++)
+                       if (val == stk8ba50_samp_freq_table[i].samp_freq) {
+                               index = i;
+                               break;
+                       }
+               if (index < 0)
+                       return -EINVAL;
+
+               ret = i2c_smbus_write_byte_data(data->client,
+                               STK8BA50_REG_BWSEL,
+                               stk8ba50_samp_freq_table[index].reg_val);
+               if (ret < 0)
+                       dev_err(&data->client->dev,
+                                       "failed to set sampling rate\n");
+               else
+                       data->sample_rate_idx = index;
+
                return ret;
        }
 
@@ -165,30 +315,100 @@ static const struct iio_info stk8ba50_info = {
        .attrs                  = &stk8ba50_attribute_group,
 };
 
-static int stk8ba50_set_power(struct stk8ba50_data *data, bool mode)
+static irqreturn_t stk8ba50_trigger_handler(int irq, void *p)
 {
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct stk8ba50_data *data = iio_priv(indio_dev);
+       int bit, ret, i = 0;
+
+       mutex_lock(&data->lock);
+       /*
+        * Do a bulk read if all channels are requested,
+        * from 0x02 (XOUT1) to 0x07 (ZOUT2)
+        */
+       if (*(indio_dev->active_scan_mask) == STK8BA50_ALL_CHANNEL_MASK) {
+               ret = i2c_smbus_read_i2c_block_data(data->client,
+                                                   STK8BA50_REG_XOUT,
+                                                   STK8BA50_ALL_CHANNEL_SIZE,
+                                                   (u8 *)data->buffer);
+               if (ret < STK8BA50_ALL_CHANNEL_SIZE) {
+                       dev_err(&data->client->dev, "register read failed\n");
+                       goto err;
+               }
+       } else {
+               for_each_set_bit(bit, indio_dev->active_scan_mask,
+                                indio_dev->masklength) {
+                       ret = stk8ba50_read_accel(data,
+                                                 stk8ba50_channel_table[bit]);
+                       if (ret < 0)
+                               goto err;
+
+                       data->buffer[i++] = ret;
+               }
+       }
+       iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+                                          pf->timestamp);
+err:
+       mutex_unlock(&data->lock);
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t stk8ba50_data_rdy_trig_poll(int irq, void *private)
+{
+       struct iio_dev *indio_dev = private;
+       struct stk8ba50_data *data = iio_priv(indio_dev);
+
+       if (data->dready_trigger_on)
+               iio_trigger_poll(data->dready_trig);
+
+       return IRQ_HANDLED;
+}
+
+static int stk8ba50_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct stk8ba50_data *data = iio_priv(indio_dev);
+
+       return stk8ba50_set_power(data, STK8BA50_MODE_NORMAL);
+}
+
+static int stk8ba50_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct stk8ba50_data *data = iio_priv(indio_dev);
+
+       return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+}
+
+static const struct iio_buffer_setup_ops stk8ba50_buffer_setup_ops = {
+       .preenable   = stk8ba50_buffer_preenable,
+       .postenable  = iio_triggered_buffer_postenable,
+       .predisable  = iio_triggered_buffer_predisable,
+       .postdisable = stk8ba50_buffer_postdisable,
+};
+
+static int stk8ba50_gpio_probe(struct i2c_client *client)
+{
+       struct device *dev;
+       struct gpio_desc *gpio;
        int ret;
-       u8 masked_reg;
-       struct i2c_client *client = data->client;
 
-       ret = i2c_smbus_read_byte_data(client, STK8BA50_REG_POWMODE);
-       if (ret < 0)
-               goto exit_err;
+       if (!client)
+               return -EINVAL;
 
-       if (mode)
-               masked_reg = ret | STK8BA50_MODE_POWERBIT;
-       else
-               masked_reg = ret & (~STK8BA50_MODE_POWERBIT);
+       dev = &client->dev;
 
-       ret = i2c_smbus_write_byte_data(client, STK8BA50_REG_POWMODE,
-                                       masked_reg);
-       if (ret < 0)
-               goto exit_err;
+       /* data ready gpio interrupt pin */
+       gpio = devm_gpiod_get_index(dev, STK8BA50_GPIO, 0, GPIOD_IN);
+       if (IS_ERR(gpio)) {
+               dev_err(dev, "acpi gpio get index failed\n");
+               return PTR_ERR(gpio);
+       }
 
-       return ret;
+       ret = gpiod_to_irq(gpio);
+       dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
 
-exit_err:
-       dev_err(&client->dev, "failed to change sensor mode\n");
        return ret;
 }
 
@@ -222,28 +442,104 @@ static int stk8ba50_probe(struct i2c_client *client,
                        STK8BA50_REG_SWRST, STK8BA50_RESET_CMD);
        if (ret < 0) {
                dev_err(&client->dev, "failed to reset sensor\n");
-               return ret;
+               goto err_power_off;
        }
 
        /* The default range is +/-2g */
        data->range = 0;
 
+       /* The default sampling rate is 1792 Hz (maximum) */
+       data->sample_rate_idx = STK8BA50_SR_1792HZ_IDX;
+
+       /* Set up interrupts */
+       ret = i2c_smbus_write_byte_data(client,
+                       STK8BA50_REG_INTEN2, STK8BA50_DREADY_INT_MASK);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed to set up interrupts\n");
+               goto err_power_off;
+       }
+       ret = i2c_smbus_write_byte_data(client,
+                       STK8BA50_REG_INTMAP2, STK8BA50_DREADY_INT_MAP);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed to set up interrupts\n");
+               goto err_power_off;
+       }
+
+       if (client->irq < 0)
+               client->irq = stk8ba50_gpio_probe(client);
+
+       if (client->irq >= 0) {
+               ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                               stk8ba50_data_rdy_trig_poll,
+                                               NULL,
+                                               IRQF_TRIGGER_RISING |
+                                               IRQF_ONESHOT,
+                                               STK8BA50_IRQ_NAME,
+                                               indio_dev);
+               if (ret < 0) {
+                       dev_err(&client->dev, "request irq %d failed\n",
+                               client->irq);
+                       goto err_power_off;
+               }
+
+               data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+                                                          "%s-dev%d",
+                                                          indio_dev->name,
+                                                          indio_dev->id);
+               if (!data->dready_trig) {
+                       ret = -ENOMEM;
+                       goto err_power_off;
+               }
+
+               data->dready_trig->dev.parent = &client->dev;
+               data->dready_trig->ops = &stk8ba50_trigger_ops;
+               iio_trigger_set_drvdata(data->dready_trig, indio_dev);
+               ret = iio_trigger_register(data->dready_trig);
+               if (ret) {
+                       dev_err(&client->dev, "iio trigger register failed\n");
+                       goto err_power_off;
+               }
+       }
+
+       ret = iio_triggered_buffer_setup(indio_dev,
+                                        iio_pollfunc_store_time,
+                                        stk8ba50_trigger_handler,
+                                        &stk8ba50_buffer_setup_ops);
+       if (ret < 0) {
+               dev_err(&client->dev, "iio triggered buffer setup failed\n");
+               goto err_trigger_unregister;
+       }
+
        ret = iio_device_register(indio_dev);
        if (ret < 0) {
                dev_err(&client->dev, "device_register failed\n");
-               stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+               goto err_buffer_cleanup;
        }
 
        return ret;
+
+err_buffer_cleanup:
+       iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+       if (data->dready_trig)
+               iio_trigger_unregister(data->dready_trig);
+err_power_off:
+       stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+       return ret;
 }
 
 static int stk8ba50_remove(struct i2c_client *client)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct stk8ba50_data *data = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
 
-       return stk8ba50_set_power(iio_priv(indio_dev), STK8BA50_MODE_SUSPEND);
+       if (data->dready_trig)
+               iio_trigger_unregister(data->dready_trig);
+
+       return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -276,6 +572,7 @@ static const struct i2c_device_id stk8ba50_i2c_id[] = {
        {"stk8ba50", 0},
        {}
 };
+MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id);
 
 static const struct acpi_device_id stk8ba50_acpi_id[] = {
        {"STK8BA50", 0},
index eb0cd897714a26b619b9e6c924ce4c3a65a5806b..50c103d75af90cc86e62d4f77d012954659d2c8e 100644 (file)
@@ -20,6 +20,9 @@ config AD7266
          Say yes here to build support for Analog Devices AD7265 and AD7266
          ADCs.
 
+         To compile this driver as a module, choose M here: the module will be
+         called ad7266.
+
 config AD7291
        tristate "Analog Devices AD7291 ADC driver"
        depends on I2C
@@ -52,8 +55,6 @@ config AD7476
          AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
          AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
 
-         If unsure, say N (but it's safe to say "Y").
-
          To compile this driver as a module, choose M here: the
          module will be called ad7476.
 
@@ -63,8 +64,7 @@ config AD7791
        select AD_SIGMA_DELTA
        help
          Say yes here to build support for Analog Devices AD7787, AD7788, AD7789,
-         AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say
-         N (but it is safe to say "Y").
+         AD7790 and AD7791 SPI analog to digital converters (ADC).
 
          To compile this driver as a module, choose M here: the module will be
          called ad7791.
@@ -76,7 +76,6 @@ config AD7793
        help
          Say yes here to build support for Analog Devices AD7785, AD7792, AD7793,
          AD7794 and AD7795 SPI analog to digital converters (ADC).
-         If unsure, say N (but it's safe to say "Y").
 
          To compile this driver as a module, choose M here: the
          module will be called AD7793.
@@ -89,7 +88,6 @@ config AD7887
        help
          Say yes here to build support for Analog Devices
          AD7887 SPI analog to digital converter (ADC).
-         If unsure, say N (but it's safe to say "Y").
 
          To compile this driver as a module, choose M here: the
          module will be called ad7887.
@@ -117,6 +115,9 @@ config AD799X
          i2c analog to digital converters (ADC). Provides direct access
          via sysfs.
 
+         To compile this driver as a module, choose M here: the module will be
+         called ad799x.
+
 config AT91_ADC
        tristate "Atmel AT91 ADC"
        depends on ARCH_AT91
@@ -127,6 +128,9 @@ config AT91_ADC
        help
          Say yes here to build support for Atmel AT91 ADC.
 
+         To compile this driver as a module, choose M here: the module will be
+         called at91_adc.
+
 config AXP288_ADC
        tristate "X-Powers AXP288 ADC driver"
        depends on MFD_AXP20X
@@ -135,6 +139,9 @@ config AXP288_ADC
          device. Depending on platform configuration, this general purpose ADC can
          be used for sampling sensors such as thermal resistors.
 
+         To compile this driver as a module, choose M here: the module will be
+         called axp288_adc.
+
 config BERLIN2_ADC
        tristate "Marvell Berlin2 ADC driver"
        depends on ARCH_BERLIN
@@ -151,6 +158,9 @@ config DA9150_GPADC
          This driver can also be built as a module. If chosen, the module name
          will be da9150-gpadc.
 
+         To compile this driver as a module, choose M here: the module will be
+         called berlin2-adc.
+
 config CC10001_ADC
        tristate "Cosmic Circuits 10001 ADC driver"
        depends on HAS_IOMEM && HAVE_CLK && REGULATOR
@@ -170,12 +180,18 @@ config EXYNOS_ADC
          of SoCs for drivers such as the touchscreen and hwmon to use to share
          this resource.
 
+         To compile this driver as a module, choose M here: the module will be
+         called exynos_adc.
+
 config LP8788_ADC
        tristate "LP8788 ADC driver"
        depends on MFD_LP8788
        help
          Say yes here to build support for TI LP8788 ADC.
 
+         To compile this driver as a module, choose M here: the module will be
+         called lp8788_adc.
+
 config MAX1027
        tristate "Maxim max1027 ADC driver"
        depends on SPI
@@ -185,6 +201,9 @@ config MAX1027
          Say yes here to build support for Maxim SPI ADC models
          max1027, max1029 and max1031.
 
+         To compile this driver as a module, choose M here: the module will be
+         called max1027.
+
 config MAX1363
        tristate "Maxim max1363 ADC driver"
        depends on I2C
@@ -201,13 +220,16 @@ config MAX1363
          max11646, max11647) Provides direct access via sysfs and buffered
          data via the iio dev interface.
 
+         To compile this driver as a module, choose M here: the module will be
+         called max1363.
+
 config MCP320X
        tristate "Microchip Technology MCP3x01/02/04/08"
        depends on SPI
        help
          Say yes here to build support for Microchip Technology's
-         MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204 or
-         MCP3208 analog to digital converter.
+         MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204,
+         MCP3208 or MCP3301 analog to digital converter.
 
          This driver can also be built as a module. If so, the module will be
          called mcp320x.
@@ -309,15 +331,18 @@ config TI_AM335X_ADC
          Say yes here to build support for Texas Instruments ADC
          driver which is also a MFD client.
 
+         To compile this driver as a module, choose M here: the module will be
+         called ti_am335x_adc.
+
 config TWL4030_MADC
        tristate "TWL4030 MADC (Monitoring A/D Converter)"
        depends on TWL4030_CORE
        help
-       This driver provides support for Triton TWL4030-MADC. The
-       driver supports both RT and SW conversion methods.
+         This driver provides support for Triton TWL4030-MADC. The
+         driver supports both RT and SW conversion methods.
 
-       This driver can also be built as a module. If so, the module will be
-       called twl4030-madc.
+         This driver can also be built as a module. If so, the module will be
+         called twl4030-madc.
 
 config TWL6030_GPADC
        tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
@@ -350,6 +375,9 @@ config VIPERBOARD_ADC
          Say yes here to access the ADC part of the Nano River
          Technologies Viperboard.
 
+         To compile this driver as a module, choose M here: the module will be
+         called viperboard_adc.
+
 config XILINX_XADC
        tristate "Xilinx XADC driver"
        depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
index aecc9ad995ada4809ef928651c1622f9fed6316f..4946d9bf1764302d5250a56852115814acc7be32 100644 (file)
@@ -26,7 +26,7 @@
 #define BERLIN2_SM_CTRL                                0x14
 #define  BERLIN2_SM_CTRL_SM_SOC_INT            BIT(1)
 #define  BERLIN2_SM_CTRL_SOC_SM_INT            BIT(2)
-#define  BERLIN2_SM_CTRL_ADC_SEL(x)            (BIT(x) << 5)   /* 0-15 */
+#define  BERLIN2_SM_CTRL_ADC_SEL(x)            ((x) << 5)      /* 0-15 */
 #define  BERLIN2_SM_CTRL_ADC_SEL_MASK          (0xf << 5)
 #define  BERLIN2_SM_CTRL_ADC_POWER             BIT(9)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2       (0x0 << 10)
 #define  BERLIN2_SM_ADC_MASK                   0x3ff
 #define BERLIN2_SM_ADC_STATUS                  0x1c
 #define  BERLIN2_SM_ADC_STATUS_DATA_RDY(x)     BIT(x)          /* 0-15 */
-#define  BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK   0xf
+#define  BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK   GENMASK(15, 0)
 #define  BERLIN2_SM_ADC_STATUS_INT_EN(x)       (BIT(x) << 16)  /* 0-15 */
-#define  BERLIN2_SM_ADC_STATUS_INT_EN_MASK     (0xf << 16)
+#define  BERLIN2_SM_ADC_STATUS_INT_EN_MASK     GENMASK(31, 16)
 #define BERLIN2_SM_TSEN_STATUS                 0x24
 #define  BERLIN2_SM_TSEN_STATUS_DATA_RDY       BIT(0)
 #define  BERLIN2_SM_TSEN_STATUS_INT_EN         BIT(1)
 #define BERLIN2_SM_TSEN_DATA                   0x28
-#define  BERLIN2_SM_TSEN_MASK                  0xfff
+#define  BERLIN2_SM_TSEN_MASK                  GENMASK(9, 0)
 #define BERLIN2_SM_TSEN_CTRL                   0x74
 #define  BERLIN2_SM_TSEN_CTRL_START            BIT(8)
 #define  BERLIN2_SM_TSEN_CTRL_SETTLING_4       (0x0 << 21)     /* 4 us */
@@ -86,7 +86,7 @@ struct berlin2_adc_priv {
                        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
                }
 
-static struct iio_chan_spec berlin2_adc_channels[] = {
+static const struct iio_chan_spec berlin2_adc_channels[] = {
        BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE),    /* external input */
        BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE),    /* external input */
        BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE),    /* external input */
@@ -103,7 +103,6 @@ static struct iio_chan_spec berlin2_adc_channels[] = {
        BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE),    /* reserved */
        IIO_CHAN_SOFT_TIMESTAMP(8),             /* timestamp */
 };
-#define BERLIN2_N_CHANNELS     ARRAY_SIZE(berlin2_adc_channels)
 
 static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
 {
@@ -221,7 +220,7 @@ static int berlin2_adc_read_raw(struct iio_dev *indio_dev,
                        return temp;
 
                if (temp > 2047)
-                       temp = -(4096 - temp);
+                       temp -= 4096;
 
                /* Convert to milli Celsius */
                *val = ((temp * 100000) / 264 - 270000);
@@ -286,8 +285,7 @@ static int berlin2_adc_probe(struct platform_device *pdev)
        int irq, tsen_irq;
        int ret;
 
-       indio_dev = devm_iio_device_alloc(&pdev->dev,
-                                         sizeof(struct berlin2_adc_priv));
+       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
        if (!indio_dev)
                return -ENOMEM;
 
@@ -301,11 +299,11 @@ static int berlin2_adc_probe(struct platform_device *pdev)
 
        irq = platform_get_irq_byname(pdev, "adc");
        if (irq < 0)
-               return -ENODEV;
+               return irq;
 
        tsen_irq = platform_get_irq_byname(pdev, "tsen");
        if (tsen_irq < 0)
-               return -ENODEV;
+               return tsen_irq;
 
        ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
                        pdev->dev.driver->name, indio_dev);
@@ -325,8 +323,8 @@ static int berlin2_adc_probe(struct platform_device *pdev)
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &berlin2_adc_info;
 
-       indio_dev->num_channels = BERLIN2_N_CHANNELS;
        indio_dev->channels = berlin2_adc_channels;
+       indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels);
 
        /* Power up the ADC */
        regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
index 115f6e99a7fa7c603ca9655d04759545c48e5932..8254f529b2a9a00738eb017f9e5d0f77c4aacfd8 100644 (file)
@@ -62,6 +62,7 @@ struct cc10001_adc_device {
        struct regulator *reg;
        u16 *buf;
 
+       bool shared;
        struct mutex lock;
        unsigned int start_delay_ns;
        unsigned int eoc_delay_ns;
@@ -153,7 +154,8 @@ static irqreturn_t cc10001_adc_trigger_h(int irq, void *p)
 
        mutex_lock(&adc_dev->lock);
 
-       cc10001_adc_power_up(adc_dev);
+       if (!adc_dev->shared)
+               cc10001_adc_power_up(adc_dev);
 
        /* Calculate delay step for eoc and sampled data */
        delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT;
@@ -177,7 +179,8 @@ static irqreturn_t cc10001_adc_trigger_h(int irq, void *p)
        }
 
 done:
-       cc10001_adc_power_down(adc_dev);
+       if (!adc_dev->shared)
+               cc10001_adc_power_down(adc_dev);
 
        mutex_unlock(&adc_dev->lock);
 
@@ -196,7 +199,8 @@ static u16 cc10001_adc_read_raw_voltage(struct iio_dev *indio_dev,
        unsigned int delay_ns;
        u16 val;
 
-       cc10001_adc_power_up(adc_dev);
+       if (!adc_dev->shared)
+               cc10001_adc_power_up(adc_dev);
 
        /* Calculate delay step for eoc and sampled data */
        delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT;
@@ -205,7 +209,8 @@ static u16 cc10001_adc_read_raw_voltage(struct iio_dev *indio_dev,
 
        val = cc10001_adc_poll_done(indio_dev, chan->channel, delay_ns);
 
-       cc10001_adc_power_down(adc_dev);
+       if (!adc_dev->shared)
+               cc10001_adc_power_down(adc_dev);
 
        return val;
 }
@@ -322,8 +327,10 @@ static int cc10001_adc_probe(struct platform_device *pdev)
        adc_dev = iio_priv(indio_dev);
 
        channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0);
-       if (!of_property_read_u32(node, "adc-reserved-channels", &ret))
+       if (!of_property_read_u32(node, "adc-reserved-channels", &ret)) {
+               adc_dev->shared = true;
                channel_map &= ~ret;
+       }
 
        adc_dev->reg = devm_regulator_get(&pdev->dev, "vref");
        if (IS_ERR(adc_dev->reg))
@@ -368,6 +375,14 @@ static int cc10001_adc_probe(struct platform_device *pdev)
        adc_dev->eoc_delay_ns = NSEC_PER_SEC / adc_clk_rate;
        adc_dev->start_delay_ns = adc_dev->eoc_delay_ns * CC10001_WAIT_CYCLES;
 
+       /*
+        * There is only one register to power-up/power-down the AUX ADC.
+        * If the ADC is shared among multiple CPUs, always power it up here.
+        * If the ADC is used only by the MIPS, power-up/power-down at runtime.
+        */
+       if (adc_dev->shared)
+               cc10001_adc_power_up(adc_dev);
+
        /* Setup the ADC channels available on the device */
        ret = cc10001_adc_channel_init(indio_dev, channel_map);
        if (ret < 0)
@@ -402,6 +417,7 @@ static int cc10001_adc_remove(struct platform_device *pdev)
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
        struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
 
+       cc10001_adc_power_down(adc_dev);
        iio_device_unregister(indio_dev);
        iio_triggered_buffer_cleanup(indio_dev);
        clk_disable_unprepare(adc_dev->adc_clk);
index d819823f725747e5cd4ac8bcb50d3d833093ed2c..b19e4f9d16e0ded7ba602ccb8269369720a64dee 100644 (file)
@@ -25,6 +25,7 @@
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf  mcp3201
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf  mcp3202
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf  mcp3204/08
+ * http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf  mcp3301
  *
  * 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
@@ -47,6 +48,7 @@ enum {
        mcp3202,
        mcp3204,
        mcp3208,
+       mcp3301,
 };
 
 struct mcp320x_chip_info {
@@ -76,6 +78,7 @@ static int mcp320x_channel_to_tx_data(int device_index,
        switch (device_index) {
        case mcp3001:
        case mcp3201:
+       case mcp3301:
                return 0;
        case mcp3002:
        case mcp3202:
@@ -102,7 +105,7 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
        adc->tx_buf = mcp320x_channel_to_tx_data(device_index,
                                                channel, differential);
 
-       if (device_index != mcp3001 && device_index != mcp3201) {
+       if (device_index != mcp3001 && device_index != mcp3201 && device_index != mcp3301) {
                ret = spi_sync(adc->spi, &adc->msg);
                if (ret < 0)
                        return ret;
@@ -125,6 +128,8 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
        case mcp3204:
        case mcp3208:
                return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+       case mcp3301:
+               return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12);
        default:
                return -EINVAL;
        }
@@ -274,6 +279,11 @@ static const struct mcp320x_chip_info mcp320x_chip_infos[] = {
                .num_channels = ARRAY_SIZE(mcp3208_channels),
                .resolution = 12
        },
+       [mcp3301] = {
+               .channels = mcp3201_channels,
+               .num_channels = ARRAY_SIZE(mcp3201_channels),
+               .resolution = 13
+       },
 };
 
 static int mcp320x_probe(struct spi_device *spi)
@@ -368,6 +378,9 @@ static const struct of_device_id mcp320x_dt_ids[] = {
        }, {
                .compatible = "mcp3208",
                .data = &mcp320x_chip_infos[mcp3208],
+       }, {
+               .compatible = "mcp3301",
+               .data = &mcp320x_chip_infos[mcp3301],
        }, {
        }
 };
@@ -383,6 +396,7 @@ static const struct spi_device_id mcp320x_id[] = {
        { "mcp3202", mcp3202 },
        { "mcp3204", mcp3204 },
        { "mcp3208", mcp3208 },
+       { "mcp3301", mcp3301 },
        { }
 };
 MODULE_DEVICE_TABLE(spi, mcp320x_id);
index b96c636470ef504e3b7f3d5612602bcc76a3a3a0..3555122008b4408950f10e860eff61647dcc71a7 100644 (file)
@@ -404,7 +404,6 @@ MODULE_DEVICE_TABLE(of, mcp3422_of_match);
 static struct i2c_driver mcp3422_driver = {
        .driver = {
                .name = "mcp3422",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(mcp3422_of_match),
        },
        .probe = mcp3422_probe,
index b3a82b4d1a7587b586077982f27856dcfdb7dee5..2c8374f8625201ea0578a1669490e3be65230abf 100644 (file)
@@ -140,7 +140,6 @@ MODULE_DEVICE_TABLE(of, adc081c_of_match);
 static struct i2c_driver adc081c_driver = {
        .driver = {
                .name = "adc081c",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(adc081c_of_match),
        },
        .probe = adc081c_probe,
index 819632bf1fda7fee8fddd2acb3c02d9ff112b1ff..6bf4c20eb231a40754e578b704c6ea17c87e5a3d 100644 (file)
@@ -68,6 +68,9 @@
 #define VF610_ADC_CLK_DIV8             0x60
 #define VF610_ADC_CLK_MASK             0x60
 #define VF610_ADC_ADLSMP_LONG          0x10
+#define VF610_ADC_ADSTS_SHORT   0x100
+#define VF610_ADC_ADSTS_NORMAL  0x200
+#define VF610_ADC_ADSTS_LONG    0x300
 #define VF610_ADC_ADSTS_MASK           0x300
 #define VF610_ADC_ADLPC_EN             0x80
 #define VF610_ADC_ADHSC_EN             0x400
 #define VF610_ADC_CALF                 0x2
 #define VF610_ADC_TIMEOUT              msecs_to_jiffies(100)
 
+#define DEFAULT_SAMPLE_TIME            1000
+
 enum clk_sel {
        VF610_ADCIOC_BUSCLK_SET,
        VF610_ADCIOC_ALTCLK_SET,
@@ -124,6 +129,17 @@ enum conversion_mode_sel {
        VF610_ADC_CONV_LOW_POWER,
 };
 
+enum lst_adder_sel {
+       VF610_ADCK_CYCLES_3,
+       VF610_ADCK_CYCLES_5,
+       VF610_ADCK_CYCLES_7,
+       VF610_ADCK_CYCLES_9,
+       VF610_ADCK_CYCLES_13,
+       VF610_ADCK_CYCLES_17,
+       VF610_ADCK_CYCLES_21,
+       VF610_ADCK_CYCLES_25,
+};
+
 struct vf610_adc_feature {
        enum clk_sel    clk_sel;
        enum vol_ref    vol_ref;
@@ -132,6 +148,8 @@ struct vf610_adc_feature {
        int     clk_div;
        int     sample_rate;
        int     res_mode;
+       u32 lst_adder_index;
+       u32 default_sample_time;
 
        bool    calibration;
        bool    ovwren;
@@ -155,11 +173,13 @@ struct vf610_adc {
 };
 
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
+static const u32 vf610_lst_adder[] = { 3, 5, 7, 9, 13, 17, 21, 25 };
 
 static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
 {
        struct vf610_adc_feature *adc_feature = &info->adc_feature;
        unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
+       u32 adck_period, lst_addr_min;
        int divisor, i;
 
        adck_rate = info->max_adck_rate[adc_feature->conv_mode];
@@ -173,6 +193,19 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
                adc_feature->clk_div = 8;
        }
 
+       /*
+        * Determine the long sample time adder value to be used based
+        * on the default minimum sample time provided.
+        */
+       adck_period = NSEC_PER_SEC / adck_rate;
+       lst_addr_min = adc_feature->default_sample_time / adck_period;
+       for (i = 0; i < ARRAY_SIZE(vf610_lst_adder); i++) {
+               if (vf610_lst_adder[i] > lst_addr_min) {
+                       adc_feature->lst_adder_index = i;
+                       break;
+               }
+       }
+
        /*
         * Calculate ADC sample frequencies
         * Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
@@ -182,12 +215,13 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
         * SFCAdder: fixed to 6 ADCK cycles
         * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
         * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
-        * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
+        * LSTAdder(Long Sample Time): 3, 5, 7, 9, 13, 17, 21, 25 ADCK cycles
         */
        adck_rate = ipg_rate / info->adc_feature.clk_div;
        for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
                info->sample_freq_avail[i] =
-                       adck_rate / (6 + vf610_hw_avgs[i] * (25 + 3));
+                       adck_rate / (6 + vf610_hw_avgs[i] *
+                        (25 + vf610_lst_adder[adc_feature->lst_adder_index]));
 }
 
 static inline void vf610_adc_cfg_init(struct vf610_adc *info)
@@ -347,8 +381,40 @@ static void vf610_adc_sample_set(struct vf610_adc *info)
                break;
        }
 
-       /* Use the short sample mode */
-       cfg_data &= ~(VF610_ADC_ADLSMP_LONG | VF610_ADC_ADSTS_MASK);
+       /*
+        * Set ADLSMP and ADSTS based on the Long Sample Time Adder value
+        * determined.
+        */
+       switch (adc_feature->lst_adder_index) {
+       case VF610_ADCK_CYCLES_3:
+               break;
+       case VF610_ADCK_CYCLES_5:
+               cfg_data |= VF610_ADC_ADSTS_SHORT;
+               break;
+       case VF610_ADCK_CYCLES_7:
+               cfg_data |= VF610_ADC_ADSTS_NORMAL;
+               break;
+       case VF610_ADCK_CYCLES_9:
+               cfg_data |= VF610_ADC_ADSTS_LONG;
+               break;
+       case VF610_ADCK_CYCLES_13:
+               cfg_data |= VF610_ADC_ADLSMP_LONG;
+               break;
+       case VF610_ADCK_CYCLES_17:
+               cfg_data |= VF610_ADC_ADLSMP_LONG;
+               cfg_data |= VF610_ADC_ADSTS_SHORT;
+               break;
+       case VF610_ADCK_CYCLES_21:
+               cfg_data |= VF610_ADC_ADLSMP_LONG;
+               cfg_data |= VF610_ADC_ADSTS_NORMAL;
+               break;
+       case VF610_ADCK_CYCLES_25:
+               cfg_data |= VF610_ADC_ADLSMP_LONG;
+               cfg_data |= VF610_ADC_ADSTS_NORMAL;
+               break;
+       default:
+               dev_err(info->dev, "error in sample time select\n");
+       }
 
        /* update hardware average selection */
        cfg_data &= ~VF610_ADC_AVGS_MASK;
@@ -713,6 +779,11 @@ static int vf610_adc_probe(struct platform_device *pdev)
        of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency",
                        info->max_adck_rate, 3);
 
+       ret = of_property_read_u32(pdev->dev.of_node, "min-sample-time",
+                       &info->adc_feature.default_sample_time);
+       if (ret)
+               info->adc_feature.default_sample_time = DEFAULT_SAMPLE_TIME;
+
        platform_set_drvdata(pdev, indio_dev);
 
        init_completion(&info->completion);
index 9a40097e7cf81439933c892d7bfc205cc43d69d7..d338bb595db3eda0ec2d472b62ef8a195f09e1e8 100644 (file)
@@ -700,7 +700,6 @@ static struct spi_driver ssp_driver = {
        .remove = ssp_remove,
        .driver = {
                .pm = &ssp_pm_ops,
-               .bus = &spi_bus_type,
                .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(ssp_of_match),
                .name = "sensorhub"
index 8086cbcff87db48a2ad0695d5a031e009b821662..2e7fdb502645b66f7042220c7d06df7166bde5c4 100644 (file)
@@ -126,6 +126,9 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
        int err, i = 0;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
+       if (sdata->sensor_settings->fs.addr == 0)
+               return 0;
+
        err = st_sensors_match_fs(sdata->sensor_settings, fs, &i);
        if (err < 0)
                goto st_accel_set_fullscale_error;
@@ -479,46 +482,43 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
                        int num_sensors_list,
                        const struct st_sensor_settings *sensor_settings)
 {
-       u8 wai;
        int i, n, err;
+       u8 wai;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
-       err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
-                                       ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
-       if (err < 0) {
-               dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
-               goto read_wai_error;
-       }
-
        for (i = 0; i < num_sensors_list; i++) {
-               if (sensor_settings[i].wai == wai)
+               for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
+                       if (strcmp(indio_dev->name,
+                               sensor_settings[i].sensors_supported[n]) == 0) {
+                               break;
+                       }
+               }
+               if (n < ST_SENSORS_MAX_4WAI)
                        break;
        }
-       if (i == num_sensors_list)
-               goto device_not_supported;
+       if (i == num_sensors_list) {
+               dev_err(&indio_dev->dev, "device name %s not recognized.\n",
+                                                       indio_dev->name);
+               return -ENODEV;
+       }
 
-       for (n = 0; n < ARRAY_SIZE(sensor_settings[i].sensors_supported); n++) {
-               if (strcmp(indio_dev->name,
-                               &sensor_settings[i].sensors_supported[n][0]) == 0)
-                       break;
+       err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
+                                       sensor_settings[i].wai_addr, &wai);
+       if (err < 0) {
+               dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
+               return err;
        }
-       if (n == ARRAY_SIZE(sensor_settings[i].sensors_supported)) {
-               dev_err(&indio_dev->dev, "device name \"%s\" and WhoAmI (0x%02x) mismatch",
-                       indio_dev->name, wai);
-               goto sensor_name_mismatch;
+
+       if (sensor_settings[i].wai != wai) {
+               dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n",
+                                               indio_dev->name, wai);
+               return -EINVAL;
        }
 
        sdata->sensor_settings =
                        (struct st_sensor_settings *)&sensor_settings[i];
 
        return i;
-
-device_not_supported:
-       dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
-sensor_name_mismatch:
-       err = -ENODEV;
-read_wai_error:
-       return err;
 }
 EXPORT_SYMBOL(st_sensors_check_device_support);
 
index f03b92fd38031e67cb4e999991148a946f9a859a..c067e682149600f5d65eab9d442744f2fd6e9f62 100644 (file)
@@ -630,7 +630,6 @@ MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
 static struct i2c_driver ad5064_i2c_driver = {
        .driver = {
                   .name = "ad5064",
-                  .owner = THIS_MODULE,
        },
        .probe = ad5064_i2c_probe,
        .remove = ad5064_i2c_remove,
index 9de4c4d382803056cd8645c52a60dac7ccf0f885..130de9b3e0bf4d0d969a87d7c1d62c3114e77848 100644 (file)
@@ -593,7 +593,6 @@ MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids);
 static struct i2c_driver ad5380_i2c_driver = {
        .driver = {
                   .name = "ad5380",
-                  .owner = THIS_MODULE,
        },
        .probe = ad5380_i2c_probe,
        .remove = ad5380_i2c_remove,
index 46bb62a5c1d4d62ad279a791d281253cfc4c356b..07e17d72a3f3d13922684c85dab2b6a13811c702 100644 (file)
@@ -569,7 +569,6 @@ MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids);
 static struct i2c_driver ad5446_i2c_driver = {
        .driver = {
                   .name = "ad5446",
-                  .owner = THIS_MODULE,
        },
        .probe = ad5446_i2c_probe,
        .remove = ad5446_i2c_remove,
index 6e914495b346450c6ebdb2bf75851de278a98863..28b8748ea8242277e0e0a9aff187c23493096e8d 100644 (file)
@@ -392,7 +392,6 @@ static struct i2c_driver max5821_driver = {
        .driver = {
                .name   = "max5821",
                .pm     = MAX5821_PM_OPS,
-               .owner  = THIS_MODULE,
        },
        .probe          = max5821_probe,
        .remove         = max5821_remove,
index 10a0dfc3b01fa8045a9c20bf597e3b1110b57d2e..9890c81c027d30b370483c3bdd778c0fcec4e79f 100644 (file)
@@ -72,7 +72,6 @@ static int adf4350_sync_config(struct adf4350_state *st)
        for (i = ADF4350_REG5; i >= ADF4350_REG0; i--) {
                if ((st->regs_hw[i] != st->regs[i]) ||
                        ((i == ADF4350_REG0) && doublebuf)) {
-
                        switch (i) {
                        case ADF4350_REG1:
                        case ADF4350_REG4:
index b3d0e94f72eb740640e9999d749fce3bc701fc68..8d2439345673989aeac41d40eebf33e00aac9c99 100644 (file)
@@ -53,7 +53,8 @@ config ADXRS450
 config BMG160
        tristate "BOSCH BMG160 Gyro Sensor"
        depends on I2C
-       select IIO_TRIGGERED_BUFFER if IIO_BUFFER
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor
          driver. This driver also supports BMI055 gyroscope.
index 591bd555e1f39781f15401646e18a69f5cf1b6b8..26de876b223d07cb7d51c437d3dec0047bf7a2ce 100644 (file)
@@ -473,6 +473,7 @@ enum adis16136_id {
        ID_ADIS16133,
        ID_ADIS16135,
        ID_ADIS16136,
+       ID_ADIS16137,
 };
 
 static const struct adis16136_chip_info adis16136_chip_info[] = {
@@ -488,6 +489,10 @@ static const struct adis16136_chip_info adis16136_chip_info[] = {
                .precision = IIO_DEGREE_TO_RAD(450),
                .fullscale = 24623,
        },
+       [ID_ADIS16137] = {
+               .precision = IIO_DEGREE_TO_RAD(1000),
+               .fullscale = 24609,
+       },
 };
 
 static int adis16136_probe(struct spi_device *spi)
@@ -557,6 +562,7 @@ static const struct spi_device_id adis16136_ids[] = {
        { "adis16133", ID_ADIS16133 },
        { "adis16135", ID_ADIS16135 },
        { "adis16136", ID_ADIS16136 },
+       { "adis16137", ID_ADIS16137 },
        { }
 };
 MODULE_DEVICE_TABLE(spi, adis16136_ids);
index 75fe0edd3d0f98a1953538de74c5e6a056415afa..00c6ad9bf35f74fcd903cd824ee3c10c19e2d5b0 100644 (file)
 #define ADIS16260_SCAN_TEMP    3
 #define ADIS16260_SCAN_ANGL    4
 
-/* Power down the device */
-static int adis16260_stop_device(struct iio_dev *indio_dev)
-{
-       struct adis *adis = iio_priv(indio_dev);
-       int ret;
-       u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+struct adis16260_chip_info {
+       unsigned int gyro_max_val;
+       unsigned int gyro_max_scale;
+       const struct iio_chan_spec *channels;
+       unsigned int num_channels;
+};
 
-       ret = adis_write_reg_16(adis, ADIS16260_SLP_CNT, val);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+struct adis16260 {
+       const struct adis16260_chip_info *info;
 
-       return ret;
-}
+       struct adis adis;
+};
+
+enum adis16260_type {
+       ADIS16251,
+       ADIS16260,
+       ADIS16266,
+};
 
 static const struct iio_chan_spec adis16260_channels[] = {
        ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
@@ -131,6 +136,55 @@ static const struct iio_chan_spec adis16260_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 
+static const struct iio_chan_spec adis16266_channels[] = {
+       ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
+               BIT(IIO_CHAN_INFO_CALIBBIAS) |
+               BIT(IIO_CHAN_INFO_CALIBSCALE),
+               BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+       ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
+               BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+       ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
+               BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+       ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
+               BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+       IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct adis16260_chip_info adis16260_chip_info_table[] = {
+       [ADIS16251] = {
+               .gyro_max_scale = 80,
+               .gyro_max_val = IIO_RAD_TO_DEGREE(4368),
+               .channels = adis16260_channels,
+               .num_channels = ARRAY_SIZE(adis16260_channels),
+       },
+       [ADIS16260] = {
+               .gyro_max_scale = 320,
+               .gyro_max_val = IIO_RAD_TO_DEGREE(4368),
+               .channels = adis16260_channels,
+               .num_channels = ARRAY_SIZE(adis16260_channels),
+       },
+       [ADIS16266] = {
+               .gyro_max_scale = 14000,
+               .gyro_max_val = IIO_RAD_TO_DEGREE(3357),
+               .channels = adis16266_channels,
+               .num_channels = ARRAY_SIZE(adis16266_channels),
+       },
+};
+
+/* Power down the device */
+static int adis16260_stop_device(struct iio_dev *indio_dev)
+{
+       struct adis16260 *adis16260 = iio_priv(indio_dev);
+       int ret;
+       u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+
+       ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
+       if (ret)
+               dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+
+       return ret;
+}
+
 static const u8 adis16260_addresses[][2] = {
        [ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
 };
@@ -140,7 +194,9 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                              int *val, int *val2,
                              long mask)
 {
-       struct adis *adis = iio_priv(indio_dev);
+       struct adis16260 *adis16260 = iio_priv(indio_dev);
+       const struct adis16260_chip_info *info = adis16260->info;
+       struct adis *adis = &adis16260->adis;
        int ret;
        u8 addr;
        s16 val16;
@@ -152,15 +208,9 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_ANGL_VEL:
-                       *val = 0;
-                       if (spi_get_device_id(adis->spi)->driver_data) {
-                               /* 0.01832 degree / sec */
-                               *val2 = IIO_DEGREE_TO_RAD(18320);
-                       } else {
-                               /* 0.07326 degree / sec */
-                               *val2 = IIO_DEGREE_TO_RAD(73260);
-                       }
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val = info->gyro_max_scale;
+                       *val2 = info->gyro_max_val;
+                       return IIO_VAL_FRACTIONAL;
                case IIO_INCLI:
                        *val = 0;
                        *val2 = IIO_DEGREE_TO_RAD(36630);
@@ -224,7 +274,8 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
                               int val2,
                               long mask)
 {
-       struct adis *adis = iio_priv(indio_dev);
+       struct adis16260 *adis16260 = iio_priv(indio_dev);
+       struct adis *adis = &adis16260->adis;
        int ret;
        u8 addr;
        u8 t;
@@ -305,35 +356,42 @@ static const struct adis_data adis16260_data = {
 
 static int adis16260_probe(struct spi_device *spi)
 {
+       const struct spi_device_id *id;
+       struct adis16260 *adis16260;
        struct iio_dev *indio_dev;
-       struct adis *adis;
        int ret;
 
+       id = spi_get_device_id(spi);
+       if (!id)
+               return -ENODEV;
+
        /* setup the industrialio driver allocated elements */
-       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis));
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
        if (!indio_dev)
                return -ENOMEM;
-       adis = iio_priv(indio_dev);
+       adis16260 = iio_priv(indio_dev);
        /* this is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
 
-       indio_dev->name = spi_get_device_id(spi)->name;
+       adis16260->info = &adis16260_chip_info_table[id->driver_data];
+
+       indio_dev->name = id->name;
        indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16260_info;
-       indio_dev->channels = adis16260_channels;
-       indio_dev->num_channels = ARRAY_SIZE(adis16260_channels);
+       indio_dev->channels = adis16260->info->channels;
+       indio_dev->num_channels = adis16260->info->num_channels;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       ret = adis_init(adis, indio_dev, spi, &adis16260_data);
+       ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
        if (ret)
                return ret;
 
-       ret = adis_setup_buffer_and_trigger(adis, indio_dev, NULL);
+       ret = adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
        if (ret)
                return ret;
 
        /* Get the device into a sane initial state */
-       ret = adis_initial_startup(adis);
+       ret = adis_initial_startup(&adis16260->adis);
        if (ret)
                goto error_cleanup_buffer_trigger;
        ret = iio_device_register(indio_dev);
@@ -343,18 +401,18 @@ static int adis16260_probe(struct spi_device *spi)
        return 0;
 
 error_cleanup_buffer_trigger:
-       adis_cleanup_buffer_and_trigger(adis, indio_dev);
+       adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
        return ret;
 }
 
 static int adis16260_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
-       struct adis *adis = iio_priv(indio_dev);
+       struct adis16260 *adis16260 = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
        adis16260_stop_device(indio_dev);
-       adis_cleanup_buffer_and_trigger(adis, indio_dev);
+       adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
 
        return 0;
 }
@@ -364,11 +422,12 @@ static int adis16260_remove(struct spi_device *spi)
  * support for the on chip filtering.
  */
 static const struct spi_device_id adis16260_id[] = {
-       {"adis16260", 0},
-       {"adis16265", 0},
-       {"adis16250", 0},
-       {"adis16255", 0},
-       {"adis16251", 1},
+       {"adis16260", ADIS16260},
+       {"adis16265", ADIS16260},
+       {"adis16266", ADIS16266},
+       {"adis16250", ADIS16260},
+       {"adis16255", ADIS16260},
+       {"adis16251", ADIS16251},
        {}
 };
 MODULE_DEVICE_TABLE(spi, adis16260_id);
index f0fd94055d8858b722a5572b564edf0de125a90b..c102a6325bb00d287ac710079b63eeca2e22fd80 100644 (file)
@@ -379,7 +379,6 @@ MODULE_DEVICE_TABLE(i2c, itg3200_id);
 
 static struct i2c_driver itg3200_driver = {
        .driver = {
-               .owner  = THIS_MODULE,
                .name   = "itg3200",
                .pm     = &itg3200_pm_ops,
        },
index ffe96642b6d049569d73356a1df541782657a912..4b993a5bc9a1196dab5ff91bfa6084ed006ed89b 100644 (file)
@@ -131,6 +131,7 @@ static const struct iio_chan_spec st_gyro_16bit_channels[] = {
 static const struct st_sensor_settings st_gyro_sensors_settings[] = {
        {
                .wai = ST_GYRO_1_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = L3G4200D_GYRO_DEV_NAME,
                        [1] = LSM330DL_GYRO_DEV_NAME,
@@ -190,6 +191,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
        },
        {
                .wai = ST_GYRO_2_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = L3GD20_GYRO_DEV_NAME,
                        [1] = LSM330D_GYRO_DEV_NAME,
@@ -252,6 +254,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
        },
        {
                .wai = ST_GYRO_3_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = L3GD20_GYRO_DEV_NAME,
                },
index 64480b16c6895373c626b47d250c17500cc03311..6848451f817a239bc853f8bd90eda7aa98935282 100644 (file)
@@ -99,7 +99,6 @@ MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
 
 static struct i2c_driver st_gyro_driver = {
        .driver = {
-               .owner = THIS_MODULE,
                .name = "st-gyro-i2c",
                .of_match_table = of_match_ptr(st_gyro_of_match),
        },
index 7d79a1ac5f5f09ba332fee3ebb94c486280ce024..1165b1c4f9d67bd93db24f784da5b13010d9fd99 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/timekeeping.h>
 
 #include <linux/iio/iio.h>
 
@@ -46,7 +47,8 @@
  * Note that when reading the sensor actually 84 edges are detected, but
  * since the last edge is not significant, we only store 83:
  */
-#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
+#define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
+                             DHT11_EDGES_PREAMBLE + 1)
 
 /* Data transmission timing (nano seconds) */
 #define DHT11_START_TRANSMISSION       18  /* ms */
@@ -62,6 +64,7 @@ struct dht11 {
        int                             irq;
 
        struct completion               completion;
+       /* The iio sysfs interface doesn't prevent concurrent reads: */
        struct mutex                    lock;
 
        s64                             timestamp;
@@ -87,32 +90,20 @@ static unsigned char dht11_decode_byte(int *timing, int threshold)
        return ret;
 }
 
-static int dht11_decode(struct dht11 *dht11, int offset)
+static int dht11_decode(struct dht11 *dht11, int offset, int timeres)
 {
-       int i, t, timing[DHT11_BITS_PER_READ], threshold,
-               timeres = DHT11_SENSOR_RESPONSE;
+       int i, t, timing[DHT11_BITS_PER_READ], threshold;
        unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
 
-       /* Calculate timestamp resolution */
-       for (i = 1; i < dht11->num_edges; ++i) {
-               t = dht11->edges[i].ts - dht11->edges[i-1].ts;
-               if (t > 0 && t < timeres)
-                       timeres = t;
-       }
-       if (2*timeres > DHT11_DATA_BIT_HIGH) {
-               pr_err("dht11: timeresolution %d too bad for decoding\n",
-                       timeres);
-               return -EIO;
-       }
        threshold = DHT11_DATA_BIT_HIGH / timeres;
-       if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold)
+       if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold)
                pr_err("dht11: WARNING: decoding ambiguous\n");
 
        /* scale down with timeres and check validity */
        for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
-               t = dht11->edges[offset + 2*i + 2].ts -
-                       dht11->edges[offset + 2*i + 1].ts;
-               if (!dht11->edges[offset + 2*i + 1].value)
+               t = dht11->edges[offset + 2 * i + 2].ts -
+                       dht11->edges[offset + 2 * i + 1].ts;
+               if (!dht11->edges[offset + 2 * i + 1].value)
                        return -EIO;  /* lost synchronisation */
                timing[i] = t / timeres;
        }
@@ -126,7 +117,7 @@ static int dht11_decode(struct dht11 *dht11, int offset)
        if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
                return -EIO;
 
-       dht11->timestamp = iio_get_time_ns();
+       dht11->timestamp = ktime_get_real_ns();
        if (hum_int < 20) {  /* DHT22 */
                dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
                                        ((temp_int & 0x80) ? -100 : 100);
@@ -154,7 +145,7 @@ static irqreturn_t dht11_handle_irq(int irq, void *data)
 
        /* TODO: Consider making the handler safe for IRQ sharing */
        if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
-               dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+               dht11->edges[dht11->num_edges].ts = ktime_get_real_ns();
                dht11->edges[dht11->num_edges++].value =
                                                gpio_get_value(dht11->gpio);
 
@@ -166,14 +157,26 @@ static irqreturn_t dht11_handle_irq(int irq, void *data)
 }
 
 static int dht11_read_raw(struct iio_dev *iio_dev,
-                       const struct iio_chan_spec *chan,
+                         const struct iio_chan_spec *chan,
                        int *val, int *val2, long m)
 {
        struct dht11 *dht11 = iio_priv(iio_dev);
-       int ret;
+       int ret, timeres;
 
        mutex_lock(&dht11->lock);
-       if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
+       if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) {
+               timeres = ktime_get_resolution_ns();
+               if (DHT11_DATA_BIT_HIGH < 2 * timeres) {
+                       dev_err(dht11->dev, "timeresolution %dns too low\n",
+                               timeres);
+                       /* In theory a better clock could become available
+                        * at some point ... and there is no error code
+                        * that really fits better.
+                        */
+                       ret = -EAGAIN;
+                       goto err;
+               }
+
                reinit_completion(&dht11->completion);
 
                dht11->num_edges = 0;
@@ -192,13 +195,13 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                        goto err;
 
                ret = wait_for_completion_killable_timeout(&dht11->completion,
-                                                                HZ);
+                                                          HZ);
 
                free_irq(dht11->irq, iio_dev);
 
                if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
                        dev_err(&iio_dev->dev,
-                                       "Only %d signal edges detected\n",
+                               "Only %d signal edges detected\n",
                                        dht11->num_edges);
                        ret = -ETIMEDOUT;
                }
@@ -206,9 +209,10 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                        goto err;
 
                ret = dht11_decode(dht11,
-                               dht11->num_edges == DHT11_EDGES_PER_READ ?
+                                  dht11->num_edges == DHT11_EDGES_PER_READ ?
                                        DHT11_EDGES_PREAMBLE :
-                                       DHT11_EDGES_PREAMBLE - 2);
+                                       DHT11_EDGES_PREAMBLE - 2,
+                               timeres);
                if (ret)
                        goto err;
        }
@@ -261,9 +265,10 @@ static int dht11_probe(struct platform_device *pdev)
        dht11 = iio_priv(iio);
        dht11->dev = dev;
 
-       dht11->gpio = ret = of_get_gpio(node, 0);
+       ret = of_get_gpio(node, 0);
        if (ret < 0)
                return ret;
+       dht11->gpio = ret;
        ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
        if (ret)
                return ret;
@@ -274,7 +279,7 @@ static int dht11_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
+       dht11->timestamp = ktime_get_real_ns() - DHT11_DATA_VALID_TIME - 1;
        dht11->num_edges = -1;
 
        platform_set_drvdata(pdev, iio);
index bdd586e6d955235a76f30303c3ac4da78fda4d66..91972ccd8aafb8d151953f344ba54933be79da3a 100644 (file)
@@ -177,7 +177,6 @@ MODULE_DEVICE_TABLE(i2c, si7005_id);
 static struct i2c_driver si7005_driver = {
        .driver = {
                .name   = "si7005",
-               .owner  = THIS_MODULE,
        },
        .probe = si7005_probe,
        .id_table = si7005_id,
index 2fd68f2219a7d422a604b91ce90138f1050528cd..abc4c50de9e8b334548560c593f6c53c5bba675c 100644 (file)
@@ -139,7 +139,9 @@ enum adis16400_chip_variant {
        ADIS16360,
        ADIS16362,
        ADIS16364,
+       ADIS16367,
        ADIS16400,
+       ADIS16445,
        ADIS16448,
 };
 
@@ -622,6 +624,17 @@ static const struct iio_chan_spec adis16400_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
+static const struct iio_chan_spec adis16445_channels[] = {
+       ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
+       ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
+       ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16),
+       ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16),
+       ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16),
+       ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16),
+       ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
+       IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+};
+
 static const struct iio_chan_spec adis16448_channels[] = {
        ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
        ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
@@ -696,7 +709,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16300] = {
                .channels = adis16300_channels,
                .num_channels = ARRAY_SIZE(adis16300_channels),
-               .flags = ADIS16400_HAS_SLOW_MODE,
+               .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
+                               ADIS16400_HAS_SERIAL_NUMBER,
                .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
                .accel_scale_micro = 5884,
                .temp_scale_nano = 140000000, /* 0.14 C */
@@ -763,6 +777,18 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .set_freq = adis16400_set_freq,
                .get_freq = adis16400_get_freq,
        },
+       [ADIS16367] = {
+               .channels = adis16350_channels,
+               .num_channels = ARRAY_SIZE(adis16350_channels),
+               .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
+                               ADIS16400_HAS_SERIAL_NUMBER,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
+               .set_freq = adis16400_set_freq,
+               .get_freq = adis16400_get_freq,
+       },
        [ADIS16400] = {
                .channels = adis16400_channels,
                .num_channels = ARRAY_SIZE(adis16400_channels),
@@ -774,13 +800,26 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .set_freq = adis16400_set_freq,
                .get_freq = adis16400_get_freq,
        },
+       [ADIS16445] = {
+               .channels = adis16445_channels,
+               .num_channels = ARRAY_SIZE(adis16445_channels),
+               .flags = ADIS16400_HAS_PROD_ID |
+                               ADIS16400_HAS_SERIAL_NUMBER |
+                               ADIS16400_BURST_DIAG_STAT,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */
+               .temp_scale_nano = 73860000, /* 0.07386 C */
+               .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
+               .set_freq = adis16334_set_freq,
+               .get_freq = adis16334_get_freq,
+       },
        [ADIS16448] = {
                .channels = adis16448_channels,
                .num_channels = ARRAY_SIZE(adis16448_channels),
                .flags = ADIS16400_HAS_PROD_ID |
                                ADIS16400_HAS_SERIAL_NUMBER |
                                ADIS16400_BURST_DIAG_STAT,
-               .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */
                .accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
                .temp_scale_nano = 73860000, /* 0.07386 C */
                .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
@@ -926,6 +965,7 @@ static int adis16400_remove(struct spi_device *spi)
 
 static const struct spi_device_id adis16400_id[] = {
        {"adis16300", ADIS16300},
+       {"adis16305", ADIS16300},
        {"adis16334", ADIS16334},
        {"adis16350", ADIS16350},
        {"adis16354", ADIS16350},
@@ -934,8 +974,10 @@ static const struct spi_device_id adis16400_id[] = {
        {"adis16362", ADIS16362},
        {"adis16364", ADIS16364},
        {"adis16365", ADIS16360},
+       {"adis16367", ADIS16367},
        {"adis16400", ADIS16400},
        {"adis16405", ADIS16400},
+       {"adis16445", ADIS16445},
        {"adis16448", ADIS16448},
        {}
 };
index 989605dd6f7810018c90d6ffc82f394406987b61..b94bfd3f595bfad7e091bda7639d35b30b4e6bc4 100644 (file)
 struct adis16480_chip_info {
        unsigned int num_channels;
        const struct iio_chan_spec *channels;
+       unsigned int gyro_max_val;
+       unsigned int gyro_max_scale;
+       unsigned int accel_max_val;
+       unsigned int accel_max_scale;
 };
 
 struct adis16480 {
@@ -497,19 +501,21 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
 static int adis16480_read_raw(struct iio_dev *indio_dev,
        const struct iio_chan_spec *chan, int *val, int *val2, long info)
 {
+       struct adis16480 *st = iio_priv(indio_dev);
+
        switch (info) {
        case IIO_CHAN_INFO_RAW:
                return adis_single_conversion(indio_dev, chan, 0, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_ANGL_VEL:
-                       *val = 0;
-                       *val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val = st->chip_info->gyro_max_scale;
+                       *val2 = st->chip_info->gyro_max_val;
+                       return IIO_VAL_FRACTIONAL;
                case IIO_ACCEL:
-                       *val = 0;
-                       *val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val = st->chip_info->accel_max_scale;
+                       *val2 = st->chip_info->accel_max_val;
+                       return IIO_VAL_FRACTIONAL;
                case IIO_MAGN:
                        *val = 0;
                        *val2 = 100; /* 0.0001 gauss */
@@ -674,18 +680,39 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
        [ADIS16375] = {
                .channels = adis16485_channels,
                .num_channels = ARRAY_SIZE(adis16485_channels),
+               /*
+                * storing the value in rad/degree and the scale in degree
+                * gives us the result in rad and better precession than
+                * storing the scale directly in rad.
+                */
+               .gyro_max_val = IIO_RAD_TO_DEGREE(22887),
+               .gyro_max_scale = 300,
+               .accel_max_val = IIO_M_S_2_TO_G(21973),
+               .accel_max_scale = 18,
        },
        [ADIS16480] = {
                .channels = adis16480_channels,
                .num_channels = ARRAY_SIZE(adis16480_channels),
+               .gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+               .gyro_max_scale = 450,
+               .accel_max_val = IIO_M_S_2_TO_G(12500),
+               .accel_max_scale = 5,
        },
        [ADIS16485] = {
                .channels = adis16485_channels,
                .num_channels = ARRAY_SIZE(adis16485_channels),
+               .gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+               .gyro_max_scale = 450,
+               .accel_max_val = IIO_M_S_2_TO_G(20000),
+               .accel_max_scale = 5,
        },
        [ADIS16488] = {
                .channels = adis16480_channels,
                .num_channels = ARRAY_SIZE(adis16480_channels),
+               .gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+               .gyro_max_scale = 450,
+               .accel_max_val = IIO_M_S_2_TO_G(22500),
+               .accel_max_scale = 18,
        },
 };
 
index 65ce86837177158aba7e4d5fd2064e0731129369..f0e06093b5e8db3ce4f9fe89f983a01efba316a0 100644 (file)
@@ -690,6 +690,10 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
 
 /* constant IIO attribute */
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500");
+static IIO_CONST_ATTR(in_anglvel_scale_available,
+                                         "0.000133090 0.000266181 0.000532362 0.001064724");
+static IIO_CONST_ATTR(in_accel_scale_available,
+                                         "0.000598 0.001196 0.002392 0.004785");
 static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
        inv_mpu6050_fifo_rate_store);
 static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
@@ -702,6 +706,8 @@ static struct attribute *inv_attributes[] = {
        &iio_dev_attr_in_accel_matrix.dev_attr.attr,
        &iio_dev_attr_sampling_frequency.dev_attr.attr,
        &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+       &iio_const_attr_in_accel_scale_available.dev_attr.attr,
+       &iio_const_attr_in_anglvel_scale_available.dev_attr.attr,
        NULL,
 };
 
@@ -921,7 +927,6 @@ static struct i2c_driver inv_mpu_driver = {
        .remove         =       inv_mpu_remove,
        .id_table       =       inv_mpu_id,
        .driver = {
-               .owner  =       THIS_MODULE,
                .name   =       "inv-mpu6050",
                .pm     =       INV_MPU6050_PMOPS,
                .acpi_match_table = ACPI_PTR(inv_acpi_match),
index 462a010628cd52421458ab113f19b45ec58bf4d2..82cdf5090fa776b1bd0bea6ce570416782d996a9 100644 (file)
@@ -1363,7 +1363,7 @@ static int kmx61_probe(struct i2c_client *client,
        if (client->irq < 0)
                client->irq = kmx61_gpio_probe(client, data);
 
-       if (client->irq >= 0) {
+       if (client->irq > 0) {
                ret = devm_request_threaded_irq(&client->dev, client->irq,
                                                kmx61_data_rdy_trig_poll,
                                                kmx61_event_handler,
@@ -1445,10 +1445,10 @@ err_iio_unregister_mag:
 err_iio_unregister_acc:
        iio_device_unregister(data->acc_indio_dev);
 err_buffer_cleanup_mag:
-       if (client->irq >= 0)
+       if (client->irq > 0)
                iio_triggered_buffer_cleanup(data->mag_indio_dev);
 err_buffer_cleanup_acc:
-       if (client->irq >= 0)
+       if (client->irq > 0)
                iio_triggered_buffer_cleanup(data->acc_indio_dev);
 err_trigger_unregister_motion:
        iio_trigger_unregister(data->motion_trig);
@@ -1472,7 +1472,7 @@ static int kmx61_remove(struct i2c_client *client)
        iio_device_unregister(data->acc_indio_dev);
        iio_device_unregister(data->mag_indio_dev);
 
-       if (client->irq >= 0) {
+       if (client->irq > 0) {
                iio_triggered_buffer_cleanup(data->acc_indio_dev);
                iio_triggered_buffer_cleanup(data->mag_indio_dev);
                iio_trigger_unregister(data->acc_dready_trig);
index 6eee1b044c60ed5806494d95bfa69a83687103a6..d7e908acb48020b3f5390030e5a3687b03ba9878 100644 (file)
@@ -71,8 +71,9 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
 
        if (avail >= to_wait) {
                /* force a flush for non-blocking reads */
-               if (!to_wait && !avail && to_flush)
-                       iio_buffer_flush_hwfifo(indio_dev, buf, to_flush);
+               if (!to_wait && avail < to_flush)
+                       iio_buffer_flush_hwfifo(indio_dev, buf,
+                                               to_flush - avail);
                return true;
        }
 
@@ -90,9 +91,16 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
 
 /**
  * iio_buffer_read_first_n_outer() - chrdev read for buffer access
+ * @filp:      File structure pointer for the char device
+ * @buf:       Destination buffer for iio buffer read
+ * @n:         First n bytes to read
+ * @f_ps:      Long offset provided by the user as a seek position
  *
  * This function relies on all buffer implementations having an
  * iio_buffer as their first element.
+ *
+ * Return: negative values corresponding to error codes or ret != 0
+ *        for ending the reading activity
  **/
 ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
                                      size_t n, loff_t *f_ps)
@@ -100,8 +108,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
        struct iio_dev *indio_dev = filp->private_data;
        struct iio_buffer *rb = indio_dev->buffer;
        size_t datum_size;
-       size_t to_wait = 0;
-       size_t to_read;
+       size_t to_wait;
        int ret;
 
        if (!indio_dev->info)
@@ -119,14 +126,14 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
        if (!datum_size)
                return 0;
 
-       to_read = min_t(size_t, n / datum_size, rb->watermark);
-
-       if (!(filp->f_flags & O_NONBLOCK))
-               to_wait = to_read;
+       if (filp->f_flags & O_NONBLOCK)
+               to_wait = 0;
+       else
+               to_wait = min_t(size_t, n / datum_size, rb->watermark);
 
        do {
                ret = wait_event_interruptible(rb->pollq,
-                       iio_buffer_ready(indio_dev, rb, to_wait, to_read));
+                     iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size));
                if (ret)
                        return ret;
 
@@ -143,6 +150,12 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
 
 /**
  * iio_buffer_poll() - poll the buffer to find out if it has data
+ * @filp:      File structure pointer for device access
+ * @wait:      Poll table structure pointer for which the driver adds
+ *             a wait queue
+ *
+ * Return: (POLLIN | POLLRDNORM) if data is available for reading
+ *        or 0 for other cases
  */
 unsigned int iio_buffer_poll(struct file *filp,
                             struct poll_table_struct *wait)
@@ -151,7 +164,7 @@ unsigned int iio_buffer_poll(struct file *filp,
        struct iio_buffer *rb = indio_dev->buffer;
 
        if (!indio_dev->info)
-               return -ENODEV;
+               return 0;
 
        poll_wait(filp, &rb->pollq, wait);
        if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
@@ -1136,7 +1149,7 @@ int iio_scan_mask_query(struct iio_dev *indio_dev,
 EXPORT_SYMBOL_GPL(iio_scan_mask_query);
 
 /**
- * struct iio_demux_table() - table describing demux memcpy ops
+ * struct iio_demux_table - table describing demux memcpy ops
  * @from:      index to copy from
  * @to:                index to copy to
  * @length:    how many bytes to copy
index 3524b0de872110d31442060a109c5c4243a3f0cf..b3fcc2c449d80e2cb1fdfe95dc6ca200d36931e3 100644 (file)
@@ -81,6 +81,14 @@ static const char * const iio_modifier_names[] = {
        [IIO_MOD_X] = "x",
        [IIO_MOD_Y] = "y",
        [IIO_MOD_Z] = "z",
+       [IIO_MOD_X_AND_Y] = "x&y",
+       [IIO_MOD_X_AND_Z] = "x&z",
+       [IIO_MOD_Y_AND_Z] = "y&z",
+       [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
+       [IIO_MOD_X_OR_Y] = "x|y",
+       [IIO_MOD_X_OR_Z] = "x|z",
+       [IIO_MOD_Y_OR_Z] = "y|z",
+       [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
        [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
        [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
        [IIO_MOD_LIGHT_BOTH] = "both",
@@ -398,10 +406,16 @@ EXPORT_SYMBOL_GPL(iio_enum_write);
 
 /**
  * iio_format_value() - Formats a IIO value into its string representation
- * @buf: The buffer to which the formated value gets written
- * @type: One of the IIO_VAL_... constants. This decides how the val and val2
- *        parameters are formatted.
- * @vals: pointer to the values, exact meaning depends on the type parameter.
+ * @buf:       The buffer to which the formatted value gets written
+ * @type:      One of the IIO_VAL_... constants. This decides how the val
+ *             and val2 parameters are formatted.
+ * @size:      Number of IIO value entries contained in vals
+ * @vals:      Pointer to the values, exact meaning depends on the
+ *             type parameter.
+ *
+ * Return: 0 by default, a negative number on failure or the
+ *        total number of characters written for a type that belongs
+ *        to the IIO_VAL_... constant.
  */
 ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
 {
@@ -1088,6 +1102,11 @@ EXPORT_SYMBOL_GPL(devm_iio_device_free);
 
 /**
  * iio_chrdev_open() - chrdev file open for buffer access and ioctls
+ * @inode:     Inode structure for identifying the device in the file system
+ * @filp:      File structure for iio device used to keep and later access
+ *             private data
+ *
+ * Return: 0 on success or -EBUSY if the device is already opened
  **/
 static int iio_chrdev_open(struct inode *inode, struct file *filp)
 {
@@ -1106,7 +1125,11 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
 
 /**
  * iio_chrdev_release() - chrdev file close buffer access and ioctls
- **/
+ * @inode:     Inode structure pointer for the char device
+ * @filp:      File structure pointer for the char device
+ *
+ * Return: 0 for successful release
+ */
 static int iio_chrdev_release(struct inode *inode, struct file *filp)
 {
        struct iio_dev *indio_dev = container_of(inode->i_cdev,
index 894d8137c4cfaf7a7b0deddfc407a550045ca3c9..cae332b1d7ea595959c53ecb3c8f51eef9ba095b 100644 (file)
@@ -32,6 +32,7 @@
  * @dev_attr_list:     list of event interface sysfs attribute
  * @flags:             file operations related flags including busy flag.
  * @group:             event interface sysfs attribute group
+ * @read_lock:         lock to protect kfifo read operations
  */
 struct iio_event_interface {
        wait_queue_head_t       wait;
@@ -75,6 +76,11 @@ EXPORT_SYMBOL(iio_push_event);
 
 /**
  * iio_event_poll() - poll the event queue to find out if it has data
+ * @filep:     File structure pointer to identify the device
+ * @wait:      Poll table pointer to add the wait queue on
+ *
+ * Return: (POLLIN | POLLRDNORM) if data is available for reading
+ *        or a negative error code on failure
  */
 static unsigned int iio_event_poll(struct file *filep,
                             struct poll_table_struct *wait)
@@ -84,7 +90,7 @@ static unsigned int iio_event_poll(struct file *filep,
        unsigned int events = 0;
 
        if (!indio_dev->info)
-               return -ENODEV;
+               return events;
 
        poll_wait(filep, &ev_int->wait, wait);
 
index d31098e0c43f484e5a0583ae7a44e4721e7a4608..570606c2adbd8ccd7167ae0cd4105c9d2744230b 100644 (file)
@@ -40,7 +40,14 @@ static DEFINE_MUTEX(iio_trigger_list_lock);
 
 /**
  * iio_trigger_read_name() - retrieve useful identifying name
- **/
+ * @dev:       device associated with the iio_trigger
+ * @attr:      pointer to the device_attribute structure that is
+ *             being processed
+ * @buf:       buffer to print the name into
+ *
+ * Return: a negative number on failure or the number of written
+ *        characters on success.
+ */
 static ssize_t iio_trigger_read_name(struct device *dev,
                                     struct device_attribute *attr,
                                     char *buf)
@@ -288,10 +295,17 @@ EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc);
 
 /**
  * iio_trigger_read_current() - trigger consumer sysfs query current trigger
+ * @dev:       device associated with an industrial I/O device
+ * @attr:      pointer to the device_attribute structure that
+ *             is being processed
+ * @buf:       buffer where the current trigger name will be printed into
  *
  * For trigger consumers the current_trigger interface allows the trigger
  * used by the device to be queried.
- **/
+ *
+ * Return: a negative number on failure, the number of characters written
+ *        on success or 0 if no trigger is available
+ */
 static ssize_t iio_trigger_read_current(struct device *dev,
                                        struct device_attribute *attr,
                                        char *buf)
@@ -305,11 +319,18 @@ static ssize_t iio_trigger_read_current(struct device *dev,
 
 /**
  * iio_trigger_write_current() - trigger consumer sysfs set current trigger
+ * @dev:       device associated with an industrial I/O device
+ * @attr:      device attribute that is being processed
+ * @buf:       string buffer that holds the name of the trigger
+ * @len:       length of the trigger name held by buf
  *
  * For trigger consumers the current_trigger interface allows the trigger
  * used for this device to be specified at run time based on the trigger's
  * name.
- **/
+ *
+ * Return: negative error code on failure or length of the buffer
+ *        on success
+ */
 static ssize_t iio_trigger_write_current(struct device *dev,
                                         struct device_attribute *attr,
                                         const char *buf,
index 15a5341b5e7b303b80257db09853a2a62560b8d1..4b2858ba1fd6c534e8a23bdcc4a6a5b9f813b56d 100644 (file)
@@ -24,8 +24,8 @@ static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
 /**
  * iio_triggered_buffer_setup() - Setup triggered buffer and pollfunc
  * @indio_dev:         IIO device structure
- * @pollfunc_bh:       Function which will be used as pollfunc bottom half
- * @pollfunc_th:       Function which will be used as pollfunc top half
+ * @h:                 Function which will be used as pollfunc top half
+ * @thread:            Function which will be used as pollfunc bottom half
  * @setup_ops:         Buffer setup functions to use for this device.
  *                     If NULL the default setup functions for triggered
  *                     buffers will be used.
@@ -42,8 +42,8 @@ static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
  * iio_triggered_buffer_cleanup().
  */
 int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
-       irqreturn_t (*pollfunc_bh)(int irq, void *p),
-       irqreturn_t (*pollfunc_th)(int irq, void *p),
+       irqreturn_t (*h)(int irq, void *p),
+       irqreturn_t (*thread)(int irq, void *p),
        const struct iio_buffer_setup_ops *setup_ops)
 {
        struct iio_buffer *buffer;
@@ -57,8 +57,8 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
 
        iio_device_attach_buffer(indio_dev, buffer);
 
-       indio_dev->pollfunc = iio_alloc_pollfunc(pollfunc_bh,
-                                                pollfunc_th,
+       indio_dev->pollfunc = iio_alloc_pollfunc(h,
+                                                thread,
                                                 IRQF_ONESHOT,
                                                 indio_dev,
                                                 "%s_consumer%d",
index a5c59251ec0e93b90eeefee7637556629a32ede6..7ed859a700c4758c05c2872e34c90e7a3e1b7837 100644 (file)
@@ -86,7 +86,7 @@ config CM3323
        depends on I2C
        tristate "Capella CM3323 color light sensor"
        help
-        Say Y here if you want to build a driver for Capela CM3323
+        Say Y here if you want to build a driver for Capella CM3323
         color sensor.
 
         To compile this driver as a module, choose M here: the module will
@@ -168,6 +168,17 @@ config JSA1212
         To compile this driver as a module, choose M here:
         the module will be called jsa1212.
 
+config RPR0521
+       tristate "ROHM RPR0521 ALS and proximity sensor driver"
+       depends on I2C
+       select REGMAP_I2C
+       help
+        Say Y here if you want to build support for ROHM's RPR0521
+        ambient light and proximity sensor device.
+
+        To compile this driver as a module, choose M here:
+        the module will be called rpr0521.
+
 config SENSORS_LM3533
        tristate "LM3533 ambient light sensor"
        depends on MFD_LM3533
@@ -199,6 +210,27 @@ config LTR501
         This driver can also be built as a module.  If so, the module
          will be called ltr501.
 
+config OPT3001
+       tristate "Texas Instruments OPT3001 Light Sensor"
+       depends on I2C
+       help
+         If you say Y or M here, you get support for Texas Instruments
+         OPT3001 Ambient Light Sensor.
+
+         If built as a dynamically linked module, it will be called
+         opt3001.
+
+config PA12203001
+        tristate "TXC PA12203001 light and proximity sensor"
+        depends on I2C
+        select REGMAP_I2C
+        help
+         If you say yes here you get support for the TXC PA12203001
+         ambient light and proximity sensor.
+
+         This driver can also be built as a module.  If so, the module
+         will be called pa12203001.
+
 config STK3310
        tristate "STK3310 ALS and proximity sensor"
        depends on I2C
index e2d50fd59c66fbadbc3c8b10098d9d11c7549399..91c74c014b6f7869787a977c68a084267cf54dc5 100644 (file)
@@ -19,6 +19,9 @@ obj-$(CONFIG_ISL29125)                += isl29125.o
 obj-$(CONFIG_JSA1212)          += jsa1212.o
 obj-$(CONFIG_SENSORS_LM3533)   += lm3533-als.o
 obj-$(CONFIG_LTR501)           += ltr501.o
+obj-$(CONFIG_OPT3001)          += opt3001.o
+obj-$(CONFIG_PA12203001)       += pa12203001.o
+obj-$(CONFIG_RPR0521)          += rpr0521.o
 obj-$(CONFIG_SENSORS_TSL2563)  += tsl2563.o
 obj-$(CONFIG_STK3310)          += stk3310.o
 obj-$(CONFIG_TCS3414)          += tcs3414.o
index 1dafa0756bfabcee8d561cf7f5b7a5f390b358d6..60537ec0c923b98c45160d011f4a17ac932e4609 100644 (file)
@@ -65,20 +65,20 @@ static const struct iio_chan_spec acpi_als_channels[] = {
  * to acpi_als_channels[], the evt_buffer below will grow
  * automatically.
  */
-#define EVT_NR_SOURCES         ARRAY_SIZE(acpi_als_channels)
-#define EVT_BUFFER_SIZE                \
-       (sizeof(s64) + (EVT_NR_SOURCES * sizeof(s32)))
+#define ACPI_ALS_EVT_NR_SOURCES                ARRAY_SIZE(acpi_als_channels)
+#define ACPI_ALS_EVT_BUFFER_SIZE               \
+       (sizeof(s64) + (ACPI_ALS_EVT_NR_SOURCES * sizeof(s32)))
 
 struct acpi_als {
        struct acpi_device      *device;
        struct mutex            lock;
 
-       s32                     evt_buffer[EVT_BUFFER_SIZE];
+       s32                     evt_buffer[ACPI_ALS_EVT_BUFFER_SIZE];
 };
 
 /*
  * All types of properties the ACPI0008 block can report. The ALI, ALC, ALT
- * and ALP can all be handled by als_read_value() below, while the ALR is
+ * and ALP can all be handled by acpi_als_read_value() below, while the ALR is
  * special.
  *
  * The _ALR property returns tables that can be used to fine-tune the values
@@ -93,7 +93,7 @@ struct acpi_als {
 #define ACPI_ALS_POLLING       "_ALP"
 #define ACPI_ALS_TABLES                "_ALR"
 
-static int als_read_value(struct acpi_als *als, char *prop, s32 *val)
+static int acpi_als_read_value(struct acpi_als *als, char *prop, s32 *val)
 {
        unsigned long long temp_val;
        acpi_status status;
@@ -122,11 +122,11 @@ static void acpi_als_notify(struct acpi_device *device, u32 event)
 
        mutex_lock(&als->lock);
 
-       memset(buffer, 0, EVT_BUFFER_SIZE);
+       memset(buffer, 0, ACPI_ALS_EVT_BUFFER_SIZE);
 
        switch (event) {
        case ACPI_ALS_NOTIFY_ILLUMINANCE:
-               ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
+               ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
                if (ret < 0)
                        goto out;
                *buffer++ = val;
@@ -159,7 +159,7 @@ static int acpi_als_read_raw(struct iio_dev *indio_dev,
        if (chan->type != IIO_LIGHT)
                return -EINVAL;
 
-       ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
+       ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
        if (ret < 0)
                return ret;
 
index 9ddde0ca9c3415106ef8821027ad55b8f0b641fa..e1b9fa5a7e9153e0923f8c5f9d7df60928cfe875 100644 (file)
@@ -515,7 +515,6 @@ MODULE_DEVICE_TABLE(i2c, apds9300_id);
 static struct i2c_driver apds9300_driver = {
        .driver = {
                .name   = APDS9300_DRV_NAME,
-               .owner  = THIS_MODULE,
                .pm     = APDS9300_PM_OPS,
        },
        .probe          = apds9300_probe,
index 564c2b3c1a83dde9ae3358e6a8a2a04a997f06a9..8b4164343f2001c2128f7d5e7c5ce33090adeb50 100644 (file)
@@ -319,7 +319,6 @@ MODULE_DEVICE_TABLE(i2c, bh1750_id);
 static struct i2c_driver bh1750_driver = {
        .driver = {
                .name = "bh1750",
-               .owner = THIS_MODULE,
                .pm = BH1750_PM_OPS,
        },
        .probe = bh1750_probe,
index 5d12ae54d0886e1179ab18e8d72480bb9d12d40a..d6fd0dace74f24bf853c2e45d7171c1c115c8ba7 100644 (file)
@@ -353,12 +353,12 @@ static const struct of_device_id cm32181_of_match[] = {
        { .compatible = "capella,cm32181" },
        { }
 };
+MODULE_DEVICE_TABLE(of, cm32181_of_match);
 
 static struct i2c_driver cm32181_driver = {
        .driver = {
                .name   = "cm32181",
                .of_match_table = of_match_ptr(cm32181_of_match),
-               .owner  = THIS_MODULE,
        },
        .id_table       = cm32181_id,
        .probe          = cm32181_probe,
index 39c8d99cc48ee988a59f17f605372d07258d0e05..fe89b6823217bf940ef58bed2b629ac84d98e9c2 100644 (file)
@@ -417,11 +417,11 @@ static const struct of_device_id cm3232_of_match[] = {
        {.compatible = "capella,cm3232"},
        {}
 };
+MODULE_DEVICE_TABLE(of, cm3232_of_match);
 
 static struct i2c_driver cm3232_driver = {
        .driver = {
                .name   = "cm3232",
-               .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(cm3232_of_match),
 #ifdef CONFIG_PM_SLEEP
                .pm     = &cm3232_pm_ops,
index a1d4905cc9d2d9680d5b3972233948fef3114035..d823c112d54bdbbf9b656e6eb8790c327cc1ccd8 100644 (file)
@@ -29,7 +29,7 @@
 
 #define CM3323_CONF_SD_BIT     BIT(0) /* sensor disable */
 #define CM3323_CONF_AF_BIT     BIT(1) /* auto/manual force mode */
-#define CM3323_CONF_IT_MASK    (BIT(4) | BIT(5) | BIT(6))
+#define CM3323_CONF_IT_MASK    GENMASK(6, 4)
 #define CM3323_CONF_IT_SHIFT   4
 
 #define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28"
@@ -133,9 +133,11 @@ static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2)
                                return ret;
 
                        data->reg_conf = reg_conf;
+
                        return 0;
                }
        }
+
        return -EINVAL;
 }
 
@@ -148,6 +150,7 @@ static int cm3323_get_it_bits(struct cm3323_data *data)
 
        if (bits >= ARRAY_SIZE(cm3323_int_time))
                return -EINVAL;
+
        return bits;
 }
 
@@ -155,7 +158,7 @@ static int cm3323_read_raw(struct iio_dev *indio_dev,
                           struct iio_chan_spec const *chan, int *val,
                           int *val2, long mask)
 {
-       int i, ret;
+       int ret;
        struct cm3323_data *data = iio_priv(indio_dev);
 
        switch (mask) {
@@ -172,14 +175,14 @@ static int cm3323_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_INT_TIME:
                mutex_lock(&data->mutex);
-               i = cm3323_get_it_bits(data);
-               if (i < 0) {
+               ret = cm3323_get_it_bits(data);
+               if (ret < 0) {
                        mutex_unlock(&data->mutex);
-                       return -EINVAL;
+                       return ret;
                }
 
-               *val = cm3323_int_time[i].val;
-               *val2 = cm3323_int_time[i].val2;
+               *val = cm3323_int_time[ret].val;
+               *val2 = cm3323_int_time[ret].val2;
                mutex_unlock(&data->mutex);
 
                return IIO_VAL_INT_PLUS_MICRO;
@@ -243,11 +246,13 @@ static int cm3323_probe(struct i2c_client *client,
                dev_err(&client->dev, "cm3323 chip init failed\n");
                return ret;
        }
+
        ret = iio_device_register(indio_dev);
        if (ret < 0) {
                dev_err(&client->dev, "failed to register iio dev\n");
                goto err_init;
        }
+
        return 0;
 err_init:
        cm3323_disable(indio_dev);
index 39fc67e82138470a1f8523d7de2902f072603a6f..c8d7b5ea7e78c880b7bfc1cc1ff829c8c4c4b8aa 100644 (file)
@@ -731,12 +731,12 @@ static const struct of_device_id cm36651_of_match[] = {
        { .compatible = "capella,cm36651" },
        { }
 };
+MODULE_DEVICE_TABLE(of, cm36651_of_match);
 
 static struct i2c_driver cm36651_driver = {
        .driver = {
                .name   = "cm36651",
                .of_match_table = cm36651_of_match,
-               .owner  = THIS_MODULE,
        },
        .probe          = cm36651_probe,
        .remove         = cm36651_remove,
index 32b6449833faf5f6102e8b55edcb6810f2c25678..6d41086f7c6462108ebcce2dd2dc7dc76ea8d519 100644 (file)
@@ -1634,13 +1634,13 @@ static const struct of_device_id gp2ap020a00f_of_match[] = {
        { .compatible = "sharp,gp2ap020a00f" },
        { }
 };
+MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
 #endif
 
 static struct i2c_driver gp2ap020a00f_driver = {
        .driver = {
                .name   = GP2A_I2C_NAME,
                .of_match_table = of_match_ptr(gp2ap020a00f_of_match),
-               .owner  = THIS_MODULE,
        },
        .probe          = gp2ap020a00f_probe,
        .remove         = gp2ap020a00f_remove,
index 0d248476f4c9b64b7479e4135fbddb95e178bae2..45ca056f019ed2832bd68f14833ae2b4a4839fd7 100644 (file)
@@ -284,8 +284,7 @@ static int hid_prox_probe(struct platform_device *pdev)
                goto error_free_dev_mem;
        }
 
-       indio_dev->num_channels =
-                               ARRAY_SIZE(prox_channels);
+       indio_dev->num_channels = ARRAY_SIZE(prox_channels);
        indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &prox_info;
        indio_dev->name = name;
index c82f4a6f84645c2dd327f17ee74fdb6bf867544f..e2945a20e5f621a7740300b0aa1e48ca732ba16f 100644 (file)
@@ -197,9 +197,21 @@ done:
        return IRQ_HANDLED;
 }
 
+static IIO_CONST_ATTR(scale_available, "0.005722 0.152590");
+
+static struct attribute *isl29125_attributes[] = {
+       &iio_const_attr_scale_available.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group isl29125_attribute_group = {
+       .attrs = isl29125_attributes,
+};
+
 static const struct iio_info isl29125_info = {
        .read_raw = isl29125_read_raw,
        .write_raw = isl29125_write_raw,
+       .attrs = &isl29125_attribute_group,
        .driver_module = THIS_MODULE,
 };
 
@@ -334,7 +346,6 @@ static struct i2c_driver isl29125_driver = {
        .driver = {
                .name   = ISL29125_DRV_NAME,
                .pm     = &isl29125_pm_ops,
-               .owner  = THIS_MODULE,
        },
        .probe          = isl29125_probe,
        .remove         = isl29125_remove,
index 3a3af89beaf962671c9a5e65d0b3dd7fc25ce2c4..c4e8c6b6c3c31ccbf0124b551694b48def01c269 100644 (file)
@@ -457,7 +457,6 @@ static struct i2c_driver jsa1212_driver = {
        .driver = {
                .name   = JSA1212_DRIVER_NAME,
                .pm     = JSA1212_PM_OPS,
-               .owner  = THIS_MODULE,
                .acpi_match_table = ACPI_PTR(jsa1212_acpi_match),
        },
        .probe          = jsa1212_probe,
index b5a0e66b5f282f09941dddf58de1b51eed3e71c2..809a961b9a7f6d0d0077114e12767e4e267c7606 100644 (file)
@@ -1551,7 +1551,6 @@ static struct i2c_driver ltr501_driver = {
                .name   = LTR501_DRV_NAME,
                .pm     = &ltr501_pm_ops,
                .acpi_match_table = ACPI_PTR(ltr_acpi_match),
-               .owner  = THIS_MODULE,
        },
        .probe  = ltr501_probe,
        .remove = ltr501_remove,
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
new file mode 100644 (file)
index 0000000..923aa6a
--- /dev/null
@@ -0,0 +1,804 @@
+/**
+ * opt3001.c - Texas Instruments OPT3001 Light Sensor
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Andreas Dannenberg <dannenberg@ti.com>
+ * Based on previous work from: Felipe Balbi <balbi@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 of the License
+ * 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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define OPT3001_RESULT         0x00
+#define OPT3001_CONFIGURATION  0x01
+#define OPT3001_LOW_LIMIT      0x02
+#define OPT3001_HIGH_LIMIT     0x03
+#define OPT3001_MANUFACTURER_ID        0x7e
+#define OPT3001_DEVICE_ID      0x7f
+
+#define OPT3001_CONFIGURATION_RN_MASK  (0xf << 12)
+#define OPT3001_CONFIGURATION_RN_AUTO  (0xc << 12)
+
+#define OPT3001_CONFIGURATION_CT       BIT(11)
+
+#define OPT3001_CONFIGURATION_M_MASK   (3 << 9)
+#define OPT3001_CONFIGURATION_M_SHUTDOWN (0 << 9)
+#define OPT3001_CONFIGURATION_M_SINGLE (1 << 9)
+#define OPT3001_CONFIGURATION_M_CONTINUOUS (2 << 9) /* also 3 << 9 */
+
+#define OPT3001_CONFIGURATION_OVF      BIT(8)
+#define OPT3001_CONFIGURATION_CRF      BIT(7)
+#define OPT3001_CONFIGURATION_FH       BIT(6)
+#define OPT3001_CONFIGURATION_FL       BIT(5)
+#define OPT3001_CONFIGURATION_L                BIT(4)
+#define OPT3001_CONFIGURATION_POL      BIT(3)
+#define OPT3001_CONFIGURATION_ME       BIT(2)
+
+#define OPT3001_CONFIGURATION_FC_MASK  (3 << 0)
+
+/* The end-of-conversion enable is located in the low-limit register */
+#define OPT3001_LOW_LIMIT_EOC_ENABLE   0xc000
+
+#define OPT3001_REG_EXPONENT(n)                ((n) >> 12)
+#define OPT3001_REG_MANTISSA(n)                ((n) & 0xfff)
+
+/*
+ * Time to wait for conversion result to be ready. The device datasheet
+ * worst-case max value is 880ms. Add some slack to be on the safe side.
+ */
+#define OPT3001_RESULT_READY_TIMEOUT   msecs_to_jiffies(1000)
+
+struct opt3001 {
+       struct i2c_client       *client;
+       struct device           *dev;
+
+       struct mutex            lock;
+       u16                     ok_to_ignore_lock:1;
+       u16                     result_ready:1;
+       wait_queue_head_t       result_ready_queue;
+       u16                     result;
+
+       u32                     int_time;
+       u32                     mode;
+
+       u16                     high_thresh_mantissa;
+       u16                     low_thresh_mantissa;
+
+       u8                      high_thresh_exp;
+       u8                      low_thresh_exp;
+};
+
+struct opt3001_scale {
+       int     val;
+       int     val2;
+};
+
+static const struct opt3001_scale opt3001_scales[] = {
+       {
+               .val = 40,
+               .val2 = 950000,
+       },
+       {
+               .val = 81,
+               .val2 = 900000,
+       },
+       {
+               .val = 163,
+               .val2 = 800000,
+       },
+       {
+               .val = 327,
+               .val2 = 600000,
+       },
+       {
+               .val = 655,
+               .val2 = 200000,
+       },
+       {
+               .val = 1310,
+               .val2 = 400000,
+       },
+       {
+               .val = 2620,
+               .val2 = 800000,
+       },
+       {
+               .val = 5241,
+               .val2 = 600000,
+       },
+       {
+               .val = 10483,
+               .val2 = 200000,
+       },
+       {
+               .val = 20966,
+               .val2 = 400000,
+       },
+       {
+               .val = 83865,
+               .val2 = 600000,
+       },
+};
+
+static int opt3001_find_scale(const struct opt3001 *opt, int val,
+               int val2, u8 *exponent)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
+               const struct opt3001_scale *scale = &opt3001_scales[i];
+
+               /*
+                * Combine the integer and micro parts for comparison
+                * purposes. Use milli lux precision to avoid 32-bit integer
+                * overflows.
+                */
+               if ((val * 1000 + val2 / 1000) <=
+                               (scale->val * 1000 + scale->val2 / 1000)) {
+                       *exponent = i;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
+               u16 mantissa, int *val, int *val2)
+{
+       int lux;
+
+       lux = 10 * (mantissa << exponent);
+       *val = lux / 1000;
+       *val2 = (lux - (*val * 1000)) * 1000;
+}
+
+static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
+{
+       *reg &= ~OPT3001_CONFIGURATION_M_MASK;
+       *reg |= mode;
+       opt->mode = mode;
+}
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.8");
+
+static struct attribute *opt3001_attributes[] = {
+       &iio_const_attr_integration_time_available.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group opt3001_attribute_group = {
+       .attrs = opt3001_attributes,
+};
+
+static const struct iio_event_spec opt3001_event_spec[] = {
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_RISING,
+               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+                       BIT(IIO_EV_INFO_ENABLE),
+       },
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_FALLING,
+               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+                       BIT(IIO_EV_INFO_ENABLE),
+       },
+};
+
+static const struct iio_chan_spec opt3001_channels[] = {
+       {
+               .type = IIO_LIGHT,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                               BIT(IIO_CHAN_INFO_INT_TIME),
+               .event_spec = opt3001_event_spec,
+               .num_event_specs = ARRAY_SIZE(opt3001_event_spec),
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
+{
+       int ret;
+       u16 mantissa;
+       u16 reg;
+       u8 exponent;
+       u16 value;
+
+       /*
+        * Enable the end-of-conversion interrupt mechanism. Note that doing
+        * so will overwrite the low-level limit value however we will restore
+        * this value later on.
+        */
+       ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
+                       OPT3001_LOW_LIMIT_EOC_ENABLE);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n",
+                               OPT3001_LOW_LIMIT);
+               return ret;
+       }
+
+       /* Reset data-ready indicator flag (will be set in the IRQ routine) */
+       opt->result_ready = false;
+
+       /* Allow IRQ to access the device despite lock being set */
+       opt->ok_to_ignore_lock = true;
+
+       /* Configure for single-conversion mode and start a new conversion */
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_CONFIGURATION);
+               goto err;
+       }
+
+       reg = ret;
+       opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SINGLE);
+
+       ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+                       reg);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n",
+                               OPT3001_CONFIGURATION);
+               goto err;
+       }
+
+       /* Wait for the IRQ to indicate the conversion is complete */
+       ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready,
+                       OPT3001_RESULT_READY_TIMEOUT);
+
+err:
+       /* Disallow IRQ to access the device while lock is active */
+       opt->ok_to_ignore_lock = false;
+
+       if (ret == 0)
+               return -ETIMEDOUT;
+       else if (ret < 0)
+               return ret;
+
+       /*
+        * Disable the end-of-conversion interrupt mechanism by restoring the
+        * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note
+        * that selectively clearing those enable bits would affect the actual
+        * limit value due to bit-overlap and therefore can't be done.
+        */
+       value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
+       ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
+                       value);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n",
+                               OPT3001_LOW_LIMIT);
+               return ret;
+       }
+
+       exponent = OPT3001_REG_EXPONENT(opt->result);
+       mantissa = OPT3001_REG_MANTISSA(opt->result);
+
+       opt3001_to_iio_ret(opt, exponent, mantissa, val, val2);
+
+       return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int opt3001_get_int_time(struct opt3001 *opt, int *val, int *val2)
+{
+       *val = 0;
+       *val2 = opt->int_time;
+
+       return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int opt3001_set_int_time(struct opt3001 *opt, int time)
+{
+       int ret;
+       u16 reg;
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_CONFIGURATION);
+               return ret;
+       }
+
+       reg = ret;
+
+       switch (time) {
+       case 100000:
+               reg &= ~OPT3001_CONFIGURATION_CT;
+               opt->int_time = 100000;
+               break;
+       case 800000:
+               reg |= OPT3001_CONFIGURATION_CT;
+               opt->int_time = 800000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+                       reg);
+}
+
+static int opt3001_read_raw(struct iio_dev *iio,
+               struct iio_chan_spec const *chan, int *val, int *val2,
+               long mask)
+{
+       struct opt3001 *opt = iio_priv(iio);
+       int ret;
+
+       if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+               return -EBUSY;
+
+       if (chan->type != IIO_LIGHT)
+               return -EINVAL;
+
+       mutex_lock(&opt->lock);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_PROCESSED:
+               ret = opt3001_get_lux(opt, val, val2);
+               break;
+       case IIO_CHAN_INFO_INT_TIME:
+               ret = opt3001_get_int_time(opt, val, val2);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       mutex_unlock(&opt->lock);
+
+       return ret;
+}
+
+static int opt3001_write_raw(struct iio_dev *iio,
+               struct iio_chan_spec const *chan, int val, int val2,
+               long mask)
+{
+       struct opt3001 *opt = iio_priv(iio);
+       int ret;
+
+       if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+               return -EBUSY;
+
+       if (chan->type != IIO_LIGHT)
+               return -EINVAL;
+
+       if (mask != IIO_CHAN_INFO_INT_TIME)
+               return -EINVAL;
+
+       if (val != 0)
+               return -EINVAL;
+
+       mutex_lock(&opt->lock);
+       ret = opt3001_set_int_time(opt, val2);
+       mutex_unlock(&opt->lock);
+
+       return ret;
+}
+
+static int opt3001_read_event_value(struct iio_dev *iio,
+               const struct iio_chan_spec *chan, enum iio_event_type type,
+               enum iio_event_direction dir, enum iio_event_info info,
+               int *val, int *val2)
+{
+       struct opt3001 *opt = iio_priv(iio);
+       int ret = IIO_VAL_INT_PLUS_MICRO;
+
+       mutex_lock(&opt->lock);
+
+       switch (dir) {
+       case IIO_EV_DIR_RISING:
+               opt3001_to_iio_ret(opt, opt->high_thresh_exp,
+                               opt->high_thresh_mantissa, val, val2);
+               break;
+       case IIO_EV_DIR_FALLING:
+               opt3001_to_iio_ret(opt, opt->low_thresh_exp,
+                               opt->low_thresh_mantissa, val, val2);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       mutex_unlock(&opt->lock);
+
+       return ret;
+}
+
+static int opt3001_write_event_value(struct iio_dev *iio,
+               const struct iio_chan_spec *chan, enum iio_event_type type,
+               enum iio_event_direction dir, enum iio_event_info info,
+               int val, int val2)
+{
+       struct opt3001 *opt = iio_priv(iio);
+       int ret;
+
+       u16 mantissa;
+       u16 value;
+       u16 reg;
+
+       u8 exponent;
+
+       if (val < 0)
+               return -EINVAL;
+
+       mutex_lock(&opt->lock);
+
+       ret = opt3001_find_scale(opt, val, val2, &exponent);
+       if (ret < 0) {
+               dev_err(opt->dev, "can't find scale for %d.%06u\n", val, val2);
+               goto err;
+       }
+
+       mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
+       value = (exponent << 12) | mantissa;
+
+       switch (dir) {
+       case IIO_EV_DIR_RISING:
+               reg = OPT3001_HIGH_LIMIT;
+               opt->high_thresh_mantissa = mantissa;
+               opt->high_thresh_exp = exponent;
+               break;
+       case IIO_EV_DIR_FALLING:
+               reg = OPT3001_LOW_LIMIT;
+               opt->low_thresh_mantissa = mantissa;
+               opt->low_thresh_exp = exponent;
+               break;
+       default:
+               ret = -EINVAL;
+               goto err;
+       }
+
+       ret = i2c_smbus_write_word_swapped(opt->client, reg, value);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n", reg);
+               goto err;
+       }
+
+err:
+       mutex_unlock(&opt->lock);
+
+       return ret;
+}
+
+static int opt3001_read_event_config(struct iio_dev *iio,
+               const struct iio_chan_spec *chan, enum iio_event_type type,
+               enum iio_event_direction dir)
+{
+       struct opt3001 *opt = iio_priv(iio);
+
+       return opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS;
+}
+
+static int opt3001_write_event_config(struct iio_dev *iio,
+               const struct iio_chan_spec *chan, enum iio_event_type type,
+               enum iio_event_direction dir, int state)
+{
+       struct opt3001 *opt = iio_priv(iio);
+       int ret;
+       u16 mode;
+       u16 reg;
+
+       if (state && opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+               return 0;
+
+       if (!state && opt->mode == OPT3001_CONFIGURATION_M_SHUTDOWN)
+               return 0;
+
+       mutex_lock(&opt->lock);
+
+       mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS
+               : OPT3001_CONFIGURATION_M_SHUTDOWN;
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_CONFIGURATION);
+               goto err;
+       }
+
+       reg = ret;
+       opt3001_set_mode(opt, &reg, mode);
+
+       ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+                       reg);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n",
+                               OPT3001_CONFIGURATION);
+               goto err;
+       }
+
+err:
+       mutex_unlock(&opt->lock);
+
+       return ret;
+}
+
+static const struct iio_info opt3001_info = {
+       .driver_module = THIS_MODULE,
+       .attrs = &opt3001_attribute_group,
+       .read_raw = opt3001_read_raw,
+       .write_raw = opt3001_write_raw,
+       .read_event_value = opt3001_read_event_value,
+       .write_event_value = opt3001_write_event_value,
+       .read_event_config = opt3001_read_event_config,
+       .write_event_config = opt3001_write_event_config,
+};
+
+static int opt3001_read_id(struct opt3001 *opt)
+{
+       char manufacturer[2];
+       u16 device_id;
+       int ret;
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_MANUFACTURER_ID);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_MANUFACTURER_ID);
+               return ret;
+       }
+
+       manufacturer[0] = ret >> 8;
+       manufacturer[1] = ret & 0xff;
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_DEVICE_ID);
+               return ret;
+       }
+
+       device_id = ret;
+
+       dev_info(opt->dev, "Found %c%c OPT%04x\n", manufacturer[0],
+                       manufacturer[1], device_id);
+
+       return 0;
+}
+
+static int opt3001_configure(struct opt3001 *opt)
+{
+       int ret;
+       u16 reg;
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_CONFIGURATION);
+               return ret;
+       }
+
+       reg = ret;
+
+       /* Enable automatic full-scale setting mode */
+       reg &= ~OPT3001_CONFIGURATION_RN_MASK;
+       reg |= OPT3001_CONFIGURATION_RN_AUTO;
+
+       /* Reflect status of the device's integration time setting */
+       if (reg & OPT3001_CONFIGURATION_CT)
+               opt->int_time = 800000;
+       else
+               opt->int_time = 100000;
+
+       /* Ensure device is in shutdown initially */
+       opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+       /* Configure for latched window-style comparison operation */
+       reg |= OPT3001_CONFIGURATION_L;
+       reg &= ~OPT3001_CONFIGURATION_POL;
+       reg &= ~OPT3001_CONFIGURATION_ME;
+       reg &= ~OPT3001_CONFIGURATION_FC_MASK;
+
+       ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+                       reg);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n",
+                               OPT3001_CONFIGURATION);
+               return ret;
+       }
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_LOW_LIMIT);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_LOW_LIMIT);
+               return ret;
+       }
+
+       opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
+       opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret);
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_HIGH_LIMIT);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_HIGH_LIMIT);
+               return ret;
+       }
+
+       opt->high_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
+       opt->high_thresh_exp = OPT3001_REG_EXPONENT(ret);
+
+       return 0;
+}
+
+static irqreturn_t opt3001_irq(int irq, void *_iio)
+{
+       struct iio_dev *iio = _iio;
+       struct opt3001 *opt = iio_priv(iio);
+       int ret;
+
+       if (!opt->ok_to_ignore_lock)
+               mutex_lock(&opt->lock);
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_CONFIGURATION);
+               goto out;
+       }
+
+       if ((ret & OPT3001_CONFIGURATION_M_MASK) ==
+                       OPT3001_CONFIGURATION_M_CONTINUOUS) {
+               if (ret & OPT3001_CONFIGURATION_FH)
+                       iio_push_event(iio,
+                                       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+                                                       IIO_EV_TYPE_THRESH,
+                                                       IIO_EV_DIR_RISING),
+                                       iio_get_time_ns());
+               if (ret & OPT3001_CONFIGURATION_FL)
+                       iio_push_event(iio,
+                                       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+                                                       IIO_EV_TYPE_THRESH,
+                                                       IIO_EV_DIR_FALLING),
+                                       iio_get_time_ns());
+       } else if (ret & OPT3001_CONFIGURATION_CRF) {
+               ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
+               if (ret < 0) {
+                       dev_err(opt->dev, "failed to read register %02x\n",
+                                       OPT3001_RESULT);
+                       goto out;
+               }
+               opt->result = ret;
+               opt->result_ready = true;
+               wake_up(&opt->result_ready_queue);
+       }
+
+out:
+       if (!opt->ok_to_ignore_lock)
+               mutex_unlock(&opt->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int opt3001_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct device *dev = &client->dev;
+
+       struct iio_dev *iio;
+       struct opt3001 *opt;
+       int irq = client->irq;
+       int ret;
+
+       iio = devm_iio_device_alloc(dev, sizeof(*opt));
+       if (!iio)
+               return -ENOMEM;
+
+       opt = iio_priv(iio);
+       opt->client = client;
+       opt->dev = dev;
+
+       mutex_init(&opt->lock);
+       init_waitqueue_head(&opt->result_ready_queue);
+       i2c_set_clientdata(client, iio);
+
+       ret = opt3001_read_id(opt);
+       if (ret)
+               return ret;
+
+       ret = opt3001_configure(opt);
+       if (ret)
+               return ret;
+
+       iio->name = client->name;
+       iio->channels = opt3001_channels;
+       iio->num_channels = ARRAY_SIZE(opt3001_channels);
+       iio->dev.parent = dev;
+       iio->modes = INDIO_DIRECT_MODE;
+       iio->info = &opt3001_info;
+
+       ret = devm_iio_device_register(dev, iio);
+       if (ret) {
+               dev_err(dev, "failed to register IIO device\n");
+               return ret;
+       }
+
+       ret = request_threaded_irq(irq, NULL, opt3001_irq,
+                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                       "opt3001", iio);
+       if (ret) {
+               dev_err(dev, "failed to request IRQ #%d\n", irq);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int opt3001_remove(struct i2c_client *client)
+{
+       struct iio_dev *iio = i2c_get_clientdata(client);
+       struct opt3001 *opt = iio_priv(iio);
+       int ret;
+       u16 reg;
+
+       free_irq(client->irq, iio);
+
+       ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to read register %02x\n",
+                               OPT3001_CONFIGURATION);
+               return ret;
+       }
+
+       reg = ret;
+       opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+       ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+                       reg);
+       if (ret < 0) {
+               dev_err(opt->dev, "failed to write register %02x\n",
+                               OPT3001_CONFIGURATION);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id opt3001_id[] = {
+       { "opt3001", 0 },
+       { } /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(i2c, opt3001_id);
+
+static const struct of_device_id opt3001_of_match[] = {
+       { .compatible = "ti,opt3001" },
+       { }
+};
+
+static struct i2c_driver opt3001_driver = {
+       .probe = opt3001_probe,
+       .remove = opt3001_remove,
+       .id_table = opt3001_id,
+
+       .driver = {
+               .name = "opt3001",
+               .of_match_table = of_match_ptr(opt3001_of_match),
+               .owner = THIS_MODULE,
+       },
+};
+
+module_i2c_driver(opt3001_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>");
+MODULE_DESCRIPTION("Texas Instruments OPT3001 Light Sensor Driver");
diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c
new file mode 100644 (file)
index 0000000..45f7bde
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Driver for TXC PA12203001 Proximity and Ambient Light 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.
+ * To do: Interrupt support.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#define PA12203001_DRIVER_NAME "pa12203001"
+
+#define PA12203001_REG_CFG0            0x00
+#define PA12203001_REG_CFG1            0x01
+#define PA12203001_REG_CFG2            0x02
+#define PA12203001_REG_CFG3            0x03
+
+#define PA12203001_REG_ADL             0x0b
+#define PA12203001_REG_PDH             0x0e
+
+#define PA12203001_REG_POFS            0x10
+#define PA12203001_REG_PSET            0x11
+
+#define PA12203001_ALS_EN_MASK         BIT(0)
+#define PA12203001_PX_EN_MASK          BIT(1)
+#define PA12203001_PX_NORMAL_MODE_MASK         GENMASK(7, 6)
+#define PA12203001_AFSR_MASK           GENMASK(5, 4)
+#define PA12203001_AFSR_SHIFT          4
+
+#define PA12203001_PSCAN                       0x03
+
+/* als range 31000, ps, als disabled */
+#define PA12203001_REG_CFG0_DEFAULT            0x30
+
+/* led current: 100 mA */
+#define PA12203001_REG_CFG1_DEFAULT            0x20
+
+/* ps mode: normal, interrupts not active */
+#define PA12203001_REG_CFG2_DEFAULT            0xcc
+
+#define PA12203001_REG_CFG3_DEFAULT            0x00
+
+#define PA12203001_SLEEP_DELAY_MS              3000
+
+#define PA12203001_CHIP_ENABLE         0xff
+#define PA12203001_CHIP_DISABLE                0x00
+
+/* available scales: corresponding to [500, 4000, 7000, 31000]  lux */
+static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029};
+
+struct pa12203001_data {
+       struct i2c_client *client;
+
+       /* protect device states */
+       struct mutex lock;
+
+       bool als_enabled;
+       bool px_enabled;
+       bool als_needs_enable;
+       bool px_needs_enable;
+
+       struct regmap *map;
+};
+
+static const struct {
+       u8 reg;
+       u8 val;
+} regvals[] = {
+       {PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT},
+       {PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT},
+       {PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT},
+       {PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT},
+       {PA12203001_REG_PSET, PA12203001_PSCAN},
+};
+
+static IIO_CONST_ATTR(in_illuminance_scale_available,
+                     "0.007629 0.061036 0.106813 0.473029");
+
+static struct attribute *pa12203001_attrs[] = {
+       &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group pa12203001_attr_group = {
+       .attrs = pa12203001_attrs,
+};
+
+static const struct iio_chan_spec pa12203001_channels[] = {
+       {
+               .type = IIO_LIGHT,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+       },
+       {
+               .type = IIO_PROXIMITY,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+       }
+};
+
+static const struct regmap_range pa12203001_volatile_regs_ranges[] = {
+       regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1),
+       regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH),
+};
+
+static const struct regmap_access_table pa12203001_volatile_regs = {
+       .yes_ranges = pa12203001_volatile_regs_ranges,
+       .n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges),
+};
+
+static const struct regmap_config pa12203001_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = PA12203001_REG_PSET,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_table = &pa12203001_volatile_regs,
+};
+
+static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable)
+{
+       int ret;
+
+       ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
+                                PA12203001_ALS_EN_MASK, enable);
+       if (ret < 0)
+               return ret;
+
+       data->als_enabled = !!enable;
+
+       return 0;
+}
+
+static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable)
+{
+       int ret;
+
+       ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
+                                PA12203001_PX_EN_MASK, enable);
+       if (ret < 0)
+               return ret;
+
+       data->px_enabled = !!enable;
+
+       return 0;
+}
+
+static int pa12203001_set_power_state(struct pa12203001_data *data, bool on,
+                                     u8 mask)
+{
+#ifdef CONFIG_PM
+       int ret;
+
+       if (on && (mask & PA12203001_ALS_EN_MASK)) {
+               mutex_lock(&data->lock);
+               if (data->px_enabled) {
+                       ret = pa12203001_als_enable(data,
+                                                   PA12203001_ALS_EN_MASK);
+                       if (ret < 0)
+                               goto err;
+               } else {
+                       data->als_needs_enable = true;
+               }
+               mutex_unlock(&data->lock);
+       }
+
+       if (on && (mask & PA12203001_PX_EN_MASK)) {
+               mutex_lock(&data->lock);
+               if (data->als_enabled) {
+                       ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
+                       if (ret < 0)
+                               goto err;
+               } else {
+                       data->px_needs_enable = true;
+               }
+               mutex_unlock(&data->lock);
+       }
+
+       if (on) {
+               ret = pm_runtime_get_sync(&data->client->dev);
+               if (ret < 0)
+                       pm_runtime_put_noidle(&data->client->dev);
+
+       } else {
+               pm_runtime_mark_last_busy(&data->client->dev);
+               ret = pm_runtime_put_autosuspend(&data->client->dev);
+       }
+
+       return ret;
+
+err:
+       mutex_unlock(&data->lock);
+       return ret;
+
+#endif
+       return 0;
+}
+
+static int pa12203001_read_raw(struct iio_dev *indio_dev,
+                              struct iio_chan_spec const *chan, int *val,
+                              int *val2, long mask)
+{
+       struct pa12203001_data *data = iio_priv(indio_dev);
+       int ret;
+       u8 dev_mask;
+       unsigned int reg_byte;
+       __le16 reg_word;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               switch (chan->type) {
+               case IIO_LIGHT:
+                       dev_mask = PA12203001_ALS_EN_MASK;
+                       ret = pa12203001_set_power_state(data, true, dev_mask);
+                       if (ret < 0)
+                               return ret;
+                       /*
+                        * ALS ADC value is stored in registers
+                        * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
+                        */
+                       ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
+                                              &reg_word, 2);
+                       if (ret < 0)
+                               goto reg_err;
+
+                       *val = le16_to_cpu(reg_word);
+                       ret = pa12203001_set_power_state(data, false, dev_mask);
+                       if (ret < 0)
+                               return ret;
+                       break;
+               case IIO_PROXIMITY:
+                       dev_mask = PA12203001_PX_EN_MASK;
+                       ret = pa12203001_set_power_state(data, true, dev_mask);
+                       if (ret < 0)
+                               return ret;
+                       ret = regmap_read(data->map, PA12203001_REG_PDH,
+                                         &reg_byte);
+                       if (ret < 0)
+                               goto reg_err;
+
+                       *val = reg_byte;
+                       ret = pa12203001_set_power_state(data, false, dev_mask);
+                       if (ret < 0)
+                               return ret;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
+               if (ret < 0)
+                       return ret;
+               *val = 0;
+               reg_byte = (reg_byte & PA12203001_AFSR_MASK);
+               *val2 = pa12203001_scales[reg_byte >> 4];
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+
+reg_err:
+       pa12203001_set_power_state(data, false, dev_mask);
+       return ret;
+}
+
+static int pa12203001_write_raw(struct iio_dev *indio_dev,
+                               struct iio_chan_spec const *chan, int val,
+                               int val2, long mask)
+{
+       struct pa12203001_data *data = iio_priv(indio_dev);
+       int i, ret, new_val;
+       unsigned int reg_byte;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
+               if (val != 0 || ret < 0)
+                       return -EINVAL;
+               for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
+                       if (val2 == pa12203001_scales[i]) {
+                               new_val = i << PA12203001_AFSR_SHIFT;
+                               return regmap_update_bits(data->map,
+                                                         PA12203001_REG_CFG0,
+                                                         PA12203001_AFSR_MASK,
+                                                         new_val);
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_info pa12203001_info = {
+       .driver_module  = THIS_MODULE,
+       .read_raw = pa12203001_read_raw,
+       .write_raw = pa12203001_write_raw,
+       .attrs = &pa12203001_attr_group,
+};
+
+static int pa12203001_init(struct iio_dev *indio_dev)
+{
+       struct pa12203001_data *data = iio_priv(indio_dev);
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(regvals); i++) {
+               ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
+{
+       struct pa12203001_data *data = iio_priv(indio_dev);
+       int ret;
+
+       mutex_lock(&data->lock);
+       ret = pa12203001_als_enable(data, state);
+       if (ret < 0)
+               goto out;
+
+       ret = pa12203001_px_enable(data, state);
+
+out:
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+static int pa12203001_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       struct pa12203001_data *data;
+       struct iio_dev *indio_dev;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&client->dev,
+                                         sizeof(struct pa12203001_data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       data = iio_priv(indio_dev);
+       i2c_set_clientdata(client, indio_dev);
+       data->client = client;
+
+       data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
+       if (IS_ERR(data->map))
+               return PTR_ERR(data->map);
+
+       mutex_init(&data->lock);
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->info = &pa12203001_info;
+       indio_dev->name = PA12203001_DRIVER_NAME;
+       indio_dev->channels = pa12203001_channels;
+       indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = pa12203001_init(indio_dev);
+       if (ret < 0)
+               return ret;
+
+       ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
+       if (ret < 0)
+               return ret;
+
+       ret = pm_runtime_set_active(&client->dev);
+       if (ret < 0) {
+               pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+               return ret;
+       }
+
+       pm_runtime_enable(&client->dev);
+       pm_runtime_set_autosuspend_delay(&client->dev,
+                                        PA12203001_SLEEP_DELAY_MS);
+       pm_runtime_use_autosuspend(&client->dev);
+
+       return iio_device_register(indio_dev);
+}
+
+static int pa12203001_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+       iio_device_unregister(indio_dev);
+
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+
+       return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+}
+
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
+static int pa12203001_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+
+       return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int pa12203001_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+
+       return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
+}
+#endif
+
+#ifdef CONFIG_PM
+static int pa12203001_runtime_resume(struct device *dev)
+{
+       struct pa12203001_data *data;
+
+       data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+       mutex_lock(&data->lock);
+       if (data->als_needs_enable) {
+               pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
+               data->als_needs_enable = false;
+       }
+       if (data->px_needs_enable) {
+               pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
+               data->px_needs_enable = false;
+       }
+       mutex_unlock(&data->lock);
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops pa12203001_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
+       SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
+};
+
+static const struct acpi_device_id pa12203001_acpi_match[] = {
+       { "TXCPA122", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
+
+static const struct i2c_device_id pa12203001_id[] = {
+               {"txcpa122", 0},
+               {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pa12203001_id);
+
+static struct i2c_driver pa12203001_driver = {
+       .driver = {
+               .name = PA12203001_DRIVER_NAME,
+               .pm = &pa12203001_pm_ops,
+               .acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
+       },
+       .probe = pa12203001_probe,
+       .remove = pa12203001_remove,
+       .id_table = pa12203001_id,
+
+};
+module_i2c_driver(pa12203001_driver);
+
+MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
+MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
new file mode 100644 (file)
index 0000000..4b75bb0
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * RPR-0521 ROHM Ambient Light and Proximity Sensor
+ *
+ * Copyright (c) 2015, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38).
+ *
+ * TODO: illuminance channel, PM support, buffer
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/pm_runtime.h>
+
+#define RPR0521_REG_SYSTEM_CTRL                0x40
+#define RPR0521_REG_MODE_CTRL          0x41
+#define RPR0521_REG_ALS_CTRL           0x42
+#define RPR0521_REG_PXS_CTRL           0x43
+#define RPR0521_REG_PXS_DATA           0x44 /* 16-bit, little endian */
+#define RPR0521_REG_ALS_DATA0          0x46 /* 16-bit, little endian */
+#define RPR0521_REG_ALS_DATA1          0x48 /* 16-bit, little endian */
+#define RPR0521_REG_ID                 0x92
+
+#define RPR0521_MODE_ALS_MASK          BIT(7)
+#define RPR0521_MODE_PXS_MASK          BIT(6)
+#define RPR0521_MODE_MEAS_TIME_MASK    GENMASK(3, 0)
+#define RPR0521_ALS_DATA0_GAIN_MASK    GENMASK(5, 4)
+#define RPR0521_ALS_DATA0_GAIN_SHIFT   4
+#define RPR0521_ALS_DATA1_GAIN_MASK    GENMASK(3, 2)
+#define RPR0521_ALS_DATA1_GAIN_SHIFT   2
+#define RPR0521_PXS_GAIN_MASK          GENMASK(5, 4)
+#define RPR0521_PXS_GAIN_SHIFT         4
+
+#define RPR0521_MODE_ALS_ENABLE                BIT(7)
+#define RPR0521_MODE_ALS_DISABLE       0x00
+#define RPR0521_MODE_PXS_ENABLE                BIT(6)
+#define RPR0521_MODE_PXS_DISABLE       0x00
+
+#define RPR0521_MANUFACT_ID            0xE0
+#define RPR0521_DEFAULT_MEAS_TIME      0x06 /* ALS - 100ms, PXS - 100ms */
+
+#define RPR0521_DRV_NAME               "RPR0521"
+#define RPR0521_REGMAP_NAME            "rpr0521_regmap"
+
+#define RPR0521_SLEEP_DELAY_MS 2000
+
+#define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1"
+#define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1"
+
+struct rpr0521_gain {
+       int scale;
+       int uscale;
+};
+
+static const struct rpr0521_gain rpr0521_als_gain[4] = {
+       {1, 0},         /* x1 */
+       {0, 500000},    /* x2 */
+       {0, 15625},     /* x64 */
+       {0, 7812},      /* x128 */
+};
+
+static const struct rpr0521_gain rpr0521_pxs_gain[3] = {
+       {1, 0},         /* x1 */
+       {0, 500000},    /* x2 */
+       {0, 125000},    /* x4 */
+};
+
+enum rpr0521_channel {
+       RPR0521_CHAN_ALS_DATA0,
+       RPR0521_CHAN_ALS_DATA1,
+       RPR0521_CHAN_PXS,
+};
+
+struct rpr0521_reg_desc {
+       u8 address;
+       u8 device_mask;
+};
+
+static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
+       [RPR0521_CHAN_ALS_DATA0] = {
+               .address        = RPR0521_REG_ALS_DATA0,
+               .device_mask    = RPR0521_MODE_ALS_MASK,
+       },
+       [RPR0521_CHAN_ALS_DATA1] = {
+               .address        = RPR0521_REG_ALS_DATA1,
+               .device_mask    = RPR0521_MODE_ALS_MASK,
+       },
+       [RPR0521_CHAN_PXS]      = {
+               .address        = RPR0521_REG_PXS_DATA,
+               .device_mask    = RPR0521_MODE_PXS_MASK,
+       },
+};
+
+static const struct rpr0521_gain_info {
+       u8 reg;
+       u8 mask;
+       u8 shift;
+       const struct rpr0521_gain *gain;
+       int size;
+} rpr0521_gain[] = {
+       [RPR0521_CHAN_ALS_DATA0] = {
+               .reg    = RPR0521_REG_ALS_CTRL,
+               .mask   = RPR0521_ALS_DATA0_GAIN_MASK,
+               .shift  = RPR0521_ALS_DATA0_GAIN_SHIFT,
+               .gain   = rpr0521_als_gain,
+               .size   = ARRAY_SIZE(rpr0521_als_gain),
+       },
+       [RPR0521_CHAN_ALS_DATA1] = {
+               .reg    = RPR0521_REG_ALS_CTRL,
+               .mask   = RPR0521_ALS_DATA1_GAIN_MASK,
+               .shift  = RPR0521_ALS_DATA1_GAIN_SHIFT,
+               .gain   = rpr0521_als_gain,
+               .size   = ARRAY_SIZE(rpr0521_als_gain),
+       },
+       [RPR0521_CHAN_PXS] = {
+               .reg    = RPR0521_REG_PXS_CTRL,
+               .mask   = RPR0521_PXS_GAIN_MASK,
+               .shift  = RPR0521_PXS_GAIN_SHIFT,
+               .gain   = rpr0521_pxs_gain,
+               .size   = ARRAY_SIZE(rpr0521_pxs_gain),
+       },
+};
+
+struct rpr0521_data {
+       struct i2c_client *client;
+
+       /* protect device params updates (e.g state, gain) */
+       struct mutex lock;
+
+       /* device active status */
+       bool als_dev_en;
+       bool pxs_dev_en;
+
+       /* optimize runtime pm ops - enable device only if needed */
+       bool als_ps_need_en;
+       bool pxs_ps_need_en;
+
+       struct regmap *regmap;
+};
+
+static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
+static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL);
+
+static struct attribute *rpr0521_attributes[] = {
+       &iio_const_attr_in_intensity_scale_available.dev_attr.attr,
+       &iio_const_attr_in_proximity_scale_available.dev_attr.attr,
+       NULL,
+};
+
+static const struct attribute_group rpr0521_attribute_group = {
+       .attrs = rpr0521_attributes,
+};
+
+static const struct iio_chan_spec rpr0521_channels[] = {
+       {
+               .type = IIO_INTENSITY,
+               .modified = 1,
+               .address = RPR0521_CHAN_ALS_DATA0,
+               .channel2 = IIO_MOD_LIGHT_BOTH,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                       BIT(IIO_CHAN_INFO_SCALE),
+       },
+       {
+               .type = IIO_INTENSITY,
+               .modified = 1,
+               .address = RPR0521_CHAN_ALS_DATA1,
+               .channel2 = IIO_MOD_LIGHT_IR,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                       BIT(IIO_CHAN_INFO_SCALE),
+       },
+       {
+               .type = IIO_PROXIMITY,
+               .address = RPR0521_CHAN_PXS,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                       BIT(IIO_CHAN_INFO_SCALE),
+       }
+};
+
+static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
+{
+       int ret;
+
+       ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+                                RPR0521_MODE_ALS_MASK,
+                                status);
+       if (ret < 0)
+               return ret;
+
+       data->als_dev_en = true;
+
+       return 0;
+}
+
+static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
+{
+       int ret;
+
+       ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+                                RPR0521_MODE_PXS_MASK,
+                                status);
+       if (ret < 0)
+               return ret;
+
+       data->pxs_dev_en = true;
+
+       return 0;
+}
+
+/**
+ * rpr0521_set_power_state - handles runtime PM state and sensors enabled status
+ *
+ * @data: rpr0521 device private data
+ * @on: state to be set for devices in @device_mask
+ * @device_mask: bitmask specifying for which device we need to update @on state
+ *
+ * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but
+ * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to
+ * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable
+ * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not
+ * be called twice.
+ */
+static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
+                                  u8 device_mask)
+{
+#ifdef CONFIG_PM
+       int ret;
+       u8 update_mask = 0;
+
+       if (device_mask & RPR0521_MODE_ALS_MASK) {
+               if (on && !data->als_ps_need_en && data->pxs_dev_en)
+                       update_mask |= RPR0521_MODE_ALS_MASK;
+               else
+                       data->als_ps_need_en = on;
+       }
+
+       if (device_mask & RPR0521_MODE_PXS_MASK) {
+               if (on && !data->pxs_ps_need_en && data->als_dev_en)
+                       update_mask |= RPR0521_MODE_PXS_MASK;
+               else
+                       data->pxs_ps_need_en = on;
+       }
+
+       if (update_mask) {
+               ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+                                        update_mask, update_mask);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (on) {
+               ret = pm_runtime_get_sync(&data->client->dev);
+       } else {
+               pm_runtime_mark_last_busy(&data->client->dev);
+               ret = pm_runtime_put_autosuspend(&data->client->dev);
+       }
+       if (ret < 0) {
+               dev_err(&data->client->dev,
+                       "Failed: rpr0521_set_power_state for %d, ret %d\n",
+                       on, ret);
+               if (on)
+                       pm_runtime_put_noidle(&data->client->dev);
+
+               return ret;
+       }
+#endif
+       return 0;
+}
+
+static int rpr0521_get_gain(struct rpr0521_data *data, int chan,
+                           int *val, int *val2)
+{
+       int ret, reg, idx;
+
+       ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, &reg);
+       if (ret < 0)
+               return ret;
+
+       idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift;
+       *val = rpr0521_gain[chan].gain[idx].scale;
+       *val2 = rpr0521_gain[chan].gain[idx].uscale;
+
+       return 0;
+}
+
+static int rpr0521_set_gain(struct rpr0521_data *data, int chan,
+                           int val, int val2)
+{
+       int i, idx = -EINVAL;
+
+       /* get gain index */
+       for (i = 0; i < rpr0521_gain[chan].size; i++)
+               if (val == rpr0521_gain[chan].gain[i].scale &&
+                   val2 == rpr0521_gain[chan].gain[i].uscale) {
+                       idx = i;
+                       break;
+               }
+
+       if (idx < 0)
+               return idx;
+
+       return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg,
+                                 rpr0521_gain[chan].mask,
+                                 idx << rpr0521_gain[chan].shift);
+}
+
+static int rpr0521_read_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan, int *val,
+                           int *val2, long mask)
+{
+       struct rpr0521_data *data = iio_priv(indio_dev);
+       int ret;
+       u8 device_mask;
+       __le16 raw_data;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY)
+                       return -EINVAL;
+
+               device_mask = rpr0521_data_reg[chan->address].device_mask;
+
+               mutex_lock(&data->lock);
+               ret = rpr0521_set_power_state(data, true, device_mask);
+               if (ret < 0) {
+                       mutex_unlock(&data->lock);
+                       return ret;
+               }
+
+               ret = regmap_bulk_read(data->regmap,
+                                      rpr0521_data_reg[chan->address].address,
+                                      &raw_data, 2);
+               if (ret < 0) {
+                       rpr0521_set_power_state(data, false, device_mask);
+                       mutex_unlock(&data->lock);
+                       return ret;
+               }
+
+               ret = rpr0521_set_power_state(data, false, device_mask);
+               mutex_unlock(&data->lock);
+               if (ret < 0)
+                       return ret;
+
+               *val = le16_to_cpu(raw_data);
+
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               mutex_lock(&data->lock);
+               ret = rpr0521_get_gain(data, chan->address, val, val2);
+               mutex_unlock(&data->lock);
+               if (ret < 0)
+                       return ret;
+
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int rpr0521_write_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan, int val,
+                            int val2, long mask)
+{
+       struct rpr0521_data *data = iio_priv(indio_dev);
+       int ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               mutex_lock(&data->lock);
+               ret = rpr0521_set_gain(data, chan->address, val, val2);
+               mutex_unlock(&data->lock);
+
+               return ret;
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_info rpr0521_info = {
+       .driver_module  = THIS_MODULE,
+       .read_raw       = rpr0521_read_raw,
+       .write_raw      = rpr0521_write_raw,
+       .attrs          = &rpr0521_attribute_group,
+};
+
+static int rpr0521_init(struct rpr0521_data *data)
+{
+       int ret;
+       int id;
+
+       ret = regmap_read(data->regmap, RPR0521_REG_ID, &id);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Failed to read REG_ID register\n");
+               return ret;
+       }
+
+       if (id != RPR0521_MANUFACT_ID) {
+               dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
+                       id, RPR0521_MANUFACT_ID);
+               return -ENODEV;
+       }
+
+       /* set default measurement time - 100 ms for both ALS and PS */
+       ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+                                RPR0521_MODE_MEAS_TIME_MASK,
+                                RPR0521_DEFAULT_MEAS_TIME);
+       if (ret) {
+               pr_err("regmap_update_bits returned %d\n", ret);
+               return ret;
+       }
+
+       ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
+       if (ret < 0)
+               return ret;
+       ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int rpr0521_poweroff(struct rpr0521_data *data)
+{
+       int ret;
+
+       ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+                                RPR0521_MODE_ALS_MASK |
+                                RPR0521_MODE_PXS_MASK,
+                                RPR0521_MODE_ALS_DISABLE |
+                                RPR0521_MODE_PXS_DISABLE);
+       if (ret < 0)
+               return ret;
+
+       data->als_dev_en = false;
+       data->pxs_dev_en = false;
+
+       return 0;
+}
+
+static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case RPR0521_REG_MODE_CTRL:
+       case RPR0521_REG_ALS_CTRL:
+       case RPR0521_REG_PXS_CTRL:
+               return false;
+       default:
+               return true;
+       }
+}
+
+static const struct regmap_config rpr0521_regmap_config = {
+       .name           = RPR0521_REGMAP_NAME,
+
+       .reg_bits       = 8,
+       .val_bits       = 8,
+
+       .max_register   = RPR0521_REG_ID,
+       .cache_type     = REGCACHE_RBTREE,
+       .volatile_reg   = rpr0521_is_volatile_reg,
+};
+
+static int rpr0521_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct rpr0521_data *data;
+       struct iio_dev *indio_dev;
+       struct regmap *regmap;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&client->dev, "regmap_init failed!\n");
+               return PTR_ERR(regmap);
+       }
+
+       data = iio_priv(indio_dev);
+       i2c_set_clientdata(client, indio_dev);
+       data->client = client;
+       data->regmap = regmap;
+
+       mutex_init(&data->lock);
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->info = &rpr0521_info;
+       indio_dev->name = RPR0521_DRV_NAME;
+       indio_dev->channels = rpr0521_channels;
+       indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = rpr0521_init(data);
+       if (ret < 0) {
+               dev_err(&client->dev, "rpr0521 chip init failed\n");
+               return ret;
+       }
+       ret = iio_device_register(indio_dev);
+       if (ret < 0)
+               return ret;
+
+       ret = pm_runtime_set_active(&client->dev);
+       if (ret < 0)
+               goto err_iio_unregister;
+
+       pm_runtime_enable(&client->dev);
+       pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
+       pm_runtime_use_autosuspend(&client->dev);
+
+       return 0;
+
+err_iio_unregister:
+       iio_device_unregister(indio_dev);
+       return ret;
+}
+
+static int rpr0521_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+       pm_runtime_put_noidle(&client->dev);
+
+       iio_device_unregister(indio_dev);
+       rpr0521_poweroff(iio_priv(indio_dev));
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int rpr0521_runtime_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct rpr0521_data *data = iio_priv(indio_dev);
+       int ret;
+
+       /* disable channels and sets {als,pxs}_dev_en to false */
+       mutex_lock(&data->lock);
+       ret = rpr0521_poweroff(data);
+       mutex_unlock(&data->lock);
+
+       return ret;
+}
+
+static int rpr0521_runtime_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct rpr0521_data *data = iio_priv(indio_dev);
+       int ret;
+
+       if (data->als_ps_need_en) {
+               ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
+               if (ret < 0)
+                       return ret;
+               data->als_ps_need_en = false;
+       }
+
+       if (data->pxs_ps_need_en) {
+               ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
+               if (ret < 0)
+                       return ret;
+               data->pxs_ps_need_en = false;
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops rpr0521_pm_ops = {
+       SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend,
+                          rpr0521_runtime_resume, NULL)
+};
+
+static const struct acpi_device_id rpr0521_acpi_match[] = {
+       {"RPR0521", 0},
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match);
+
+static const struct i2c_device_id rpr0521_id[] = {
+       {"rpr0521", 0},
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, rpr0521_id);
+
+static struct i2c_driver rpr0521_driver = {
+       .driver = {
+               .name   = RPR0521_DRV_NAME,
+               .pm     = &rpr0521_pm_ops,
+               .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
+       },
+       .probe          = rpr0521_probe,
+       .remove         = rpr0521_remove,
+       .id_table       = rpr0521_id,
+};
+
+module_i2c_driver(rpr0521_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
+MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver");
+MODULE_LICENSE("GPL v2");
index 11a027adc204aeb630c66707eaf9d5d0ce169ebb..f101bb5bddc7d710c6412dc2d982a6785953b47d 100644 (file)
@@ -676,6 +676,7 @@ static const struct i2c_device_id stk3310_i2c_id[] = {
        {"STK3311", 0},
        {}
 };
+MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id);
 
 static const struct acpi_device_id stk3310_acpi_id[] = {
        {"STK3310", 0},
index f8b1df018abeeba410c19dc48bd9723663973977..f90f8c5919fee96447a681ef2475208a9572dea8 100644 (file)
@@ -392,7 +392,6 @@ static struct i2c_driver tcs3414_driver = {
        .driver = {
                .name   = TCS3414_DRV_NAME,
                .pm     = &tcs3414_pm_ops,
-               .owner  = THIS_MODULE,
        },
        .probe          = tcs3414_probe,
        .remove         = tcs3414_remove,
index 752569985d1dff295fb00df9723926b404a7dafb..1b530bf04c8984d30feb70938b56772c72b16b98 100644 (file)
@@ -366,7 +366,6 @@ static struct i2c_driver tcs3472_driver = {
        .driver = {
                .name   = TCS3472_DRV_NAME,
                .pm     = &tcs3472_pm_ops,
-               .owner  = THIS_MODULE,
        },
        .probe          = tcs3472_probe,
        .remove         = tcs3472_remove,
index 63c26e2d5d9722242cf82b0bc8c5dc3ec3eacd46..26979183d27cf323dc934d799b415e3a2b666980 100644 (file)
@@ -247,7 +247,6 @@ static struct i2c_driver tsl4531_driver = {
        .driver = {
                .name   = TSL4531_DRV_NAME,
                .pm     = TSL4531_PM_OPS,
-               .owner  = THIS_MODULE,
        },
        .probe  = tsl4531_probe,
        .remove = tsl4531_remove,
index d948c4778ba6cc98776654edb34ec1636f08f480..c9d85bbc9230059d4483567150b7838f01c65c54 100644 (file)
@@ -185,7 +185,6 @@ static int vcnl4000_probe(struct i2c_client *client,
 static struct i2c_driver vcnl4000_driver = {
        .driver = {
                .name   = VCNL4000_DRV_NAME,
-               .owner  = THIS_MODULE,
        },
        .probe  = vcnl4000_probe,
        .id_table = vcnl4000_id,
index 1347a1f2e46f8194bad0bfe49bd91ea6a948ac8e..e330205f81947589a06d5a83232696a0613bbd1f 100644 (file)
@@ -85,6 +85,7 @@
 #define BMC150_MAGN_REG_HIGH_THRESH            0x50
 #define BMC150_MAGN_REG_REP_XY                 0x51
 #define BMC150_MAGN_REG_REP_Z                  0x52
+#define BMC150_MAGN_REG_REP_DATAMASK           GENMASK(7, 0)
 
 #define BMC150_MAGN_REG_TRIM_START             0x5D
 #define BMC150_MAGN_REG_TRIM_END               0x71
@@ -559,7 +560,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
                        }
                        ret = regmap_update_bits(data->regmap,
                                                 BMC150_MAGN_REG_REP_XY,
-                                                0xFF,
+                                                BMC150_MAGN_REG_REP_DATAMASK,
                                                 BMC150_MAGN_REPXY_TO_REGVAL
                                                 (val));
                        mutex_unlock(&data->mutex);
@@ -575,7 +576,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
                        }
                        ret = regmap_update_bits(data->regmap,
                                                 BMC150_MAGN_REG_REP_Z,
-                                                0xFF,
+                                                BMC150_MAGN_REG_REP_DATAMASK,
                                                 BMC150_MAGN_REPZ_TO_REGVAL
                                                 (val));
                        mutex_unlock(&data->mutex);
@@ -588,17 +589,6 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
        }
 }
 
-static int bmc150_magn_validate_trigger(struct iio_dev *indio_dev,
-                                       struct iio_trigger *trig)
-{
-       struct bmc150_magn_data *data = iio_priv(indio_dev);
-
-       if (data->dready_trig != trig)
-               return -EINVAL;
-
-       return 0;
-}
-
 static ssize_t bmc150_magn_show_samp_freq_avail(struct device *dev,
                                                struct device_attribute *attr,
                                                char *buf)
@@ -659,11 +649,12 @@ static const struct iio_info bmc150_magn_info = {
        .attrs = &bmc150_magn_attrs_group,
        .read_raw = bmc150_magn_read_raw,
        .write_raw = bmc150_magn_write_raw,
-       .validate_trigger = bmc150_magn_validate_trigger,
        .driver_module = THIS_MODULE,
 };
 
-static const unsigned long bmc150_magn_scan_masks[] = {0x07, 0};
+static const unsigned long bmc150_magn_scan_masks[] = {
+                                       BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+                                       0};
 
 static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
 {
@@ -674,7 +665,6 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
 
        mutex_lock(&data->mutex);
        ret = bmc150_magn_read_xyz(data, data->buffer);
-       mutex_unlock(&data->mutex);
        if (ret < 0)
                goto err;
 
@@ -682,7 +672,8 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
                                           pf->timestamp);
 
 err:
-       iio_trigger_notify_done(data->dready_trig);
+       mutex_unlock(&data->mutex);
+       iio_trigger_notify_done(indio_dev->trig);
 
        return IRQ_HANDLED;
 }
@@ -793,29 +784,23 @@ static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig,
        if (state == data->dready_trigger_on)
                goto err_unlock;
 
-       ret = bmc150_magn_set_power_state(data, state);
-       if (ret < 0)
-               goto err_unlock;
-
        ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY,
                                 BMC150_MAGN_MASK_DRDY_EN,
                                 state << BMC150_MAGN_SHIFT_DRDY_EN);
        if (ret < 0)
-               goto err_poweroff;
+               goto err_unlock;
 
        data->dready_trigger_on = state;
 
        if (state) {
                ret = bmc150_magn_reset_intr(data);
                if (ret < 0)
-                       goto err_poweroff;
+                       goto err_unlock;
        }
        mutex_unlock(&data->mutex);
 
        return 0;
 
-err_poweroff:
-       bmc150_magn_set_power_state(data, false);
 err_unlock:
        mutex_unlock(&data->mutex);
        return ret;
@@ -827,6 +812,27 @@ static const struct iio_trigger_ops bmc150_magn_trigger_ops = {
        .owner = THIS_MODULE,
 };
 
+static int bmc150_magn_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct bmc150_magn_data *data = iio_priv(indio_dev);
+
+       return bmc150_magn_set_power_state(data, true);
+}
+
+static int bmc150_magn_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct bmc150_magn_data *data = iio_priv(indio_dev);
+
+       return bmc150_magn_set_power_state(data, false);
+}
+
+static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = {
+       .preenable = bmc150_magn_buffer_preenable,
+       .postenable = iio_triggered_buffer_postenable,
+       .predisable = iio_triggered_buffer_predisable,
+       .postdisable = bmc150_magn_buffer_postdisable,
+};
+
 static int bmc150_magn_gpio_probe(struct i2c_client *client)
 {
        struct device *dev;
@@ -932,16 +938,6 @@ static int bmc150_magn_probe(struct i2c_client *client,
                        goto err_poweroff;
                }
 
-               ret = iio_triggered_buffer_setup(indio_dev,
-                                                &iio_pollfunc_store_time,
-                                                bmc150_magn_trigger_handler,
-                                                NULL);
-               if (ret < 0) {
-                       dev_err(&client->dev,
-                               "iio triggered buffer setup failed\n");
-                       goto err_trigger_unregister;
-               }
-
                ret = request_threaded_irq(client->irq,
                                           iio_trigger_generic_data_rdy_poll,
                                           NULL,
@@ -951,14 +947,24 @@ static int bmc150_magn_probe(struct i2c_client *client,
                if (ret < 0) {
                        dev_err(&client->dev, "request irq %d failed\n",
                                client->irq);
-                       goto err_buffer_cleanup;
+                       goto err_trigger_unregister;
                }
        }
 
+       ret = iio_triggered_buffer_setup(indio_dev,
+                                        iio_pollfunc_store_time,
+                                        bmc150_magn_trigger_handler,
+                                        &bmc150_magn_buffer_setup_ops);
+       if (ret < 0) {
+               dev_err(&client->dev,
+                       "iio triggered buffer setup failed\n");
+               goto err_free_irq;
+       }
+
        ret = iio_device_register(indio_dev);
        if (ret < 0) {
                dev_err(&client->dev, "unable to register iio device\n");
-               goto err_free_irq;
+               goto err_buffer_cleanup;
        }
 
        ret = pm_runtime_set_active(&client->dev);
@@ -976,12 +982,11 @@ static int bmc150_magn_probe(struct i2c_client *client,
 
 err_iio_unregister:
        iio_device_unregister(indio_dev);
+err_buffer_cleanup:
+       iio_triggered_buffer_cleanup(indio_dev);
 err_free_irq:
        if (client->irq > 0)
                free_irq(client->irq, data->dready_trig);
-err_buffer_cleanup:
-       if (data->dready_trig)
-               iio_triggered_buffer_cleanup(indio_dev);
 err_trigger_unregister:
        if (data->dready_trig)
                iio_trigger_unregister(data->dready_trig);
@@ -1000,14 +1005,13 @@ static int bmc150_magn_remove(struct i2c_client *client)
        pm_runtime_put_noidle(&client->dev);
 
        iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
 
        if (client->irq > 0)
                free_irq(data->client->irq, data->dready_trig);
 
-       if (data->dready_trig) {
-               iio_triggered_buffer_cleanup(indio_dev);
+       if (data->dready_trig)
                iio_trigger_unregister(data->dready_trig);
-       }
 
        mutex_lock(&data->mutex);
        bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true);
@@ -1034,6 +1038,9 @@ static int bmc150_magn_runtime_suspend(struct device *dev)
        return 0;
 }
 
+/*
+ * Should be called with data->mutex held.
+ */
 static int bmc150_magn_runtime_resume(struct device *dev)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1082,12 +1089,14 @@ static const struct dev_pm_ops bmc150_magn_pm_ops = {
 
 static const struct acpi_device_id bmc150_magn_acpi_match[] = {
        {"BMC150B", 0},
+       {"BMC156B", 0},
        {},
 };
 MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
 
 static const struct i2c_device_id bmc150_magn_id[] = {
        {"bmc150_magn", 0},
+       {"bmc156_magn", 0},
        {},
 };
 MODULE_DEVICE_TABLE(i2c, bmc150_magn_id);
index 706ebfd6297fa7c0a311a80bfcb431b533d2cc70..176e14a615580ac1485d765092ec68d87485e3a9 100644 (file)
@@ -316,31 +316,31 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
 static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
                                  __le16 buf[], int *val)
 {
-       int raw_x, raw_y, raw_z;
-       int sens_x, sens_y, sens_z;
+       int raw[3];
+       int sens[3];
        int nfo;
 
-       raw_x = le16_to_cpu(buf[AXIS_X]);
-       raw_y = le16_to_cpu(buf[AXIS_Y]);
-       raw_z = le16_to_cpu(buf[AXIS_Z]);
+       raw[AXIS_X] = le16_to_cpu(buf[AXIS_X]);
+       raw[AXIS_Y] = le16_to_cpu(buf[AXIS_Y]);
+       raw[AXIS_Z] = le16_to_cpu(buf[AXIS_Z]);
 
-       sens_x = mmc35240_props_table[data->res].sens[AXIS_X];
-       sens_y = mmc35240_props_table[data->res].sens[AXIS_Y];
-       sens_z = mmc35240_props_table[data->res].sens[AXIS_Z];
+       sens[AXIS_X] = mmc35240_props_table[data->res].sens[AXIS_X];
+       sens[AXIS_Y] = mmc35240_props_table[data->res].sens[AXIS_Y];
+       sens[AXIS_Z] = mmc35240_props_table[data->res].sens[AXIS_Z];
 
        nfo = mmc35240_props_table[data->res].nfo;
 
        switch (index) {
        case AXIS_X:
-               *val = (raw_x - nfo) * 1000 / sens_x;
+               *val = (raw[AXIS_X] - nfo) * 1000 / sens[AXIS_X];
                break;
        case AXIS_Y:
-               *val = (raw_y - nfo) * 1000 / sens_y -
-                       (raw_z - nfo)  * 1000 / sens_z;
+               *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] -
+                       (raw[AXIS_Z] - nfo)  * 1000 / sens[AXIS_Z];
                break;
        case AXIS_Z:
-               *val = (raw_y - nfo) * 1000 / sens_y +
-                       (raw_z - nfo) * 1000 / sens_z;
+               *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] +
+                       (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];
                break;
        default:
                return -EINVAL;
@@ -559,6 +559,12 @@ static const struct dev_pm_ops mmc35240_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume)
 };
 
+static const struct of_device_id mmc35240_of_match[] = {
+       { .compatible = "memsic,mmc35240", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mmc35240_of_match);
+
 static const struct acpi_device_id mmc35240_acpi_match[] = {
        {"MMC35240", 0},
        { },
@@ -574,6 +580,7 @@ MODULE_DEVICE_TABLE(i2c, mmc35240_id);
 static struct i2c_driver mmc35240_driver = {
        .driver = {
                .name = MMC35240_DRV_NAME,
+               .of_match_table = mmc35240_of_match,
                .pm = &mmc35240_pm_ops,
                .acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
        },
index 287691ca56c1f89924b06da7216cd5798f3668ef..06a4d9c3558196ec54d1d04200e62b14753c4c62 100644 (file)
@@ -18,6 +18,7 @@
 #define LSM303DLHC_MAGN_DEV_NAME       "lsm303dlhc_magn"
 #define LSM303DLM_MAGN_DEV_NAME                "lsm303dlm_magn"
 #define LIS3MDL_MAGN_DEV_NAME          "lis3mdl"
+#define LSM303AGR_MAGN_DEV_NAME                "lsm303agr_magn"
 
 int st_magn_common_probe(struct iio_dev *indio_dev);
 void st_magn_common_remove(struct iio_dev *indio_dev);
@@ -25,6 +26,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev);
 #ifdef CONFIG_IIO_BUFFER
 int st_magn_allocate_ring(struct iio_dev *indio_dev);
 void st_magn_deallocate_ring(struct iio_dev *indio_dev);
+int st_magn_trig_set_state(struct iio_trigger *trig, bool state);
+#define ST_MAGN_TRIGGER_SET_STATE (&st_magn_trig_set_state)
 #else /* CONFIG_IIO_BUFFER */
 static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
 {
index bf427dc0d226c40de9adc92257ece78ab6b14de6..ecd3bd0a97693420c13bfae8fc583ff74854edf8 100644 (file)
 #include <linux/iio/common/st_sensors.h>
 #include "st_magn.h"
 
+int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
+{
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+
+       return st_sensors_set_dataready_irq(indio_dev, state);
+}
+
 static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
 {
        return st_sensors_set_enable(indio_dev, true);
index b4bcfb790f49fe2060247b259e141d76bf1aff92..f8dc4b85d70c60858f26b18aba3e3be8ffe43c92 100644 (file)
@@ -43,6 +43,7 @@
 #define ST_MAGN_FS_AVL_8000MG                  8000
 #define ST_MAGN_FS_AVL_8100MG                  8100
 #define ST_MAGN_FS_AVL_12000MG                 12000
+#define ST_MAGN_FS_AVL_15000MG                 15000
 #define ST_MAGN_FS_AVL_16000MG                 16000
 
 /* CUSTOM VALUES FOR SENSOR 0 */
 #define ST_MAGN_2_OUT_Y_L_ADDR                 0x2a
 #define ST_MAGN_2_OUT_Z_L_ADDR                 0x2c
 
+/* CUSTOM VALUES FOR SENSOR 3 */
+#define ST_MAGN_3_WAI_ADDR                     0x4f
+#define ST_MAGN_3_WAI_EXP                      0x40
+#define ST_MAGN_3_ODR_ADDR                     0x60
+#define ST_MAGN_3_ODR_MASK                     0x0c
+#define ST_MAGN_3_ODR_AVL_10HZ_VAL             0x00
+#define ST_MAGN_3_ODR_AVL_20HZ_VAL             0x01
+#define ST_MAGN_3_ODR_AVL_50HZ_VAL             0x02
+#define ST_MAGN_3_ODR_AVL_100HZ_VAL            0x03
+#define ST_MAGN_3_PW_ADDR                      0x60
+#define ST_MAGN_3_PW_MASK                      0x03
+#define ST_MAGN_3_PW_ON                                0x00
+#define ST_MAGN_3_PW_OFF                       0x03
+#define ST_MAGN_3_BDU_ADDR                     0x62
+#define ST_MAGN_3_BDU_MASK                     0x10
+#define ST_MAGN_3_DRDY_IRQ_ADDR                        0x62
+#define ST_MAGN_3_DRDY_INT_MASK                        0x01
+#define ST_MAGN_3_FS_AVL_15000_GAIN            1500
+#define ST_MAGN_3_MULTIREAD_BIT                        false
+#define ST_MAGN_3_OUT_X_L_ADDR                 0x68
+#define ST_MAGN_3_OUT_Y_L_ADDR                 0x6a
+#define ST_MAGN_3_OUT_Z_L_ADDR                 0x6c
+
 static const struct iio_chan_spec st_magn_16bit_channels[] = {
        ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -189,9 +213,26 @@ static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(3)
 };
 
+static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
+       ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+                       ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
+                       ST_MAGN_3_OUT_X_L_ADDR),
+       ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+                       ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
+                       ST_MAGN_3_OUT_Y_L_ADDR),
+       ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+                       ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
+                       ST_MAGN_3_OUT_Z_L_ADDR),
+       IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
 static const struct st_sensor_settings st_magn_sensors_settings[] = {
        {
                .wai = 0, /* This sensor has no valid WhoAmI report 0 */
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LSM303DLH_MAGN_DEV_NAME,
                },
@@ -268,6 +309,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
        },
        {
                .wai = ST_MAGN_1_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LSM303DLHC_MAGN_DEV_NAME,
                        [1] = LSM303DLM_MAGN_DEV_NAME,
@@ -346,6 +388,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
        },
        {
                .wai = ST_MAGN_2_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LIS3MDL_MAGN_DEV_NAME,
                },
@@ -399,6 +442,48 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
                .multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
                .bootime = 2,
        },
+       {
+               .wai = ST_MAGN_3_WAI_EXP,
+               .wai_addr = ST_MAGN_3_WAI_ADDR,
+               .sensors_supported = {
+                       [0] = LSM303AGR_MAGN_DEV_NAME,
+               },
+               .ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
+               .odr = {
+                       .addr = ST_MAGN_3_ODR_ADDR,
+                       .mask = ST_MAGN_3_ODR_MASK,
+                       .odr_avl = {
+                               { 10, ST_MAGN_3_ODR_AVL_10HZ_VAL, },
+                               { 20, ST_MAGN_3_ODR_AVL_20HZ_VAL, },
+                               { 50, ST_MAGN_3_ODR_AVL_50HZ_VAL, },
+                               { 100, ST_MAGN_3_ODR_AVL_100HZ_VAL, },
+                       },
+               },
+               .pw = {
+                       .addr = ST_MAGN_3_PW_ADDR,
+                       .mask = ST_MAGN_3_PW_MASK,
+                       .value_on = ST_MAGN_3_PW_ON,
+                       .value_off = ST_MAGN_3_PW_OFF,
+               },
+               .fs = {
+                       .fs_avl = {
+                               [0] = {
+                                       .num = ST_MAGN_FS_AVL_15000MG,
+                                       .gain = ST_MAGN_3_FS_AVL_15000_GAIN,
+                               },
+                       },
+               },
+               .bdu = {
+                       .addr = ST_MAGN_3_BDU_ADDR,
+                       .mask = ST_MAGN_3_BDU_MASK,
+               },
+               .drdy_irq = {
+                       .addr = ST_MAGN_3_DRDY_IRQ_ADDR,
+                       .mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
+               },
+               .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
+               .bootime = 2,
+       },
 };
 
 static int st_magn_read_raw(struct iio_dev *indio_dev,
@@ -477,6 +562,16 @@ static const struct iio_info magn_info = {
        .write_raw = &st_magn_write_raw,
 };
 
+#ifdef CONFIG_IIO_TRIGGER
+static const struct iio_trigger_ops st_magn_trigger_ops = {
+       .owner = THIS_MODULE,
+       .set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
+};
+#define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
+#else
+#define ST_MAGN_TRIGGER_OPS NULL
+#endif
+
 int st_magn_common_probe(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *mdata = iio_priv(indio_dev);
@@ -513,7 +608,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
                return err;
 
        if (irq > 0) {
-               err = st_sensors_allocate_trigger(indio_dev, NULL);
+               err = st_sensors_allocate_trigger(indio_dev,
+                                               ST_MAGN_TRIGGER_OPS);
                if (err < 0)
                        goto st_magn_probe_trigger_error;
        }
index 5311d8aea8cc13ee73dd36bdbcdd202f61538120..8aa37af306edd61f83424f77314a922523a8c2f1 100644 (file)
@@ -36,6 +36,10 @@ static const struct of_device_id st_magn_of_match[] = {
                .compatible = "st,lis3mdl-magn",
                .data = LIS3MDL_MAGN_DEV_NAME,
        },
+       {
+               .compatible = "st,lsm303agr-magn",
+               .data = LSM303AGR_MAGN_DEV_NAME,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, st_magn_of_match);
@@ -79,13 +83,13 @@ static const struct i2c_device_id st_magn_id_table[] = {
        { LSM303DLHC_MAGN_DEV_NAME },
        { LSM303DLM_MAGN_DEV_NAME },
        { LIS3MDL_MAGN_DEV_NAME },
+       { LSM303AGR_MAGN_DEV_NAME },
        {},
 };
 MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
 
 static struct i2c_driver st_magn_driver = {
        .driver = {
-               .owner = THIS_MODULE,
                .name = "st-magn-i2c",
                .of_match_table = of_match_ptr(st_magn_of_match),
        },
index 7adacf160146eba9af2e4f9034f064729a8e966d..0abca2c6afa6787c3eff0deb84cbd71864030f61 100644 (file)
@@ -51,6 +51,7 @@ static const struct spi_device_id st_magn_id_table[] = {
        { LSM303DLHC_MAGN_DEV_NAME },
        { LSM303DLM_MAGN_DEV_NAME },
        { LIS3MDL_MAGN_DEV_NAME },
+       { LSM303AGR_MAGN_DEV_NAME },
        {},
 };
 MODULE_DEVICE_TABLE(spi, st_magn_id_table);
index fa62950419479233a3aecf0f1b3fe03c42e5fe6f..4745179ff64b4b6afee6f237555dec5294e0fdf1 100644 (file)
@@ -53,10 +53,10 @@ config MPL3115
           will be called mpl3115.
 
 config MS5611
-       tristate "Measurement Specialities MS5611 pressure sensor driver"
+       tristate "Measurement Specialties MS5611 pressure sensor driver"
        help
-         Say Y here to build support for the Measurement Specialities
-         MS5611 pressure and temperature sensor.
+         Say Y here to build support for the Measurement Specialties
+         MS5611, MS5607 pressure and temperature sensors.
 
          To compile this driver as a module, choose M here: the module will
          be called ms5611_core.
index 099c6cdea43f12572e118202d6a6eb10f4788cff..23b93c797dba7009cafacdb07b5c895652d834e0 100644 (file)
 
 #define MS5611_PROM_WORDS_NB           8
 
+enum {
+       MS5611,
+       MS5607,
+};
+
+struct ms5611_chip_info {
+       u16 prom[MS5611_PROM_WORDS_NB];
+
+       int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info,
+                                           s32 *temp, s32 *pressure);
+};
+
 struct ms5611_state {
        void *client;
        struct mutex lock;
@@ -36,9 +48,9 @@ struct ms5611_state {
        int (*read_adc_temp_and_pressure)(struct device *dev,
                                          s32 *temp, s32 *pressure);
 
-       u16 prom[MS5611_PROM_WORDS_NB];
+       struct ms5611_chip_info *chip_info;
 };
 
-int ms5611_probe(struct iio_dev *indio_dev, struct device *dev);
+int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type);
 
 #endif /* _MS5611_H */
index e42c8531d9b35d65f360fae6dc020c9b34465364..2f3d9b4aca4ec695b99f75e53e93af6107bf1d01 100644 (file)
@@ -9,6 +9,7 @@
  *
  * Data sheet:
  *  http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
+ *  http://www.meas-spec.com/downloads/MS5607-02BA03.pdf
  *
  */
 
@@ -50,7 +51,8 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)
        struct ms5611_state *st = iio_priv(indio_dev);
 
        for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
-               ret = st->read_prom_word(&indio_dev->dev, i, &st->prom[i]);
+               ret = st->read_prom_word(&indio_dev->dev,
+                                        i, &st->chip_info->prom[i]);
                if (ret < 0) {
                        dev_err(&indio_dev->dev,
                                "failed to read prom at %d\n", i);
@@ -58,7 +60,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)
                }
        }
 
-       if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) {
+       if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) {
                dev_err(&indio_dev->dev, "PROM integrity check failed\n");
                return -ENODEV;
        }
@@ -70,22 +72,30 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
                                         s32 *temp, s32 *pressure)
 {
        int ret;
-       s32 t, p;
-       s64 off, sens, dt;
        struct ms5611_state *st = iio_priv(indio_dev);
 
-       ret = st->read_adc_temp_and_pressure(&indio_dev->dev, &t, &p);
+       ret = st->read_adc_temp_and_pressure(&indio_dev->dev, temp, pressure);
        if (ret < 0) {
                dev_err(&indio_dev->dev,
                        "failed to read temperature and pressure\n");
                return ret;
        }
 
-       dt = t - (st->prom[5] << 8);
-       off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7);
-       sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8);
+       return st->chip_info->temp_and_pressure_compensate(st->chip_info,
+                                                          temp, pressure);
+}
+
+static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
+                                              s32 *temp, s32 *pressure)
+{
+       s32 t = *temp, p = *pressure;
+       s64 off, sens, dt;
 
-       t = 2000 + ((st->prom[6] * dt) >> 23);
+       dt = t - (chip_info->prom[5] << 8);
+       off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7);
+       sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8);
+
+       t = 2000 + ((chip_info->prom[6] * dt) >> 23);
        if (t < 2000) {
                s64 off2, sens2, t2;
 
@@ -111,6 +121,42 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
        return 0;
 }
 
+static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
+                                              s32 *temp, s32 *pressure)
+{
+       s32 t = *temp, p = *pressure;
+       s64 off, sens, dt;
+
+       dt = t - (chip_info->prom[5] << 8);
+       off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6);
+       sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7);
+
+       t = 2000 + ((chip_info->prom[6] * dt) >> 23);
+       if (t < 2000) {
+               s64 off2, sens2, t2;
+
+               t2 = (dt * dt) >> 31;
+               off2 = (61 * (t - 2000) * (t - 2000)) >> 4;
+               sens2 = off2 << 1;
+
+               if (t < -1500) {
+                       s64 tmp = (t + 1500) * (t + 1500);
+
+                       off2 += 15 * tmp;
+                       sens2 += (8 * tmp);
+               }
+
+               t -= t2;
+               off -= off2;
+               sens -= sens2;
+       }
+
+       *temp = t;
+       *pressure = (((p * sens) >> 21) - off) >> 15;
+
+       return 0;
+}
+
 static int ms5611_reset(struct iio_dev *indio_dev)
 {
        int ret;
@@ -160,16 +206,23 @@ static int ms5611_read_raw(struct iio_dev *indio_dev,
        return -EINVAL;
 }
 
+static struct ms5611_chip_info chip_info_tbl[] = {
+       [MS5611] = {
+               .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate,
+       },
+       [MS5607] = {
+               .temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate,
+       }
+};
+
 static const struct iio_chan_spec ms5611_channels[] = {
        {
                .type = IIO_PRESSURE,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-                       BIT(IIO_CHAN_INFO_SCALE)
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
        },
        {
                .type = IIO_TEMP,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-                       BIT(IIO_CHAN_INFO_SCALE)
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
        }
 };
 
@@ -189,12 +242,13 @@ static int ms5611_init(struct iio_dev *indio_dev)
        return ms5611_read_prom(indio_dev);
 }
 
-int ms5611_probe(struct iio_dev *indio_dev, struct device *dev)
+int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type)
 {
        int ret;
        struct ms5611_state *st = iio_priv(indio_dev);
 
        mutex_init(&st->lock);
+       st->chip_info = &chip_info_tbl[type];
        indio_dev->dev.parent = dev;
        indio_dev->name = dev->driver->name;
        indio_dev->info = &ms5611_info;
index 748fd9acaad8fc5af78ce8b33bcd0818acdd8990..245797d1ecf0677f4c59c8ecb3766b329298050b 100644 (file)
@@ -104,11 +104,12 @@ static int ms5611_i2c_probe(struct i2c_client *client,
        st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure;
        st->client = client;
 
-       return ms5611_probe(indio_dev, &client->dev);
+       return ms5611_probe(indio_dev, &client->dev, id->driver_data);
 }
 
 static const struct i2c_device_id ms5611_id[] = {
-       { "ms5611", 0 },
+       { "ms5611", MS5611 },
+       { "ms5607", MS5607 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, ms5611_id);
@@ -116,7 +117,6 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id);
 static struct i2c_driver ms5611_driver = {
        .driver = {
                .name = "ms5611",
-               .owner = THIS_MODULE,
        },
        .id_table = ms5611_id,
        .probe = ms5611_i2c_probe,
index 976726fd4e6ce6b6e6fff65c25a468968c24f3f7..08ee6e88c79ff7068ce3e4751b35db827b1e7578 100644 (file)
@@ -103,11 +103,13 @@ static int ms5611_spi_probe(struct spi_device *spi)
        st->read_adc_temp_and_pressure = ms5611_spi_read_adc_temp_and_pressure;
        st->client = spi;
 
-       return ms5611_probe(indio_dev, &spi->dev);
+       return ms5611_probe(indio_dev, &spi->dev,
+                           spi_get_device_id(spi)->driver_data);
 }
 
 static const struct spi_device_id ms5611_id[] = {
-       { "ms5611", 0 },
+       { "ms5611", MS5611 },
+       { "ms5607", MS5607 },
        { }
 };
 MODULE_DEVICE_TABLE(spi, ms5611_id);
index e881fa6291e9228a56cc0a7f3d6cf3ee51621855..eb41d2b92c24048ce2c65918bc7d42e03640f19d 100644 (file)
@@ -178,6 +178,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
 static const struct st_sensor_settings st_press_sensors_settings[] = {
        {
                .wai = ST_PRESS_LPS331AP_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LPS331AP_PRESS_DEV_NAME,
                },
@@ -225,6 +226,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
        },
        {
                .wai = ST_PRESS_LPS001WP_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LPS001WP_PRESS_DEV_NAME,
                },
@@ -260,6 +262,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
        },
        {
                .wai = ST_PRESS_LPS25H_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
                .sensors_supported = {
                        [0] = LPS25H_PRESS_DEV_NAME,
                },
index 137788bba4a322a772f517a2348f165be24a8400..8fcf9766eaecbf0f3ef191e21a58e242e6419624 100644 (file)
@@ -79,7 +79,6 @@ MODULE_DEVICE_TABLE(i2c, st_press_id_table);
 
 static struct i2c_driver st_press_driver = {
        .driver = {
-               .owner = THIS_MODULE,
                .name = "st-press-i2c",
                .of_match_table = of_match_ptr(st_press_of_match),
        },
index 7a2b639eaa96e2ea440f3102c5da101d41edcd2b..5d033a5af615429c8f3eb38c6986dc5a728c123b 100644 (file)
 
 #define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
 
+/* Magic constants */
+#define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */
+#define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */
+#define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
+#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */
+#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */
+
 struct mlx90614_data {
        struct i2c_client *client;
        struct mutex lock; /* for EEPROM access only */
@@ -204,11 +211,11 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
                *val = ret;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
-               *val = -13657;
-               *val2 = 500000;
+               *val = MLX90614_CONST_OFFSET_DEC;
+               *val2 = MLX90614_CONST_OFFSET_REM;
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_SCALE:
-               *val = 20;
+               *val = MLX90614_CONST_SCALE;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
                mlx90614_power_get(data, false);
@@ -221,12 +228,12 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
                if (ret < 0)
                        return ret;
 
-               if (ret == 65535) {
+               if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) {
                        *val = 1;
                        *val2 = 0;
                } else {
                        *val = 0;
-                       *val2 = ret * 15259; /* 1/65535 ~ 0.000015259 */
+                       *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
                }
                return IIO_VAL_INT_PLUS_NANO;
        default:
@@ -245,7 +252,8 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
                if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
                        return -EINVAL;
-               val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */
+               val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX +
+                       val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION;
 
                mlx90614_power_get(data, false);
                mutex_lock(&data->lock);
@@ -551,7 +559,6 @@ static const struct dev_pm_ops mlx90614_pm_ops = {
 static struct i2c_driver mlx90614_driver = {
        .driver = {
                .name   = "mlx90614",
-               .owner  = THIS_MODULE,
                .pm     = &mlx90614_pm_ops,
        },
        .probe = mlx90614_probe,
index 8f21f32f9739e23f9558e8b38434daa5a5856f3e..e78c1069a6a9f66bcd3f0969a94678a956279152 100644 (file)
@@ -36,9 +36,9 @@
 #define TMP006_CONFIG_DRDY_EN BIT(8)
 #define TMP006_CONFIG_DRDY BIT(7)
 
-#define TMP006_CONFIG_MOD_MASK 0x7000
+#define TMP006_CONFIG_MOD_MASK GENMASK(14, 12)
 
-#define TMP006_CONFIG_CR_MASK 0x0e00
+#define TMP006_CONFIG_CR_MASK GENMASK(11, 9)
 #define TMP006_CONFIG_CR_SHIFT 9
 
 #define TMP006_MANUFACTURER_MAGIC 0x5449
@@ -280,7 +280,6 @@ static struct i2c_driver tmp006_driver = {
        .driver = {
                .name   = "tmp006",
                .pm     = &tmp006_pm_ops,
-               .owner  = THIS_MODULE,
        },
        .probe = tmp006_probe,
        .remove = tmp006_remove,
index c7aab48f07cdfcdebf3efb6374416619c9095e04..92d518382a9fce90c3e1dbae45034675072da274 100644 (file)
@@ -814,7 +814,7 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
                        printk(KERN_ERR MOD
                               "Unexpected cqe_status 0x%x for QPID=0x%0x\n",
                               CQE_STATUS(&cqe), CQE_QPID(&cqe));
-                       ret = -EINVAL;
+                       wc->status = IB_WC_FATAL_ERR;
                }
        }
 out:
index 097d7216d98ee4e4d394726e9d4c9743067d14f8..c6dc644aa5806b37cb4e0dcbbc6217d915e8a562 100644 (file)
@@ -246,7 +246,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
                 * convert it to descriptor.
                 */
                if (!button->gpiod && gpio_is_valid(button->gpio)) {
-                       unsigned flags = 0;
+                       unsigned flags = GPIOF_IN;
 
                        if (button->active_low)
                                flags |= GPIOF_ACTIVE_LOW;
index d4f0a817e858262bf0d0e3072723f75ee3ec3047..c41dec819cdfbd9a8fdd2388f102819b2e8a357b 100644 (file)
@@ -167,28 +167,16 @@ config INPUT_M68K_BEEP
        depends on M68K
 
 config INPUT_MAX77693_HAPTIC
-       tristate "MAXIM MAX77693 haptic controller support"
-       depends on MFD_MAX77693 && PWM
+       tristate "MAXIM MAX77693/MAX77843 haptic controller support"
+       depends on (MFD_MAX77693 || MFD_MAX77843) && PWM
        select INPUT_FF_MEMLESS
        help
          This option enables support for the haptic controller on
-         MAXIM MAX77693 chip.
+         MAXIM MAX77693 and MAX77843 chips.
 
          To compile this driver as module, choose M here: the
          module will be called max77693-haptic.
 
-config INPUT_MAX77843_HAPTIC
-    tristate "MAXIM MAX77843 haptic controller support"
-    depends on MFD_MAX77843 && REGULATOR
-    select INPUT_FF_MEMLESS
-    help
-      This option enables support for the haptic controller on
-      MAXIM MAX77843 chip. The driver supports ff-memless interface
-      from input framework.
-
-      To compile this driver as module, choose M here: the
-      module will be called max77843-haptic.
-
 config INPUT_MAX8925_ONKEY
        tristate "MAX8925 ONKEY support"
        depends on MFD_MAX8925
index 53df07dcc23c73263d8db3914dc0a4704d3dbaca..0357a088c6a9e2e132ef1d24d44dce7ace24b554 100644 (file)
@@ -41,7 +41,6 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)    += keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)              += kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
 obj-$(CONFIG_INPUT_MAX77693_HAPTIC)    += max77693-haptic.o
-obj-$(CONFIG_INPUT_MAX77843_HAPTIC)    += max77843-haptic.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)      += max8925_onkey.o
 obj-$(CONFIG_INPUT_MAX8997_HAPTIC)     += max8997_haptic.o
 obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)  += mc13783-pwrbutton.o
index 39e930c10ebbd9d46154dff935aa05404b5918d8..6d96bff32a0e3776190ee2c34bf2ea461866c057 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * MAXIM MAX77693 Haptic device driver
+ * MAXIM MAX77693/MAX77843 Haptic device driver
  *
- * Copyright (C) 2014 Samsung Electronics
+ * Copyright (C) 2014,2015 Samsung Electronics
  * Jaewon Kim <jaewon02.kim@samsung.com>
+ * Krzysztof Kozlowski <k.kozlowski@samsung.com>
  *
  * This program is not provided / owned by Maxim Integrated Products.
  *
@@ -24,7 +25,9 @@
 #include <linux/workqueue.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
+#include <linux/mfd/max77843-private.h>
 
 #define MAX_MAGNITUDE_SHIFT    16
 
@@ -46,6 +49,8 @@ enum max77693_haptic_pwm_divisor {
 };
 
 struct max77693_haptic {
+       enum max77693_types dev_type;
+
        struct regmap *regmap_pmic;
        struct regmap *regmap_haptic;
        struct device *dev;
@@ -59,7 +64,6 @@ struct max77693_haptic {
        unsigned int pwm_duty;
        enum max77693_haptic_motor_type type;
        enum max77693_haptic_pulse_mode mode;
-       enum max77693_haptic_pwm_divisor pwm_divisor;
 
        struct work_struct work;
 };
@@ -78,19 +82,52 @@ static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)
        return 0;
 }
 
+static int max77843_haptic_bias(struct max77693_haptic *haptic, bool on)
+{
+       int error;
+
+       if (haptic->dev_type != TYPE_MAX77843)
+               return 0;
+
+       error = regmap_update_bits(haptic->regmap_haptic,
+                                  MAX77843_SYS_REG_MAINCTRL1,
+                                  MAX77843_MAINCTRL1_BIASEN_MASK,
+                                  on << MAINCTRL1_BIASEN_SHIFT);
+       if (error) {
+               dev_err(haptic->dev, "failed to %s bias: %d\n",
+                       on ? "enable" : "disable", error);
+               return error;
+       }
+
+       return 0;
+}
+
 static int max77693_haptic_configure(struct max77693_haptic *haptic,
                                     bool enable)
 {
-       unsigned int value;
+       unsigned int value, config_reg;
        int error;
 
-       value = ((haptic->type << MAX77693_CONFIG2_MODE) |
-               (enable << MAX77693_CONFIG2_MEN) |
-               (haptic->mode << MAX77693_CONFIG2_HTYP) |
-               (haptic->pwm_divisor));
+       switch (haptic->dev_type) {
+       case TYPE_MAX77693:
+               value = ((haptic->type << MAX77693_CONFIG2_MODE) |
+                       (enable << MAX77693_CONFIG2_MEN) |
+                       (haptic->mode << MAX77693_CONFIG2_HTYP) |
+                       MAX77693_HAPTIC_PWM_DIVISOR_128);
+               config_reg = MAX77693_HAPTIC_REG_CONFIG2;
+               break;
+       case TYPE_MAX77843:
+               value = (haptic->type << MCONFIG_MODE_SHIFT) |
+                       (enable << MCONFIG_MEN_SHIFT) |
+                       MAX77693_HAPTIC_PWM_DIVISOR_128;
+               config_reg = MAX77843_HAP_REG_MCONFIG;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        error = regmap_write(haptic->regmap_haptic,
-                            MAX77693_HAPTIC_REG_CONFIG2, value);
+                            config_reg, value);
        if (error) {
                dev_err(haptic->dev,
                        "failed to update haptic config: %d\n", error);
@@ -104,6 +141,9 @@ static int max77693_haptic_lowsys(struct max77693_haptic *haptic, bool enable)
 {
        int error;
 
+       if (haptic->dev_type != TYPE_MAX77693)
+               return 0;
+
        error = regmap_update_bits(haptic->regmap_pmic,
                                   MAX77693_PMIC_REG_LSCNFG,
                                   MAX77693_PMIC_LOW_SYS_MASK,
@@ -219,6 +259,10 @@ static int max77693_haptic_open(struct input_dev *dev)
        struct max77693_haptic *haptic = input_get_drvdata(dev);
        int error;
 
+       error = max77843_haptic_bias(haptic, true);
+       if (error)
+               return error;
+
        error = regulator_enable(haptic->motor_reg);
        if (error) {
                dev_err(haptic->dev,
@@ -241,6 +285,8 @@ static void max77693_haptic_close(struct input_dev *dev)
        if (error)
                dev_err(haptic->dev,
                        "failed to disable regulator: %d\n", error);
+
+       max77843_haptic_bias(haptic, false);
 }
 
 static int max77693_haptic_probe(struct platform_device *pdev)
@@ -254,13 +300,26 @@ static int max77693_haptic_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        haptic->regmap_pmic = max77693->regmap;
-       haptic->regmap_haptic = max77693->regmap_haptic;
        haptic->dev = &pdev->dev;
        haptic->type = MAX77693_HAPTIC_LRA;
        haptic->mode = MAX77693_HAPTIC_EXTERNAL_MODE;
-       haptic->pwm_divisor = MAX77693_HAPTIC_PWM_DIVISOR_128;
        haptic->suspend_state = false;
 
+       /* Variant-specific init */
+       haptic->dev_type = platform_get_device_id(pdev)->driver_data;
+       switch (haptic->dev_type) {
+       case TYPE_MAX77693:
+               haptic->regmap_haptic = max77693->regmap_haptic;
+               break;
+       case TYPE_MAX77843:
+               haptic->regmap_haptic = max77693->regmap;
+               break;
+       default:
+               dev_err(&pdev->dev, "unsupported device type: %u\n",
+                       haptic->dev_type);
+               return -EINVAL;
+       }
+
        INIT_WORK(&haptic->work, max77693_haptic_play_work);
 
        /* Get pwm and regulatot for haptic device */
@@ -338,16 +397,25 @@ static int __maybe_unused max77693_haptic_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
                         max77693_haptic_suspend, max77693_haptic_resume);
 
+static const struct platform_device_id max77693_haptic_id[] = {
+       { "max77693-haptic", TYPE_MAX77693 },
+       { "max77843-haptic", TYPE_MAX77843 },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, max77693_haptic_id);
+
 static struct platform_driver max77693_haptic_driver = {
        .driver         = {
                .name   = "max77693-haptic",
                .pm     = &max77693_haptic_pm_ops,
        },
        .probe          = max77693_haptic_probe,
+       .id_table       = max77693_haptic_id,
 };
 module_platform_driver(max77693_haptic_driver);
 
 MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
-MODULE_DESCRIPTION("MAXIM MAX77693 Haptic driver");
+MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>");
+MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver");
 MODULE_ALIAS("platform:max77693-haptic");
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/max77843-haptic.c b/drivers/input/misc/max77843-haptic.c
deleted file mode 100644 (file)
index dccbb46..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * MAXIM MAX77693 Haptic device driver
- *
- * Copyright (C) 2015 Samsung Electronics
- * Author: Jaewon Kim <jaewon02.kim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/mfd/max77843-private.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pwm.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-
-#define MAX_MAGNITUDE_SHIFT        16
-
-enum max77843_haptic_motor_type {
-       MAX77843_HAPTIC_ERM = 0,
-       MAX77843_HAPTIC_LRA,
-};
-
-enum max77843_haptic_pwm_divisor {
-       MAX77843_HAPTIC_PWM_DIVISOR_32 = 0,
-       MAX77843_HAPTIC_PWM_DIVISOR_64,
-       MAX77843_HAPTIC_PWM_DIVISOR_128,
-       MAX77843_HAPTIC_PWM_DIVISOR_256,
-};
-
-struct max77843_haptic {
-       struct regmap *regmap_haptic;
-       struct device *dev;
-       struct input_dev *input_dev;
-       struct pwm_device *pwm_dev;
-       struct regulator *motor_reg;
-       struct work_struct work;
-       struct mutex mutex;
-
-       unsigned int magnitude;
-       unsigned int pwm_duty;
-
-       bool active;
-       bool suspended;
-
-       enum max77843_haptic_motor_type type;
-       enum max77843_haptic_pwm_divisor pwm_divisor;
-};
-
-static int max77843_haptic_set_duty_cycle(struct max77843_haptic *haptic)
-{
-       int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2;
-       int error;
-
-       error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
-       if (error) {
-               dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
-               return error;
-       }
-
-       return 0;
-}
-
-static int max77843_haptic_bias(struct max77843_haptic *haptic, bool on)
-{
-       int error;
-
-       error = regmap_update_bits(haptic->regmap_haptic,
-                                  MAX77843_SYS_REG_MAINCTRL1,
-                                  MAX77843_MAINCTRL1_BIASEN_MASK,
-                                  on << MAINCTRL1_BIASEN_SHIFT);
-       if (error) {
-               dev_err(haptic->dev, "failed to %s bias: %d\n",
-                       on ? "enable" : "disable", error);
-               return error;
-       }
-
-       return 0;
-}
-
-static int max77843_haptic_config(struct max77843_haptic *haptic, bool enable)
-{
-       unsigned int value;
-       int error;
-
-       value = (haptic->type << MCONFIG_MODE_SHIFT) |
-               (enable << MCONFIG_MEN_SHIFT) |
-               (haptic->pwm_divisor << MCONFIG_PDIV_SHIFT);
-
-       error = regmap_write(haptic->regmap_haptic,
-                            MAX77843_HAP_REG_MCONFIG, value);
-       if (error) {
-               dev_err(haptic->dev,
-                       "failed to update haptic config: %d\n", error);
-               return error;
-       }
-
-       return 0;
-}
-
-static int max77843_haptic_enable(struct max77843_haptic *haptic)
-{
-       int error;
-
-       if (haptic->active)
-               return 0;
-
-       error = pwm_enable(haptic->pwm_dev);
-       if (error) {
-               dev_err(haptic->dev,
-                       "failed to enable pwm device: %d\n", error);
-               return error;
-       }
-
-       error = max77843_haptic_config(haptic, true);
-       if (error)
-               goto err_config;
-
-       haptic->active = true;
-
-       return 0;
-
-err_config:
-       pwm_disable(haptic->pwm_dev);
-
-       return error;
-}
-
-static int max77843_haptic_disable(struct max77843_haptic *haptic)
-{
-       int error;
-
-       if (!haptic->active)
-               return 0;
-
-       error = max77843_haptic_config(haptic, false);
-       if (error)
-               return error;
-
-       pwm_disable(haptic->pwm_dev);
-
-       haptic->active = false;
-
-       return 0;
-}
-
-static void max77843_haptic_play_work(struct work_struct *work)
-{
-       struct max77843_haptic *haptic =
-                       container_of(work, struct max77843_haptic, work);
-       int error;
-
-       mutex_lock(&haptic->mutex);
-
-       if (haptic->suspended)
-               goto out_unlock;
-
-       if (haptic->magnitude) {
-               error = max77843_haptic_set_duty_cycle(haptic);
-               if (error) {
-                       dev_err(haptic->dev,
-                               "failed to set duty cycle: %d\n", error);
-                       goto out_unlock;
-               }
-
-               error = max77843_haptic_enable(haptic);
-               if (error)
-                       dev_err(haptic->dev,
-                               "cannot enable haptic: %d\n", error);
-       } else {
-               error = max77843_haptic_disable(haptic);
-               if (error)
-                       dev_err(haptic->dev,
-                               "cannot disable haptic: %d\n", error);
-       }
-
-out_unlock:
-       mutex_unlock(&haptic->mutex);
-}
-
-static int max77843_haptic_play_effect(struct input_dev *dev, void *data,
-               struct ff_effect *effect)
-{
-       struct max77843_haptic *haptic = input_get_drvdata(dev);
-       u64 period_mag_multi;
-
-       haptic->magnitude = effect->u.rumble.strong_magnitude;
-       if (!haptic->magnitude)
-               haptic->magnitude = effect->u.rumble.weak_magnitude;
-
-       period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude;
-       haptic->pwm_duty = (unsigned int)(period_mag_multi >>
-                                               MAX_MAGNITUDE_SHIFT);
-
-       schedule_work(&haptic->work);
-
-       return 0;
-}
-
-static int max77843_haptic_open(struct input_dev *dev)
-{
-       struct max77843_haptic *haptic = input_get_drvdata(dev);
-       int error;
-
-       error = max77843_haptic_bias(haptic, true);
-       if (error)
-               return error;
-
-       error = regulator_enable(haptic->motor_reg);
-       if (error) {
-               dev_err(haptic->dev,
-                       "failed to enable regulator: %d\n", error);
-               return error;
-       }
-
-       return 0;
-}
-
-static void max77843_haptic_close(struct input_dev *dev)
-{
-       struct max77843_haptic *haptic = input_get_drvdata(dev);
-       int error;
-
-       cancel_work_sync(&haptic->work);
-       max77843_haptic_disable(haptic);
-
-       error = regulator_disable(haptic->motor_reg);
-       if (error)
-               dev_err(haptic->dev,
-                       "failed to disable regulator: %d\n", error);
-
-       max77843_haptic_bias(haptic, false);
-}
-
-static int max77843_haptic_probe(struct platform_device *pdev)
-{
-       struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent);
-       struct max77843_haptic *haptic;
-       int error;
-
-       haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
-       if (!haptic)
-               return -ENOMEM;
-
-       haptic->regmap_haptic = max77843->regmap;
-       haptic->dev = &pdev->dev;
-       haptic->type = MAX77843_HAPTIC_LRA;
-       haptic->pwm_divisor = MAX77843_HAPTIC_PWM_DIVISOR_128;
-
-       INIT_WORK(&haptic->work, max77843_haptic_play_work);
-       mutex_init(&haptic->mutex);
-
-       haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL);
-       if (IS_ERR(haptic->pwm_dev)) {
-               dev_err(&pdev->dev, "failed to get pwm device\n");
-               return PTR_ERR(haptic->pwm_dev);
-       }
-
-       haptic->motor_reg = devm_regulator_get_exclusive(&pdev->dev, "haptic");
-       if (IS_ERR(haptic->motor_reg)) {
-               dev_err(&pdev->dev, "failed to get regulator\n");
-               return PTR_ERR(haptic->motor_reg);
-       }
-
-       haptic->input_dev = devm_input_allocate_device(&pdev->dev);
-       if (!haptic->input_dev) {
-               dev_err(&pdev->dev, "failed to allocate input device\n");
-               return -ENOMEM;
-       }
-
-       haptic->input_dev->name = "max77843-haptic";
-       haptic->input_dev->id.version = 1;
-       haptic->input_dev->dev.parent = &pdev->dev;
-       haptic->input_dev->open = max77843_haptic_open;
-       haptic->input_dev->close = max77843_haptic_close;
-       input_set_drvdata(haptic->input_dev, haptic);
-       input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
-
-       error = input_ff_create_memless(haptic->input_dev, NULL,
-                       max77843_haptic_play_effect);
-       if (error) {
-               dev_err(&pdev->dev, "failed to create force-feedback\n");
-               return error;
-       }
-
-       error = input_register_device(haptic->input_dev);
-       if (error) {
-               dev_err(&pdev->dev, "failed to register input device\n");
-               return error;
-       }
-
-       platform_set_drvdata(pdev, haptic);
-
-       return 0;
-}
-
-static int __maybe_unused max77843_haptic_suspend(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct max77843_haptic *haptic = platform_get_drvdata(pdev);
-       int error;
-
-       error = mutex_lock_interruptible(&haptic->mutex);
-       if (error)
-               return error;
-
-       max77843_haptic_disable(haptic);
-
-       haptic->suspended = true;
-
-       mutex_unlock(&haptic->mutex);
-
-       return 0;
-}
-
-static int __maybe_unused max77843_haptic_resume(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct max77843_haptic *haptic = platform_get_drvdata(pdev);
-       unsigned int magnitude;
-
-       mutex_lock(&haptic->mutex);
-
-       haptic->suspended = false;
-
-       magnitude = ACCESS_ONCE(haptic->magnitude);
-       if (magnitude)
-               max77843_haptic_enable(haptic);
-
-       mutex_unlock(&haptic->mutex);
-
-       return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(max77843_haptic_pm_ops,
-               max77843_haptic_suspend, max77843_haptic_resume);
-
-static struct platform_driver max77843_haptic_driver = {
-       .driver         = {
-               .name   = "max77843-haptic",
-               .pm     = &max77843_haptic_pm_ops,
-       },
-       .probe          = max77843_haptic_probe,
-};
-module_platform_driver(max77843_haptic_driver);
-
-MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
-MODULE_DESCRIPTION("MAXIM MAX77843 Haptic driver");
-MODULE_LICENSE("GPL");
index 0649b94f59584ca5b885cd0ecad595a84af0d89d..697291aceea71103855d281d2a434a142e176808 100644 (file)
@@ -408,6 +408,10 @@ struct device_domain_info {
        struct list_head global; /* link to global list */
        u8 bus;                 /* PCI bus number */
        u8 devfn;               /* PCI devfn number */
+       struct {
+               u8 enabled:1;
+               u8 qdep;
+       } ats;                  /* ATS state */
        struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
        struct intel_iommu *iommu; /* IOMMU used by this device */
        struct dmar_domain *domain; /* pointer to domain */
@@ -1391,19 +1395,26 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
 
 static void iommu_enable_dev_iotlb(struct device_domain_info *info)
 {
+       struct pci_dev *pdev;
+
        if (!info || !dev_is_pci(info->dev))
                return;
 
-       pci_enable_ats(to_pci_dev(info->dev), VTD_PAGE_SHIFT);
+       pdev = to_pci_dev(info->dev);
+       if (pci_enable_ats(pdev, VTD_PAGE_SHIFT))
+               return;
+
+       info->ats.enabled = 1;
+       info->ats.qdep = pci_ats_queue_depth(pdev);
 }
 
 static void iommu_disable_dev_iotlb(struct device_domain_info *info)
 {
-       if (!info->dev || !dev_is_pci(info->dev) ||
-           !pci_ats_enabled(to_pci_dev(info->dev)))
+       if (!info->ats.enabled)
                return;
 
        pci_disable_ats(to_pci_dev(info->dev));
+       info->ats.enabled = 0;
 }
 
 static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
@@ -1415,16 +1426,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
 
        spin_lock_irqsave(&device_domain_lock, flags);
        list_for_each_entry(info, &domain->devices, link) {
-               struct pci_dev *pdev;
-               if (!info->dev || !dev_is_pci(info->dev))
-                       continue;
-
-               pdev = to_pci_dev(info->dev);
-               if (!pci_ats_enabled(pdev))
+               if (!info->ats.enabled)
                        continue;
 
                sid = info->bus << 8 | info->devfn;
-               qdep = pci_ats_queue_depth(pdev);
+               qdep = info->ats.qdep;
                qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
        }
        spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -2275,6 +2281,8 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
 
        info->bus = bus;
        info->devfn = devfn;
+       info->ats.enabled = 0;
+       info->ats.qdep = 0;
        info->dev = dev;
        info->domain = domain;
        info->iommu = iommu;
index 692fe2bc81979b6b48f984ec6d88c117fbfdebdd..c12bb93334ff99e7a5ddc72d274b00c4eeb9c24c 100644 (file)
@@ -68,7 +68,9 @@ static struct irq_chip crossbar_chip = {
        .irq_mask               = irq_chip_mask_parent,
        .irq_unmask             = irq_chip_unmask_parent,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
-       .irq_set_wake           = irq_chip_set_wake_parent,
+       .irq_set_type           = irq_chip_set_type_parent,
+       .flags                  = IRQCHIP_MASK_ON_SUSPEND |
+                                 IRQCHIP_SKIP_SET_WAKE,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
 #endif
index 9ad35f72ab4c077791cf7942cceb36301325872d..23408bd68fdc0c8b18f4e140bc367c2a07e53619 100644 (file)
@@ -43,7 +43,7 @@ config LEDS_AAT1290
        tristate "LED support for the AAT1290"
        depends on LEDS_CLASS_FLASH
        depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
-       depends on GPIOLIB
+       depends on GPIOLIB || COMPILE_TEST
        depends on OF
        depends on PINCTRL
        help
@@ -419,7 +419,7 @@ config LEDS_INTEL_SS4200
 config LEDS_LT3593
        tristate "LED driver for LT3593 controllers"
        depends on LEDS_CLASS
-       depends on GPIOLIB
+       depends on GPIOLIB || COMPILE_TEST
        help
          This option enables support for LEDs driven by a Linear Technology
          LT3593 controller. This controller uses a special one-wire pulse
@@ -455,12 +455,16 @@ config LEDS_MC13783
 config LEDS_NS2
        tristate "LED support for Network Space v2 GPIO LEDs"
        depends on LEDS_CLASS
-       depends on MACH_KIRKWOOD
+       depends on MACH_KIRKWOOD || MACH_ARMADA_370
        default y
        help
-         This option enable support for the dual-GPIO LED found on the
-         Network Space v2 board (and parents). This include Internet Space v2,
-         Network Space (Max) v2 and d2 Network v2 boards.
+         This option enables support for the dual-GPIO LEDs found on the
+         following LaCie/Seagate boards:
+
+               Network Space v2 (and parents: Max, Mini)
+               Internet Space v2
+               d2 Network v2
+               n090401 (Seagate NAS 4-Bay)
 
 config LEDS_NETXBIG
        tristate "LED support for Big Network series LEDs"
@@ -543,7 +547,8 @@ config LEDS_MENF21BMC
 
 config LEDS_KTD2692
        tristate "LED support for KTD2692 flash LED controller"
-       depends on LEDS_CLASS_FLASH && GPIOLIB && OF
+       depends on LEDS_CLASS_FLASH && OF
+       depends on GPIOLIB || COMPILE_TEST
        help
          This option enables support for KTD2692 LED flash connected
          through ExpressWire interface.
index beabfbc6f7cdd406f6ba96692bd5b376a893bdc4..ca51d58bed244c488d815003c366d03acf79e418 100644 (file)
@@ -228,12 +228,15 @@ static int led_classdev_next_name(const char *init_name, char *name,
 {
        unsigned int i = 0;
        int ret = 0;
+       struct device *dev;
 
        strlcpy(name, init_name, len);
 
-       while (class_find_device(leds_class, NULL, name, match_name) &&
-              (ret < len))
+       while ((ret < len) &&
+              (dev = class_find_device(leds_class, NULL, name, match_name))) {
+               put_device(dev);
                ret = snprintf(name, len, "%s_%u", init_name, ++i);
+       }
 
        if (ret >= len)
                return -ENOMEM;
index 2b4dc738dcd657092176822fc2613349e8066246..257a813c73f31ddf6b336a82895e7ca65fe7974d 100644 (file)
@@ -156,63 +156,35 @@ static int fsg_led_probe(struct platform_device *pdev)
        latch_value = 0xffff;
        *latch_address = latch_value;
 
-       ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
+       ret = devm_led_classdev_register(&pdev->dev, &fsg_wlan_led);
        if (ret < 0)
-               goto failwlan;
+               return ret;
 
-       ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
+       ret = devm_led_classdev_register(&pdev->dev, &fsg_wan_led);
        if (ret < 0)
-               goto failwan;
+               return ret;
 
-       ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
+       ret = devm_led_classdev_register(&pdev->dev, &fsg_sata_led);
        if (ret < 0)
-               goto failsata;
+               return ret;
 
-       ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
+       ret = devm_led_classdev_register(&pdev->dev, &fsg_usb_led);
        if (ret < 0)
-               goto failusb;
+               return ret;
 
-       ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
+       ret = devm_led_classdev_register(&pdev->dev, &fsg_sync_led);
        if (ret < 0)
-               goto failsync;
+               return ret;
 
-       ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
+       ret = devm_led_classdev_register(&pdev->dev, &fsg_ring_led);
        if (ret < 0)
-               goto failring;
-
-       return ret;
-
- failring:
-       led_classdev_unregister(&fsg_sync_led);
- failsync:
-       led_classdev_unregister(&fsg_usb_led);
- failusb:
-       led_classdev_unregister(&fsg_sata_led);
- failsata:
-       led_classdev_unregister(&fsg_wan_led);
- failwan:
-       led_classdev_unregister(&fsg_wlan_led);
- failwlan:
+               return ret;
 
        return ret;
 }
 
-static int fsg_led_remove(struct platform_device *pdev)
-{
-       led_classdev_unregister(&fsg_wlan_led);
-       led_classdev_unregister(&fsg_wan_led);
-       led_classdev_unregister(&fsg_sata_led);
-       led_classdev_unregister(&fsg_usb_led);
-       led_classdev_unregister(&fsg_sync_led);
-       led_classdev_unregister(&fsg_ring_led);
-
-       return 0;
-}
-
-
 static struct platform_driver fsg_led_driver = {
        .probe          = fsg_led_probe,
-       .remove         = fsg_led_remove,
        .driver         = {
                .name           = "fsg-led",
        },
index 91325de3cd3305ad589820ff07bf44cd99e36a4a..b38430cb10ad0a8de7082745732ddf8d49ed6796 100644 (file)
@@ -492,7 +492,6 @@ static struct i2c_driver lm3530_i2c_driver = {
        .id_table = lm3530_id,
        .driver = {
                .name = LM3530_NAME,
-               .owner = THIS_MODULE,
        },
 };
 
index f5112cb2d9915359957b2b90f432dee11918778b..48872997d6b4b35391affa52d07496082fb261f7 100644 (file)
@@ -555,7 +555,6 @@ MODULE_DEVICE_TABLE(i2c, lm355x_id);
 static struct i2c_driver lm355x_i2c_driver = {
        .driver = {
                   .name = LM355x_NAME,
-                  .owner = THIS_MODULE,
                   .pm = NULL,
                   },
        .probe = lm355x_probe,
index d3dec0132769dd1d2e648a1bb69d5a78029a1461..02ebe342f5af219ae4bd576a78794adc5d6fc88f 100644 (file)
@@ -446,7 +446,6 @@ MODULE_DEVICE_TABLE(i2c, lm3642_id);
 static struct i2c_driver lm3642_i2c_driver = {
        .driver = {
                   .name = LM3642_NAME,
-                  .owner = THIS_MODULE,
                   .pm = NULL,
                   },
        .probe = lm3642_probe,
index 8ca197af2864841391edb94aaee13c85c60854ea..63a92542c8cb0953d17d5dcd8502075348dad9cf 100644 (file)
@@ -514,20 +514,19 @@ static int lp5521_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index 584dbbcec65955d49f8e9603e129b1c0f83c2122..1d0187f42941aadfd91eb7b17d36b876484fff51 100644 (file)
@@ -880,20 +880,19 @@ static int lp5523_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index ca85724ab138b30997f3afc643dbeb6fe590d37b..0360c59dbdc91b122d0d08273c48203e6755ca6b 100644 (file)
@@ -515,20 +515,19 @@ static int lp5562_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index 96d51e9879c905d2c4eb6bac2325af174665a9f1..59b76833f0d32d1d114421ed17b160fd60d2a9c2 100644 (file)
@@ -543,7 +543,8 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
 }
 EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
 
-int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
+struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
+                                                     struct device_node *np)
 {
        struct device_node *child;
        struct lp55xx_platform_data *pdata;
@@ -553,17 +554,17 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        num_channels = of_get_child_count(np);
        if (num_channels == 0) {
                dev_err(dev, "no LED channels\n");
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
        }
 
        cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL);
        if (!cfg)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        pdata->led_config = &cfg[0];
        pdata->num_channels = num_channels;
@@ -588,9 +589,7 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
        /* LP8501 specific */
        of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
 
-       dev->platform_data = pdata;
-
-       return 0;
+       return pdata;
 }
 EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata);
 
index cceab483edd04a14174224a0d8b253a738376e66..c7f1e6155001f6eeb76818f6a4dcf3904624c7e8 100644 (file)
@@ -202,7 +202,7 @@ extern int lp55xx_register_sysfs(struct lp55xx_chip *chip);
 extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip);
 
 /* common device tree population function */
-extern int lp55xx_of_populate_pdata(struct device *dev,
-                                   struct device_node *np);
+extern struct lp55xx_platform_data
+*lp55xx_of_populate_pdata(struct device *dev, struct device_node *np);
 
 #endif /* _LEDS_LP55XX_COMMON_H */
index d3098e395fff469c30950ce73542519f6f880c80..3f54f6f2b821d2684f326cda03ac1957ac1015ef 100644 (file)
@@ -308,20 +308,19 @@ static int lp8501_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index 8c2b7fbe23924fcdf45cf02976112e95274c91fd..79f084354e679930f1efa36f30745e867ed72b27 100644 (file)
@@ -302,7 +302,7 @@ out:
        return ret;
 }
 
-static struct reg_default lp8860_reg_defs[] = {
+static const struct reg_default lp8860_reg_defs[] = {
        { LP8860_DISP_CL1_BRT_MSB, 0x00},
        { LP8860_DISP_CL1_BRT_LSB, 0x00},
        { LP8860_DISP_CL1_CURR_MSB, 0x00},
@@ -332,7 +332,7 @@ static const struct regmap_config lp8860_regmap_config = {
        .cache_type = REGCACHE_NONE,
 };
 
-static struct reg_default lp8860_eeprom_defs[] = {
+static const struct reg_default lp8860_eeprom_defs[] = {
        { LP8860_EEPROM_REG_0, 0x00 },
        { LP8860_EEPROM_REG_1, 0x00 },
        { LP8860_EEPROM_REG_2, 0x00 },
index b8b0eec7b54058cb1c671e4e76739277589406aa..df348a06d8c71faa60d80530f29bec8a050469dc 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/led-class-flash.h>
 #include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
index 1fd6adbb43b7937637fe0a048a37e1bac8c669b0..b33514d9f427e279bf091abab4126f55e0d48182 100644 (file)
 #include <linux/platform_data/leds-kirkwood-ns2.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include "leds.h"
 
 /*
- * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
- * relation with the SATA activity. This capability is exposed through the
- * "sata" sysfs attribute.
- *
- * The following array detail the different LED registers and the combination
- * of their possible values:
- *
- *  cmd_led   |  slow_led  | /SATA active | LED state
- *            |            |              |
- *     1      |     0      |      x       |  off
- *     -      |     1      |      x       |  on
- *     0      |     0      |      1       |  on
- *     0      |     0      |      0       |  blink (rate 300ms)
+ * The Network Space v2 dual-GPIO LED is wired to a CPLD. Three different LED
+ * modes are available: off, on and SATA activity blinking. The LED modes are
+ * controlled through two GPIOs (command and slow): each combination of values
+ * for the command/slow GPIOs corresponds to a LED mode.
  */
 
-enum ns2_led_modes {
-       NS_V2_LED_OFF,
-       NS_V2_LED_ON,
-       NS_V2_LED_SATA,
-};
-
-struct ns2_led_mode_value {
-       enum ns2_led_modes      mode;
-       int                     cmd_level;
-       int                     slow_level;
-};
-
-static struct ns2_led_mode_value ns2_led_modval[] = {
-       { NS_V2_LED_OFF , 1, 0 },
-       { NS_V2_LED_ON  , 0, 1 },
-       { NS_V2_LED_ON  , 1, 1 },
-       { NS_V2_LED_SATA, 0, 0 },
-};
-
 struct ns2_led_data {
        struct led_classdev     cdev;
        unsigned                cmd;
        unsigned                slow;
+       bool                    can_sleep;
+       int                     mode_index;
        unsigned char           sata; /* True when SATA mode active. */
        rwlock_t                rw_lock; /* Lock GPIOs. */
+       struct work_struct      work;
+       int                     num_modes;
+       struct ns2_led_modval   *modval;
 };
 
+static void ns2_led_work(struct work_struct *work)
+{
+       struct ns2_led_data *led_dat =
+               container_of(work, struct ns2_led_data, work);
+       int i = led_dat->mode_index;
+
+       gpio_set_value_cansleep(led_dat->cmd, led_dat->modval[i].cmd_level);
+       gpio_set_value_cansleep(led_dat->slow, led_dat->modval[i].slow_level);
+}
+
 static int ns2_led_get_mode(struct ns2_led_data *led_dat,
                            enum ns2_led_modes *mode)
 {
@@ -83,22 +71,18 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat,
        int cmd_level;
        int slow_level;
 
-       read_lock_irq(&led_dat->rw_lock);
+       cmd_level = gpio_get_value_cansleep(led_dat->cmd);
+       slow_level = gpio_get_value_cansleep(led_dat->slow);
 
-       cmd_level = gpio_get_value(led_dat->cmd);
-       slow_level = gpio_get_value(led_dat->slow);
-
-       for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) {
-               if (cmd_level == ns2_led_modval[i].cmd_level &&
-                   slow_level == ns2_led_modval[i].slow_level) {
-                       *mode = ns2_led_modval[i].mode;
+       for (i = 0; i < led_dat->num_modes; i++) {
+               if (cmd_level == led_dat->modval[i].cmd_level &&
+                   slow_level == led_dat->modval[i].slow_level) {
+                       *mode = led_dat->modval[i].mode;
                        ret = 0;
                        break;
                }
        }
 
-       read_unlock_irq(&led_dat->rw_lock);
-
        return ret;
 }
 
@@ -106,19 +90,32 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat,
                             enum ns2_led_modes mode)
 {
        int i;
+       bool found = false;
        unsigned long flags;
 
+       for (i = 0; i < led_dat->num_modes; i++)
+               if (mode == led_dat->modval[i].mode) {
+                       found = true;
+                       break;
+               }
+
+       if (!found)
+               return;
+
        write_lock_irqsave(&led_dat->rw_lock, flags);
 
-       for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) {
-               if (mode == ns2_led_modval[i].mode) {
-                       gpio_set_value(led_dat->cmd,
-                                      ns2_led_modval[i].cmd_level);
-                       gpio_set_value(led_dat->slow,
-                                      ns2_led_modval[i].slow_level);
-               }
+       if (!led_dat->can_sleep) {
+               gpio_set_value(led_dat->cmd,
+                              led_dat->modval[i].cmd_level);
+               gpio_set_value(led_dat->slow,
+                              led_dat->modval[i].slow_level);
+               goto exit_unlock;
        }
 
+       led_dat->mode_index = i;
+       schedule_work(&led_dat->work);
+
+exit_unlock:
        write_unlock_irqrestore(&led_dat->rw_lock, flags);
 }
 
@@ -148,7 +145,6 @@ static ssize_t ns2_led_sata_store(struct device *dev,
                container_of(led_cdev, struct ns2_led_data, cdev);
        int ret;
        unsigned long enable;
-       enum ns2_led_modes mode;
 
        ret = kstrtoul(buff, 10, &enable);
        if (ret < 0)
@@ -157,19 +153,19 @@ static ssize_t ns2_led_sata_store(struct device *dev,
        enable = !!enable;
 
        if (led_dat->sata == enable)
-               return count;
+               goto exit;
 
-       ret = ns2_led_get_mode(led_dat, &mode);
-       if (ret < 0)
-               return ret;
+       led_dat->sata = enable;
+
+       if (!led_get_brightness(led_cdev))
+               goto exit;
 
-       if (enable && mode == NS_V2_LED_ON)
+       if (enable)
                ns2_led_set_mode(led_dat, NS_V2_LED_SATA);
-       if (!enable && mode == NS_V2_LED_SATA)
+       else
                ns2_led_set_mode(led_dat, NS_V2_LED_ON);
 
-       led_dat->sata = enable;
-
+exit:
        return count;
 }
 
@@ -199,7 +195,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
        enum ns2_led_modes mode;
 
        ret = devm_gpio_request_one(&pdev->dev, template->cmd,
-                       gpio_get_value(template->cmd) ?
+                       gpio_get_value_cansleep(template->cmd) ?
                        GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
                        template->name);
        if (ret) {
@@ -209,7 +205,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
        }
 
        ret = devm_gpio_request_one(&pdev->dev, template->slow,
-                       gpio_get_value(template->slow) ?
+                       gpio_get_value_cansleep(template->slow) ?
                        GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
                        template->name);
        if (ret) {
@@ -228,6 +224,10 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
        led_dat->cdev.groups = ns2_led_groups;
        led_dat->cmd = template->cmd;
        led_dat->slow = template->slow;
+       led_dat->can_sleep = gpio_cansleep(led_dat->cmd) |
+                               gpio_cansleep(led_dat->slow);
+       led_dat->modval = template->modval;
+       led_dat->num_modes = template->num_modes;
 
        ret = ns2_led_get_mode(led_dat, &mode);
        if (ret < 0)
@@ -238,6 +238,8 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
        led_dat->cdev.brightness =
                (mode == NS_V2_LED_OFF) ? LED_OFF : LED_FULL;
 
+       INIT_WORK(&led_dat->work, ns2_led_work);
+
        ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
        if (ret < 0)
                return ret;
@@ -248,6 +250,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
 static void delete_ns2_led(struct ns2_led_data *led_dat)
 {
        led_classdev_unregister(&led_dat->cdev);
+       cancel_work_sync(&led_dat->work);
 }
 
 #ifdef CONFIG_OF_GPIO
@@ -259,9 +262,8 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
 {
        struct device_node *np = dev->of_node;
        struct device_node *child;
-       struct ns2_led *leds;
+       struct ns2_led *led, *leds;
        int num_leds = 0;
-       int i = 0;
 
        num_leds = of_get_child_count(np);
        if (!num_leds)
@@ -272,26 +274,57 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
        if (!leds)
                return -ENOMEM;
 
+       led = leds;
        for_each_child_of_node(np, child) {
                const char *string;
-               int ret;
+               int ret, i, num_modes;
+               struct ns2_led_modval *modval;
 
                ret = of_get_named_gpio(child, "cmd-gpio", 0);
                if (ret < 0)
                        return ret;
-               leds[i].cmd = ret;
+               led->cmd = ret;
                ret = of_get_named_gpio(child, "slow-gpio", 0);
                if (ret < 0)
                        return ret;
-               leds[i].slow = ret;
+               led->slow = ret;
                ret = of_property_read_string(child, "label", &string);
-               leds[i].name = (ret == 0) ? string : child->name;
+               led->name = (ret == 0) ? string : child->name;
                ret = of_property_read_string(child, "linux,default-trigger",
                                              &string);
                if (ret == 0)
-                       leds[i].default_trigger = string;
+                       led->default_trigger = string;
+
+               ret = of_property_count_u32_elems(child, "modes-map");
+               if (ret < 0 || ret % 3) {
+                       dev_err(dev,
+                               "Missing or malformed modes-map property\n");
+                       return -EINVAL;
+               }
+
+               num_modes = ret / 3;
+               modval = devm_kzalloc(dev,
+                                     num_modes * sizeof(struct ns2_led_modval),
+                                     GFP_KERNEL);
+               if (!modval)
+                       return -ENOMEM;
+
+               for (i = 0; i < num_modes; i++) {
+                       of_property_read_u32_index(child,
+                                               "modes-map", 3 * i,
+                                               (u32 *) &modval[i].mode);
+                       of_property_read_u32_index(child,
+                                               "modes-map", 3 * i + 1,
+                                               (u32 *) &modval[i].cmd_level);
+                       of_property_read_u32_index(child,
+                                               "modes-map", 3 * i + 2,
+                                               (u32 *) &modval[i].slow_level);
+               }
+
+               led->num_modes = num_modes;
+               led->modval = modval;
 
-               i++;
+               led++;
        }
 
        pdata->leds = leds;
index c3a08b60535bc31048d1246c1d5ef01dd5c12c6b..b775e1efecd3b6711acd61847652caf2352f194c 100644 (file)
@@ -379,7 +379,6 @@ static int pca955x_remove(struct i2c_client *client)
 static struct i2c_driver pca955x_driver = {
        .driver = {
                .name   = "leds-pca955x",
-               .owner  = THIS_MODULE,
        },
        .probe  = pca955x_probe,
        .remove = pca955x_remove,
index bee3e1ab27fd92fd7b71ab0a34812cd80ac5c8d0..41f269fe09205f48c3216179d30da652a4574bb3 100644 (file)
@@ -332,6 +332,7 @@ static const struct of_device_id of_pca963x_match[] = {
        { .compatible = "nxp,pca9635", },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_pca963x_match);
 #else
 static struct pca963x_platform_data *
 pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
@@ -458,7 +459,6 @@ static int pca963x_remove(struct i2c_client *client)
 static struct i2c_driver pca963x_driver = {
        .driver = {
                .name   = "leds-pca963x",
-               .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(of_pca963x_match),
        },
        .probe  = pca963x_probe,
index d1660b0398125943b58822401d350b9ce983d5f2..b88900d721e4494e9e05c494e7d9977501cda97b 100644 (file)
@@ -83,9 +83,9 @@ static int syscon_led_probe(struct platform_device *pdev)
                return -ENODEV;
        }
        map = syscon_node_to_regmap(parent->of_node);
-       if (!map) {
+       if (IS_ERR(map)) {
                dev_err(dev, "no regmap for syscon LED parent\n");
-               return -ENODEV;
+               return PTR_ERR(map);
        }
 
        sled = devm_kzalloc(dev, sizeof(*sled), GFP_KERNEL);
index 20fa8e77f1863c5aa9bbe78a5eb028d6c32cc49c..edbecc4ca2da4c2df887e56c34fcee33c88ca847 100644 (file)
@@ -735,6 +735,7 @@ static const struct of_device_id of_tca6507_leds_match[] = {
        { .compatible = "ti,tca6507", },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_tca6507_leds_match);
 
 #else
 static struct tca6507_platform_data *
@@ -830,7 +831,6 @@ static int tca6507_remove(struct i2c_client *client)
 static struct i2c_driver tca6507_driver = {
        .driver   = {
                .name    = "leds-tca6507",
-               .owner   = THIS_MODULE,
                .of_match_table = of_match_ptr(of_tca6507_leds_match),
        },
        .probe    = tca6507_probe,
index de16c29d7895412ce48368b4b01a011b0449e587..b806eca83d27ede6ead3c08568a221767fd8bbae 100644 (file)
@@ -231,10 +231,6 @@ tlc591xx_probe(struct i2c_client *client,
        if (!count || count > tlc591xx->max_leds)
                return -EINVAL;
 
-       if (!i2c_check_functionality(client->adapter,
-                                    I2C_FUNC_SMBUS_BYTE_DATA))
-               return -EIO;
-
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
index 49794b47b51c498daa4921c2616693af92eaf2fd..5bda6a9b56bbd90b4a3749f87bc0c6fda8dd5034 100644 (file)
@@ -72,7 +72,7 @@ config LEDS_TRIGGER_CPU
 config LEDS_TRIGGER_GPIO
        tristate "LED GPIO Trigger"
        depends on LEDS_TRIGGERS
-       depends on GPIOLIB
+       depends on GPIOLIB || COMPILE_TEST
        help
          This allows LEDs to be controlled by gpio events. It's good
          when using gpios as switches and triggering the needed LEDs
index 32814371b8d304539a2eb1cfece077510b4ca394..aa1b41ca40f778dcb4e6c0e393ab4ee33d25d388 100644 (file)
@@ -1471,5 +1471,3 @@ module_exit(mq_exit);
 MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("mq cache policy");
-
-MODULE_ALIAS("dm-cache-default");
index 48a4a826ae07649419d033b99c564b2adb9da6ea..200366c62231dd5f8f38f74284a42810c8603d19 100644 (file)
@@ -1789,3 +1789,5 @@ module_exit(smq_exit);
 MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("smq cache policy");
+
+MODULE_ALIAS("dm-cache-default");
index 720ceeb7fa9b29118bea02dcb59e82a9f2638ee6..80a43954325966a872cf8ebc95fb23c92c0b8819 100644 (file)
@@ -1919,9 +1919,7 @@ int __init dm_interface_init(void)
 
 void dm_interface_exit(void)
 {
-       if (misc_deregister(&_dm_misc) < 0)
-               DMERR("misc_deregister failed for control device");
-
+       misc_deregister(&_dm_misc);
        dm_hash_exit();
 }
 
index 48dfe3c4d6aa7968bbc1986eafcb9e965fe55950..6ba47cfb1443748ccf092819a6a5ef160bb856fd 100644 (file)
@@ -1293,8 +1293,8 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd)
                return r;
 
        disk_super = dm_block_data(copy);
-       dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->data_mapping_root));
-       dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->device_details_root));
+       dm_btree_del(&pmd->info, le64_to_cpu(disk_super->data_mapping_root));
+       dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root));
        dm_sm_dec_block(pmd->metadata_sm, held_root);
 
        return dm_tm_unlock(pmd->tm, copy);
index bf2b80d5c4707a64210b5e57deb785069dc7d921..8731b6ea026bd9b8cfbe2a21bbc06366e509181c 100644 (file)
@@ -138,4 +138,10 @@ int lower_bound(struct btree_node *n, uint64_t key);
 
 extern struct dm_block_validator btree_node_validator;
 
+/*
+ * Value type for upper levels of multi-level btrees.
+ */
+extern void init_le64_type(struct dm_transaction_manager *tm,
+                          struct dm_btree_value_type *vt);
+
 #endif /* DM_BTREE_INTERNAL_H */
index 9ca9eccd512fd99f8116a20ab1b3ed67d821cb6d..4222f774cf369b1eb1b031bd652854c573b224af 100644 (file)
@@ -544,14 +544,6 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
        return r;
 }
 
-static struct dm_btree_value_type le64_type = {
-       .context = NULL,
-       .size = sizeof(__le64),
-       .inc = NULL,
-       .dec = NULL,
-       .equal = NULL
-};
-
 int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
                    uint64_t *keys, dm_block_t *new_root)
 {
@@ -559,12 +551,14 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
        int index = 0, r = 0;
        struct shadow_spine spine;
        struct btree_node *n;
+       struct dm_btree_value_type le64_vt;
 
+       init_le64_type(info->tm, &le64_vt);
        init_shadow_spine(&spine, info);
        for (level = 0; level < info->levels; level++) {
                r = remove_raw(&spine, info,
                               (level == last_level ?
-                               &info->value_type : &le64_type),
+                               &info->value_type : &le64_vt),
                               root, keys[level], (unsigned *)&index);
                if (r < 0)
                        break;
@@ -654,11 +648,13 @@ static int remove_one(struct dm_btree_info *info, dm_block_t root,
        int index = 0, r = 0;
        struct shadow_spine spine;
        struct btree_node *n;
+       struct dm_btree_value_type le64_vt;
        uint64_t k;
 
+       init_le64_type(info->tm, &le64_vt);
        init_shadow_spine(&spine, info);
        for (level = 0; level < last_level; level++) {
-               r = remove_raw(&spine, info, &le64_type,
+               r = remove_raw(&spine, info, &le64_vt,
                               root, keys[level], (unsigned *) &index);
                if (r < 0)
                        goto out;
index 1b5e13ec7f96a670ed7a9b5b472a5d2ee95a7dff..0dee514ba4c5f9e8d34d16e9d239ef333395c7d4 100644 (file)
@@ -249,3 +249,40 @@ int shadow_root(struct shadow_spine *s)
 {
        return s->root;
 }
+
+static void le64_inc(void *context, const void *value_le)
+{
+       struct dm_transaction_manager *tm = context;
+       __le64 v_le;
+
+       memcpy(&v_le, value_le, sizeof(v_le));
+       dm_tm_inc(tm, le64_to_cpu(v_le));
+}
+
+static void le64_dec(void *context, const void *value_le)
+{
+       struct dm_transaction_manager *tm = context;
+       __le64 v_le;
+
+       memcpy(&v_le, value_le, sizeof(v_le));
+       dm_tm_dec(tm, le64_to_cpu(v_le));
+}
+
+static int le64_equal(void *context, const void *value1_le, const void *value2_le)
+{
+       __le64 v1_le, v2_le;
+
+       memcpy(&v1_le, value1_le, sizeof(v1_le));
+       memcpy(&v2_le, value2_le, sizeof(v2_le));
+       return v1_le == v2_le;
+}
+
+void init_le64_type(struct dm_transaction_manager *tm,
+                   struct dm_btree_value_type *vt)
+{
+       vt->context = tm;
+       vt->size = sizeof(__le64);
+       vt->inc = le64_inc;
+       vt->dec = le64_dec;
+       vt->equal = le64_equal;
+}
index fdd3793e22f957ef08db71f897607c68ce6eb6a3..c7726cebc4950c24cb6f6f2b7cacfa6465bddeb6 100644 (file)
@@ -667,12 +667,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root,
        struct btree_node *n;
        struct dm_btree_value_type le64_type;
 
-       le64_type.context = NULL;
-       le64_type.size = sizeof(__le64);
-       le64_type.inc = NULL;
-       le64_type.dec = NULL;
-       le64_type.equal = NULL;
-
+       init_le64_type(info->tm, &le64_type);
        init_shadow_spine(&spine, info);
 
        for (level = 0; level < (info->levels - 1); level++) {
index 0d35f5850ff1ea8e9910168f55fe04f05c42600e..5ab90f36a6a687c3c64edd56f09d3f8708dba635 100644 (file)
@@ -240,7 +240,7 @@ config DVB_SI21XX
 
 config DVB_TS2020
        tristate "Montage Tehnology TS2020 based tuners"
-       depends on DVB_CORE
+       depends on DVB_CORE && I2C
        select REGMAP_I2C
        default m if !MEDIA_SUBDRV_AUTOSELECT
        help
index 3be1b2c3c3860ec48c2e9a1e5e5cd41daf56046f..6a1c0089bb6279c6660b6154681c1c7cdeb129d4 100644 (file)
@@ -2,6 +2,7 @@ config VIDEO_COBALT
        tristate "Cisco Cobalt support"
        depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER
        depends on PCI_MSI && MTD_COMPLEX_MAPPINGS && GPIOLIB
+       depends on SND
        select I2C_ALGOBIT
        select VIDEO_ADV7604
        select VIDEO_ADV7511
index dd4bff9cf3390a4f167c6e5d1a9ae4886dae9750..d1f5898d11ba1c046737b2bb2a7ba48fa7547b9d 100644 (file)
@@ -139,7 +139,7 @@ done:
           also know about dropped frames. */
        cb->vb.v4l2_buf.sequence = s->sequence++;
        vb2_buffer_done(&cb->vb, (skip || s->unstable_frame) ?
-                       VB2_BUF_STATE_QUEUED : VB2_BUF_STATE_DONE);
+                       VB2_BUF_STATE_REQUEUEING : VB2_BUF_STATE_DONE);
 }
 
 irqreturn_t cobalt_irq_handler(int irq, void *dev_id)
index 1d59c7e039f7d41e989dc986cf6ac09815165747..87990ece5848957baf4af40dd5100f356466b901 100644 (file)
@@ -130,10 +130,11 @@ err:
 
 int mantis_dma_init(struct mantis_pci *mantis)
 {
-       int err = 0;
+       int err;
 
        dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
-       if (mantis_alloc_buffers(mantis) < 0) {
+       err = mantis_alloc_buffers(mantis);
+       if (err < 0) {
                dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
 
                /* Stop RISC Engine */
index 8939ebd7439198161935f573652f25babb438840..84fa6e9b59a1acd9360364fbd30ca0a4e00d3a56 100644 (file)
@@ -184,125 +184,9 @@ out:
        return -EINVAL;
 }
 
-static struct ir_raw_timings_manchester ir_rc5_timings = {
-       .leader                 = RC5_UNIT,
-       .pulse_space_start      = 0,
-       .clock                  = RC5_UNIT,
-       .trailer_space          = RC5_UNIT * 10,
-};
-
-static struct ir_raw_timings_manchester ir_rc5x_timings[2] = {
-       {
-               .leader                 = RC5_UNIT,
-               .pulse_space_start      = 0,
-               .clock                  = RC5_UNIT,
-               .trailer_space          = RC5X_SPACE,
-       },
-       {
-               .clock                  = RC5_UNIT,
-               .trailer_space          = RC5_UNIT * 10,
-       },
-};
-
-static struct ir_raw_timings_manchester ir_rc5_sz_timings = {
-       .leader                         = RC5_UNIT,
-       .pulse_space_start              = 0,
-       .clock                          = RC5_UNIT,
-       .trailer_space                  = RC5_UNIT * 10,
-};
-
-static int ir_rc5_validate_filter(const struct rc_scancode_filter *scancode,
-                                 unsigned int important_bits)
-{
-       /* all important bits of scancode should be set in mask */
-       if (~scancode->mask & important_bits)
-               return -EINVAL;
-       /* extra bits in mask should be zero in data */
-       if (scancode->mask & scancode->data & ~important_bits)
-               return -EINVAL;
-       return 0;
-}
-
-/**
- * ir_rc5_encode() - Encode a scancode as a stream of raw events
- *
- * @protocols: allowed protocols
- * @scancode:  scancode filter describing scancode (helps distinguish between
- *             protocol subtypes when scancode is ambiguous)
- * @events:    array of raw ir events to write into
- * @max:       maximum size of @events
- *
- * Returns:    The number of events written.
- *             -ENOBUFS if there isn't enough space in the array to fit the
- *             encoding. In this case all @max events will have been written.
- *             -EINVAL if the scancode is ambiguous or invalid.
- */
-static int ir_rc5_encode(u64 protocols,
-                        const struct rc_scancode_filter *scancode,
-                        struct ir_raw_event *events, unsigned int max)
-{
-       int ret;
-       struct ir_raw_event *e = events;
-       unsigned int data, xdata, command, commandx, system;
-
-       /* Detect protocol and convert scancode to raw data */
-       if (protocols & RC_BIT_RC5 &&
-           !ir_rc5_validate_filter(scancode, 0x1f7f)) {
-               /* decode scancode */
-               command  = (scancode->data & 0x003f) >> 0;
-               commandx = (scancode->data & 0x0040) >> 6;
-               system   = (scancode->data & 0x1f00) >> 8;
-               /* encode data */
-               data = !commandx << 12 | system << 6 | command;
-
-               /* Modulate the data */
-               ret = ir_raw_gen_manchester(&e, max, &ir_rc5_timings, RC5_NBITS,
-                                           data);
-               if (ret < 0)
-                       return ret;
-       } else if (protocols & RC_BIT_RC5X &&
-                  !ir_rc5_validate_filter(scancode, 0x1f7f3f)) {
-               /* decode scancode */
-               xdata    = (scancode->data & 0x00003f) >> 0;
-               command  = (scancode->data & 0x003f00) >> 8;
-               commandx = (scancode->data & 0x004000) >> 14;
-               system   = (scancode->data & 0x1f0000) >> 16;
-               /* commandx and system overlap, bits must match when encoded */
-               if (commandx == (system & 0x1))
-                       return -EINVAL;
-               /* encode data */
-               data = 1 << 18 | system << 12 | command << 6 | xdata;
-
-               /* Modulate the data */
-               ret = ir_raw_gen_manchester(&e, max, &ir_rc5x_timings[0],
-                                       CHECK_RC5X_NBITS,
-                                       data >> (RC5X_NBITS-CHECK_RC5X_NBITS));
-               if (ret < 0)
-                       return ret;
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                       &ir_rc5x_timings[1],
-                                       RC5X_NBITS - CHECK_RC5X_NBITS,
-                                       data);
-               if (ret < 0)
-                       return ret;
-       } else if (protocols & RC_BIT_RC5_SZ &&
-                  !ir_rc5_validate_filter(scancode, 0x2fff)) {
-               /* RC5-SZ scancode is raw enough for Manchester as it is */
-               ret = ir_raw_gen_manchester(&e, max, &ir_rc5_sz_timings,
-                                       RC5_SZ_NBITS, scancode->data & 0x2fff);
-               if (ret < 0)
-                       return ret;
-       } else {
-               return -EINVAL;
-       }
-
-       return e - events;
-}
-
 static struct ir_raw_handler rc5_handler = {
        .protocols      = RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
        .decode         = ir_rc5_decode,
-       .encode         = ir_rc5_encode,
 };
 
 static int __init ir_rc5_decode_init(void)
index f9c70baf6e0cb1f071f0a6f7e2ac9e81cf131817..d16bc67af732251998fb280b86d887835cf39e1b 100644 (file)
@@ -291,133 +291,11 @@ out:
        return -EINVAL;
 }
 
-static struct ir_raw_timings_manchester ir_rc6_timings[4] = {
-       {
-               .leader                 = RC6_PREFIX_PULSE,
-               .pulse_space_start      = 0,
-               .clock                  = RC6_UNIT,
-               .invert                 = 1,
-               .trailer_space          = RC6_PREFIX_SPACE,
-       },
-       {
-               .clock                  = RC6_UNIT,
-               .invert                 = 1,
-       },
-       {
-               .clock                  = RC6_UNIT * 2,
-               .invert                 = 1,
-       },
-       {
-               .clock                  = RC6_UNIT,
-               .invert                 = 1,
-               .trailer_space          = RC6_SUFFIX_SPACE,
-       },
-};
-
-static int ir_rc6_validate_filter(const struct rc_scancode_filter *scancode,
-                                 unsigned int important_bits)
-{
-       /* all important bits of scancode should be set in mask */
-       if (~scancode->mask & important_bits)
-               return -EINVAL;
-       /* extra bits in mask should be zero in data */
-       if (scancode->mask & scancode->data & ~important_bits)
-               return -EINVAL;
-       return 0;
-}
-
-/**
- * ir_rc6_encode() - Encode a scancode as a stream of raw events
- *
- * @protocols: allowed protocols
- * @scancode:  scancode filter describing scancode (helps distinguish between
- *             protocol subtypes when scancode is ambiguous)
- * @events:    array of raw ir events to write into
- * @max:       maximum size of @events
- *
- * Returns:    The number of events written.
- *             -ENOBUFS if there isn't enough space in the array to fit the
- *             encoding. In this case all @max events will have been written.
- *             -EINVAL if the scancode is ambiguous or invalid.
- */
-static int ir_rc6_encode(u64 protocols,
-                        const struct rc_scancode_filter *scancode,
-                        struct ir_raw_event *events, unsigned int max)
-{
-       int ret;
-       struct ir_raw_event *e = events;
-
-       if (protocols & RC_BIT_RC6_0 &&
-           !ir_rc6_validate_filter(scancode, 0xffff)) {
-
-               /* Modulate the preamble */
-               ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0);
-               if (ret < 0)
-                       return ret;
-
-               /* Modulate the header (Start Bit & Mode-0) */
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                           &ir_rc6_timings[1],
-                                           RC6_HEADER_NBITS, (1 << 3));
-               if (ret < 0)
-                       return ret;
-
-               /* Modulate Trailer Bit */
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                           &ir_rc6_timings[2], 1, 0);
-               if (ret < 0)
-                       return ret;
-
-               /* Modulate rest of the data */
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                           &ir_rc6_timings[3], RC6_0_NBITS,
-                                           scancode->data);
-               if (ret < 0)
-                       return ret;
-
-       } else if (protocols & (RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
-                               RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE) &&
-                  !ir_rc6_validate_filter(scancode, 0x8fffffff)) {
-
-               /* Modulate the preamble */
-               ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0);
-               if (ret < 0)
-                       return ret;
-
-               /* Modulate the header (Start Bit & Header-version 6 */
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                           &ir_rc6_timings[1],
-                                           RC6_HEADER_NBITS, (1 << 3 | 6));
-               if (ret < 0)
-                       return ret;
-
-               /* Modulate Trailer Bit */
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                           &ir_rc6_timings[2], 1, 0);
-               if (ret < 0)
-                       return ret;
-
-               /* Modulate rest of the data */
-               ret = ir_raw_gen_manchester(&e, max - (e - events),
-                                           &ir_rc6_timings[3],
-                                           fls(scancode->mask),
-                                           scancode->data);
-               if (ret < 0)
-                       return ret;
-
-       } else {
-               return -EINVAL;
-       }
-
-       return e - events;
-}
-
 static struct ir_raw_handler rc6_handler = {
        .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,
-       .encode         = ir_rc6_encode,
 };
 
 static int __init ir_rc6_decode_init(void)
index baeb5971fd52cecca1a01f436713f9f3a77c65ca..85af7a8691677a9b3965f469f37bc49b741de6b7 100644 (file)
@@ -526,130 +526,6 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)
        return 0;
 }
 
-static int nvt_write_wakeup_codes(struct rc_dev *dev,
-                                 const u8 *wakeup_sample_buf, int count)
-{
-       int i = 0;
-       u8 reg, reg_learn_mode;
-       unsigned long flags;
-       struct nvt_dev *nvt = dev->priv;
-
-       nvt_dbg_wake("writing wakeup samples");
-
-       reg = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON);
-       reg_learn_mode = reg & ~CIR_WAKE_IRCON_MODE0;
-       reg_learn_mode |= CIR_WAKE_IRCON_MODE1;
-
-       /* Lock the learn area to prevent racing with wake-isr */
-       spin_lock_irqsave(&nvt->nvt_lock, flags);
-
-       /* Enable fifo writes */
-       nvt_cir_wake_reg_write(nvt, reg_learn_mode, CIR_WAKE_IRCON);
-
-       /* Clear cir wake rx fifo */
-       nvt_clear_cir_wake_fifo(nvt);
-
-       if (count > WAKE_FIFO_LEN) {
-               nvt_dbg_wake("HW FIFO too small for all wake samples");
-               count = WAKE_FIFO_LEN;
-       }
-
-       if (count)
-               pr_info("Wake samples (%d) =", count);
-       else
-               pr_info("Wake sample fifo cleared");
-
-       /* Write wake samples to fifo */
-       for (i = 0; i < count; i++) {
-               pr_cont(" %02x", wakeup_sample_buf[i]);
-               nvt_cir_wake_reg_write(nvt, wakeup_sample_buf[i],
-                                      CIR_WAKE_WR_FIFO_DATA);
-       }
-       pr_cont("\n");
-
-       /* Switch cir to wakeup mode and disable fifo writing */
-       nvt_cir_wake_reg_write(nvt, reg, CIR_WAKE_IRCON);
-
-       /* Set number of bytes needed for wake */
-       nvt_cir_wake_reg_write(nvt, count ? count :
-                              CIR_WAKE_FIFO_CMP_BYTES,
-                              CIR_WAKE_FIFO_CMP_DEEP);
-
-       spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
-       return 0;
-}
-
-static int nvt_ir_raw_set_wakeup_filter(struct rc_dev *dev,
-                                       struct rc_scancode_filter *sc_filter)
-{
-       u8 *reg_buf;
-       u8 buf_val;
-       int i, ret, count;
-       unsigned int val;
-       struct ir_raw_event *raw;
-       bool complete;
-
-       /* Require both mask and data to be set before actually committing */
-       if (!sc_filter->mask || !sc_filter->data)
-               return 0;
-
-       raw = kmalloc_array(WAKE_FIFO_LEN, sizeof(*raw), GFP_KERNEL);
-       if (!raw)
-               return -ENOMEM;
-
-       ret = ir_raw_encode_scancode(dev->enabled_wakeup_protocols, sc_filter,
-                                    raw, WAKE_FIFO_LEN);
-       complete = (ret != -ENOBUFS);
-       if (!complete)
-               ret = WAKE_FIFO_LEN;
-       else if (ret < 0)
-               goto out_raw;
-
-       reg_buf = kmalloc_array(WAKE_FIFO_LEN, sizeof(*reg_buf), GFP_KERNEL);
-       if (!reg_buf) {
-               ret = -ENOMEM;
-               goto out_raw;
-       }
-
-       /* Inspect the ir samples */
-       for (i = 0, count = 0; i < ret && count < WAKE_FIFO_LEN; ++i) {
-               val = NS_TO_US((raw[i]).duration) / SAMPLE_PERIOD;
-
-               /* Split too large values into several smaller ones */
-               while (val > 0 && count < WAKE_FIFO_LEN) {
-
-                       /* Skip last value for better comparison tolerance */
-                       if (complete && i == ret - 1 && val < BUF_LEN_MASK)
-                               break;
-
-                       /* Clamp values to BUF_LEN_MASK at most */
-                       buf_val = (val > BUF_LEN_MASK) ? BUF_LEN_MASK : val;
-
-                       reg_buf[count] = buf_val;
-                       val -= buf_val;
-                       if ((raw[i]).pulse)
-                               reg_buf[count] |= BUF_PULSE_BIT;
-                       count++;
-               }
-       }
-
-       ret = nvt_write_wakeup_codes(dev, reg_buf, count);
-
-       kfree(reg_buf);
-out_raw:
-       kfree(raw);
-
-       return ret;
-}
-
-/* Dummy implementation. nuvoton is agnostic to the protocol used */
-static int nvt_ir_raw_change_wakeup_protocol(struct rc_dev *dev,
-                                            u64 *rc_type)
-{
-       return 0;
-}
-
 /*
  * nvt_tx_ir
  *
@@ -1167,14 +1043,11 @@ 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->encode_wakeup = true;
        rdev->allowed_protocols = RC_BIT_ALL;
        rdev->open = nvt_open;
        rdev->close = nvt_close;
        rdev->tx_ir = nvt_tx_ir;
        rdev->s_tx_carrier = nvt_set_tx_carrier;
-       rdev->s_wakeup_filter = nvt_ir_raw_set_wakeup_filter;
-       rdev->change_wakeup_protocol = nvt_ir_raw_change_wakeup_protocol;
        rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver";
        rdev->input_phys = "nuvoton/cir0";
        rdev->input_id.bustype = BUS_HOST;
index 9d0e161c2a886c511d3fde3928b154b0cfb7f0db..e1cf23c3875b16ead52464d4e6ad3c479fd1e951 100644 (file)
@@ -63,7 +63,6 @@ static int debug;
  */
 #define TX_BUF_LEN 256
 #define RX_BUF_LEN 32
-#define WAKE_FIFO_LEN 67
 
 struct nvt_dev {
        struct pnp_dev *pdev;
index 4b994aa2f2a7d1f763fd5bb7eccfb95f8ba1b6d6..b68d4f76273448fcbc98fc1e215a6656c9b6c6ec 100644 (file)
@@ -25,8 +25,6 @@ struct ir_raw_handler {
 
        u64 protocols; /* which are handled by this handler */
        int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
-       int (*encode)(u64 protocols, const struct rc_scancode_filter *scancode,
-                     struct ir_raw_event *events, unsigned int max);
 
        /* These two should only be used by the lirc decoder */
        int (*raw_register)(struct rc_dev *dev);
@@ -152,44 +150,10 @@ static inline bool is_timing_event(struct ir_raw_event ev)
 #define TO_US(duration)                        DIV_ROUND_CLOSEST((duration), 1000)
 #define TO_STR(is_pulse)               ((is_pulse) ? "pulse" : "space")
 
-/* functions for IR encoders */
-
-static inline void init_ir_raw_event_duration(struct ir_raw_event *ev,
-                                             unsigned int pulse,
-                                             u32 duration)
-{
-       init_ir_raw_event(ev);
-       ev->duration = duration;
-       ev->pulse = pulse;
-}
-
-/**
- * struct ir_raw_timings_manchester - Manchester coding timings
- * @leader:            duration of leader pulse (if any) 0 if continuing
- *                     existing signal (see @pulse_space_start)
- * @pulse_space_start: 1 for starting with pulse (0 for starting with space)
- * @clock:             duration of each pulse/space in ns
- * @invert:            if set clock logic is inverted
- *                     (0 = space + pulse, 1 = pulse + space)
- * @trailer_space:     duration of trailer space in ns
- */
-struct ir_raw_timings_manchester {
-       unsigned int leader;
-       unsigned int pulse_space_start:1;
-       unsigned int clock;
-       unsigned int invert:1;
-       unsigned int trailer_space;
-};
-
-int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
-                         const struct ir_raw_timings_manchester *timings,
-                         unsigned int n, unsigned int data);
-
 /*
  * Routines from rc-raw.c to be used internally and by decoders
  */
 u64 ir_raw_get_allowed_protocols(void);
-u64 ir_raw_get_encode_protocols(void);
 int ir_raw_event_register(struct rc_dev *dev);
 void ir_raw_event_unregister(struct rc_dev *dev);
 int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
index b9e4645c731c087f3dea99fa652fe09ef19dc8de..b732ac6a26d8065cc26ecb3a648ced999db71367 100644 (file)
@@ -30,7 +30,6 @@ static LIST_HEAD(ir_raw_client_list);
 static DEFINE_MUTEX(ir_raw_handler_lock);
 static LIST_HEAD(ir_raw_handler_list);
 static u64 available_protocols;
-static u64 encode_protocols;
 
 static int ir_raw_event_thread(void *data)
 {
@@ -241,146 +240,12 @@ ir_raw_get_allowed_protocols(void)
        return protocols;
 }
 
-/* used internally by the sysfs interface */
-u64
-ir_raw_get_encode_protocols(void)
-{
-       u64 protocols;
-
-       mutex_lock(&ir_raw_handler_lock);
-       protocols = encode_protocols;
-       mutex_unlock(&ir_raw_handler_lock);
-       return protocols;
-}
-
 static int change_protocol(struct rc_dev *dev, u64 *rc_type)
 {
        /* the caller will update dev->enabled_protocols */
        return 0;
 }
 
-/**
- * ir_raw_gen_manchester() - Encode data with Manchester (bi-phase) modulation.
- * @ev:                Pointer to pointer to next free event. *@ev is incremented for
- *             each raw event filled.
- * @max:       Maximum number of raw events to fill.
- * @timings:   Manchester modulation timings.
- * @n:         Number of bits of data.
- * @data:      Data bits to encode.
- *
- * Encodes the @n least significant bits of @data using Manchester (bi-phase)
- * modulation with the timing characteristics described by @timings, writing up
- * to @max raw IR events using the *@ev pointer.
- *
- * Returns:    0 on success.
- *             -ENOBUFS if there isn't enough space in the array to fit the
- *             full encoded data. In this case all @max events will have been
- *             written.
- */
-int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
-                         const struct ir_raw_timings_manchester *timings,
-                         unsigned int n, unsigned int data)
-{
-       bool need_pulse;
-       unsigned int i;
-       int ret = -ENOBUFS;
-
-       i = 1 << (n - 1);
-
-       if (timings->leader) {
-               if (!max--)
-                       return ret;
-               if (timings->pulse_space_start) {
-                       init_ir_raw_event_duration((*ev)++, 1, timings->leader);
-
-                       if (!max--)
-                               return ret;
-                       init_ir_raw_event_duration((*ev), 0, timings->leader);
-               } else {
-                       init_ir_raw_event_duration((*ev), 1, timings->leader);
-               }
-               i >>= 1;
-       } else {
-               /* continue existing signal */
-               --(*ev);
-       }
-       /* from here on *ev will point to the last event rather than the next */
-
-       while (n && i > 0) {
-               need_pulse = !(data & i);
-               if (timings->invert)
-                       need_pulse = !need_pulse;
-               if (need_pulse == !!(*ev)->pulse) {
-                       (*ev)->duration += timings->clock;
-               } else {
-                       if (!max--)
-                               goto nobufs;
-                       init_ir_raw_event_duration(++(*ev), need_pulse,
-                                                  timings->clock);
-               }
-
-               if (!max--)
-                       goto nobufs;
-               init_ir_raw_event_duration(++(*ev), !need_pulse,
-                                          timings->clock);
-               i >>= 1;
-       }
-
-       if (timings->trailer_space) {
-               if (!(*ev)->pulse)
-                       (*ev)->duration += timings->trailer_space;
-               else if (!max--)
-                       goto nobufs;
-               else
-                       init_ir_raw_event_duration(++(*ev), 0,
-                                                  timings->trailer_space);
-       }
-
-       ret = 0;
-nobufs:
-       /* point to the next event rather than last event before returning */
-       ++(*ev);
-       return ret;
-}
-EXPORT_SYMBOL(ir_raw_gen_manchester);
-
-/**
- * ir_raw_encode_scancode() - Encode a scancode as raw events
- *
- * @protocols:         permitted protocols
- * @scancode:          scancode filter describing a single scancode
- * @events:            array of raw events to write into
- * @max:               max number of raw events
- *
- * Attempts to encode the scancode as raw events.
- *
- * Returns:    The number of events written.
- *             -ENOBUFS if there isn't enough space in the array to fit the
- *             encoding. In this case all @max events will have been written.
- *             -EINVAL if the scancode is ambiguous or invalid, or if no
- *             compatible encoder was found.
- */
-int ir_raw_encode_scancode(u64 protocols,
-                          const struct rc_scancode_filter *scancode,
-                          struct ir_raw_event *events, unsigned int max)
-{
-       struct ir_raw_handler *handler;
-       int ret = -EINVAL;
-
-       mutex_lock(&ir_raw_handler_lock);
-       list_for_each_entry(handler, &ir_raw_handler_list, list) {
-               if (handler->protocols & protocols && handler->encode) {
-                       ret = handler->encode(protocols, scancode, events, max);
-                       if (ret >= 0 || ret == -ENOBUFS)
-                               break;
-               }
-       }
-       mutex_unlock(&ir_raw_handler_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL(ir_raw_encode_scancode);
-
 /*
  * Used to (un)register raw event clients
  */
@@ -463,8 +328,6 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
                list_for_each_entry(raw, &ir_raw_client_list, list)
                        ir_raw_handler->raw_register(raw->dev);
        available_protocols |= ir_raw_handler->protocols;
-       if (ir_raw_handler->encode)
-               encode_protocols |= ir_raw_handler->protocols;
        mutex_unlock(&ir_raw_handler_lock);
 
        return 0;
@@ -481,8 +344,6 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
                list_for_each_entry(raw, &ir_raw_client_list, list)
                        ir_raw_handler->raw_unregister(raw->dev);
        available_protocols &= ~ir_raw_handler->protocols;
-       if (ir_raw_handler->encode)
-               encode_protocols &= ~ir_raw_handler->protocols;
        mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
index d8bdf63ce9858ccfc78536fc698698e16c751670..63dace8198b0b3dbcb116108e238351fe9684a9e 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/slab.h>
 #include <media/rc-core.h>
 
 #define DRIVER_NAME    "rc-loopback"
@@ -177,39 +176,6 @@ static int loop_set_carrier_report(struct rc_dev *dev, int enable)
        return 0;
 }
 
-static int loop_set_wakeup_filter(struct rc_dev *dev,
-                                 struct rc_scancode_filter *sc_filter)
-{
-       static const unsigned int max = 512;
-       struct ir_raw_event *raw;
-       int ret;
-       int i;
-
-       /* fine to disable filter */
-       if (!sc_filter->mask)
-               return 0;
-
-       /* encode the specified filter and loop it back */
-       raw = kmalloc_array(max, sizeof(*raw), GFP_KERNEL);
-       ret = ir_raw_encode_scancode(dev->enabled_wakeup_protocols, sc_filter,
-                                    raw, max);
-       /* still loop back the partial raw IR even if it's incomplete */
-       if (ret == -ENOBUFS)
-               ret = max;
-       if (ret >= 0) {
-               /* do the loopback */
-               for (i = 0; i < ret; ++i)
-                       ir_raw_event_store(dev, &raw[i]);
-               ir_raw_event_handle(dev);
-
-               ret = 0;
-       }
-
-       kfree(raw);
-
-       return ret;
-}
-
 static int __init loop_init(void)
 {
        struct rc_dev *rc;
@@ -229,7 +195,6 @@ static int __init loop_init(void)
        rc->map_name            = RC_MAP_EMPTY;
        rc->priv                = &loopdev;
        rc->driver_type         = RC_DRIVER_IR_RAW;
-       rc->encode_wakeup       = true;
        rc->allowed_protocols   = RC_BIT_ALL;
        rc->timeout             = 100 * 1000 * 1000; /* 100 ms */
        rc->min_timeout         = 1;
@@ -244,7 +209,6 @@ static int __init loop_init(void)
        rc->s_idle              = loop_set_idle;
        rc->s_learning_mode     = loop_set_learning_mode;
        rc->s_carrier_report    = loop_set_carrier_report;
-       rc->s_wakeup_filter     = loop_set_wakeup_filter;
 
        loopdev.txmask          = RXMASK_REGULAR;
        loopdev.txcarrier       = 36000;
index 9d015db652808fcb54fc0abfff19e9018dbad488..0ff388a1616876d50ade807ff5bff20204d1b8cd 100644 (file)
@@ -865,8 +865,6 @@ static ssize_t show_protocols(struct device *device,
        } else {
                enabled = dev->enabled_wakeup_protocols;
                allowed = dev->allowed_wakeup_protocols;
-               if (dev->encode_wakeup && !allowed)
-                       allowed = ir_raw_get_encode_protocols();
        }
 
        mutex_unlock(&dev->lock);
@@ -1408,16 +1406,13 @@ int rc_register_device(struct rc_dev *dev)
                path ? path : "N/A");
        kfree(path);
 
-       if (dev->driver_type == RC_DRIVER_IR_RAW || dev->encode_wakeup) {
+       if (dev->driver_type == RC_DRIVER_IR_RAW) {
                /* Load raw decoders, if they aren't already */
                if (!raw_init) {
                        IR_dprintk(1, "Loading raw decoders\n");
                        ir_raw_init();
                        raw_init = true;
                }
-       }
-
-       if (dev->driver_type == RC_DRIVER_IR_RAW) {
                /* calls ir_register_device so unlock mutex here*/
                mutex_unlock(&dev->lock);
                rc = ir_raw_event_register(dev);
index 93b315459098932381d61d282cdb3f04194b18ae..a14c428f70e992460ed869b492723a5a08f155b9 100644 (file)
@@ -715,6 +715,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
                break;
        case VB2_BUF_STATE_PREPARING:
        case VB2_BUF_STATE_DEQUEUED:
+       case VB2_BUF_STATE_REQUEUEING:
                /* nothing */
                break;
        }
@@ -1182,7 +1183,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 
        if (WARN_ON(state != VB2_BUF_STATE_DONE &&
                    state != VB2_BUF_STATE_ERROR &&
-                   state != VB2_BUF_STATE_QUEUED))
+                   state != VB2_BUF_STATE_QUEUED &&
+                   state != VB2_BUF_STATE_REQUEUEING))
                state = VB2_BUF_STATE_ERROR;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1199,22 +1201,30 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
        for (plane = 0; plane < vb->num_planes; ++plane)
                call_void_memop(vb, finish, vb->planes[plane].mem_priv);
 
-       /* Add the buffer to the done buffers list */
        spin_lock_irqsave(&q->done_lock, flags);
-       vb->state = state;
-       if (state != VB2_BUF_STATE_QUEUED)
+       if (state == VB2_BUF_STATE_QUEUED ||
+           state == VB2_BUF_STATE_REQUEUEING) {
+               vb->state = VB2_BUF_STATE_QUEUED;
+       } else {
+               /* Add the buffer to the done buffers list */
                list_add_tail(&vb->done_entry, &q->done_list);
+               vb->state = state;
+       }
        atomic_dec(&q->owned_by_drv_count);
        spin_unlock_irqrestore(&q->done_lock, flags);
 
-       if (state == VB2_BUF_STATE_QUEUED) {
+       switch (state) {
+       case VB2_BUF_STATE_QUEUED:
+               return;
+       case VB2_BUF_STATE_REQUEUEING:
                if (q->start_streaming_called)
                        __enqueue_in_driver(vb);
                return;
+       default:
+               /* Inform any processes that may be waiting for buffers */
+               wake_up(&q->done_wq);
+               break;
        }
-
-       /* Inform any processes that may be waiting for buffers */
-       wake_up(&q->done_wq);
 }
 EXPORT_SYMBOL_GPL(vb2_buffer_done);
 
@@ -1244,19 +1254,19 @@ EXPORT_SYMBOL_GPL(vb2_discard_done);
 
 static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
 {
-       static bool __check_once __read_mostly;
+       static bool check_once;
 
-       if (__check_once)
+       if (check_once)
                return;
 
-       __check_once = true;
-       __WARN();
+       check_once = true;
+       WARN_ON(1);
 
-       pr_warn_once("use of bytesused == 0 is deprecated and will be removed in the future,\n");
+       pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
        if (vb->vb2_queue->allow_zero_bytesused)
-               pr_warn_once("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
+               pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
        else
-               pr_warn_once("use the actual size instead.\n");
+               pr_warn("use the actual size instead.\n");
 }
 
 /**
index 3a27a84ad3ec376a2543c1ac9568c30e5d7c131b..9426276dbe1402b1445dd7b84da6d7fca38893a6 100644 (file)
@@ -2245,6 +2245,9 @@ void omap3_gpmc_save_context(void)
 {
        int i;
 
+       if (!gpmc_base)
+               return;
+
        gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
        gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
        gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
@@ -2277,6 +2280,9 @@ void omap3_gpmc_restore_context(void)
 {
        int i;
 
+       if (!gpmc_base)
+               return;
+
        gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
        gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
        gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
index cb14afa97e6fbbf9403cd55687b39d43de5a7919..67bc53fdc38927a206c3d44b505afe4e8747a5fa 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mutex.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
 #include <linux/regulator/machine.h>
 #include <linux/regmap.h>
@@ -193,22 +194,22 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
        } else
                dev_info(max77693->dev, "device ID: 0x%x\n", reg_data);
 
-       max77693->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
-       if (!max77693->muic) {
+       max77693->i2c_muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
+       if (!max77693->i2c_muic) {
                dev_err(max77693->dev, "Failed to allocate I2C device for MUIC\n");
                return -ENODEV;
        }
-       i2c_set_clientdata(max77693->muic, max77693);
+       i2c_set_clientdata(max77693->i2c_muic, max77693);
 
-       max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
-       if (!max77693->haptic) {
+       max77693->i2c_haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
+       if (!max77693->i2c_haptic) {
                dev_err(max77693->dev, "Failed to allocate I2C device for Haptic\n");
                ret = -ENODEV;
                goto err_i2c_haptic;
        }
-       i2c_set_clientdata(max77693->haptic, max77693);
+       i2c_set_clientdata(max77693->i2c_haptic, max77693);
 
-       max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic,
+       max77693->regmap_haptic = devm_regmap_init_i2c(max77693->i2c_haptic,
                                        &max77693_regmap_haptic_config);
        if (IS_ERR(max77693->regmap_haptic)) {
                ret = PTR_ERR(max77693->regmap_haptic);
@@ -222,7 +223,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
         * instance of MUIC device when irq of max77693 is initialized
         * before call max77693-muic probe() function.
         */
-       max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic,
+       max77693->regmap_muic = devm_regmap_init_i2c(max77693->i2c_muic,
                                         &max77693_regmap_muic_config);
        if (IS_ERR(max77693->regmap_muic)) {
                ret = PTR_ERR(max77693->regmap_muic);
@@ -255,7 +256,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                                IRQF_ONESHOT | IRQF_SHARED |
                                IRQF_TRIGGER_FALLING, 0,
                                &max77693_charger_irq_chip,
-                               &max77693->irq_data_charger);
+                               &max77693->irq_data_chg);
        if (ret) {
                dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
                goto err_irq_charger;
@@ -296,15 +297,15 @@ err_mfd:
 err_intsrc:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
 err_irq_muic:
-       regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+       regmap_del_irq_chip(max77693->irq, max77693->irq_data_chg);
 err_irq_charger:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
 err_irq_topsys:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
 err_regmap:
-       i2c_unregister_device(max77693->haptic);
+       i2c_unregister_device(max77693->i2c_haptic);
 err_i2c_haptic:
-       i2c_unregister_device(max77693->muic);
+       i2c_unregister_device(max77693->i2c_muic);
        return ret;
 }
 
@@ -315,12 +316,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c)
        mfd_remove_devices(max77693->dev);
 
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
-       regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+       regmap_del_irq_chip(max77693->irq, max77693->irq_data_chg);
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
 
-       i2c_unregister_device(max77693->muic);
-       i2c_unregister_device(max77693->haptic);
+       i2c_unregister_device(max77693->i2c_muic);
+       i2c_unregister_device(max77693->i2c_haptic);
 
        return 0;
 }
index a354ac677ec7027fa427ce40dd034899b4204866..c52162ea3d0ab1daf8bd375220669f3ba53db15e 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/mfd/core.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77843-private.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -71,7 +72,7 @@ static const struct regmap_irq_chip max77843_irq_chip = {
 };
 
 /* Charger and Charger regulator use same regmap. */
-static int max77843_chg_init(struct max77843 *max77843)
+static int max77843_chg_init(struct max77693_dev *max77843)
 {
        int ret;
 
@@ -101,7 +102,7 @@ err_chg_i2c:
 static int max77843_probe(struct i2c_client *i2c,
                          const struct i2c_device_id *id)
 {
-       struct max77843 *max77843;
+       struct max77693_dev *max77843;
        unsigned int reg_data;
        int ret;
 
@@ -113,6 +114,7 @@ static int max77843_probe(struct i2c_client *i2c,
        max77843->dev = &i2c->dev;
        max77843->i2c = i2c;
        max77843->irq = i2c->irq;
+       max77843->type = id->driver_data;
 
        max77843->regmap = devm_regmap_init_i2c(i2c,
                        &max77843_regmap_config);
@@ -123,7 +125,7 @@ static int max77843_probe(struct i2c_client *i2c,
 
        ret = regmap_add_irq_chip(max77843->regmap, max77843->irq,
                        IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
-                       0, &max77843_irq_chip, &max77843->irq_data);
+                       0, &max77843_irq_chip, &max77843->irq_data_topsys);
        if (ret) {
                dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n");
                return ret;
@@ -164,18 +166,18 @@ static int max77843_probe(struct i2c_client *i2c,
        return 0;
 
 err_pmic_id:
-       regmap_del_irq_chip(max77843->irq, max77843->irq_data);
+       regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys);
 
        return ret;
 }
 
 static int max77843_remove(struct i2c_client *i2c)
 {
-       struct max77843 *max77843 = i2c_get_clientdata(i2c);
+       struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
 
        mfd_remove_devices(max77843->dev);
 
-       regmap_del_irq_chip(max77843->irq, max77843->irq_data);
+       regmap_del_irq_chip(max77843->irq, max77843->irq_data_topsys);
 
        i2c_unregister_device(max77843->i2c_chg);
 
@@ -188,7 +190,7 @@ static const struct of_device_id max77843_dt_match[] = {
 };
 
 static const struct i2c_device_id max77843_id[] = {
-       { "max77843", },
+       { "max77843", TYPE_MAX77843, },
        { },
 };
 MODULE_DEVICE_TABLE(i2c, max77843_id);
@@ -196,7 +198,7 @@ MODULE_DEVICE_TABLE(i2c, max77843_id);
 static int __maybe_unused max77843_suspend(struct device *dev)
 {
        struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
-       struct max77843 *max77843 = i2c_get_clientdata(i2c);
+       struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
 
        disable_irq(max77843->irq);
        if (device_may_wakeup(dev))
@@ -208,7 +210,7 @@ static int __maybe_unused max77843_suspend(struct device *dev)
 static int __maybe_unused max77843_resume(struct device *dev)
 {
        struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
-       struct max77843 *max77843 = i2c_get_clientdata(i2c);
+       struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
 
        if (device_may_wakeup(dev))
                disable_irq_wake(max77843->irq);
index 489674a2497e042b4431545b687a52fe0bd59d71..831696ee2472b4ccee8c16304e32f98b54670a25 100644 (file)
@@ -788,9 +788,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                static struct regulator_consumer_supply usb1v8 = {
                        .supply =       "usb1v8",
                };
-               static struct regulator_consumer_supply usb3v1[] = {
-                       { .supply =     "usb3v1" },
-                       { .supply =     "bci3v1" },
+               static struct regulator_consumer_supply usb3v1 = {
+                       .supply =       "usb3v1",
                };
 
        /* First add the regulators so that they can be used by transceiver */
@@ -818,7 +817,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                                return PTR_ERR(child);
 
                        child = add_regulator_linked(TWL4030_REG_VUSB3V1,
-                                                     &usb_fixed, usb3v1, 2,
+                                                     &usb_fixed, &usb3v1, 1,
                                                      features);
                        if (IS_ERR(child))
                                return PTR_ERR(child);
@@ -838,7 +837,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
                        usb1v5.dev_name = dev_name(child);
                        usb1v8.dev_name = dev_name(child);
-                       usb3v1[0].dev_name = dev_name(child);
+                       usb3v1.dev_name = dev_name(child);
                }
        }
 
index 42c38525904b854d8e6a3b5051dbfb133f226f84..ccccc2943f2fde2d06955bdf5453a327f60dc153 100644 (file)
@@ -271,6 +271,16 @@ config HP_ILO
          To compile this driver as a module, choose M here: the
          module will be called hpilo.
 
+config QCOM_COINCELL
+       tristate "Qualcomm coincell charger support"
+       depends on MFD_SPMI_PMIC || COMPILE_TEST
+       help
+         This driver supports the coincell block found inside of
+         Qualcomm PMICs.  The coincell charger provides a means to
+         charge a coincell battery or backup capacitor which is used
+         to maintain PMIC register and RTC state in the absence of
+         external power.
+
 config SGI_GRU
        tristate "SGI GRU driver"
        depends on X86_UV && SMP
index d056fb7186fe1b31867457abb3e56b18ab1beb10..537d7f3b78da9a35afcf4fe41053bbcbef1dd1f2 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_LKDTM)           += lkdtm.o
 obj-$(CONFIG_TIFM_CORE)        += tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)        += tifm_7xx1.o
 obj-$(CONFIG_PHANTOM)          += phantom.o
+obj-$(CONFIG_QCOM_COINCELL)    += qcom-coincell.o
 obj-$(CONFIG_SENSORS_BH1780)   += bh1780gli.o
 obj-$(CONFIG_SENSORS_BH1770)   += bh1770glc.o
 obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
index 705b881e186d536ccb2bc97c392d108b3ecf765c..d11187d36ddd59b2d8ec6c8caf53dbc54d1fa928 100644 (file)
@@ -106,7 +106,6 @@ MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
 static struct i2c_driver ad_dpot_i2c_driver = {
        .driver = {
                .name   = "ad_dpot",
-               .owner  = THIS_MODULE,
        },
        .probe          = ad_dpot_i2c_probe,
        .remove         = ad_dpot_i2c_remove,
index 3739ffa9cdf132e28098ad088b620c655c624dce..a3e789b85cc82e441530981736ba227b0226bcf7 100644 (file)
@@ -1275,7 +1275,6 @@ static const struct dev_pm_ops apds990x_pm_ops = {
 static struct i2c_driver apds990x_driver = {
        .driver  = {
                .name   = "apds990x",
-               .owner  = THIS_MODULE,
                .pm     = &apds990x_pm_ops,
        },
        .probe    = apds990x_probe,
index b756381b825071f09bfbf73aa1de57bf560d128c..753d7ecdadaa78a27df6c47c54a0bd0265192ac4 100644 (file)
@@ -1396,7 +1396,6 @@ static const struct dev_pm_ops bh1770_pm_ops = {
 static struct i2c_driver bh1770_driver = {
        .driver  = {
                .name   = "bh1770glc",
-               .owner  = THIS_MODULE,
                .pm     = &bh1770_pm_ops,
        },
        .probe    = bh1770_probe,
index a7c16295b8161f30ea2578c29ce02084554d2097..f35c218aaa1a80bb77bb322e6707f6af9bb97aaa 100644 (file)
@@ -66,7 +66,6 @@ MODULE_DEVICE_TABLE(i2c, bmp085_id);
 
 static struct i2c_driver bmp085_i2c_driver = {
        .driver = {
-               .owner  = THIS_MODULE,
                .name   = BMP085_NAME,
        },
        .id_table       = bmp085_id,
index 31f38bc71a3d5d113263998141b62c4b9285d343..87cd747bb511c83f000023d4b1fc49714d3df598 100644 (file)
@@ -443,12 +443,7 @@ static ssize_t afu_read_config(struct file *filp, struct kobject *kobj,
        struct afu_config_record *cr = to_cr(kobj);
        struct cxl_afu *afu = to_cxl_afu(container_of(kobj->parent, struct device, kobj));
 
-       u64 i, j, val, size = afu->crs_len;
-
-       if (off > size)
-               return 0;
-       if (off + count > size)
-               count = size - off;
+       u64 i, j, val;
 
        for (i = 0; i < count;) {
                val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7);
index b909fb30232adbdc3771c8b2154d906a23e7269c..c7112276a039c755289f943e313a95ea5de39f37 100644 (file)
@@ -148,12 +148,6 @@ static ssize_t ds1682_eeprom_read(struct file *filp, struct kobject *kobj,
        dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n",
                buf, off, count);
 
-       if (off >= DS1682_EEPROM_SIZE)
-               return 0;
-
-       if (off + count > DS1682_EEPROM_SIZE)
-               count = DS1682_EEPROM_SIZE - off;
-
        rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off,
                                           count, buf);
        if (rc < 0)
@@ -171,12 +165,6 @@ static ssize_t ds1682_eeprom_write(struct file *filp, struct kobject *kobj,
        dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n",
                buf, off, count);
 
-       if (off >= DS1682_EEPROM_SIZE)
-               return -ENOSPC;
-
-       if (off + count > DS1682_EEPROM_SIZE)
-               count = DS1682_EEPROM_SIZE - off;
-
        /* Write out to the device */
        if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off,
                                           count, buf) < 0)
index 9536852fd4c68e28673b6325737fdf1cd82df5c1..04f2e1fa9dd15b10871919a788c81aff782178f8 100644 (file)
@@ -96,17 +96,4 @@ config EEPROM_DIGSY_MTC_CFG
 
          If unsure, say N.
 
-config EEPROM_SUNXI_SID
-       tristate "Allwinner sunxi security ID support"
-       depends on ARCH_SUNXI && SYSFS
-       help
-         This is a driver for the 'security ID' available on various Allwinner
-         devices.
-
-         Due to the potential risks involved with changing e-fuses,
-         this driver is read-only.
-
-         This driver can also be built as a module. If so, the module
-         will be called sunxi_sid.
-
 endmenu
index 9507aec95e948f88f31579585e60b8632c0b3782..fc1e81d292673b14732e9268b7cb9cdca9d921fb 100644 (file)
@@ -4,5 +4,4 @@ obj-$(CONFIG_EEPROM_LEGACY)     += eeprom.o
 obj-$(CONFIG_EEPROM_MAX6875)   += max6875.o
 obj-$(CONFIG_EEPROM_93CX6)     += eeprom_93cx6.o
 obj-$(CONFIG_EEPROM_93XX46)    += eeprom_93xx46.o
-obj-$(CONFIG_EEPROM_SUNXI_SID) += sunxi_sid.o
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
index 6ded3dc36644a31a0bd4775f36df72f1c00a7e0d..2b254f3a1154e641628dc9e92a84572f4a4174f9 100644 (file)
@@ -686,7 +686,6 @@ static int at24_remove(struct i2c_client *client)
 static struct i2c_driver at24_driver = {
        .driver = {
                .name = "at24",
-               .owner = THIS_MODULE,
        },
        .probe = at24_probe,
        .remove = at24_remove,
index b432873def96b5f489a50279205b0df0c7070453..7342fd637031335a21ed4779442ca69eb39fb045 100644 (file)
@@ -88,11 +88,6 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
        struct eeprom_data *data = i2c_get_clientdata(client);
        u8 slice;
 
-       if (off > EEPROM_SIZE)
-               return 0;
-       if (off + count > EEPROM_SIZE)
-               count = EEPROM_SIZE - off;
-
        /* Only refresh slices which contain requested bytes */
        for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
                eeprom_update_client(client, slice);
index 9ebeacdb8ec4a06381974c8e3137cebe7d5fe41d..a6bd9e3fe9d3fb1d730c99a05386c490633f67a0 100644 (file)
@@ -48,13 +48,6 @@ eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
        dev = container_of(kobj, struct device, kobj);
        edev = dev_get_drvdata(dev);
 
-       if (unlikely(off >= edev->bin.size))
-               return 0;
-       if ((off + count) > edev->bin.size)
-               count = edev->bin.size - off;
-       if (unlikely(!count))
-               return count;
-
        cmd_addr = OP_READ << edev->addrlen;
 
        if (edev->addrlen == 7) {
@@ -200,13 +193,6 @@ eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
        dev = container_of(kobj, struct device, kobj);
        edev = dev_get_drvdata(dev);
 
-       if (unlikely(off >= edev->bin.size))
-               return -EFBIG;
-       if ((off + count) > edev->bin.size)
-               count = edev->bin.size - off;
-       if (unlikely(!count))
-               return count;
-
        /* only write even number of bytes on 16-bit devices */
        if (edev->addrlen == 6) {
                step = 2;
index 580ff9df55296ccbb29e18561a98d7756e9c60b6..9aa4332a6b04d43034a93b54116ea7578d2a00bb 100644 (file)
@@ -114,12 +114,6 @@ static ssize_t max6875_read(struct file *filp, struct kobject *kobj,
        struct max6875_data *data = i2c_get_clientdata(client);
        int slice, max_slice;
 
-       if (off > USER_EEPROM_SIZE)
-               return 0;
-
-       if (off + count > USER_EEPROM_SIZE)
-               count = USER_EEPROM_SIZE - off;
-
        /* refresh slices which contain requested bytes */
        max_slice = (off + count - 1) >> SLICE_BITS;
        for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
deleted file mode 100644 (file)
index 8385177..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://www.linux-sunxi.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.
- *
- * This driver exposes the Allwinner security ID, efuses exported in byte-
- * sized chunks.
- */
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define DRV_NAME "sunxi-sid"
-
-struct sunxi_sid_data {
-       void __iomem *reg_base;
-       unsigned int keysize;
-};
-
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
- * want to return the requested byte, this results in somewhat slower code and
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
- * only very rarely probed, this is not really an issue.
- */
-static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
-                             const unsigned int offset)
-{
-       u32 sid_key;
-
-       if (offset >= sid_data->keysize)
-               return 0;
-
-       sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
-       sid_key >>= (offset % 4) * 8;
-
-       return sid_key; /* Only return the last byte */
-}
-
-static ssize_t sid_read(struct file *fd, struct kobject *kobj,
-                       struct bin_attribute *attr, char *buf,
-                       loff_t pos, size_t size)
-{
-       struct platform_device *pdev;
-       struct sunxi_sid_data *sid_data;
-       int i;
-
-       pdev = to_platform_device(kobj_to_dev(kobj));
-       sid_data = platform_get_drvdata(pdev);
-
-       if (pos < 0 || pos >= sid_data->keysize)
-               return 0;
-       if (size > sid_data->keysize - pos)
-               size = sid_data->keysize - pos;
-
-       for (i = 0; i < size; i++)
-               buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
-
-       return i;
-}
-
-static struct bin_attribute sid_bin_attr = {
-       .attr = { .name = "eeprom", .mode = S_IRUGO, },
-       .read = sid_read,
-};
-
-static int sunxi_sid_remove(struct platform_device *pdev)
-{
-       device_remove_bin_file(&pdev->dev, &sid_bin_attr);
-       dev_dbg(&pdev->dev, "driver unloaded\n");
-
-       return 0;
-}
-
-static const struct of_device_id sunxi_sid_of_match[] = {
-       { .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
-       { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
-       {/* sentinel */},
-};
-MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
-
-static int sunxi_sid_probe(struct platform_device *pdev)
-{
-       struct sunxi_sid_data *sid_data;
-       struct resource *res;
-       const struct of_device_id *of_dev_id;
-       u8 *entropy;
-       unsigned int i;
-
-       sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
-                               GFP_KERNEL);
-       if (!sid_data)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(sid_data->reg_base))
-               return PTR_ERR(sid_data->reg_base);
-
-       of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
-       if (!of_dev_id)
-               return -ENODEV;
-       sid_data->keysize = (int)of_dev_id->data;
-
-       platform_set_drvdata(pdev, sid_data);
-
-       sid_bin_attr.size = sid_data->keysize;
-       if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
-               return -ENODEV;
-
-       entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
-       for (i = 0; i < sid_data->keysize; i++)
-               entropy[i] = sunxi_sid_read_byte(sid_data, i);
-       add_device_randomness(entropy, sid_data->keysize);
-       kfree(entropy);
-
-       dev_dbg(&pdev->dev, "loaded\n");
-
-       return 0;
-}
-
-static struct platform_driver sunxi_sid_driver = {
-       .probe = sunxi_sid_probe,
-       .remove = sunxi_sid_remove,
-       .driver = {
-               .name = DRV_NAME,
-               .of_match_table = sunxi_sid_of_match,
-       },
-};
-module_platform_driver(sunxi_sid_driver);
-
-MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
-MODULE_DESCRIPTION("Allwinner sunxi security id driver");
-MODULE_LICENSE("GPL");
index 12c30b486b27c01ab8a741cbb743cbb8dbd58cbc..976df001363355c8f396408ec297433eadffd13a 100644 (file)
@@ -465,7 +465,6 @@ MODULE_DEVICE_TABLE(i2c, isl29003_id);
 static struct i2c_driver isl29003_driver = {
        .driver = {
                .name   = ISL29003_DRV_NAME,
-               .owner  = THIS_MODULE,
                .pm     = ISL29003_PM_OPS,
        },
        .probe  = isl29003_probe,
index e3e7f1dc27ba5df5daf8ad647953c10d92a69caa..0c3bb7e3ee80d45b4a122c4f4ad05fc1b9ff1ad3 100644 (file)
@@ -274,7 +274,6 @@ static const struct dev_pm_ops lis3_pm_ops = {
 static struct i2c_driver lis3lv02d_i2c_driver = {
        .driver  = {
                .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
                .pm     = &lis3_pm_ops,
                .of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
        },
index 518914a82b83755ba05d6bdb214aabcf2c05d563..01447ca21c262db797bce8dd3b2b7eee6f73b1fa 100644 (file)
@@ -11,7 +11,7 @@ mei-objs += main.o
 mei-objs += amthif.o
 mei-objs += wd.o
 mei-objs += bus.o
-mei-objs += nfc.o
+mei-objs += bus-fixup.o
 mei-$(CONFIG_DEBUG_FS) += debugfs.o
 
 obj-$(CONFIG_INTEL_MEI_ME) += mei-me.o
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
new file mode 100644 (file)
index 0000000..3e536ca
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2003-2013, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+
+#include <linux/mei_cl_bus.h>
+
+#include "mei_dev.h"
+#include "client.h"
+
+#define MEI_UUID_NFC_INFO UUID_LE(0xd2de1625, 0x382d, 0x417d, \
+                       0x48, 0xa4, 0xef, 0xab, 0xba, 0x8a, 0x12, 0x06)
+
+static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
+
+#define MEI_UUID_NFC_HCI UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, \
+                       0x94, 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
+
+#define MEI_UUID_ANY NULL_UUID_LE
+
+/**
+ * number_of_connections - determine whether an client be on the bus
+ *    according number of connections
+ *    We support only clients:
+ *       1. with single connection
+ *       2. and fixed clients (max_number_of_connections == 0)
+ *
+ * @cldev: me clients device
+ */
+static void number_of_connections(struct mei_cl_device *cldev)
+{
+       dev_dbg(&cldev->dev, "running hook %s on %pUl\n",
+                       __func__, mei_me_cl_uuid(cldev->me_cl));
+
+       if (cldev->me_cl->props.max_number_of_connections > 1)
+               cldev->do_match = 0;
+}
+
+/**
+ * blacklist - blacklist a client from the bus
+ *
+ * @cldev: me clients device
+ */
+static void blacklist(struct mei_cl_device *cldev)
+{
+       dev_dbg(&cldev->dev, "running hook %s on %pUl\n",
+                       __func__, mei_me_cl_uuid(cldev->me_cl));
+       cldev->do_match = 0;
+}
+
+struct mei_nfc_cmd {
+       u8 command;
+       u8 status;
+       u16 req_id;
+       u32 reserved;
+       u16 data_size;
+       u8 sub_command;
+       u8 data[];
+} __packed;
+
+struct mei_nfc_reply {
+       u8 command;
+       u8 status;
+       u16 req_id;
+       u32 reserved;
+       u16 data_size;
+       u8 sub_command;
+       u8 reply_status;
+       u8 data[];
+} __packed;
+
+struct mei_nfc_if_version {
+       u8 radio_version_sw[3];
+       u8 reserved[3];
+       u8 radio_version_hw[3];
+       u8 i2c_addr;
+       u8 fw_ivn;
+       u8 vendor_id;
+       u8 radio_type;
+} __packed;
+
+
+#define MEI_NFC_CMD_MAINTENANCE 0x00
+#define MEI_NFC_SUBCMD_IF_VERSION 0x01
+
+/* Vendors */
+#define MEI_NFC_VENDOR_INSIDE 0x00
+#define MEI_NFC_VENDOR_NXP    0x01
+
+/* Radio types */
+#define MEI_NFC_VENDOR_INSIDE_UREAD 0x00
+#define MEI_NFC_VENDOR_NXP_PN544    0x01
+
+/**
+ * mei_nfc_if_version - get NFC interface version
+ *
+ * @cl: host client (nfc info)
+ * @ver: NFC interface version to be filled in
+ *
+ * Return: 0 on success; < 0 otherwise
+ */
+static int mei_nfc_if_version(struct mei_cl *cl,
+                             struct mei_nfc_if_version *ver)
+{
+       struct mei_device *bus;
+       struct mei_nfc_cmd cmd = {
+               .command = MEI_NFC_CMD_MAINTENANCE,
+               .data_size = 1,
+               .sub_command = MEI_NFC_SUBCMD_IF_VERSION,
+       };
+       struct mei_nfc_reply *reply = NULL;
+       size_t if_version_length;
+       int bytes_recv, ret;
+
+       bus = cl->dev;
+
+       WARN_ON(mutex_is_locked(&bus->device_lock));
+
+       ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
+       if (ret < 0) {
+               dev_err(bus->dev, "Could not send IF version cmd\n");
+               return ret;
+       }
+
+       /* to be sure on the stack we alloc memory */
+       if_version_length = sizeof(struct mei_nfc_reply) +
+               sizeof(struct mei_nfc_if_version);
+
+       reply = kzalloc(if_version_length, GFP_KERNEL);
+       if (!reply)
+               return -ENOMEM;
+
+       ret = 0;
+       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
+       if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
+               dev_err(bus->dev, "Could not read IF version\n");
+               ret = -EIO;
+               goto err;
+       }
+
+       memcpy(ver, reply->data, sizeof(struct mei_nfc_if_version));
+
+       dev_info(bus->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
+               ver->fw_ivn, ver->vendor_id, ver->radio_type);
+
+err:
+       kfree(reply);
+       return ret;
+}
+
+/**
+ * mei_nfc_radio_name - derive nfc radio name from the interface version
+ *
+ * @ver: NFC radio version
+ *
+ * Return: radio name string
+ */
+static const char *mei_nfc_radio_name(struct mei_nfc_if_version *ver)
+{
+
+       if (ver->vendor_id == MEI_NFC_VENDOR_INSIDE) {
+               if (ver->radio_type == MEI_NFC_VENDOR_INSIDE_UREAD)
+                       return "microread";
+       }
+
+       if (ver->vendor_id == MEI_NFC_VENDOR_NXP) {
+               if (ver->radio_type == MEI_NFC_VENDOR_NXP_PN544)
+                       return "pn544";
+       }
+
+       return NULL;
+}
+
+/**
+ * mei_nfc - The nfc fixup function. The function retrieves nfc radio
+ *    name and set is as device attribute so we can load
+ *    the proper device driver for it
+ *
+ * @cldev: me client device (nfc)
+ */
+static void mei_nfc(struct mei_cl_device *cldev)
+{
+       struct mei_device *bus;
+       struct mei_cl *cl;
+       struct mei_me_client *me_cl = NULL;
+       struct mei_nfc_if_version ver;
+       const char *radio_name = NULL;
+       int ret;
+
+       bus = cldev->bus;
+
+       dev_dbg(bus->dev, "running hook %s: %pUl match=%d\n",
+               __func__, mei_me_cl_uuid(cldev->me_cl), cldev->do_match);
+
+       mutex_lock(&bus->device_lock);
+       /* we need to connect to INFO GUID */
+       cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
+       if (IS_ERR(cl)) {
+               ret = PTR_ERR(cl);
+               cl = NULL;
+               dev_err(bus->dev, "nfc hook alloc failed %d\n", ret);
+               goto out;
+       }
+
+       me_cl = mei_me_cl_by_uuid(bus, &mei_nfc_info_guid);
+       if (!me_cl) {
+               ret = -ENOTTY;
+               dev_err(bus->dev, "Cannot find nfc info %d\n", ret);
+               goto out;
+       }
+
+       ret = mei_cl_connect(cl, me_cl, NULL);
+       if (ret < 0) {
+               dev_err(&cldev->dev, "Can't connect to the NFC INFO ME ret = %d\n",
+                       ret);
+               goto out;
+       }
+
+       mutex_unlock(&bus->device_lock);
+
+       ret = mei_nfc_if_version(cl, &ver);
+       if (ret)
+               goto disconnect;
+
+       radio_name = mei_nfc_radio_name(&ver);
+
+       if (!radio_name) {
+               ret = -ENOENT;
+               dev_err(&cldev->dev, "Can't get the NFC interface version ret = %d\n",
+                       ret);
+               goto disconnect;
+       }
+
+       dev_dbg(bus->dev, "nfc radio %s\n", radio_name);
+       strlcpy(cldev->name, radio_name, sizeof(cldev->name));
+
+disconnect:
+       mutex_lock(&bus->device_lock);
+       if (mei_cl_disconnect(cl) < 0)
+               dev_err(bus->dev, "Can't disconnect the NFC INFO ME\n");
+
+       mei_cl_flush_queues(cl, NULL);
+
+out:
+       mei_cl_unlink(cl);
+       mutex_unlock(&bus->device_lock);
+       mei_me_cl_put(me_cl);
+       kfree(cl);
+
+       if (ret)
+               cldev->do_match = 0;
+
+       dev_dbg(bus->dev, "end of fixup match = %d\n", cldev->do_match);
+}
+
+#define MEI_FIXUP(_uuid, _hook) { _uuid, _hook }
+
+static struct mei_fixup {
+
+       const uuid_le uuid;
+       void (*hook)(struct mei_cl_device *cldev);
+} mei_fixups[] = {
+       MEI_FIXUP(MEI_UUID_ANY, number_of_connections),
+       MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist),
+       MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc),
+};
+
+/**
+ * mei_cl_dev_fixup - run fixup handlers
+ *
+ * @cldev: me client device
+ */
+void mei_cl_dev_fixup(struct mei_cl_device *cldev)
+{
+       struct mei_fixup *f;
+       const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mei_fixups); i++) {
+
+               f = &mei_fixups[i];
+               if (uuid_le_cmp(f->uuid, MEI_UUID_ANY) == 0 ||
+                   uuid_le_cmp(f->uuid, *uuid) == 0)
+                       f->hook(cldev);
+       }
+}
+
index 458aa5a09c522816febc6abef20d034a67cfea5d..eef1c6b46ad819eca61ef1cf651cabe7aeff6a63 100644 (file)
 #define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
 #define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
 
-static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       struct mei_cl_driver *driver = to_mei_cl_driver(drv);
-       const struct mei_cl_device_id *id;
-       const uuid_le *uuid;
-       const char *name;
-
-       if (!device)
-               return 0;
-
-       uuid = mei_me_cl_uuid(device->me_cl);
-       name = device->name;
-
-       if (!driver || !driver->id_table)
-               return 0;
-
-       id = driver->id_table;
-
-       while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
-
-               if (!uuid_le_cmp(*uuid, id->uuid)) {
-                       if (id->name[0]) {
-                               if (!strncmp(name, id->name, sizeof(id->name)))
-                                       return 1;
-                       } else {
-                               return 1;
-                       }
-               }
-
-               id++;
-       }
-
-       return 0;
-}
-
-static int mei_cl_device_probe(struct device *dev)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       struct mei_cl_driver *driver;
-       struct mei_cl_device_id id;
-
-       if (!device)
-               return 0;
-
-       driver = to_mei_cl_driver(dev->driver);
-       if (!driver || !driver->probe)
-               return -ENODEV;
-
-       dev_dbg(dev, "Device probe\n");
-
-       strlcpy(id.name, device->name, sizeof(id.name));
-
-       return driver->probe(device, &id);
-}
-
-static int mei_cl_device_remove(struct device *dev)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       struct mei_cl_driver *driver;
-
-       if (!device || !dev->driver)
-               return 0;
-
-       if (device->event_cb) {
-               device->event_cb = NULL;
-               cancel_work_sync(&device->event_work);
-       }
-
-       driver = to_mei_cl_driver(dev->driver);
-       if (!driver->remove) {
-               dev->driver = NULL;
-
-               return 0;
-       }
-
-       return driver->remove(device);
-}
-
-static ssize_t name_show(struct device *dev, struct device_attribute *a,
-                            char *buf)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       size_t len;
-
-       len = snprintf(buf, PAGE_SIZE, "%s", device->name);
-
-       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
-}
-static DEVICE_ATTR_RO(name);
-
-static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
-                            char *buf)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
-       size_t len;
-
-       len = snprintf(buf, PAGE_SIZE, "%pUl", uuid);
-
-       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
-}
-static DEVICE_ATTR_RO(uuid);
-
-static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
-                            char *buf)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
-       size_t len;
-
-       len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
-               device->name, MEI_CL_UUID_ARGS(uuid->b));
-
-       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *mei_cl_dev_attrs[] = {
-       &dev_attr_name.attr,
-       &dev_attr_uuid.attr,
-       &dev_attr_modalias.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(mei_cl_dev);
-
-static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-       const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
-
-       if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
-               return -ENOMEM;
-
-       if (add_uevent_var(env, "MEI_CL_NAME=%s", device->name))
-               return -ENOMEM;
-
-       if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
-               device->name, MEI_CL_UUID_ARGS(uuid->b)))
-               return -ENOMEM;
-
-       return 0;
-}
-
-static struct bus_type mei_cl_bus_type = {
-       .name           = "mei",
-       .dev_groups     = mei_cl_dev_groups,
-       .match          = mei_cl_device_match,
-       .probe          = mei_cl_device_probe,
-       .remove         = mei_cl_device_remove,
-       .uevent         = mei_cl_uevent,
-};
-
-static void mei_cl_dev_release(struct device *dev)
-{
-       struct mei_cl_device *device = to_mei_cl_device(dev);
-
-       if (!device)
-               return;
-
-       mei_me_cl_put(device->me_cl);
-       kfree(device);
-}
-
-static struct device_type mei_cl_device_type = {
-       .release        = mei_cl_dev_release,
-};
-
-struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
-                                        uuid_le uuid)
-{
-       struct mei_cl *cl;
-
-       list_for_each_entry(cl, &dev->device_list, device_link) {
-               if (cl->device && cl->device->me_cl &&
-                   !uuid_le_cmp(uuid, *mei_me_cl_uuid(cl->device->me_cl)))
-                       return cl;
-       }
-
-       return NULL;
-}
-
-struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
-                                       struct mei_me_client *me_cl,
-                                       struct mei_cl *cl,
-                                       char *name)
-{
-       struct mei_cl_device *device;
-       int status;
-
-       device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
-       if (!device)
-               return NULL;
-
-       device->me_cl = mei_me_cl_get(me_cl);
-       if (!device->me_cl) {
-               kfree(device);
-               return NULL;
-       }
-
-       device->cl = cl;
-       device->dev.parent = dev->dev;
-       device->dev.bus = &mei_cl_bus_type;
-       device->dev.type = &mei_cl_device_type;
-
-       strlcpy(device->name, name, sizeof(device->name));
-
-       dev_set_name(&device->dev, "mei:%s:%pUl", name, mei_me_cl_uuid(me_cl));
-
-       status = device_register(&device->dev);
-       if (status) {
-               dev_err(dev->dev, "Failed to register MEI device\n");
-               mei_me_cl_put(device->me_cl);
-               kfree(device);
-               return NULL;
-       }
-
-       cl->device = device;
-
-       dev_dbg(&device->dev, "client %s registered\n", name);
-
-       return device;
-}
-EXPORT_SYMBOL_GPL(mei_cl_add_device);
-
-void mei_cl_remove_device(struct mei_cl_device *device)
-{
-       device_unregister(&device->dev);
-}
-EXPORT_SYMBOL_GPL(mei_cl_remove_device);
-
-int __mei_cl_driver_register(struct mei_cl_driver *driver, struct module *owner)
-{
-       int err;
-
-       driver->driver.name = driver->name;
-       driver->driver.owner = owner;
-       driver->driver.bus = &mei_cl_bus_type;
-
-       err = driver_register(&driver->driver);
-       if (err)
-               return err;
-
-       pr_debug("mei: driver [%s] registered\n", driver->driver.name);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
-
-void mei_cl_driver_unregister(struct mei_cl_driver *driver)
-{
-       driver_unregister(&driver->driver);
-
-       pr_debug("mei: driver [%s] unregistered\n", driver->driver.name);
-}
-EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
-
+/**
+ * __mei_cl_send - internal client send (write)
+ *
+ * @cl: host client
+ * @buf: buffer to send
+ * @length: buffer length
+ * @blocking: wait for write completion
+ *
+ * Return: written size bytes or < 0 on error
+ */
 ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
                        bool blocking)
 {
-       struct mei_device *dev;
+       struct mei_device *bus;
        struct mei_cl_cb *cb = NULL;
        ssize_t rets;
 
        if (WARN_ON(!cl || !cl->dev))
                return -ENODEV;
 
-       dev = cl->dev;
+       bus = cl->dev;
 
-       mutex_lock(&dev->device_lock);
+       mutex_lock(&bus->device_lock);
        if (!mei_cl_is_connected(cl)) {
                rets = -ENODEV;
                goto out;
@@ -327,16 +80,25 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
        rets = mei_cl_write(cl, cb, blocking);
 
 out:
-       mutex_unlock(&dev->device_lock);
+       mutex_unlock(&bus->device_lock);
        if (rets < 0)
                mei_io_cb_free(cb);
 
        return rets;
 }
 
+/**
+ * __mei_cl_recv - internal client receive (read)
+ *
+ * @cl: host client
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ */
 ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 {
-       struct mei_device *dev;
+       struct mei_device *bus;
        struct mei_cl_cb *cb;
        size_t r_length;
        ssize_t rets;
@@ -344,9 +106,9 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
        if (WARN_ON(!cl || !cl->dev))
                return -ENODEV;
 
-       dev = cl->dev;
+       bus = cl->dev;
 
-       mutex_lock(&dev->device_lock);
+       mutex_lock(&bus->device_lock);
 
        cb = mei_cl_read_cb(cl, NULL);
        if (cb)
@@ -356,9 +118,10 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
        if (rets && rets != -EBUSY)
                goto out;
 
+       /* wait on event only if there is no other waiter */
        if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
 
-               mutex_unlock(&dev->device_lock);
+               mutex_unlock(&bus->device_lock);
 
                if (wait_event_interruptible(cl->rx_wait,
                                (!list_empty(&cl->rd_completed)) ||
@@ -369,7 +132,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
                        return -ERESTARTSYS;
                }
 
-               mutex_lock(&dev->device_lock);
+               mutex_lock(&bus->device_lock);
 
                if (!mei_cl_is_connected(cl)) {
                        rets = -EBUSY;
@@ -396,14 +159,23 @@ copy:
 free:
        mei_io_cb_free(cb);
 out:
-       mutex_unlock(&dev->device_lock);
+       mutex_unlock(&bus->device_lock);
 
        return rets;
 }
 
-ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
+/**
+ * mei_cl_send - me device send  (write)
+ *
+ * @cldev: me client device
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return: written size in bytes or < 0 on error
+ */
+ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
 {
-       struct mei_cl *cl = device->cl;
+       struct mei_cl *cl = cldev->cl;
 
        if (cl == NULL)
                return -ENODEV;
@@ -412,9 +184,18 @@ ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
 }
 EXPORT_SYMBOL_GPL(mei_cl_send);
 
-ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
+/**
+ * mei_cl_recv - client receive (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ */
+ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
 {
-       struct mei_cl *cl = device->cl;
+       struct mei_cl *cl = cldev->cl;
 
        if (cl == NULL)
                return -ENODEV;
@@ -423,134 +204,697 @@ ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
 }
 EXPORT_SYMBOL_GPL(mei_cl_recv);
 
+/**
+ * mei_bus_event_work  - dispatch rx event for a bus device
+ *    and schedule new work
+ *
+ * @work: work
+ */
 static void mei_bus_event_work(struct work_struct *work)
 {
-       struct mei_cl_device *device;
+       struct mei_cl_device *cldev;
 
-       device = container_of(work, struct mei_cl_device, event_work);
+       cldev = container_of(work, struct mei_cl_device, event_work);
 
-       if (device->event_cb)
-               device->event_cb(device, device->events, device->event_context);
+       if (cldev->event_cb)
+               cldev->event_cb(cldev, cldev->events, cldev->event_context);
 
-       device->events = 0;
+       cldev->events = 0;
 
        /* Prepare for the next read */
-       mei_cl_read_start(device->cl, 0, NULL);
+       if (cldev->events_mask & BIT(MEI_CL_EVENT_RX))
+               mei_cl_read_start(cldev->cl, 0, NULL);
 }
 
-int mei_cl_register_event_cb(struct mei_cl_device *device,
+/**
+ * mei_cl_bus_notify_event - schedule notify cb on bus client
+ *
+ * @cl: host client
+ */
+void mei_cl_bus_notify_event(struct mei_cl *cl)
+{
+       struct mei_cl_device *cldev = cl->cldev;
+
+       if (!cldev || !cldev->event_cb)
+               return;
+
+       if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)))
+               return;
+
+       if (!cl->notify_ev)
+               return;
+
+       set_bit(MEI_CL_EVENT_NOTIF, &cldev->events);
+
+       schedule_work(&cldev->event_work);
+
+       cl->notify_ev = false;
+}
+
+/**
+ * mei_cl_bus_rx_event  - schedule rx evenet
+ *
+ * @cl: host client
+ */
+void mei_cl_bus_rx_event(struct mei_cl *cl)
+{
+       struct mei_cl_device *cldev = cl->cldev;
+
+       if (!cldev || !cldev->event_cb)
+               return;
+
+       if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX)))
+               return;
+
+       set_bit(MEI_CL_EVENT_RX, &cldev->events);
+
+       schedule_work(&cldev->event_work);
+}
+
+/**
+ * mei_cl_register_event_cb - register event callback
+ *
+ * @cldev: me client devices
+ * @event_cb: callback function
+ * @events_mask: requested events bitmask
+ * @context: driver context data
+ *
+ * Return: 0 on success
+ *         -EALREADY if an callback is already registered
+ *         <0 on other errors
+ */
+int mei_cl_register_event_cb(struct mei_cl_device *cldev,
+                         unsigned long events_mask,
                          mei_cl_event_cb_t event_cb, void *context)
 {
-       if (device->event_cb)
+       int ret;
+
+       if (cldev->event_cb)
                return -EALREADY;
 
-       device->events = 0;
-       device->event_cb = event_cb;
-       device->event_context = context;
-       INIT_WORK(&device->event_work, mei_bus_event_work);
+       cldev->events = 0;
+       cldev->events_mask = events_mask;
+       cldev->event_cb = event_cb;
+       cldev->event_context = context;
+       INIT_WORK(&cldev->event_work, mei_bus_event_work);
 
-       mei_cl_read_start(device->cl, 0, NULL);
+       if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
+               ret = mei_cl_read_start(cldev->cl, 0, NULL);
+               if (ret && ret != -EBUSY)
+                       return ret;
+       }
+
+       if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
+               mutex_lock(&cldev->cl->dev->device_lock);
+               ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
+               mutex_unlock(&cldev->cl->dev->device_lock);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
 
-void *mei_cl_get_drvdata(const struct mei_cl_device *device)
+/**
+ * mei_cl_get_drvdata - driver data getter
+ *
+ * @cldev: mei client device
+ *
+ * Return: driver private data
+ */
+void *mei_cl_get_drvdata(const struct mei_cl_device *cldev)
 {
-       return dev_get_drvdata(&device->dev);
+       return dev_get_drvdata(&cldev->dev);
 }
 EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
 
-void mei_cl_set_drvdata(struct mei_cl_device *device, void *data)
+/**
+ * mei_cl_set_drvdata - driver data setter
+ *
+ * @cldev: mei client device
+ * @data: data to store
+ */
+void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data)
 {
-       dev_set_drvdata(&device->dev, data);
+       dev_set_drvdata(&cldev->dev, data);
 }
 EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
 
-int mei_cl_enable_device(struct mei_cl_device *device)
+/**
+ * mei_cl_enable_device - enable me client device
+ *     create connection with me client
+ *
+ * @cldev: me client device
+ *
+ * Return: 0 on success and < 0 on error
+ */
+int mei_cl_enable_device(struct mei_cl_device *cldev)
 {
-       int err;
-       struct mei_device *dev;
-       struct mei_cl *cl = device->cl;
-
-       if (cl == NULL)
-               return -ENODEV;
-
-       dev = cl->dev;
-
-       mutex_lock(&dev->device_lock);
+       struct mei_device *bus = cldev->bus;
+       struct mei_cl *cl;
+       int ret;
+
+       cl = cldev->cl;
+
+       if (!cl) {
+               mutex_lock(&bus->device_lock);
+               cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
+               mutex_unlock(&bus->device_lock);
+               if (IS_ERR(cl))
+                       return PTR_ERR(cl);
+               /* update pointers */
+               cldev->cl = cl;
+               cl->cldev = cldev;
+       }
 
+       mutex_lock(&bus->device_lock);
        if (mei_cl_is_connected(cl)) {
-               mutex_unlock(&dev->device_lock);
-               dev_warn(dev->dev, "Already connected");
-               return -EBUSY;
+               ret = 0;
+               goto out;
        }
 
-       err = mei_cl_connect(cl, device->me_cl, NULL);
-       if (err < 0) {
-               mutex_unlock(&dev->device_lock);
-               dev_err(dev->dev, "Could not connect to the ME client");
-
-               return err;
+       if (!mei_me_cl_is_active(cldev->me_cl)) {
+               dev_err(&cldev->dev, "me client is not active\n");
+               ret = -ENOTTY;
+               goto out;
        }
 
-       mutex_unlock(&dev->device_lock);
+       ret = mei_cl_connect(cl, cldev->me_cl, NULL);
+       if (ret < 0)
+               dev_err(&cldev->dev, "cannot connect\n");
 
-       if (device->event_cb)
-               mei_cl_read_start(device->cl, 0, NULL);
+out:
+       mutex_unlock(&bus->device_lock);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mei_cl_enable_device);
 
-int mei_cl_disable_device(struct mei_cl_device *device)
+/**
+ * mei_cl_disable_device - disable me client device
+ *     disconnect form the me client
+ *
+ * @cldev: me client device
+ *
+ * Return: 0 on success and < 0 on error
+ */
+int mei_cl_disable_device(struct mei_cl_device *cldev)
 {
+       struct mei_device *bus;
+       struct mei_cl *cl;
        int err;
-       struct mei_device *dev;
-       struct mei_cl *cl = device->cl;
 
-       if (cl == NULL)
+       if (!cldev || !cldev->cl)
                return -ENODEV;
 
-       dev = cl->dev;
+       cl = cldev->cl;
 
-       device->event_cb = NULL;
+       bus = cldev->bus;
 
-       mutex_lock(&dev->device_lock);
+       cldev->event_cb = NULL;
+
+       mutex_lock(&bus->device_lock);
 
        if (!mei_cl_is_connected(cl)) {
-               dev_err(dev->dev, "Already disconnected");
+               dev_err(bus->dev, "Already disconnected");
                err = 0;
                goto out;
        }
 
        err = mei_cl_disconnect(cl);
-       if (err < 0) {
-               dev_err(dev->dev, "Could not disconnect from the ME client");
-               goto out;
-       }
+       if (err < 0)
+               dev_err(bus->dev, "Could not disconnect from the ME client");
 
+out:
        /* Flush queues and remove any pending read */
        mei_cl_flush_queues(cl, NULL);
+       mei_cl_unlink(cl);
 
-out:
-       mutex_unlock(&dev->device_lock);
-       return err;
+       kfree(cl);
+       cldev->cl = NULL;
 
+       mutex_unlock(&bus->device_lock);
+       return err;
 }
 EXPORT_SYMBOL_GPL(mei_cl_disable_device);
 
-void mei_cl_bus_rx_event(struct mei_cl *cl)
+/**
+ * mei_cl_device_find - find matching entry in the driver id table
+ *
+ * @cldev: me client device
+ * @cldrv: me client driver
+ *
+ * Return: id on success; NULL if no id is matching
+ */
+static const
+struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
+                                           struct mei_cl_driver *cldrv)
 {
-       struct mei_cl_device *device = cl->device;
+       const struct mei_cl_device_id *id;
+       const uuid_le *uuid;
+
+       uuid = mei_me_cl_uuid(cldev->me_cl);
+
+       id = cldrv->id_table;
+       while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
+               if (!uuid_le_cmp(*uuid, id->uuid)) {
+
+                       if (!cldev->name[0])
+                               return id;
+
+                       if (!strncmp(cldev->name, id->name, sizeof(id->name)))
+                               return id;
+               }
+
+               id++;
+       }
+
+       return NULL;
+}
+
+/**
+ * mei_cl_device_match  - device match function
+ *
+ * @dev: device
+ * @drv: driver
+ *
+ * Return:  1 if matching device was found 0 otherwise
+ */
+static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+       struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
+       const struct mei_cl_device_id *found_id;
+
+       if (!cldev)
+               return 0;
+
+       if (!cldev->do_match)
+               return 0;
+
+       if (!cldrv || !cldrv->id_table)
+               return 0;
+
+       found_id = mei_cl_device_find(cldev, cldrv);
+       if (found_id)
+               return 1;
+
+       return 0;
+}
+
+/**
+ * mei_cl_device_probe - bus probe function
+ *
+ * @dev: device
+ *
+ * Return:  0 on success; < 0 otherwise
+ */
+static int mei_cl_device_probe(struct device *dev)
+{
+       struct mei_cl_device *cldev;
+       struct mei_cl_driver *cldrv;
+       const struct mei_cl_device_id *id;
+
+       cldev = to_mei_cl_device(dev);
+       cldrv = to_mei_cl_driver(dev->driver);
+
+       if (!cldev)
+               return 0;
+
+       if (!cldrv || !cldrv->probe)
+               return -ENODEV;
+
+       id = mei_cl_device_find(cldev, cldrv);
+       if (!id)
+               return -ENODEV;
+
+       __module_get(THIS_MODULE);
+
+       return cldrv->probe(cldev, id);
+}
+
+/**
+ * mei_cl_device_remove - remove device from the bus
+ *
+ * @dev: device
+ *
+ * Return:  0 on success; < 0 otherwise
+ */
+static int mei_cl_device_remove(struct device *dev)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+       struct mei_cl_driver *cldrv;
+       int ret = 0;
+
+       if (!cldev || !dev->driver)
+               return 0;
+
+       if (cldev->event_cb) {
+               cldev->event_cb = NULL;
+               cancel_work_sync(&cldev->event_work);
+       }
+
+       cldrv = to_mei_cl_driver(dev->driver);
+       if (cldrv->remove)
+               ret = cldrv->remove(cldev);
+
+       module_put(THIS_MODULE);
+       dev->driver = NULL;
+       return ret;
+
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *a,
+                            char *buf)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+       size_t len;
+
+       len = snprintf(buf, PAGE_SIZE, "%s", cldev->name);
+
+       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(name);
+
+static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
+                            char *buf)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+       const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+       size_t len;
+
+       len = snprintf(buf, PAGE_SIZE, "%pUl", uuid);
+
+       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(uuid);
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
+                            char *buf)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+       const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+       size_t len;
+
+       len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
+               cldev->name, MEI_CL_UUID_ARGS(uuid->b));
+
+       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *mei_cl_dev_attrs[] = {
+       &dev_attr_name.attr,
+       &dev_attr_uuid.attr,
+       &dev_attr_modalias.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(mei_cl_dev);
+
+/**
+ * mei_cl_device_uevent - me client bus uevent handler
+ *
+ * @dev: device
+ * @env: uevent kobject
+ *
+ * Return: 0 on success -ENOMEM on when add_uevent_var fails
+ */
+static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+       const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+
+       if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
+               cldev->name, MEI_CL_UUID_ARGS(uuid->b)))
+               return -ENOMEM;
 
-       if (!device || !device->event_cb)
+       return 0;
+}
+
+static struct bus_type mei_cl_bus_type = {
+       .name           = "mei",
+       .dev_groups     = mei_cl_dev_groups,
+       .match          = mei_cl_device_match,
+       .probe          = mei_cl_device_probe,
+       .remove         = mei_cl_device_remove,
+       .uevent         = mei_cl_device_uevent,
+};
+
+static struct mei_device *mei_dev_bus_get(struct mei_device *bus)
+{
+       if (bus)
+               get_device(bus->dev);
+
+       return bus;
+}
+
+static void mei_dev_bus_put(struct mei_device *bus)
+{
+       if (bus)
+               put_device(bus->dev);
+}
+
+static void mei_cl_dev_release(struct device *dev)
+{
+       struct mei_cl_device *cldev = to_mei_cl_device(dev);
+
+       if (!cldev)
+               return;
+
+       mei_me_cl_put(cldev->me_cl);
+       mei_dev_bus_put(cldev->bus);
+       kfree(cldev);
+}
+
+static struct device_type mei_cl_device_type = {
+       .release        = mei_cl_dev_release,
+};
+
+/**
+ * mei_cl_dev_alloc - initialize and allocate mei client device
+ *
+ * @bus: mei device
+ * @me_cl: me client
+ *
+ * Return: allocated device structur or NULL on allocation failure
+ */
+static struct mei_cl_device *mei_cl_dev_alloc(struct mei_device *bus,
+                                             struct mei_me_client *me_cl)
+{
+       struct mei_cl_device *cldev;
+
+       cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
+       if (!cldev)
+               return NULL;
+
+       device_initialize(&cldev->dev);
+       cldev->dev.parent = bus->dev;
+       cldev->dev.bus    = &mei_cl_bus_type;
+       cldev->dev.type   = &mei_cl_device_type;
+       cldev->bus        = mei_dev_bus_get(bus);
+       cldev->me_cl      = mei_me_cl_get(me_cl);
+       cldev->is_added   = 0;
+       INIT_LIST_HEAD(&cldev->bus_list);
+
+       return cldev;
+}
+
+/**
+ * mei_cl_dev_setup - setup me client device
+ *    run fix up routines and set the device name
+ *
+ * @bus: mei device
+ * @cldev: me client device
+ *
+ * Return: true if the device is eligible for enumeration
+ */
+static bool mei_cl_dev_setup(struct mei_device *bus,
+                            struct mei_cl_device *cldev)
+{
+       cldev->do_match = 1;
+       mei_cl_dev_fixup(cldev);
+
+       if (cldev->do_match)
+               dev_set_name(&cldev->dev, "mei:%s:%pUl",
+                            cldev->name, mei_me_cl_uuid(cldev->me_cl));
+
+       return cldev->do_match == 1;
+}
+
+/**
+ * mei_cl_bus_dev_add - add me client devices
+ *
+ * @cldev: me client device
+ *
+ * Return: 0 on success; < 0 on failre
+ */
+static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
+{
+       int ret;
+
+       dev_dbg(cldev->bus->dev, "adding %pUL\n", mei_me_cl_uuid(cldev->me_cl));
+       ret = device_add(&cldev->dev);
+       if (!ret)
+               cldev->is_added = 1;
+
+       return ret;
+}
+
+/**
+ * mei_cl_bus_dev_stop - stop the driver
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_dev_stop(struct mei_cl_device *cldev)
+{
+       if (cldev->is_added)
+               device_release_driver(&cldev->dev);
+}
+
+/**
+ * mei_cl_bus_dev_destroy - destroy me client devices object
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
+{
+       if (!cldev->is_added)
+               return;
+
+       device_del(&cldev->dev);
+
+       mutex_lock(&cldev->bus->cl_bus_lock);
+       list_del_init(&cldev->bus_list);
+       mutex_unlock(&cldev->bus->cl_bus_lock);
+
+       cldev->is_added = 0;
+       put_device(&cldev->dev);
+}
+
+/**
+ * mei_cl_bus_remove_device - remove a devices form the bus
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_remove_device(struct mei_cl_device *cldev)
+{
+       mei_cl_bus_dev_stop(cldev);
+       mei_cl_bus_dev_destroy(cldev);
+}
+
+/**
+ * mei_cl_bus_remove_devices - remove all devices form the bus
+ *
+ * @bus: mei device
+ */
+void mei_cl_bus_remove_devices(struct mei_device *bus)
+{
+       struct mei_cl_device *cldev, *next;
+
+       list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
+               mei_cl_bus_remove_device(cldev);
+}
+
+
+/**
+ * mei_cl_dev_init - allocate and initializes an mei client devices
+ *     based on me client
+ *
+ * @bus: mei device
+ * @me_cl: me client
+ */
+static void mei_cl_dev_init(struct mei_device *bus, struct mei_me_client *me_cl)
+{
+       struct mei_cl_device *cldev;
+
+       dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));
+
+       if (me_cl->bus_added)
                return;
 
-       set_bit(MEI_CL_EVENT_RX, &device->events);
+       cldev = mei_cl_dev_alloc(bus, me_cl);
+       if (!cldev)
+               return;
+
+       mutex_lock(&cldev->bus->cl_bus_lock);
+       me_cl->bus_added = true;
+       list_add_tail(&cldev->bus_list, &bus->device_list);
+       mutex_unlock(&cldev->bus->cl_bus_lock);
+
+}
+
+/**
+ * mei_cl_bus_rescan - scan me clients list and add create
+ *    devices for eligible clients
+ *
+ * @bus: mei device
+ */
+void mei_cl_bus_rescan(struct mei_device *bus)
+{
+       struct mei_cl_device *cldev, *n;
+       struct mei_me_client *me_cl;
+
+       down_read(&bus->me_clients_rwsem);
+       list_for_each_entry(me_cl, &bus->me_clients, list)
+               mei_cl_dev_init(bus, me_cl);
+       up_read(&bus->me_clients_rwsem);
+
+       mutex_lock(&bus->cl_bus_lock);
+       list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
+
+               if (!mei_me_cl_is_active(cldev->me_cl)) {
+                       mei_cl_bus_remove_device(cldev);
+                       continue;
+               }
+
+               if (cldev->is_added)
+                       continue;
+
+               if (mei_cl_dev_setup(bus, cldev))
+                       mei_cl_bus_dev_add(cldev);
+               else {
+                       list_del_init(&cldev->bus_list);
+                       put_device(&cldev->dev);
+               }
+       }
+       mutex_unlock(&bus->cl_bus_lock);
+
+       dev_dbg(bus->dev, "rescan end");
+}
+
+int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner)
+{
+       int err;
+
+       cldrv->driver.name = cldrv->name;
+       cldrv->driver.owner = owner;
+       cldrv->driver.bus = &mei_cl_bus_type;
+
+       err = driver_register(&cldrv->driver);
+       if (err)
+               return err;
 
-       schedule_work(&device->event_work);
+       pr_debug("mei: driver [%s] registered\n", cldrv->driver.name);
+
+       return 0;
 }
+EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
+
+void mei_cl_driver_unregister(struct mei_cl_driver *cldrv)
+{
+       driver_unregister(&cldrv->driver);
+
+       pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
+}
+EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
+
 
 int __init mei_cl_bus_init(void)
 {
index 6decbe136ea7d834b2c91a96578896933cdcf187..a6c87c713193808365071a8e0ad34fd17cea0eab 100644 (file)
@@ -555,10 +555,10 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
        init_waitqueue_head(&cl->wait);
        init_waitqueue_head(&cl->rx_wait);
        init_waitqueue_head(&cl->tx_wait);
+       init_waitqueue_head(&cl->ev_wait);
        INIT_LIST_HEAD(&cl->rd_completed);
        INIT_LIST_HEAD(&cl->rd_pending);
        INIT_LIST_HEAD(&cl->link);
-       INIT_LIST_HEAD(&cl->device_link);
        cl->writing_state = MEI_IDLE;
        cl->state = MEI_FILE_INITIALIZING;
        cl->dev = dev;
@@ -690,16 +690,12 @@ void mei_host_client_init(struct work_struct *work)
                mei_wd_host_init(dev, me_cl);
        mei_me_cl_put(me_cl);
 
-       me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
-       if (me_cl)
-               mei_nfc_host_init(dev, me_cl);
-       mei_me_cl_put(me_cl);
-
-
        dev->dev_state = MEI_DEV_ENABLED;
        dev->reset_count = 0;
        mutex_unlock(&dev->device_lock);
 
+       mei_cl_bus_rescan(dev);
+
        pm_runtime_mark_last_busy(dev->dev);
        dev_dbg(dev->dev, "rpm: autosuspend\n");
        pm_runtime_autosuspend(dev->dev);
@@ -841,45 +837,22 @@ int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
        return ret;
 }
 
-
-
 /**
- * mei_cl_disconnect - disconnect host client from the me one
+ * __mei_cl_disconnect - disconnect host client from the me one
+ *     internal function runtime pm has to be already acquired
  *
  * @cl: host client
  *
- * Locking: called under "dev->device_lock" lock
- *
  * Return: 0 on success, <0 on failure.
  */
-int mei_cl_disconnect(struct mei_cl *cl)
+static int __mei_cl_disconnect(struct mei_cl *cl)
 {
        struct mei_device *dev;
        struct mei_cl_cb *cb;
        int rets;
 
-       if (WARN_ON(!cl || !cl->dev))
-               return -ENODEV;
-
        dev = cl->dev;
 
-       cl_dbg(dev, cl, "disconnecting");
-
-       if (!mei_cl_is_connected(cl))
-               return 0;
-
-       if (mei_cl_is_fixed_address(cl)) {
-               mei_cl_set_disconnected(cl);
-               return 0;
-       }
-
-       rets = pm_runtime_get(dev->dev);
-       if (rets < 0 && rets != -EINPROGRESS) {
-               pm_runtime_put_noidle(dev->dev);
-               cl_err(dev, cl, "rpm: get failed %d\n", rets);
-               return rets;
-       }
-
        cl->state = MEI_FILE_DISCONNECTING;
 
        cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT, NULL);
@@ -915,11 +888,52 @@ out:
        if (!rets)
                cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
 
+       mei_io_cb_free(cb);
+       return rets;
+}
+
+/**
+ * mei_cl_disconnect - disconnect host client from the me one
+ *
+ * @cl: host client
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: 0 on success, <0 on failure.
+ */
+int mei_cl_disconnect(struct mei_cl *cl)
+{
+       struct mei_device *dev;
+       int rets;
+
+       if (WARN_ON(!cl || !cl->dev))
+               return -ENODEV;
+
+       dev = cl->dev;
+
+       cl_dbg(dev, cl, "disconnecting");
+
+       if (!mei_cl_is_connected(cl))
+               return 0;
+
+       if (mei_cl_is_fixed_address(cl)) {
+               mei_cl_set_disconnected(cl);
+               return 0;
+       }
+
+       rets = pm_runtime_get(dev->dev);
+       if (rets < 0 && rets != -EINPROGRESS) {
+               pm_runtime_put_noidle(dev->dev);
+               cl_err(dev, cl, "rpm: get failed %d\n", rets);
+               return rets;
+       }
+
+       rets = __mei_cl_disconnect(cl);
+
        cl_dbg(dev, cl, "rpm: autosuspend\n");
        pm_runtime_mark_last_busy(dev->dev);
        pm_runtime_put_autosuspend(dev->dev);
 
-       mei_io_cb_free(cb);
        return rets;
 }
 
@@ -1064,11 +1078,23 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
        mutex_unlock(&dev->device_lock);
        wait_event_timeout(cl->wait,
                        (cl->state == MEI_FILE_CONNECTED ||
+                        cl->state == MEI_FILE_DISCONNECT_REQUIRED ||
                         cl->state == MEI_FILE_DISCONNECT_REPLY),
                        mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
        mutex_lock(&dev->device_lock);
 
        if (!mei_cl_is_connected(cl)) {
+               if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) {
+                       mei_io_list_flush(&dev->ctrl_rd_list, cl);
+                       mei_io_list_flush(&dev->ctrl_wr_list, cl);
+                        /* ignore disconnect return valuue;
+                         * in case of failure reset will be invoked
+                         */
+                       __mei_cl_disconnect(cl);
+                       rets = -EFAULT;
+                       goto out;
+               }
+
                /* timeout or something went really wrong */
                if (!cl->status)
                        cl->status = -EFAULT;
@@ -1180,6 +1206,221 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
        return 0;
 }
 
+/**
+ *  mei_cl_notify_fop2req - convert fop to proper request
+ *
+ * @fop: client notification start response command
+ *
+ * Return:  MEI_HBM_NOTIFICATION_START/STOP
+ */
+u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop)
+{
+       if (fop == MEI_FOP_NOTIFY_START)
+               return MEI_HBM_NOTIFICATION_START;
+       else
+               return MEI_HBM_NOTIFICATION_STOP;
+}
+
+/**
+ *  mei_cl_notify_req2fop - convert notification request top file operation type
+ *
+ * @req: hbm notification request type
+ *
+ * Return:  MEI_FOP_NOTIFY_START/STOP
+ */
+enum mei_cb_file_ops mei_cl_notify_req2fop(u8 req)
+{
+       if (req == MEI_HBM_NOTIFICATION_START)
+               return MEI_FOP_NOTIFY_START;
+       else
+               return MEI_FOP_NOTIFY_STOP;
+}
+
+/**
+ * mei_cl_irq_notify - send notification request in irq_thread context
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @cmpl_list: complete list.
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
+                     struct mei_cl_cb *cmpl_list)
+{
+       struct mei_device *dev = cl->dev;
+       u32 msg_slots;
+       int slots;
+       int ret;
+       bool request;
+
+       msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+       slots = mei_hbuf_empty_slots(dev);
+
+       if (slots < msg_slots)
+               return -EMSGSIZE;
+
+       request = mei_cl_notify_fop2req(cb->fop_type);
+       ret = mei_hbm_cl_notify_req(dev, cl, request);
+       if (ret) {
+               cl->status = ret;
+               list_move_tail(&cb->list, &cmpl_list->list);
+               return ret;
+       }
+
+       list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
+       return 0;
+}
+
+/**
+ * mei_cl_notify_request - send notification stop/start request
+ *
+ * @cl: host client
+ * @file: associate request with file
+ * @request: 1 for start or 0 for stop
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request)
+{
+       struct mei_device *dev;
+       struct mei_cl_cb *cb;
+       enum mei_cb_file_ops fop_type;
+       int rets;
+
+       if (WARN_ON(!cl || !cl->dev))
+               return -ENODEV;
+
+       dev = cl->dev;
+
+       if (!dev->hbm_f_ev_supported) {
+               cl_dbg(dev, cl, "notifications not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       rets = pm_runtime_get(dev->dev);
+       if (rets < 0 && rets != -EINPROGRESS) {
+               pm_runtime_put_noidle(dev->dev);
+               cl_err(dev, cl, "rpm: get failed %d\n", rets);
+               return rets;
+       }
+
+       fop_type = mei_cl_notify_req2fop(request);
+       cb = mei_io_cb_init(cl, fop_type, file);
+       if (!cb) {
+               rets = -ENOMEM;
+               goto out;
+       }
+
+       if (mei_hbuf_acquire(dev)) {
+               if (mei_hbm_cl_notify_req(dev, cl, request)) {
+                       rets = -ENODEV;
+                       goto out;
+               }
+               list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
+       } else {
+               list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
+       }
+
+       mutex_unlock(&dev->device_lock);
+       wait_event_timeout(cl->wait, cl->notify_en == request,
+                       mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
+       mutex_lock(&dev->device_lock);
+
+       if (cl->notify_en != request) {
+               mei_io_list_flush(&dev->ctrl_rd_list, cl);
+               mei_io_list_flush(&dev->ctrl_wr_list, cl);
+               if (!cl->status)
+                       cl->status = -EFAULT;
+       }
+
+       rets = cl->status;
+
+out:
+       cl_dbg(dev, cl, "rpm: autosuspend\n");
+       pm_runtime_mark_last_busy(dev->dev);
+       pm_runtime_put_autosuspend(dev->dev);
+
+       mei_io_cb_free(cb);
+       return rets;
+}
+
+/**
+ * mei_cl_notify - raise notification
+ *
+ * @cl: host client
+ *
+ * Locking: called under "dev->device_lock" lock
+ */
+void mei_cl_notify(struct mei_cl *cl)
+{
+       struct mei_device *dev;
+
+       if (!cl || !cl->dev)
+               return;
+
+       dev = cl->dev;
+
+       if (!cl->notify_en)
+               return;
+
+       cl_dbg(dev, cl, "notify event");
+       cl->notify_ev = true;
+       wake_up_interruptible_all(&cl->ev_wait);
+
+       if (cl->ev_async)
+               kill_fasync(&cl->ev_async, SIGIO, POLL_PRI);
+
+       mei_cl_bus_notify_event(cl);
+}
+
+/**
+ * mei_cl_notify_get - get or wait for notification event
+ *
+ * @cl: host client
+ * @block: this request is blocking
+ * @notify_ev: true if notification event was received
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
+{
+       struct mei_device *dev;
+       int rets;
+
+       *notify_ev = false;
+
+       if (WARN_ON(!cl || !cl->dev))
+               return -ENODEV;
+
+       dev = cl->dev;
+
+       if (!mei_cl_is_connected(cl))
+               return -ENODEV;
+
+       if (cl->notify_ev)
+               goto out;
+
+       if (!block)
+               return -EAGAIN;
+
+       mutex_unlock(&dev->device_lock);
+       rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev);
+       mutex_lock(&dev->device_lock);
+
+       if (rets < 0)
+               return rets;
+
+out:
+       *notify_ev = cl->notify_ev;
+       cl->notify_ev = false;
+       return 0;
+}
+
 /**
  * mei_cl_read_start - the start read client message function.
  *
@@ -1356,6 +1597,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
        struct mei_device *dev;
        struct mei_msg_data *buf;
        struct mei_msg_hdr mei_hdr;
+       int size;
        int rets;
 
 
@@ -1367,10 +1609,10 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
        dev = cl->dev;
 
-
        buf = &cb->buf;
+       size = buf->size;
 
-       cl_dbg(dev, cl, "size=%d\n", buf->size);
+       cl_dbg(dev, cl, "size=%d\n", size);
 
        rets = pm_runtime_get(dev->dev);
        if (rets < 0 && rets != -EINPROGRESS) {
@@ -1394,21 +1636,21 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
        if (rets == 0) {
                cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
-               rets = buf->size;
+               rets = size;
                goto out;
        }
        if (!mei_hbuf_acquire(dev)) {
                cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
-               rets = buf->size;
+               rets = size;
                goto out;
        }
 
        /* Check for a maximum length */
-       if (buf->size > mei_hbuf_max_len(dev)) {
+       if (size > mei_hbuf_max_len(dev)) {
                mei_hdr.length = mei_hbuf_max_len(dev);
                mei_hdr.msg_complete = 0;
        } else {
-               mei_hdr.length = buf->size;
+               mei_hdr.length = size;
                mei_hdr.msg_complete = 1;
        }
 
@@ -1430,6 +1672,7 @@ out:
        else
                list_add_tail(&cb->list, &dev->write_list.list);
 
+       cb = NULL;
        if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
 
                mutex_unlock(&dev->device_lock);
@@ -1444,7 +1687,7 @@ out:
                }
        }
 
-       rets = buf->size;
+       rets = size;
 err:
        cl_dbg(dev, cl, "rpm: autosuspend\n");
        pm_runtime_mark_last_busy(dev->dev);
@@ -1486,6 +1729,8 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
 
        case MEI_FOP_CONNECT:
        case MEI_FOP_DISCONNECT:
+       case MEI_FOP_NOTIFY_STOP:
+       case MEI_FOP_NOTIFY_START:
                if (waitqueue_active(&cl->wait))
                        wake_up(&cl->wait);
 
@@ -1528,6 +1773,12 @@ void mei_cl_all_wakeup(struct mei_device *dev)
                        cl_dbg(dev, cl, "Waking up writing client!\n");
                        wake_up_interruptible(&cl->tx_wait);
                }
+
+               /* synchronized under device mutex */
+               if (waitqueue_active(&cl->ev_wait)) {
+                       cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
+                       wake_up_interruptible(&cl->ev_wait);
+               }
        }
 }
 
index 8d7f057f104507d9f10d1526592e791e91acf6c5..1c7cad07d7319e187a8c6784440cad897f28678f 100644 (file)
@@ -219,6 +219,14 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb);
 
 void mei_host_client_init(struct work_struct *work);
 
+u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop);
+enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request);
+int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request);
+int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
+                     struct mei_cl_cb *cmpl_list);
+int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev);
+void mei_cl_notify(struct mei_cl *cl);
+
 void mei_cl_all_disconnect(struct mei_device *dev);
 void mei_cl_all_wakeup(struct mei_device *dev);
 void mei_cl_all_write_clear(struct mei_device *dev);
index eb868341247fba3fc4fafb060ddb4781ffc8eb79..4b469cf9e60f8d77d07fe64f8cc958b19f2ff0e7 100644 (file)
@@ -154,6 +154,12 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf,
                pos += scnprintf(buf + pos, bufsz - pos, "hbm features:\n");
                pos += scnprintf(buf + pos, bufsz - pos, "\tPG: %01d\n",
                                 dev->hbm_f_pg_supported);
+               pos += scnprintf(buf + pos, bufsz - pos, "\tDC: %01d\n",
+                                dev->hbm_f_dc_supported);
+               pos += scnprintf(buf + pos, bufsz - pos, "\tDOT: %01d\n",
+                                dev->hbm_f_dot_supported);
+               pos += scnprintf(buf + pos, bufsz - pos, "\tEV: %01d\n",
+                                dev->hbm_f_ev_supported);
        }
 
        pos += scnprintf(buf + pos, bufsz - pos, "pg:  %s, %s\n",
index a4f283165a335c7da6164ed5689edca6c367ae94..8eec887c8f701ce732a6278a49b1fbe298ca0635 100644 (file)
@@ -52,6 +52,7 @@ static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status)
        MEI_CL_CS(ALREADY_STARTED);
        MEI_CL_CS(OUT_OF_RESOURCES);
        MEI_CL_CS(MESSAGE_SMALL);
+       MEI_CL_CS(NOT_ALLOWED);
        default: return "unknown";
        }
 #undef MEI_CL_CCS
@@ -89,6 +90,7 @@ static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
        case MEI_CL_CONN_ALREADY_STARTED:  return -EBUSY;
        case MEI_CL_CONN_OUT_OF_RESOURCES: return -EBUSY;
        case MEI_CL_CONN_MESSAGE_SMALL:    return -EINVAL;
+       case MEI_CL_CONN_NOT_ALLOWED:      return -EBUSY;
        default:                           return -EINVAL;
        }
 }
@@ -299,6 +301,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
        enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data;
        memset(enum_req, 0, len);
        enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
+       enum_req->allow_add = dev->hbm_f_dc_supported;
 
        ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
        if (ret) {
@@ -343,6 +346,180 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
        return 0;
 }
 
+/**
+ * mei_hbm_add_cl_resp - send response to fw on client add request
+ *
+ * @dev: the device structure
+ * @addr: me address
+ * @status: response status
+ *
+ * Return: 0 on success and < 0 on failure
+ */
+static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
+{
+       struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+       struct hbm_add_client_response *resp;
+       const size_t len = sizeof(struct hbm_add_client_response);
+       int ret;
+
+       dev_dbg(dev->dev, "adding client response\n");
+
+       resp = (struct hbm_add_client_response *)dev->wr_msg.data;
+
+       mei_hbm_hdr(mei_hdr, len);
+       memset(resp, 0, sizeof(struct hbm_add_client_response));
+
+       resp->hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
+       resp->me_addr = addr;
+       resp->status  = status;
+
+       ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+       if (ret)
+               dev_err(dev->dev, "add client response write failed: ret = %d\n",
+                       ret);
+       return ret;
+}
+
+/**
+ * mei_hbm_fw_add_cl_req - request from the fw to add a client
+ *
+ * @dev: the device structure
+ * @req: add client request
+ *
+ * Return: 0 on success and < 0 on failure
+ */
+static int mei_hbm_fw_add_cl_req(struct mei_device *dev,
+                             struct hbm_add_client_request *req)
+{
+       int ret;
+       u8 status = MEI_HBMS_SUCCESS;
+
+       BUILD_BUG_ON(sizeof(struct hbm_add_client_request) !=
+                       sizeof(struct hbm_props_response));
+
+       ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req);
+       if (ret)
+               status = !MEI_HBMS_SUCCESS;
+
+       return mei_hbm_add_cl_resp(dev, req->me_addr, status);
+}
+
+/**
+ * mei_hbm_cl_notify_req - send notification request
+ *
+ * @dev: the device structure
+ * @cl: a client to disconnect from
+ * @start: true for start false for stop
+ *
+ * Return: 0 on success and -EIO on write failure
+ */
+int mei_hbm_cl_notify_req(struct mei_device *dev,
+                         struct mei_cl *cl, u8 start)
+{
+
+       struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+       struct hbm_notification_request *req;
+       const size_t len = sizeof(struct hbm_notification_request);
+       int ret;
+
+       mei_hbm_hdr(mei_hdr, len);
+       mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, dev->wr_msg.data, len);
+
+       req = (struct hbm_notification_request *)dev->wr_msg.data;
+       req->start = start;
+
+       ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+       if (ret)
+               dev_err(dev->dev, "notify request failed: ret = %d\n", ret);
+
+       return ret;
+}
+
+/**
+ *  notify_res_to_fop - convert notification response to the proper
+ *      notification FOP
+ *
+ * @cmd: client notification start response command
+ *
+ * Return:  MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP;
+ */
+static inline enum mei_cb_file_ops notify_res_to_fop(struct mei_hbm_cl_cmd *cmd)
+{
+       struct hbm_notification_response *rs =
+               (struct hbm_notification_response *)cmd;
+
+       return mei_cl_notify_req2fop(rs->start);
+}
+
+/**
+ * mei_hbm_cl_notify_start_res - update the client state according
+ *       notify start response
+ *
+ * @dev: the device structure
+ * @cl: mei host client
+ * @cmd: client notification start response command
+ */
+static void mei_hbm_cl_notify_start_res(struct mei_device *dev,
+                                       struct mei_cl *cl,
+                                       struct mei_hbm_cl_cmd *cmd)
+{
+       struct hbm_notification_response *rs =
+               (struct hbm_notification_response *)cmd;
+
+       cl_dbg(dev, cl, "hbm: notify start response status=%d\n", rs->status);
+
+       if (rs->status == MEI_HBMS_SUCCESS ||
+           rs->status == MEI_HBMS_ALREADY_STARTED) {
+               cl->notify_en = true;
+               cl->status = 0;
+       } else {
+               cl->status = -EINVAL;
+       }
+}
+
+/**
+ * mei_hbm_cl_notify_stop_res - update the client state according
+ *       notify stop response
+ *
+ * @dev: the device structure
+ * @cl: mei host client
+ * @cmd: client notification stop response command
+ */
+static void mei_hbm_cl_notify_stop_res(struct mei_device *dev,
+                                      struct mei_cl *cl,
+                                      struct mei_hbm_cl_cmd *cmd)
+{
+       struct hbm_notification_response *rs =
+               (struct hbm_notification_response *)cmd;
+
+       cl_dbg(dev, cl, "hbm: notify stop response status=%d\n", rs->status);
+
+       if (rs->status == MEI_HBMS_SUCCESS ||
+           rs->status == MEI_HBMS_NOT_STARTED) {
+               cl->notify_en = false;
+               cl->status = 0;
+       } else {
+               /* TODO: spec is not clear yet about other possible issues */
+               cl->status = -EINVAL;
+       }
+}
+
+/**
+ * mei_hbm_cl_notify - signal notification event
+ *
+ * @dev: the device structure
+ * @cmd: notification client message
+ */
+static void mei_hbm_cl_notify(struct mei_device *dev,
+                             struct mei_hbm_cl_cmd *cmd)
+{
+       struct mei_cl *cl;
+
+       cl = mei_hbm_cl_find_by_cmd(dev, cmd);
+       if (cl)
+               mei_cl_notify(cl);
+}
+
 /**
  * mei_hbm_prop_req - request property for a single client
  *
@@ -610,8 +787,11 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
 
        if (rs->status == MEI_CL_CONN_SUCCESS)
                cl->state = MEI_FILE_CONNECTED;
-       else
+       else {
                cl->state = MEI_FILE_DISCONNECT_REPLY;
+               if (rs->status == MEI_CL_CONN_NOT_FOUND)
+                       mei_me_cl_del(dev, cl->me_cl);
+       }
        cl->status = mei_cl_conn_status_to_errno(rs->status);
 }
 
@@ -654,6 +834,12 @@ static void mei_hbm_cl_res(struct mei_device *dev,
        case MEI_FOP_DISCONNECT:
                mei_hbm_cl_disconnect_res(dev, cl, rs);
                break;
+       case MEI_FOP_NOTIFY_START:
+               mei_hbm_cl_notify_start_res(dev, cl, rs);
+               break;
+       case MEI_FOP_NOTIFY_STOP:
+               mei_hbm_cl_notify_stop_res(dev, cl, rs);
+               break;
        default:
                return;
        }
@@ -693,6 +879,79 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
        return 0;
 }
 
+/**
+ * mei_hbm_pg_enter_res - PG enter response received
+ *
+ * @dev: the device structure.
+ *
+ * Return: 0 on success, -EPROTO on state mismatch
+ */
+static int mei_hbm_pg_enter_res(struct mei_device *dev)
+{
+       if (mei_pg_state(dev) != MEI_PG_OFF ||
+           dev->pg_event != MEI_PG_EVENT_WAIT) {
+               dev_err(dev->dev, "hbm: pg entry response: state mismatch [%s, %d]\n",
+                       mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
+               return -EPROTO;
+       }
+
+       dev->pg_event = MEI_PG_EVENT_RECEIVED;
+       wake_up(&dev->wait_pg);
+
+       return 0;
+}
+
+/**
+ * mei_hbm_pg_resume - process with PG resume
+ *
+ * @dev: the device structure.
+ */
+void mei_hbm_pg_resume(struct mei_device *dev)
+{
+       pm_request_resume(dev->dev);
+}
+EXPORT_SYMBOL_GPL(mei_hbm_pg_resume);
+
+/**
+ * mei_hbm_pg_exit_res - PG exit response received
+ *
+ * @dev: the device structure.
+ *
+ * Return: 0 on success, -EPROTO on state mismatch
+ */
+static int mei_hbm_pg_exit_res(struct mei_device *dev)
+{
+       if (mei_pg_state(dev) != MEI_PG_ON ||
+           (dev->pg_event != MEI_PG_EVENT_WAIT &&
+            dev->pg_event != MEI_PG_EVENT_IDLE)) {
+               dev_err(dev->dev, "hbm: pg exit response: state mismatch [%s, %d]\n",
+                       mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
+               return -EPROTO;
+       }
+
+       switch (dev->pg_event) {
+       case MEI_PG_EVENT_WAIT:
+               dev->pg_event = MEI_PG_EVENT_RECEIVED;
+               wake_up(&dev->wait_pg);
+               break;
+       case MEI_PG_EVENT_IDLE:
+               /*
+               * If the driver is not waiting on this then
+               * this is HW initiated exit from PG.
+               * Start runtime pm resume sequence to exit from PG.
+               */
+               dev->pg_event = MEI_PG_EVENT_RECEIVED;
+               mei_hbm_pg_resume(dev);
+               break;
+       default:
+               WARN(1, "hbm: pg exit response: unexpected pg event = %d\n",
+                    dev->pg_event);
+               return -EPROTO;
+       }
+
+       return 0;
+}
+
 /**
  * mei_hbm_config_features - check what hbm features and commands
  *        are supported by the fw
@@ -709,6 +968,17 @@ static void mei_hbm_config_features(struct mei_device *dev)
        if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
            dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
                dev->hbm_f_pg_supported = 1;
+
+       if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
+               dev->hbm_f_dc_supported = 1;
+
+       /* disconnect on connect timeout instead of link reset */
+       if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
+               dev->hbm_f_dot_supported = 1;
+
+       /* Notification Event Support */
+       if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
+               dev->hbm_f_ev_supported = 1;
 }
 
 /**
@@ -740,6 +1010,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
        struct hbm_host_version_response *version_res;
        struct hbm_props_response *props_res;
        struct hbm_host_enum_response *enum_res;
+       struct hbm_add_client_request *add_cl_req;
+       int ret;
 
        struct mei_hbm_cl_cmd *cl_cmd;
        struct hbm_client_connect_request *disconnect_req;
@@ -828,24 +1100,17 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                break;
 
        case MEI_PG_ISOLATION_ENTRY_RES_CMD:
-               dev_dbg(dev->dev, "power gate isolation entry response received\n");
-               dev->pg_event = MEI_PG_EVENT_RECEIVED;
-               if (waitqueue_active(&dev->wait_pg))
-                       wake_up(&dev->wait_pg);
+               dev_dbg(dev->dev, "hbm: power gate isolation entry response received\n");
+               ret = mei_hbm_pg_enter_res(dev);
+               if (ret)
+                       return ret;
                break;
 
        case MEI_PG_ISOLATION_EXIT_REQ_CMD:
-               dev_dbg(dev->dev, "power gate isolation exit request received\n");
-               dev->pg_event = MEI_PG_EVENT_RECEIVED;
-               if (waitqueue_active(&dev->wait_pg))
-                       wake_up(&dev->wait_pg);
-               else
-                       /*
-                       * If the driver is not waiting on this then
-                       * this is HW initiated exit from PG.
-                       * Start runtime pm resume sequence to exit from PG.
-                       */
-                       pm_request_resume(dev->dev);
+               dev_dbg(dev->dev, "hbm: power gate isolation exit request received\n");
+               ret = mei_hbm_pg_exit_res(dev);
+               if (ret)
+                       return ret;
                break;
 
        case HOST_CLIENT_PROPERTIES_RES_CMD:
@@ -937,6 +1202,39 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                        return -EIO;
                }
                break;
+
+       case MEI_HBM_ADD_CLIENT_REQ_CMD:
+               dev_dbg(dev->dev, "hbm: add client request received\n");
+               /*
+                * after the host receives the enum_resp
+                * message clients may be added or removed
+                */
+               if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS &&
+                   dev->hbm_state >= MEI_HBM_STOPPED) {
+                       dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
+                               dev->dev_state, dev->hbm_state);
+                       return -EPROTO;
+               }
+               add_cl_req = (struct hbm_add_client_request *)mei_msg;
+               ret = mei_hbm_fw_add_cl_req(dev, add_cl_req);
+               if (ret) {
+                       dev_err(dev->dev, "hbm: add client: failed to send response %d\n",
+                               ret);
+                       return -EIO;
+               }
+               dev_dbg(dev->dev, "hbm: add client request processed\n");
+               break;
+
+       case MEI_HBM_NOTIFY_RES_CMD:
+               dev_dbg(dev->dev, "hbm: notify response received\n");
+               mei_hbm_cl_res(dev, cl_cmd, notify_res_to_fop(cl_cmd));
+               break;
+
+       case MEI_HBM_NOTIFICATION_CMD:
+               dev_dbg(dev->dev, "hbm: notification\n");
+               mei_hbm_cl_notify(dev, cl_cmd);
+               break;
+
        default:
                BUG();
                break;
index 2544db7d1649b75b4a313e0c498e1727c416c494..a2025a5083a39f51882195613a4bac1af8b62941 100644 (file)
@@ -54,6 +54,9 @@ int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
 bool mei_hbm_version_is_supported(struct mei_device *dev);
 int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd);
+void mei_hbm_pg_resume(struct mei_device *dev);
+int mei_hbm_cl_notify_req(struct mei_device *dev,
+                         struct mei_cl *cl, u8 request);
 
 #endif /* _MEI_HBM_H_ */
 
index 9eb7ed70ace2193e2d729f21702c08f81687fa6b..a8a68acd326752980e8b31a61c8b0b9a891018c8 100644 (file)
 #define MEI_DEV_ID_WPT_LP     0x9CBA  /* Wildcat Point LP */
 #define MEI_DEV_ID_WPT_LP_2   0x9CBB  /* Wildcat Point LP 2 */
 
+#define MEI_DEV_ID_SPT        0x9D3A  /* Sunrise Point */
+#define MEI_DEV_ID_SPT_2      0x9D3B  /* Sunrise Point 2 */
+#define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
+#define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
 /*
  * MEI HW Section
  */
 
 /* Host Firmware Status Registers in PCI Config Space */
 #define PCI_CFG_HFS_1         0x40
+#  define PCI_CFG_HFS_1_D0I3_MSK     0x80000000
 #define PCI_CFG_HFS_2         0x48
 #define PCI_CFG_HFS_3         0x60
 #define PCI_CFG_HFS_4         0x64
 #define ME_CSR_HA  0xC
 /* H_HGC_CSR - PGI register */
 #define H_HPG_CSR  0x10
-
+/* H_D0I3C - D0I3 Control  */
+#define H_D0I3C    0x800
 
 /* register bits of H_CSR (Host Control Status register) */
 /* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
 #define H_IS              0x00000002
 /* Host Interrupt Enable */
 #define H_IE              0x00000001
+/* Host D0I3 Interrupt Enable */
+#define H_D0I3C_IE        0x00000020
+/* Host D0I3 Interrupt Status */
+#define H_D0I3C_IS        0x00000040
 
+/* H_CSR masks */
+#define H_CSR_IE_MASK     (H_IE | H_D0I3C_IE)
+#define H_CSR_IS_MASK     (H_IS | H_D0I3C_IS)
 
 /* register bits of ME_CSR_HA (ME Control Status Host Access register) */
 /* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only
@@ -183,8 +196,14 @@ access to ME_CBD */
 #define ME_IE_HRA         0x00000001
 
 
-/* register bits - H_HPG_CSR */
-#define H_HPG_CSR_PGIHEXR       0x00000001
-#define H_HPG_CSR_PGI           0x00000002
+/* H_HPG_CSR register bits */
+#define H_HPG_CSR_PGIHEXR 0x00000001
+#define H_HPG_CSR_PGI     0x00000002
+
+/* H_D0I3C register bits */
+#define H_D0I3C_CIP      0x00000001
+#define H_D0I3C_IR       0x00000002
+#define H_D0I3C_I3       0x00000004
+#define H_D0I3C_RR       0x00000008
 
 #endif /* _MEI_HW_MEI_REGS_H_ */
index 43d7101ff9933aef7511ab57b03e6f0f21fe53da..65511d39d89b86eb3acab01d02c41bc4431f17ae 100644 (file)
@@ -134,10 +134,39 @@ static inline void mei_hcsr_write(struct mei_device *dev, u32 reg)
  */
 static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
 {
-       reg &= ~H_IS;
+       reg &= ~H_CSR_IS_MASK;
        mei_hcsr_write(dev, reg);
 }
 
+/**
+ * mei_me_d0i3c_read - Reads 32bit data from the D0I3C register
+ *
+ * @dev: the device structure
+ *
+ * Return: H_D0I3C register value (u32)
+ */
+static inline u32 mei_me_d0i3c_read(const struct mei_device *dev)
+{
+       u32 reg;
+
+       reg = mei_me_reg_read(to_me_hw(dev), H_D0I3C);
+       trace_mei_reg_read(dev->dev, "H_D0I3C", H_CSR, reg);
+
+       return reg;
+}
+
+/**
+ * mei_me_d0i3c_write - writes H_D0I3C register to device
+ *
+ * @dev: the device structure
+ * @reg: new register value
+ */
+static inline void mei_me_d0i3c_write(struct mei_device *dev, u32 reg)
+{
+       trace_mei_reg_write(dev->dev, "H_D0I3C", H_CSR, reg);
+       mei_me_reg_write(to_me_hw(dev), H_D0I3C, reg);
+}
+
 /**
  * mei_me_fw_status - read fw status register from pci config space
  *
@@ -176,12 +205,25 @@ static int mei_me_fw_status(struct mei_device *dev,
  */
 static void mei_me_hw_config(struct mei_device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
        struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(dev);
+       u32 hcsr, reg;
+
        /* Doesn't change in runtime */
+       hcsr = mei_hcsr_read(dev);
        dev->hbuf_depth = (hcsr & H_CBD) >> 24;
 
+       reg = 0;
+       pci_read_config_dword(pdev, PCI_CFG_HFS_1, &reg);
+       hw->d0i3_supported =
+               ((reg & PCI_CFG_HFS_1_D0I3_MSK) == PCI_CFG_HFS_1_D0I3_MSK);
+
        hw->pg_state = MEI_PG_OFF;
+       if (hw->d0i3_supported) {
+               reg = mei_me_d0i3c_read(dev);
+               if (reg & H_D0I3C_I3)
+                       hw->pg_state = MEI_PG_ON;
+       }
 }
 
 /**
@@ -208,7 +250,7 @@ static void mei_me_intr_clear(struct mei_device *dev)
 {
        u32 hcsr = mei_hcsr_read(dev);
 
-       if ((hcsr & H_IS) == H_IS)
+       if (hcsr & H_CSR_IS_MASK)
                mei_hcsr_write(dev, hcsr);
 }
 /**
@@ -220,7 +262,7 @@ static void mei_me_intr_enable(struct mei_device *dev)
 {
        u32 hcsr = mei_hcsr_read(dev);
 
-       hcsr |= H_IE;
+       hcsr |= H_CSR_IE_MASK;
        mei_hcsr_set(dev, hcsr);
 }
 
@@ -233,7 +275,7 @@ static void mei_me_intr_disable(struct mei_device *dev)
 {
        u32 hcsr = mei_hcsr_read(dev);
 
-       hcsr  &= ~H_IE;
+       hcsr  &= ~H_CSR_IE_MASK;
        mei_hcsr_set(dev, hcsr);
 }
 
@@ -253,57 +295,6 @@ static void mei_me_hw_reset_release(struct mei_device *dev)
        /* complete this write before we set host ready on another CPU */
        mmiowb();
 }
-/**
- * mei_me_hw_reset - resets fw via mei csr register.
- *
- * @dev: the device structure
- * @intr_enable: if interrupt should be enabled after reset.
- *
- * Return: always 0
- */
-static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
-{
-       u32 hcsr = mei_hcsr_read(dev);
-
-       /* H_RST may be found lit before reset is started,
-        * for example if preceding reset flow hasn't completed.
-        * In that case asserting H_RST will be ignored, therefore
-        * we need to clean H_RST bit to start a successful reset sequence.
-        */
-       if ((hcsr & H_RST) == H_RST) {
-               dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
-               hcsr &= ~H_RST;
-               mei_hcsr_set(dev, hcsr);
-               hcsr = mei_hcsr_read(dev);
-       }
-
-       hcsr |= H_RST | H_IG | H_IS;
-
-       if (intr_enable)
-               hcsr |= H_IE;
-       else
-               hcsr &= ~H_IE;
-
-       dev->recvd_hw_ready = false;
-       mei_hcsr_write(dev, hcsr);
-
-       /*
-        * Host reads the H_CSR once to ensure that the
-        * posted write to H_CSR completes.
-        */
-       hcsr = mei_hcsr_read(dev);
-
-       if ((hcsr & H_RST) == 0)
-               dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
-
-       if ((hcsr & H_RDY) == H_RDY)
-               dev_warn(dev->dev, "H_RDY is not cleared 0x%08X", hcsr);
-
-       if (intr_enable == false)
-               mei_me_hw_reset_release(dev);
-
-       return 0;
-}
 
 /**
  * mei_me_host_set_ready - enable device
@@ -314,7 +305,7 @@ static void mei_me_host_set_ready(struct mei_device *dev)
 {
        u32 hcsr = mei_hcsr_read(dev);
 
-       hcsr |= H_IE | H_IG | H_RDY;
+       hcsr |= H_CSR_IE_MASK | H_IG | H_RDY;
        mei_hcsr_set(dev, hcsr);
 }
 
@@ -601,13 +592,13 @@ static void mei_me_pg_unset(struct mei_device *dev)
 }
 
 /**
- * mei_me_pg_enter_sync - perform pg entry procedure
+ * mei_me_pg_legacy_enter_sync - perform legacy pg entry procedure
  *
  * @dev: the device structure
  *
  * Return: 0 on success an error code otherwise
  */
-int mei_me_pg_enter_sync(struct mei_device *dev)
+static int mei_me_pg_legacy_enter_sync(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
        unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -638,13 +629,13 @@ int mei_me_pg_enter_sync(struct mei_device *dev)
 }
 
 /**
- * mei_me_pg_exit_sync - perform pg exit procedure
+ * mei_me_pg_legacy_exit_sync - perform legacy pg exit procedure
  *
  * @dev: the device structure
  *
  * Return: 0 on success an error code otherwise
  */
-int mei_me_pg_exit_sync(struct mei_device *dev)
+static int mei_me_pg_legacy_exit_sync(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
        unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -712,8 +703,12 @@ static bool mei_me_pg_in_transition(struct mei_device *dev)
  */
 static bool mei_me_pg_is_enabled(struct mei_device *dev)
 {
+       struct mei_me_hw *hw = to_me_hw(dev);
        u32 reg = mei_me_mecsr_read(dev);
 
+       if (hw->d0i3_supported)
+               return true;
+
        if ((reg & ME_PGIC_HRA) == 0)
                goto notsupported;
 
@@ -723,7 +718,8 @@ static bool mei_me_pg_is_enabled(struct mei_device *dev)
        return true;
 
 notsupported:
-       dev_dbg(dev->dev, "pg: not supported: HGP = %d hbm version %d.%d ?= %d.%d\n",
+       dev_dbg(dev->dev, "pg: not supported: d0i3 = %d HGP = %d hbm version %d.%d ?= %d.%d\n",
+               hw->d0i3_supported,
                !!(reg & ME_PGIC_HRA),
                dev->version.major_version,
                dev->version.minor_version,
@@ -734,11 +730,211 @@ notsupported:
 }
 
 /**
- * mei_me_pg_intr - perform pg processing in interrupt thread handler
+ * mei_me_d0i3_set - write d0i3 register bit on mei device.
  *
  * @dev: the device structure
+ * @intr: ask for interrupt
+ *
+ * Return: D0I3C register value
  */
-static void mei_me_pg_intr(struct mei_device *dev)
+static u32 mei_me_d0i3_set(struct mei_device *dev, bool intr)
+{
+       u32 reg = mei_me_d0i3c_read(dev);
+
+       reg |= H_D0I3C_I3;
+       if (intr)
+               reg |= H_D0I3C_IR;
+       else
+               reg &= ~H_D0I3C_IR;
+       mei_me_d0i3c_write(dev, reg);
+       /* read it to ensure HW consistency */
+       reg = mei_me_d0i3c_read(dev);
+       return reg;
+}
+
+/**
+ * mei_me_d0i3_unset - clean d0i3 register bit on mei device.
+ *
+ * @dev: the device structure
+ *
+ * Return: D0I3C register value
+ */
+static u32 mei_me_d0i3_unset(struct mei_device *dev)
+{
+       u32 reg = mei_me_d0i3c_read(dev);
+
+       reg &= ~H_D0I3C_I3;
+       reg |= H_D0I3C_IR;
+       mei_me_d0i3c_write(dev, reg);
+       /* read it to ensure HW consistency */
+       reg = mei_me_d0i3c_read(dev);
+       return reg;
+}
+
+/**
+ * mei_me_d0i3_enter_sync - perform d0i3 entry procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_d0i3_enter_sync(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+       unsigned long d0i3_timeout = mei_secs_to_jiffies(MEI_D0I3_TIMEOUT);
+       unsigned long pgi_timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
+       int ret;
+       u32 reg;
+
+       reg = mei_me_d0i3c_read(dev);
+       if (reg & H_D0I3C_I3) {
+               /* we are in d0i3, nothing to do */
+               dev_dbg(dev->dev, "d0i3 set not needed\n");
+               ret = 0;
+               goto on;
+       }
+
+       /* PGI entry procedure */
+       dev->pg_event = MEI_PG_EVENT_WAIT;
+
+       ret = mei_hbm_pg(dev, MEI_PG_ISOLATION_ENTRY_REQ_CMD);
+       if (ret)
+               /* FIXME: should we reset here? */
+               goto out;
+
+       mutex_unlock(&dev->device_lock);
+       wait_event_timeout(dev->wait_pg,
+               dev->pg_event == MEI_PG_EVENT_RECEIVED, pgi_timeout);
+       mutex_lock(&dev->device_lock);
+
+       if (dev->pg_event != MEI_PG_EVENT_RECEIVED) {
+               ret = -ETIME;
+               goto out;
+       }
+       /* end PGI entry procedure */
+
+       dev->pg_event = MEI_PG_EVENT_INTR_WAIT;
+
+       reg = mei_me_d0i3_set(dev, true);
+       if (!(reg & H_D0I3C_CIP)) {
+               dev_dbg(dev->dev, "d0i3 enter wait not needed\n");
+               ret = 0;
+               goto on;
+       }
+
+       mutex_unlock(&dev->device_lock);
+       wait_event_timeout(dev->wait_pg,
+               dev->pg_event == MEI_PG_EVENT_INTR_RECEIVED, d0i3_timeout);
+       mutex_lock(&dev->device_lock);
+
+       if (dev->pg_event != MEI_PG_EVENT_INTR_RECEIVED) {
+               reg = mei_me_d0i3c_read(dev);
+               if (!(reg & H_D0I3C_I3)) {
+                       ret = -ETIME;
+                       goto out;
+               }
+       }
+
+       ret = 0;
+on:
+       hw->pg_state = MEI_PG_ON;
+out:
+       dev->pg_event = MEI_PG_EVENT_IDLE;
+       dev_dbg(dev->dev, "d0i3 enter ret = %d\n", ret);
+       return ret;
+}
+
+/**
+ * mei_me_d0i3_enter - perform d0i3 entry procedure
+ *   no hbm PG handshake
+ *   no waiting for confirmation; runs with interrupts
+ *   disabled
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_d0i3_enter(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+       u32 reg;
+
+       reg = mei_me_d0i3c_read(dev);
+       if (reg & H_D0I3C_I3) {
+               /* we are in d0i3, nothing to do */
+               dev_dbg(dev->dev, "already d0i3 : set not needed\n");
+               goto on;
+       }
+
+       mei_me_d0i3_set(dev, false);
+on:
+       hw->pg_state = MEI_PG_ON;
+       dev->pg_event = MEI_PG_EVENT_IDLE;
+       dev_dbg(dev->dev, "d0i3 enter\n");
+       return 0;
+}
+
+/**
+ * mei_me_d0i3_exit_sync - perform d0i3 exit procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_d0i3_exit_sync(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+       unsigned long timeout = mei_secs_to_jiffies(MEI_D0I3_TIMEOUT);
+       int ret;
+       u32 reg;
+
+       dev->pg_event = MEI_PG_EVENT_INTR_WAIT;
+
+       reg = mei_me_d0i3c_read(dev);
+       if (!(reg & H_D0I3C_I3)) {
+               /* we are not in d0i3, nothing to do */
+               dev_dbg(dev->dev, "d0i3 exit not needed\n");
+               ret = 0;
+               goto off;
+       }
+
+       reg = mei_me_d0i3_unset(dev);
+       if (!(reg & H_D0I3C_CIP)) {
+               dev_dbg(dev->dev, "d0i3 exit wait not needed\n");
+               ret = 0;
+               goto off;
+       }
+
+       mutex_unlock(&dev->device_lock);
+       wait_event_timeout(dev->wait_pg,
+               dev->pg_event == MEI_PG_EVENT_INTR_RECEIVED, timeout);
+       mutex_lock(&dev->device_lock);
+
+       if (dev->pg_event != MEI_PG_EVENT_INTR_RECEIVED) {
+               reg = mei_me_d0i3c_read(dev);
+               if (reg & H_D0I3C_I3) {
+                       ret = -ETIME;
+                       goto out;
+               }
+       }
+
+       ret = 0;
+off:
+       hw->pg_state = MEI_PG_OFF;
+out:
+       dev->pg_event = MEI_PG_EVENT_IDLE;
+
+       dev_dbg(dev->dev, "d0i3 exit ret = %d\n", ret);
+       return ret;
+}
+
+/**
+ * mei_me_pg_legacy_intr - perform legacy pg processing
+ *                        in interrupt thread handler
+ *
+ * @dev: the device structure
+ */
+static void mei_me_pg_legacy_intr(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
 
@@ -751,6 +947,162 @@ static void mei_me_pg_intr(struct mei_device *dev)
                wake_up(&dev->wait_pg);
 }
 
+/**
+ * mei_me_d0i3_intr - perform d0i3 processing in interrupt thread handler
+ *
+ * @dev: the device structure
+ */
+static void mei_me_d0i3_intr(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+
+       if (dev->pg_event == MEI_PG_EVENT_INTR_WAIT &&
+           (hw->intr_source & H_D0I3C_IS)) {
+               dev->pg_event = MEI_PG_EVENT_INTR_RECEIVED;
+               if (hw->pg_state == MEI_PG_ON) {
+                       hw->pg_state = MEI_PG_OFF;
+                       if (dev->hbm_state != MEI_HBM_IDLE) {
+                               /*
+                                * force H_RDY because it could be
+                                * wiped off during PG
+                                */
+                               dev_dbg(dev->dev, "d0i3 set host ready\n");
+                               mei_me_host_set_ready(dev);
+                       }
+               } else {
+                       hw->pg_state = MEI_PG_ON;
+               }
+
+               wake_up(&dev->wait_pg);
+       }
+
+       if (hw->pg_state == MEI_PG_ON && (hw->intr_source & H_IS)) {
+               /*
+                * HW sent some data and we are in D0i3, so
+                * we got here because of HW initiated exit from D0i3.
+                * Start runtime pm resume sequence to exit low power state.
+                */
+               dev_dbg(dev->dev, "d0i3 want resume\n");
+               mei_hbm_pg_resume(dev);
+       }
+}
+
+/**
+ * mei_me_pg_intr - perform pg processing in interrupt thread handler
+ *
+ * @dev: the device structure
+ */
+static void mei_me_pg_intr(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+
+       if (hw->d0i3_supported)
+               mei_me_d0i3_intr(dev);
+       else
+               mei_me_pg_legacy_intr(dev);
+}
+
+/**
+ * mei_me_pg_enter_sync - perform runtime pm entry procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+int mei_me_pg_enter_sync(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+
+       if (hw->d0i3_supported)
+               return mei_me_d0i3_enter_sync(dev);
+       else
+               return mei_me_pg_legacy_enter_sync(dev);
+}
+
+/**
+ * mei_me_pg_exit_sync - perform runtime pm exit procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+int mei_me_pg_exit_sync(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+
+       if (hw->d0i3_supported)
+               return mei_me_d0i3_exit_sync(dev);
+       else
+               return mei_me_pg_legacy_exit_sync(dev);
+}
+
+/**
+ * mei_me_hw_reset - resets fw via mei csr register.
+ *
+ * @dev: the device structure
+ * @intr_enable: if interrupt should be enabled after reset.
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+       int ret;
+       u32 hcsr;
+
+       if (intr_enable) {
+               mei_me_intr_enable(dev);
+               if (hw->d0i3_supported) {
+                       ret = mei_me_d0i3_exit_sync(dev);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       hcsr = mei_hcsr_read(dev);
+       /* H_RST may be found lit before reset is started,
+        * for example if preceding reset flow hasn't completed.
+        * In that case asserting H_RST will be ignored, therefore
+        * we need to clean H_RST bit to start a successful reset sequence.
+        */
+       if ((hcsr & H_RST) == H_RST) {
+               dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
+               hcsr &= ~H_RST;
+               mei_hcsr_set(dev, hcsr);
+               hcsr = mei_hcsr_read(dev);
+       }
+
+       hcsr |= H_RST | H_IG | H_CSR_IS_MASK;
+
+       if (!intr_enable)
+               hcsr &= ~H_CSR_IE_MASK;
+
+       dev->recvd_hw_ready = false;
+       mei_hcsr_write(dev, hcsr);
+
+       /*
+        * Host reads the H_CSR once to ensure that the
+        * posted write to H_CSR completes.
+        */
+       hcsr = mei_hcsr_read(dev);
+
+       if ((hcsr & H_RST) == 0)
+               dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
+
+       if ((hcsr & H_RDY) == H_RDY)
+               dev_warn(dev->dev, "H_RDY is not cleared 0x%08X", hcsr);
+
+       if (!intr_enable) {
+               mei_me_hw_reset_release(dev);
+               if (hw->d0i3_supported) {
+                       ret = mei_me_d0i3_enter(dev);
+                       if (ret)
+                               return ret;
+               }
+       }
+       return 0;
+}
+
 /**
  * mei_me_irq_quick_handler - The ISR of the MEI device
  *
@@ -759,16 +1111,20 @@ static void mei_me_pg_intr(struct mei_device *dev)
  *
  * Return: irqreturn_t
  */
-
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
 {
-       struct mei_device *dev = (struct mei_device *) dev_id;
-       u32 hcsr = mei_hcsr_read(dev);
+       struct mei_device *dev = (struct mei_device *)dev_id;
+       struct mei_me_hw *hw = to_me_hw(dev);
+       u32 hcsr;
 
-       if ((hcsr & H_IS) != H_IS)
+       hcsr = mei_hcsr_read(dev);
+       if (!(hcsr & H_CSR_IS_MASK))
                return IRQ_NONE;
 
-       /* clear H_IS bit in H_CSR */
+       hw->intr_source = hcsr & H_CSR_IS_MASK;
+       dev_dbg(dev->dev, "interrupt source 0x%08X.\n", hw->intr_source);
+
+       /* clear H_IS and H_D0I3C_IS bits in H_CSR to clear the interrupts */
        mei_hcsr_write(dev, hcsr);
 
        return IRQ_WAKE_THREAD;
@@ -796,11 +1152,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
        mutex_lock(&dev->device_lock);
        mei_io_list_init(&complete_list);
 
-       /* Ack the interrupt here
-        * In case of MSI we don't go through the quick handler */
-       if (pci_dev_msi_enabled(to_pci_dev(dev->dev)))
-               mei_clear_interrupts(dev);
-
        /* check if ME wants a reset */
        if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
                dev_warn(dev->dev, "FW not ready: resetting.\n");
index 6022d52af6f6fb8ad57e6339b38f9c4c3cc133ba..2ee14dc1b2ea55a8dc6c198640bb2f56034bf597 100644 (file)
@@ -50,13 +50,17 @@ struct mei_cfg {
  * struct mei_me_hw - me hw specific data
  *
  * @cfg: per device generation config and ops
- * @mem_addr:  io memory address
- * @pg_state:      power gating state
+ * @mem_addr: io memory address
+ * @intr_source: interrupt source
+ * @pg_state: power gating state
+ * @d0i3_supported: di03 support
  */
 struct mei_me_hw {
        const struct mei_cfg *cfg;
        void __iomem *mem_addr;
+       u32 intr_source;
        enum mei_pg_state pg_state;
+       bool d0i3_supported;
 };
 
 #define to_me_hw(dev) (struct mei_me_hw *)((dev)->hw)
index 16fef6dc4dd7135612c0379904d255b6c6e54b5a..4cebde85924f8f33085b45e27b7df8deae17ada5 100644 (file)
 #define MEI_IAMTHIF_STALL_TIMER    12  /* HPS */
 #define MEI_IAMTHIF_READ_TIMER     10  /* HPS */
 
-#define MEI_PGI_TIMEOUT            1  /* PG Isolation time response 1 sec */
-#define MEI_HBM_TIMEOUT            1   /* 1 second */
+#define MEI_PGI_TIMEOUT             1  /* PG Isolation time response 1 sec */
+#define MEI_D0I3_TIMEOUT            5  /* D0i3 set/unset max response time */
+#define MEI_HBM_TIMEOUT             1  /* 1 second */
 
 /*
  * MEI Version
  */
-#define HBM_MINOR_VERSION                   1
-#define HBM_MAJOR_VERSION                   1
+#define HBM_MINOR_VERSION                   0
+#define HBM_MAJOR_VERSION                   2
 
 /*
  * MEI version with PGI support
 #define HBM_MINOR_VERSION_PGI               1
 #define HBM_MAJOR_VERSION_PGI               1
 
+/*
+ * MEI version with Dynamic clients support
+ */
+#define HBM_MINOR_VERSION_DC               0
+#define HBM_MAJOR_VERSION_DC               2
+
+/*
+ * MEI version with disconnect on connection timeout support
+ */
+#define HBM_MINOR_VERSION_DOT              0
+#define HBM_MAJOR_VERSION_DOT              2
+
+/*
+ * MEI version with notifcation support
+ */
+#define HBM_MINOR_VERSION_EV               0
+#define HBM_MAJOR_VERSION_EV               2
+
 /* Host bus message command opcode */
 #define MEI_HBM_CMD_OP_MSK                  0x7f
 /* Host bus message command RESPONSE */
 #define MEI_PG_ISOLATION_EXIT_REQ_CMD       0x0b
 #define MEI_PG_ISOLATION_EXIT_RES_CMD       0x8b
 
+#define MEI_HBM_ADD_CLIENT_REQ_CMD          0x0f
+#define MEI_HBM_ADD_CLIENT_RES_CMD          0x8f
+
+#define MEI_HBM_NOTIFY_REQ_CMD              0x10
+#define MEI_HBM_NOTIFY_RES_CMD              0x90
+#define MEI_HBM_NOTIFICATION_CMD            0x11
+
 /*
  * MEI Stop Reason
  * used by hbm_host_stop_request.reason
@@ -136,6 +162,7 @@ enum mei_cl_connect_status {
        MEI_CL_CONN_ALREADY_STARTED  = MEI_HBMS_ALREADY_EXISTS,
        MEI_CL_CONN_OUT_OF_RESOURCES = MEI_HBMS_REJECTED,
        MEI_CL_CONN_MESSAGE_SMALL    = MEI_HBMS_INVALID_PARAMETER,
+       MEI_CL_CONN_NOT_ALLOWED      = MEI_HBMS_NOT_ALLOWED,
 };
 
 /*
@@ -213,9 +240,17 @@ struct hbm_me_stop_request {
        u8 reserved[2];
 } __packed;
 
+/**
+ * struct hbm_host_enum_request -  enumeration request from host to fw
+ *
+ * @hbm_cmd: bus message command header
+ * @allow_add: allow dynamic clients add HBM version >= 2.0
+ * @reserved: reserved
+ */
 struct hbm_host_enum_request {
        u8 hbm_cmd;
-       u8 reserved[3];
+       u8 allow_add;
+       u8 reserved[2];
 } __packed;
 
 struct hbm_host_enum_response {
@@ -247,6 +282,38 @@ struct hbm_props_response {
        struct mei_client_properties client_properties;
 } __packed;
 
+/**
+ * struct hbm_add_client_request - request to add a client
+ *     might be sent by fw after enumeration has already completed
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @reserved: reserved
+ * @client_properties: client properties
+ */
+struct hbm_add_client_request {
+       u8 hbm_cmd;
+       u8 me_addr;
+       u8 reserved[2];
+       struct mei_client_properties client_properties;
+} __packed;
+
+/**
+ * struct hbm_add_client_response - response to add a client
+ *     sent by the host to report client addition status to fw
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @status: if HBMS_SUCCESS then the client can now accept connections.
+ * @reserved: reserved
+ */
+struct hbm_add_client_response {
+       u8 hbm_cmd;
+       u8 me_addr;
+       u8 status;
+       u8 reserved[1];
+} __packed;
+
 /**
  * struct hbm_power_gate - power gate request/response
  *
@@ -298,5 +365,62 @@ struct hbm_flow_control {
        u8 reserved[MEI_FC_MESSAGE_RESERVED_LENGTH];
 } __packed;
 
+#define MEI_HBM_NOTIFICATION_START 1
+#define MEI_HBM_NOTIFICATION_STOP  0
+/**
+ * struct hbm_notification_request - start/stop notification request
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: address of the client in the driver
+ * @start:  start = 1 or stop = 0 asynchronous notifications
+ */
+struct hbm_notification_request {
+       u8 hbm_cmd;
+       u8 me_addr;
+       u8 host_addr;
+       u8 start;
+} __packed;
+
+/**
+ * struct hbm_notification_response - start/stop notification response
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: - address of the client in the driver
+ * @status: (mei_hbm_status) response status for the request
+ *  - MEI_HBMS_SUCCESS: successful stop/start
+ *  - MEI_HBMS_CLIENT_NOT_FOUND: if the connection could not be found.
+ *  - MEI_HBMS_ALREADY_STARTED: for start requests for a previously
+ *                         started notification.
+ *  - MEI_HBMS_NOT_STARTED: for stop request for a connected client for whom
+ *                         asynchronous notifications are currently disabled.
+ *
+ * @start:  start = 1 or stop = 0 asynchronous notifications
+ * @reserved: reserved
+ */
+struct hbm_notification_response {
+       u8 hbm_cmd;
+       u8 me_addr;
+       u8 host_addr;
+       u8 status;
+       u8 start;
+       u8 reserved[3];
+} __packed;
+
+/**
+ * struct hbm_notification - notification event
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr:  address of the client in ME
+ * @host_addr:  address of the client in the driver
+ * @reserved: reserved for alignment
+ */
+struct hbm_notification {
+       u8 hbm_cmd;
+       u8 me_addr;
+       u8 host_addr;
+       u8 reserved[1];
+} __packed;
 
 #endif
index 00c3865ca3b1d42042d78d5558eac547ea8c03a8..e374661652cd6a5460556ba8b8661c1e5247a46c 100644 (file)
@@ -331,7 +331,7 @@ void mei_stop(struct mei_device *dev)
 
        mei_cancel_work(dev);
 
-       mei_nfc_host_exit(dev);
+       mei_cl_bus_remove_devices(dev);
 
        mutex_lock(&dev->device_lock);
 
@@ -390,6 +390,7 @@ void mei_device_init(struct mei_device *dev,
        INIT_LIST_HEAD(&dev->me_clients);
        mutex_init(&dev->device_lock);
        init_rwsem(&dev->me_clients_rwsem);
+       mutex_init(&dev->cl_bus_lock);
        init_waitqueue_head(&dev->wait_hw_ready);
        init_waitqueue_head(&dev->wait_pg);
        init_waitqueue_head(&dev->wait_hbm_start);
index 3f3405269c39d537634e2895ae0ecf64ab0b1775..c418d788899418a6f0dc09fd4b89282ec487e23d 100644 (file)
@@ -403,6 +403,13 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
                        if (ret)
                                return ret;
                        break;
+
+               case MEI_FOP_NOTIFY_START:
+               case MEI_FOP_NOTIFY_STOP:
+                       ret = mei_cl_irq_notify(cl, cb, cmpl_list);
+                       if (ret)
+                               return ret;
+                       break;
                default:
                        BUG();
                }
@@ -424,6 +431,24 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 EXPORT_SYMBOL_GPL(mei_irq_write_handler);
 
 
+/**
+ * mei_connect_timeout  - connect/disconnect timeouts
+ *
+ * @cl: host client
+ */
+static void mei_connect_timeout(struct mei_cl *cl)
+{
+       struct mei_device *dev = cl->dev;
+
+       if (cl->state == MEI_FILE_CONNECTING) {
+               if (dev->hbm_f_dot_supported) {
+                       cl->state = MEI_FILE_DISCONNECT_REQUIRED;
+                       wake_up(&cl->wait);
+                       return;
+               }
+       }
+       mei_reset(dev);
+}
 
 /**
  * mei_timer - timer function.
@@ -464,7 +489,7 @@ void mei_timer(struct work_struct *work)
                if (cl->timer_count) {
                        if (--cl->timer_count == 0) {
                                dev_err(dev->dev, "timer: connect/disconnect timeout.\n");
-                               mei_reset(dev);
+                               mei_connect_timeout(cl);
                                goto out;
                        }
                }
index e9513d651cd36b611920a2f6410c905b344fbf13..b2f2486b3d757cd1bba127d8328177716d539591 100644 (file)
@@ -445,6 +445,45 @@ end:
        return rets;
 }
 
+/**
+ * mei_ioctl_client_notify_request -
+ *     propagate event notification request to client
+ *
+ * @file: pointer to file structure
+ * @request: 0 - disable, 1 - enable
+ *
+ * Return: 0 on success , <0 on error
+ */
+static int mei_ioctl_client_notify_request(struct file *file, u32 request)
+{
+       struct mei_cl *cl = file->private_data;
+
+       return mei_cl_notify_request(cl, file, request);
+}
+
+/**
+ * mei_ioctl_client_notify_get -  wait for notification request
+ *
+ * @file: pointer to file structure
+ * @notify_get: 0 - disable, 1 - enable
+ *
+ * Return: 0 on success , <0 on error
+ */
+static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get)
+{
+       struct mei_cl *cl = file->private_data;
+       bool notify_ev;
+       bool block = (file->f_flags & O_NONBLOCK) == 0;
+       int rets;
+
+       rets = mei_cl_notify_get(cl, block, &notify_ev);
+       if (rets)
+               return rets;
+
+       *notify_get = notify_ev ? 1 : 0;
+       return 0;
+}
+
 /**
  * mei_ioctl - the IOCTL function
  *
@@ -459,6 +498,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
        struct mei_device *dev;
        struct mei_cl *cl = file->private_data;
        struct mei_connect_client_data connect_data;
+       u32 notify_get, notify_req;
        int rets;
 
 
@@ -499,6 +539,33 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
 
                break;
 
+       case IOCTL_MEI_NOTIFY_SET:
+               dev_dbg(dev->dev, ": IOCTL_MEI_NOTIFY_SET.\n");
+               if (copy_from_user(&notify_req,
+                                  (char __user *)data, sizeof(notify_req))) {
+                       dev_dbg(dev->dev, "failed to copy data from userland\n");
+                       rets = -EFAULT;
+                       goto out;
+               }
+               rets = mei_ioctl_client_notify_request(file, notify_req);
+               break;
+
+       case IOCTL_MEI_NOTIFY_GET:
+               dev_dbg(dev->dev, ": IOCTL_MEI_NOTIFY_GET.\n");
+               rets = mei_ioctl_client_notify_get(file, &notify_get);
+               if (rets)
+                       goto out;
+
+               dev_dbg(dev->dev, "copy connect data to user\n");
+               if (copy_to_user((char __user *)data,
+                               &notify_get, sizeof(notify_get))) {
+                       dev_dbg(dev->dev, "failed to copy data to userland\n");
+                       rets = -EFAULT;
+                       goto out;
+
+               }
+               break;
+
        default:
                dev_err(dev->dev, ": unsupported ioctl %d.\n", cmd);
                rets = -ENOIOCTLCMD;
@@ -541,6 +608,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
        struct mei_cl *cl = file->private_data;
        struct mei_device *dev;
        unsigned int mask = 0;
+       bool notify_en;
 
        if (WARN_ON(!cl || !cl->dev))
                return POLLERR;
@@ -549,6 +617,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 
        mutex_lock(&dev->device_lock);
 
+       notify_en = cl->notify_en && (req_events & POLLPRI);
 
        if (dev->dev_state != MEI_DEV_ENABLED ||
            !mei_cl_is_connected(cl)) {
@@ -561,6 +630,12 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
                goto out;
        }
 
+       if (notify_en) {
+               poll_wait(file, &cl->ev_wait, wait);
+               if (cl->notify_ev)
+                       mask |= POLLPRI;
+       }
+
        if (req_events & (POLLIN | POLLRDNORM)) {
                poll_wait(file, &cl->rx_wait, wait);
 
@@ -575,6 +650,26 @@ out:
        return mask;
 }
 
+/**
+ * mei_fasync - asynchronous io support
+ *
+ * @fd: file descriptor
+ * @file: pointer to file structure
+ * @band: band bitmap
+ *
+ * Return: poll mask
+ */
+static int mei_fasync(int fd, struct file *file, int band)
+{
+
+       struct mei_cl *cl = file->private_data;
+
+       if (!mei_cl_is_connected(cl))
+               return POLLERR;
+
+       return fasync_helper(fd, file, band, &cl->ev_async);
+}
+
 /**
  * fw_status_show - mei device attribute show method
  *
@@ -627,6 +722,7 @@ static const struct file_operations mei_fops = {
        .release = mei_release,
        .write = mei_write,
        .poll = mei_poll,
+       .fasync = mei_fasync,
        .llseek = no_llseek
 };
 
index 453f6a333b42960a9f33cd31d70ff9e8a9d1cb8a..e25ee16c658ed2f64d47ef8df7c1a365d134fa21 100644 (file)
@@ -89,6 +89,7 @@ enum file_state {
        MEI_FILE_CONNECTED,
        MEI_FILE_DISCONNECTING,
        MEI_FILE_DISCONNECT_REPLY,
+       MEI_FILE_DISCONNECT_REQUIRED,
        MEI_FILE_DISCONNECTED,
 };
 
@@ -135,6 +136,8 @@ enum mei_wd_states {
  * @MEI_FOP_CONNECT:    connect
  * @MEI_FOP_DISCONNECT: disconnect
  * @MEI_FOP_DISCONNECT_RSP: disconnect response
+ * @MEI_FOP_NOTIFY_START:   start notification
+ * @MEI_FOP_NOTIFY_STOP:    stop notification
  */
 enum mei_cb_file_ops {
        MEI_FOP_READ = 0,
@@ -142,6 +145,8 @@ enum mei_cb_file_ops {
        MEI_FOP_CONNECT,
        MEI_FOP_DISCONNECT,
        MEI_FOP_DISCONNECT_RSP,
+       MEI_FOP_NOTIFY_START,
+       MEI_FOP_NOTIFY_STOP,
 };
 
 /*
@@ -178,7 +183,7 @@ struct mei_fw_status {
  * @client_id: me client id
  * @mei_flow_ctrl_creds: flow control credits
  * @connect_count: number connections to this client
- * @reserved: reserved
+ * @bus_added: added to bus
  */
 struct mei_me_client {
        struct list_head list;
@@ -187,7 +192,7 @@ struct mei_me_client {
        u8 client_id;
        u8 mei_flow_ctrl_creds;
        u8 connect_count;
-       u8 reserved;
+       u8 bus_added;
 };
 
 
@@ -230,18 +235,21 @@ struct mei_cl_cb {
  * @tx_wait: wait queue for tx completion
  * @rx_wait: wait queue for rx completion
  * @wait:  wait queue for management operation
+ * @ev_wait: notification wait queue
+ * @ev_async: event async notification
  * @status: connection status
  * @me_cl: fw client connected
  * @host_client_id: host id
  * @mei_flow_ctrl_creds: transmit flow credentials
  * @timer_count:  watchdog timer for operation completion
  * @reserved: reserved for alignment
+ * @notify_en: notification - enabled/disabled
+ * @notify_ev: pending notification event
  * @writing_state: state of the tx
  * @rd_pending: pending read credits
  * @rd_completed: completed read
  *
- * @device: device on the mei client bus
- * @device_link:  link to bus clients
+ * @cldev: device on the mei client bus
  */
 struct mei_cl {
        struct list_head link;
@@ -250,19 +258,21 @@ struct mei_cl {
        wait_queue_head_t tx_wait;
        wait_queue_head_t rx_wait;
        wait_queue_head_t wait;
+       wait_queue_head_t ev_wait;
+       struct fasync_struct *ev_async;
        int status;
        struct mei_me_client *me_cl;
        u8 host_client_id;
        u8 mei_flow_ctrl_creds;
        u8 timer_count;
        u8 reserved;
+       u8 notify_en;
+       u8 notify_ev;
        enum mei_file_transaction_states writing_state;
        struct list_head rd_pending;
        struct list_head rd_completed;
 
-       /* MEI CL bus data */
-       struct mei_cl_device *device;
-       struct list_head device_link;
+       struct mei_cl_device *cldev;
 };
 
 /** struct mei_hw_ops
@@ -329,21 +339,16 @@ struct mei_hw_ops {
 };
 
 /* MEI bus API*/
-
-struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
-                                       struct mei_me_client *me_cl,
-                                       struct mei_cl *cl,
-                                       char *name);
-void mei_cl_remove_device(struct mei_cl_device *device);
-
+void mei_cl_bus_rescan(struct mei_device *bus);
+void mei_cl_dev_fixup(struct mei_cl_device *dev);
 ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
                        bool blocking);
 ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
 void mei_cl_bus_rx_event(struct mei_cl *cl);
-void mei_cl_bus_remove_devices(struct mei_device *dev);
+void mei_cl_bus_notify_event(struct mei_cl *cl);
+void mei_cl_bus_remove_devices(struct mei_device *bus);
 int mei_cl_bus_init(void);
 void mei_cl_bus_exit(void);
-struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev, uuid_le uuid);
 
 /**
  * enum mei_pg_event - power gating transition events
@@ -416,7 +421,10 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @wr_msg      : the buffer for hbm control messages
  *
  * @version     : HBM protocol version in use
- * @hbm_f_pg_supported : hbm feature pgi protocol
+ * @hbm_f_pg_supported  : hbm feature pgi protocol
+ * @hbm_f_dc_supported  : hbm feature dynamic clients
+ * @hbm_f_dot_supported : hbm feature disconnect on timeout
+ * @hbm_f_ev_supported  : hbm feature event notification
  *
  * @me_clients_rwsem: rw lock over me_clients list
  * @me_clients  : list of FW clients
@@ -447,6 +455,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @reset_work  : work item for the device reset
  *
  * @device_list : mei client bus list
+ * @cl_bus_lock : client bus list lock
  *
  * @dbgfs_dir   : debugfs mei root directory
  *
@@ -509,6 +518,9 @@ struct mei_device {
 
        struct hbm_version version;
        unsigned int hbm_f_pg_supported:1;
+       unsigned int hbm_f_dc_supported:1;
+       unsigned int hbm_f_dot_supported:1;
+       unsigned int hbm_f_ev_supported:1;
 
        struct rw_semaphore me_clients_rwsem;
        struct list_head me_clients;
@@ -543,6 +555,7 @@ struct mei_device {
 
        /* List of bus devices */
        struct list_head device_list;
+       struct mutex cl_bus_lock;
 
 #if IS_ENABLED(CONFIG_DEBUG_FS)
        struct dentry *dbgfs_dir;
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
deleted file mode 100644 (file)
index 290ef30..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- *
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2013, 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-
-#include <linux/mei_cl_bus.h>
-
-#include "mei_dev.h"
-#include "client.h"
-
-struct mei_nfc_cmd {
-       u8 command;
-       u8 status;
-       u16 req_id;
-       u32 reserved;
-       u16 data_size;
-       u8 sub_command;
-       u8 data[];
-} __packed;
-
-struct mei_nfc_reply {
-       u8 command;
-       u8 status;
-       u16 req_id;
-       u32 reserved;
-       u16 data_size;
-       u8 sub_command;
-       u8 reply_status;
-       u8 data[];
-} __packed;
-
-struct mei_nfc_if_version {
-       u8 radio_version_sw[3];
-       u8 reserved[3];
-       u8 radio_version_hw[3];
-       u8 i2c_addr;
-       u8 fw_ivn;
-       u8 vendor_id;
-       u8 radio_type;
-} __packed;
-
-struct mei_nfc_connect {
-       u8 fw_ivn;
-       u8 vendor_id;
-} __packed;
-
-struct mei_nfc_connect_resp {
-       u8 fw_ivn;
-       u8 vendor_id;
-       u16 me_major;
-       u16 me_minor;
-       u16 me_hotfix;
-       u16 me_build;
-} __packed;
-
-struct mei_nfc_hci_hdr {
-       u8 cmd;
-       u8 status;
-       u16 req_id;
-       u32 reserved;
-       u16 data_size;
-} __packed;
-
-#define MEI_NFC_CMD_MAINTENANCE 0x00
-#define MEI_NFC_CMD_HCI_SEND 0x01
-#define MEI_NFC_CMD_HCI_RECV 0x02
-
-#define MEI_NFC_SUBCMD_CONNECT    0x00
-#define MEI_NFC_SUBCMD_IF_VERSION 0x01
-
-#define MEI_NFC_HEADER_SIZE 10
-
-/**
- * struct mei_nfc_dev - NFC mei device
- *
- * @me_cl: NFC me client
- * @cl: NFC host client
- * @cl_info: NFC info host client
- * @init_work: perform connection to the info client
- * @fw_ivn: NFC Interface Version Number
- * @vendor_id: NFC manufacturer ID
- * @radio_type: NFC radio type
- * @bus_name: bus name
- *
- */
-struct mei_nfc_dev {
-       struct mei_me_client *me_cl;
-       struct mei_cl *cl;
-       struct mei_cl *cl_info;
-       struct work_struct init_work;
-       u8 fw_ivn;
-       u8 vendor_id;
-       u8 radio_type;
-       char *bus_name;
-};
-
-/* UUIDs for NFC F/W clients */
-const uuid_le mei_nfc_guid = UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50,
-                                    0x94, 0xd4, 0x50, 0x26,
-                                    0x67, 0x23, 0x77, 0x5c);
-
-static const uuid_le mei_nfc_info_guid = UUID_LE(0xd2de1625, 0x382d, 0x417d,
-                                       0x48, 0xa4, 0xef, 0xab,
-                                       0xba, 0x8a, 0x12, 0x06);
-
-/* Vendors */
-#define MEI_NFC_VENDOR_INSIDE 0x00
-#define MEI_NFC_VENDOR_NXP    0x01
-
-/* Radio types */
-#define MEI_NFC_VENDOR_INSIDE_UREAD 0x00
-#define MEI_NFC_VENDOR_NXP_PN544    0x01
-
-static void mei_nfc_free(struct mei_nfc_dev *ndev)
-{
-       if (!ndev)
-               return;
-
-       if (ndev->cl) {
-               list_del(&ndev->cl->device_link);
-               mei_cl_unlink(ndev->cl);
-               kfree(ndev->cl);
-       }
-
-       if (ndev->cl_info) {
-               list_del(&ndev->cl_info->device_link);
-               mei_cl_unlink(ndev->cl_info);
-               kfree(ndev->cl_info);
-       }
-
-       mei_me_cl_put(ndev->me_cl);
-       kfree(ndev);
-}
-
-static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
-{
-       struct mei_device *dev;
-
-       if (!ndev->cl)
-               return -ENODEV;
-
-       dev = ndev->cl->dev;
-
-       switch (ndev->vendor_id) {
-       case MEI_NFC_VENDOR_INSIDE:
-               switch (ndev->radio_type) {
-               case MEI_NFC_VENDOR_INSIDE_UREAD:
-                       ndev->bus_name = "microread";
-                       return 0;
-
-               default:
-                       dev_err(dev->dev, "Unknown radio type 0x%x\n",
-                               ndev->radio_type);
-
-                       return -EINVAL;
-               }
-
-       case MEI_NFC_VENDOR_NXP:
-               switch (ndev->radio_type) {
-               case MEI_NFC_VENDOR_NXP_PN544:
-                       ndev->bus_name = "pn544";
-                       return 0;
-               default:
-                       dev_err(dev->dev, "Unknown radio type 0x%x\n",
-                               ndev->radio_type);
-
-                       return -EINVAL;
-               }
-
-       default:
-               dev_err(dev->dev, "Unknown vendor ID 0x%x\n",
-                       ndev->vendor_id);
-
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
-{
-       struct mei_device *dev;
-       struct mei_cl *cl;
-
-       struct mei_nfc_cmd cmd;
-       struct mei_nfc_reply *reply = NULL;
-       struct mei_nfc_if_version *version;
-       size_t if_version_length;
-       int bytes_recv, ret;
-
-       cl = ndev->cl_info;
-       dev = cl->dev;
-
-       memset(&cmd, 0, sizeof(struct mei_nfc_cmd));
-       cmd.command = MEI_NFC_CMD_MAINTENANCE;
-       cmd.data_size = 1;
-       cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
-
-       ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
-       if (ret < 0) {
-               dev_err(dev->dev, "Could not send IF version cmd\n");
-               return ret;
-       }
-
-       /* to be sure on the stack we alloc memory */
-       if_version_length = sizeof(struct mei_nfc_reply) +
-               sizeof(struct mei_nfc_if_version);
-
-       reply = kzalloc(if_version_length, GFP_KERNEL);
-       if (!reply)
-               return -ENOMEM;
-
-       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
-       if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
-               dev_err(dev->dev, "Could not read IF version\n");
-               ret = -EIO;
-               goto err;
-       }
-
-       version = (struct mei_nfc_if_version *)reply->data;
-
-       ndev->fw_ivn = version->fw_ivn;
-       ndev->vendor_id = version->vendor_id;
-       ndev->radio_type = version->radio_type;
-
-err:
-       kfree(reply);
-       return ret;
-}
-
-static void mei_nfc_init(struct work_struct *work)
-{
-       struct mei_device *dev;
-       struct mei_cl_device *cldev;
-       struct mei_nfc_dev *ndev;
-       struct mei_cl *cl_info;
-       struct mei_me_client *me_cl_info;
-
-       ndev = container_of(work, struct mei_nfc_dev, init_work);
-
-       cl_info = ndev->cl_info;
-       dev = cl_info->dev;
-
-       mutex_lock(&dev->device_lock);
-
-       /* check for valid client id */
-       me_cl_info = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
-       if (!me_cl_info) {
-               mutex_unlock(&dev->device_lock);
-               dev_info(dev->dev, "nfc: failed to find the info client\n");
-               goto err;
-       }
-
-       if (mei_cl_connect(cl_info, me_cl_info, NULL) < 0) {
-               mei_me_cl_put(me_cl_info);
-               mutex_unlock(&dev->device_lock);
-               dev_err(dev->dev, "Could not connect to the NFC INFO ME client");
-
-               goto err;
-       }
-       mei_me_cl_put(me_cl_info);
-       mutex_unlock(&dev->device_lock);
-
-       if (mei_nfc_if_version(ndev) < 0) {
-               dev_err(dev->dev, "Could not get the NFC interface version");
-
-               goto err;
-       }
-
-       dev_info(dev->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
-               ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);
-
-       mutex_lock(&dev->device_lock);
-
-       if (mei_cl_disconnect(cl_info) < 0) {
-               mutex_unlock(&dev->device_lock);
-               dev_err(dev->dev, "Could not disconnect the NFC INFO ME client");
-
-               goto err;
-       }
-
-       mutex_unlock(&dev->device_lock);
-
-       if (mei_nfc_build_bus_name(ndev) < 0) {
-               dev_err(dev->dev, "Could not build the bus ID name\n");
-               return;
-       }
-
-       cldev = mei_cl_add_device(dev, ndev->me_cl, ndev->cl,
-                                 ndev->bus_name);
-       if (!cldev) {
-               dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");
-
-               goto err;
-       }
-
-       cldev->priv_data = ndev;
-
-
-       return;
-
-err:
-       mutex_lock(&dev->device_lock);
-       mei_nfc_free(ndev);
-       mutex_unlock(&dev->device_lock);
-
-}
-
-
-int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
-{
-       struct mei_nfc_dev *ndev;
-       struct mei_cl *cl_info, *cl;
-       int ret;
-
-
-       /* in case of internal reset bail out
-        * as the device is already setup
-        */
-       cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
-       if (cl)
-               return 0;
-
-       ndev = kzalloc(sizeof(struct mei_nfc_dev), GFP_KERNEL);
-       if (!ndev) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       ndev->me_cl = mei_me_cl_get(me_cl);
-       if (!ndev->me_cl) {
-               ret = -ENODEV;
-               goto err;
-       }
-
-       cl_info = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
-       if (IS_ERR(cl_info)) {
-               ret = PTR_ERR(cl_info);
-               goto err;
-       }
-
-       list_add_tail(&cl_info->device_link, &dev->device_list);
-
-       ndev->cl_info = cl_info;
-
-       cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
-       if (IS_ERR(cl)) {
-               ret = PTR_ERR(cl);
-               goto err;
-       }
-
-       list_add_tail(&cl->device_link, &dev->device_list);
-
-       ndev->cl = cl;
-
-       INIT_WORK(&ndev->init_work, mei_nfc_init);
-       schedule_work(&ndev->init_work);
-
-       return 0;
-
-err:
-       mei_nfc_free(ndev);
-
-       return ret;
-}
-
-void mei_nfc_host_exit(struct mei_device *dev)
-{
-       struct mei_nfc_dev *ndev;
-       struct mei_cl *cl;
-       struct mei_cl_device *cldev;
-
-       cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
-       if (!cl)
-               return;
-
-       cldev = cl->device;
-       if (!cldev)
-               return;
-
-       ndev = (struct mei_nfc_dev *)cldev->priv_data;
-       if (ndev)
-               cancel_work_sync(&ndev->init_work);
-
-       cldev->priv_data = NULL;
-
-       /* Need to remove the device here
-        * since mei_nfc_free will unlink the clients
-        */
-       mei_cl_remove_device(cldev);
-
-       mutex_lock(&dev->device_lock);
-       mei_nfc_free(ndev);
-       mutex_unlock(&dev->device_lock);
-}
-
-
index 23f71f5ce4fb07be4bb9c32021bf3babef6b938d..27678d8154e074ea698952832aac64bb843032f9 100644 (file)
@@ -82,6 +82,11 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch8_cfg)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch8_cfg)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_cfg)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_cfg)},
+
        /* required last entry */
        {0, }
 };
@@ -128,6 +133,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data);
        struct mei_device *dev;
        struct mei_me_hw *hw;
+       unsigned int irqflags;
        int err;
 
 
@@ -180,17 +186,12 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_enable_msi(pdev);
 
         /* request and enable interrupt */
-       if (pci_dev_msi_enabled(pdev))
-               err = request_threaded_irq(pdev->irq,
-                       NULL,
-                       mei_me_irq_thread_handler,
-                       IRQF_ONESHOT, KBUILD_MODNAME, dev);
-       else
-               err = request_threaded_irq(pdev->irq,
+       irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
+
+       err = request_threaded_irq(pdev->irq,
                        mei_me_irq_quick_handler,
                        mei_me_irq_thread_handler,
-                       IRQF_SHARED, KBUILD_MODNAME, dev);
-
+                       irqflags, KBUILD_MODNAME, dev);
        if (err) {
                dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
                       pdev->irq);
@@ -319,6 +320,7 @@ static int mei_me_pci_resume(struct device *device)
 {
        struct pci_dev *pdev = to_pci_dev(device);
        struct mei_device *dev;
+       unsigned int irqflags;
        int err;
 
        dev = pci_get_drvdata(pdev);
@@ -327,17 +329,13 @@ static int mei_me_pci_resume(struct device *device)
 
        pci_enable_msi(pdev);
 
+       irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
+
        /* request and enable interrupt */
-       if (pci_dev_msi_enabled(pdev))
-               err = request_threaded_irq(pdev->irq,
-                       NULL,
-                       mei_me_irq_thread_handler,
-                       IRQF_ONESHOT, KBUILD_MODNAME, dev);
-       else
-               err = request_threaded_irq(pdev->irq,
+       err = request_threaded_irq(pdev->irq,
                        mei_me_irq_quick_handler,
                        mei_me_irq_thread_handler,
-                       IRQF_SHARED, KBUILD_MODNAME, dev);
+                       irqflags, KBUILD_MODNAME, dev);
 
        if (err) {
                dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
diff --git a/drivers/misc/qcom-coincell.c b/drivers/misc/qcom-coincell.c
new file mode 100644 (file)
index 0000000..7b4a2da
--- /dev/null
@@ -0,0 +1,152 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, Sony Mobile Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+struct qcom_coincell {
+       struct device   *dev;
+       struct regmap   *regmap;
+       u32             base_addr;
+};
+
+#define QCOM_COINCELL_REG_RSET         0x44
+#define QCOM_COINCELL_REG_VSET         0x45
+#define QCOM_COINCELL_REG_ENABLE       0x46
+
+#define QCOM_COINCELL_ENABLE           BIT(7)
+
+static const int qcom_rset_map[] = { 2100, 1700, 1200, 800 };
+static const int qcom_vset_map[] = { 2500, 3200, 3100, 3000 };
+/* NOTE: for pm8921 and others, voltage of 2500 is 16 (10000b), not 0 */
+
+/* if enable==0, rset and vset are ignored */
+static int qcom_coincell_chgr_config(struct qcom_coincell *chgr, int rset,
+                                    int vset, bool enable)
+{
+       int i, j, rc;
+
+       /* if disabling, just do that and skip other operations */
+       if (!enable)
+               return regmap_write(chgr->regmap,
+                         chgr->base_addr + QCOM_COINCELL_REG_ENABLE, 0);
+
+       /* find index for current-limiting resistor */
+       for (i = 0; i < ARRAY_SIZE(qcom_rset_map); i++)
+               if (rset == qcom_rset_map[i])
+                       break;
+
+       if (i >= ARRAY_SIZE(qcom_rset_map)) {
+               dev_err(chgr->dev, "invalid rset-ohms value %d\n", rset);
+               return -EINVAL;
+       }
+
+       /* find index for charge voltage */
+       for (j = 0; j < ARRAY_SIZE(qcom_vset_map); j++)
+               if (vset == qcom_vset_map[j])
+                       break;
+
+       if (j >= ARRAY_SIZE(qcom_vset_map)) {
+               dev_err(chgr->dev, "invalid vset-millivolts value %d\n", vset);
+               return -EINVAL;
+       }
+
+       rc = regmap_write(chgr->regmap,
+                         chgr->base_addr + QCOM_COINCELL_REG_RSET, i);
+       if (rc) {
+               /*
+                * This is mainly to flag a bad base_addr (reg) from dts.
+                * Other failures writing to the registers should be
+                * extremely rare, or indicative of problems that
+                * should be reported elsewhere (eg. spmi failure).
+                */
+               dev_err(chgr->dev, "could not write to RSET register\n");
+               return rc;
+       }
+
+       rc = regmap_write(chgr->regmap,
+               chgr->base_addr + QCOM_COINCELL_REG_VSET, j);
+       if (rc)
+               return rc;
+
+       /* set 'enable' register */
+       return regmap_write(chgr->regmap,
+                           chgr->base_addr + QCOM_COINCELL_REG_ENABLE,
+                           QCOM_COINCELL_ENABLE);
+}
+
+static int qcom_coincell_probe(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct qcom_coincell chgr;
+       u32 rset, vset;
+       bool enable;
+       int rc;
+
+       chgr.dev = &pdev->dev;
+
+       chgr.regmap = dev_get_regmap(pdev->dev.parent, NULL);
+       if (!chgr.regmap) {
+               dev_err(chgr.dev, "Unable to get regmap\n");
+               return -EINVAL;
+       }
+
+       rc = of_property_read_u32(node, "reg", &chgr.base_addr);
+       if (rc)
+               return rc;
+
+       enable = !of_property_read_bool(node, "qcom,charger-disable");
+
+       if (enable) {
+               rc = of_property_read_u32(node, "qcom,rset-ohms", &rset);
+               if (rc) {
+                       dev_err(chgr.dev,
+                               "can't find 'qcom,rset-ohms' in DT block");
+                       return rc;
+               }
+
+               rc = of_property_read_u32(node, "qcom,vset-millivolts", &vset);
+               if (rc) {
+                       dev_err(chgr.dev,
+                           "can't find 'qcom,vset-millivolts' in DT block");
+                       return rc;
+               }
+       }
+
+       return qcom_coincell_chgr_config(&chgr, rset, vset, enable);
+}
+
+static const struct of_device_id qcom_coincell_match_table[] = {
+       { .compatible = "qcom,pm8941-coincell", },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, qcom_coincell_match_table);
+
+static struct platform_driver qcom_coincell_driver = {
+       .driver = {
+               .name           = "qcom-spmi-coincell",
+               .of_match_table = qcom_coincell_match_table,
+       },
+       .probe          = qcom_coincell_probe,
+};
+
+module_platform_driver(qcom_coincell_driver);
+
+MODULE_DESCRIPTION("Qualcomm PMIC coincell charger driver");
+MODULE_LICENSE("GPL v2");
index 5027b8ffae4378e0aeda58513f993778bb34c30c..71b64550b591840ef1712f09f3f93a107d04e2ae 100644 (file)
@@ -36,8 +36,6 @@
 #include <linux/skbuff.h>
 #include <linux/ti_wilink_st.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
 
 #define MAX_ST_DEVICES 3       /* Imagine 1 on each UART for now */
 static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
@@ -45,9 +43,6 @@ static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
 /**********************************************************************/
 /* internal functions */
 
-struct ti_st_plat_data *dt_pdata;
-static struct ti_st_plat_data *get_platform_data(struct device *dev);
-
 /**
  * st_get_plat_device -
  *     function which returns the reference to the platform device
@@ -469,12 +464,7 @@ long st_kim_start(void *kim_data)
        struct kim_data_s       *kim_gdata = (struct kim_data_s *)kim_data;
 
        pr_info(" %s", __func__);
-       if (kim_gdata->kim_pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else {
-               pdata = kim_gdata->kim_pdev->dev.platform_data;
-       }
+       pdata = kim_gdata->kim_pdev->dev.platform_data;
 
        do {
                /* platform specific enabling code here */
@@ -482,9 +472,9 @@ long st_kim_start(void *kim_data)
                        pdata->chip_enable(kim_gdata);
 
                /* Configure BT nShutdown to HIGH state */
-               gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+               gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
                mdelay(5);      /* FIXME: a proper toggle */
-               gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+               gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
                mdelay(100);
                /* re-initialize the completion */
                reinit_completion(&kim_gdata->ldisc_installed);
@@ -534,18 +524,12 @@ long st_kim_stop(void *kim_data)
 {
        long err = 0;
        struct kim_data_s       *kim_gdata = (struct kim_data_s *)kim_data;
-       struct ti_st_plat_data  *pdata;
+       struct ti_st_plat_data  *pdata =
+               kim_gdata->kim_pdev->dev.platform_data;
        struct tty_struct       *tty = kim_gdata->core_data->tty;
 
        reinit_completion(&kim_gdata->ldisc_installed);
 
-       if (kim_gdata->kim_pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else
-               pdata = kim_gdata->kim_pdev->dev.platform_data;
-
-
        if (tty) {      /* can be called before ldisc is installed */
                /* Flush any pending characters in the driver and discipline. */
                tty_ldisc_flush(tty);
@@ -566,11 +550,11 @@ long st_kim_stop(void *kim_data)
        }
 
        /* By default configure BT nShutdown to LOW state */
-       gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+       gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
        mdelay(1);
-       gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+       gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
        mdelay(1);
-       gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+       gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
 
        /* platform specific disable */
        if (pdata->chip_disable)
@@ -737,52 +721,13 @@ static const struct file_operations list_debugfs_fops = {
  * board-*.c file
  */
 
-static const struct of_device_id kim_of_match[] = {
-{
-       .compatible = "kim",
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, kim_of_match);
-
-static struct ti_st_plat_data *get_platform_data(struct device *dev)
-{
-       struct device_node *np = dev->of_node;
-       const u32 *dt_property;
-       int len;
-
-       dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL);
-       if (!dt_pdata)
-               return NULL;
-
-       dt_property = of_get_property(np, "dev_name", &len);
-       if (dt_property)
-               memcpy(&dt_pdata->dev_name, dt_property, len);
-       of_property_read_u32(np, "nshutdown_gpio",
-                            &dt_pdata->nshutdown_gpio);
-       of_property_read_u32(np, "flow_cntrl", &dt_pdata->flow_cntrl);
-       of_property_read_u32(np, "baud_rate", &dt_pdata->baud_rate);
-
-       return dt_pdata;
-}
-
 static struct dentry *kim_debugfs_dir;
 static int kim_probe(struct platform_device *pdev)
 {
        struct kim_data_s       *kim_gdata;
-       struct ti_st_plat_data  *pdata;
+       struct ti_st_plat_data  *pdata = pdev->dev.platform_data;
        int err;
 
-       if (pdev->dev.of_node)
-               pdata = get_platform_data(&pdev->dev);
-       else
-               pdata = pdev->dev.platform_data;
-
-       if (pdata == NULL) {
-               dev_err(&pdev->dev, "Platform Data is missing\n");
-               return -ENXIO;
-       }
-
        if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
                /* multiple devices could exist */
                st_kim_devices[pdev->id] = pdev;
@@ -863,16 +808,9 @@ err_core_init:
 static int kim_remove(struct platform_device *pdev)
 {
        /* free the GPIOs requested */
-       struct ti_st_plat_data  *pdata;
+       struct ti_st_plat_data  *pdata = pdev->dev.platform_data;
        struct kim_data_s       *kim_gdata;
 
-       if (pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else {
-               pdata = pdev->dev.platform_data;
-       }
-
        kim_gdata = platform_get_drvdata(pdev);
 
        /* Free the Bluetooth/FM/GPIO
@@ -890,22 +828,12 @@ static int kim_remove(struct platform_device *pdev)
 
        kfree(kim_gdata);
        kim_gdata = NULL;
-       kfree(dt_pdata);
-       dt_pdata = NULL;
-
        return 0;
 }
 
 static int kim_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct ti_st_plat_data  *pdata;
-
-       if (pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else {
-               pdata = pdev->dev.platform_data;
-       }
+       struct ti_st_plat_data  *pdata = pdev->dev.platform_data;
 
        if (pdata->suspend)
                return pdata->suspend(pdev, state);
@@ -915,14 +843,7 @@ static int kim_suspend(struct platform_device *pdev, pm_message_t state)
 
 static int kim_resume(struct platform_device *pdev)
 {
-       struct ti_st_plat_data  *pdata;
-
-       if (pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else {
-               pdata = pdev->dev.platform_data;
-       }
+       struct ti_st_plat_data  *pdata = pdev->dev.platform_data;
 
        if (pdata->resume)
                return pdata->resume(pdev);
@@ -939,8 +860,6 @@ static struct platform_driver kim_platform_driver = {
        .resume = kim_resume,
        .driver = {
                .name = "kim",
-               .owner = THIS_MODULE,
-               .of_match_table = of_match_ptr(kim_of_match),
        },
 };
 
index 518e1b7f2f95a58c2611cb20640de7228e8a8504..93b4d67cc4a3a6bc30197acf709d4f73faaad070 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/ti_wilink_st.h>
 
 /**********************************************************************/
-
 /* internal functions */
 static void send_ll_cmd(struct st_data_s *st_data,
        unsigned char cmd)
@@ -54,13 +53,7 @@ static void ll_device_want_to_sleep(struct st_data_s *st_data)
 
        /* communicate to platform about chip asleep */
        kim_data = st_data->kim_data;
-       if (kim_data->kim_pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else {
-               pdata = kim_data->kim_pdev->dev.platform_data;
-       }
-
+       pdata = kim_data->kim_pdev->dev.platform_data;
        if (pdata->chip_asleep)
                pdata->chip_asleep(NULL);
 }
@@ -93,13 +86,7 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data)
 
        /* communicate to platform about chip wakeup */
        kim_data = st_data->kim_data;
-       if (kim_data->kim_pdev->dev.of_node) {
-               pr_debug("use device tree data");
-               pdata = dt_pdata;
-       } else {
-               pdata = kim_data->kim_pdev->dev.platform_data;
-       }
-
+       pdata = kim_data->kim_pdev->dev.platform_data;
        if (pdata->chip_awake)
                pdata->chip_awake(NULL);
 }
index b00335652e52ac45087a65510f0c82a799920879..87a13374fdc0daac33fc84f6dc0b69740df7d076 100644 (file)
@@ -446,7 +446,6 @@ MODULE_DEVICE_TABLE(i2c, tsl2550_id);
 static struct i2c_driver tsl2550_driver = {
        .driver = {
                .name   = TSL2550_DRV_NAME,
-               .owner  = THIS_MODULE,
                .pm     = TSL2550_PM_OPS,
        },
        .probe  = tsl2550_probe,
index 191617492181bcfb1a8ec6ddce27f725f1b8ca07..ffb56340d0c7c28bf2daaf0f512ae835fa659f38 100644 (file)
@@ -46,7 +46,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.3-k");
+MODULE_VERSION("1.3.0.0-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -110,9 +110,18 @@ MODULE_LICENSE("GPL");
  */
 #define VMW_BALLOON_HV_PORT            0x5670
 #define VMW_BALLOON_HV_MAGIC           0x456c6d6f
-#define VMW_BALLOON_PROTOCOL_VERSION   2
 #define VMW_BALLOON_GUEST_ID           1       /* Linux */
 
+enum vmwballoon_capabilities {
+       /*
+        * Bit 0 is reserved and not associated to any capability.
+        */
+       VMW_BALLOON_BASIC_CMDS          = (1 << 1),
+       VMW_BALLOON_BATCHED_CMDS        = (1 << 2)
+};
+
+#define VMW_BALLOON_CAPABILITIES       (VMW_BALLOON_BASIC_CMDS)
+
 #define VMW_BALLOON_CMD_START          0
 #define VMW_BALLOON_CMD_GET_TARGET     1
 #define VMW_BALLOON_CMD_LOCK           2
@@ -120,32 +129,36 @@ MODULE_LICENSE("GPL");
 #define VMW_BALLOON_CMD_GUEST_ID       4
 
 /* error codes */
-#define VMW_BALLOON_SUCCESS            0
-#define VMW_BALLOON_FAILURE            -1
-#define VMW_BALLOON_ERROR_CMD_INVALID  1
-#define VMW_BALLOON_ERROR_PPN_INVALID  2
-#define VMW_BALLOON_ERROR_PPN_LOCKED   3
-#define VMW_BALLOON_ERROR_PPN_UNLOCKED 4
-#define VMW_BALLOON_ERROR_PPN_PINNED   5
-#define VMW_BALLOON_ERROR_PPN_NOTNEEDED        6
-#define VMW_BALLOON_ERROR_RESET                7
-#define VMW_BALLOON_ERROR_BUSY         8
-
-#define VMWARE_BALLOON_CMD(cmd, data, result)          \
-({                                                     \
-       unsigned long __stat, __dummy1, __dummy2;       \
-       __asm__ __volatile__ ("inl %%dx" :              \
-               "=a"(__stat),                           \
-               "=c"(__dummy1),                         \
-               "=d"(__dummy2),                         \
-               "=b"(result) :                          \
-               "0"(VMW_BALLOON_HV_MAGIC),              \
-               "1"(VMW_BALLOON_CMD_##cmd),             \
-               "2"(VMW_BALLOON_HV_PORT),               \
-               "3"(data) :                             \
-               "memory");                              \
-       result &= -1UL;                                 \
-       __stat & -1UL;                                  \
+#define VMW_BALLOON_SUCCESS                    0
+#define VMW_BALLOON_FAILURE                    -1
+#define VMW_BALLOON_ERROR_CMD_INVALID          1
+#define VMW_BALLOON_ERROR_PPN_INVALID          2
+#define VMW_BALLOON_ERROR_PPN_LOCKED           3
+#define VMW_BALLOON_ERROR_PPN_UNLOCKED         4
+#define VMW_BALLOON_ERROR_PPN_PINNED           5
+#define VMW_BALLOON_ERROR_PPN_NOTNEEDED                6
+#define VMW_BALLOON_ERROR_RESET                        7
+#define VMW_BALLOON_ERROR_BUSY                 8
+
+#define VMW_BALLOON_SUCCESS_WITH_CAPABILITIES  (0x03000000)
+
+#define VMWARE_BALLOON_CMD(cmd, data, result)                  \
+({                                                             \
+       unsigned long __status, __dummy1, __dummy2;             \
+       __asm__ __volatile__ ("inl %%dx" :                      \
+               "=a"(__status),                                 \
+               "=c"(__dummy1),                                 \
+               "=d"(__dummy2),                                 \
+               "=b"(result) :                                  \
+               "0"(VMW_BALLOON_HV_MAGIC),                      \
+               "1"(VMW_BALLOON_CMD_##cmd),                     \
+               "2"(VMW_BALLOON_HV_PORT),                       \
+               "3"(data) :                                     \
+               "memory");                                      \
+       if (VMW_BALLOON_CMD_##cmd == VMW_BALLOON_CMD_START)     \
+               result = __dummy1;                              \
+       result &= -1UL;                                         \
+       __status & -1UL;                                        \
 })
 
 #ifdef CONFIG_DEBUG_FS
@@ -223,11 +236,12 @@ static struct vmballoon balloon;
  */
 static bool vmballoon_send_start(struct vmballoon *b)
 {
-       unsigned long status, dummy;
+       unsigned long status, capabilities;
 
        STATS_INC(b->stats.start);
 
-       status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_PROTOCOL_VERSION, dummy);
+       status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_CAPABILITIES,
+                               capabilities);
        if (status == VMW_BALLOON_SUCCESS)
                return true;
 
@@ -402,55 +416,37 @@ static void vmballoon_reset(struct vmballoon *b)
 }
 
 /*
- * Allocate (or reserve) a page for the balloon and notify the host.  If host
- * refuses the page put it on "refuse" list and allocate another one until host
- * is satisfied. "Refused" pages are released at the end of inflation cycle
- * (when we allocate b->rate_alloc pages).
+ * Notify the host of a ballooned page. If host rejects the page put it on the
+ * refuse list, those refused page are then released at the end of the
+ * inflation cycle.
  */
-static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
+static int vmballoon_lock_page(struct vmballoon *b, struct page *page)
 {
-       struct page *page;
-       gfp_t flags;
-       unsigned int hv_status;
-       int locked;
-       flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
-
-       do {
-               if (!can_sleep)
-                       STATS_INC(b->stats.alloc);
-               else
-                       STATS_INC(b->stats.sleep_alloc);
+       int locked, hv_status;
 
-               page = alloc_page(flags);
-               if (!page) {
-                       if (!can_sleep)
-                               STATS_INC(b->stats.alloc_fail);
-                       else
-                               STATS_INC(b->stats.sleep_alloc_fail);
-                       return -ENOMEM;
-               }
+       locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
+       if (locked > 0) {
+               STATS_INC(b->stats.refused_alloc);
 
-               /* inform monitor */
-               locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
-               if (locked > 0) {
-                       STATS_INC(b->stats.refused_alloc);
-
-                       if (hv_status == VMW_BALLOON_ERROR_RESET ||
-                           hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
-                               __free_page(page);
-                               return -EIO;
-                       }
+               if (hv_status == VMW_BALLOON_ERROR_RESET ||
+                               hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
+                       __free_page(page);
+                       return -EIO;
+               }
 
-                       /*
-                        * Place page on the list of non-balloonable pages
-                        * and retry allocation, unless we already accumulated
-                        * too many of them, in which case take a breather.
-                        */
+               /*
+                * Place page on the list of non-balloonable pages
+                * and retry allocation, unless we already accumulated
+                * too many of them, in which case take a breather.
+                */
+               if (b->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
+                       b->n_refused_pages++;
                        list_add(&page->lru, &b->refused_pages);
-                       if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
-                               return -EIO;
+               } else {
+                       __free_page(page);
                }
-       } while (locked != 0);
+               return -EIO;
+       }
 
        /* track allocated page */
        list_add(&page->lru, &b->pages);
@@ -512,7 +508,7 @@ static void vmballoon_inflate(struct vmballoon *b)
        unsigned int i;
        unsigned int allocations = 0;
        int error = 0;
-       bool alloc_can_sleep = false;
+       gfp_t flags = VMW_PAGE_ALLOC_NOSLEEP;
 
        pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
 
@@ -543,19 +539,16 @@ static void vmballoon_inflate(struct vmballoon *b)
                 __func__, goal, rate, b->rate_alloc);
 
        for (i = 0; i < goal; i++) {
+               struct page *page;
 
-               error = vmballoon_reserve_page(b, alloc_can_sleep);
-               if (error) {
-                       if (error != -ENOMEM) {
-                               /*
-                                * Not a page allocation failure, stop this
-                                * cycle. Maybe we'll get new target from
-                                * the host soon.
-                                */
-                               break;
-                       }
+               if (flags == VMW_PAGE_ALLOC_NOSLEEP)
+                       STATS_INC(b->stats.alloc);
+               else
+                       STATS_INC(b->stats.sleep_alloc);
 
-                       if (alloc_can_sleep) {
+               page = alloc_page(flags);
+               if (!page) {
+                       if (flags == VMW_PAGE_ALLOC_CANSLEEP) {
                                /*
                                 * CANSLEEP page allocation failed, so guest
                                 * is under severe memory pressure. Quickly
@@ -563,8 +556,10 @@ static void vmballoon_inflate(struct vmballoon *b)
                                 */
                                b->rate_alloc = max(b->rate_alloc / 2,
                                                    VMW_BALLOON_RATE_ALLOC_MIN);
+                               STATS_INC(b->stats.sleep_alloc_fail);
                                break;
                        }
+                       STATS_INC(b->stats.alloc_fail);
 
                        /*
                         * NOSLEEP page allocation failed, so the guest is
@@ -579,11 +574,16 @@ static void vmballoon_inflate(struct vmballoon *b)
                        if (i >= b->rate_alloc)
                                break;
 
-                       alloc_can_sleep = true;
+                       flags = VMW_PAGE_ALLOC_CANSLEEP;
                        /* Lower rate for sleeping allocations. */
                        rate = b->rate_alloc;
+                       continue;
                }
 
+               error = vmballoon_lock_page(b, page);
+               if (error)
+                       break;
+
                if (++allocations > VMW_BALLOON_YIELD_THRESHOLD) {
                        cond_resched();
                        allocations = 0;
index a721b5d8a9dacdafe85257c64ea7c1f545e6f743..9ec262a526564134a0a61b4fa442549ea0ea2c57 100644 (file)
@@ -1031,14 +1031,9 @@ int __init vmci_host_init(void)
 
 void __exit vmci_host_exit(void)
 {
-       int error;
-
        vmci_host_device_initialized = false;
 
-       error = misc_deregister(&vmci_host_miscdev);
-       if (error)
-               pr_warn("Error unregistering character device: %d\n", error);
-
+       misc_deregister(&vmci_host_miscdev);
        vmci_ctx_destroy(host_context);
        vmci_qp_broker_exit();
 
index e1ccefce9a9de629505344f9fc22042ab09b9684..a98dd4f1b0e33126ca04d1a7cecb8ad1e41d8d72 100644 (file)
@@ -786,6 +786,7 @@ static bool bond_should_notify_peers(struct bonding *bond)
                   slave ? slave->dev->name : "NULL");
 
        if (!slave || !bond->send_peer_notif ||
+           !netif_carrier_ok(bond->dev) ||
            test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
                return false;
 
index 6b94007ae05221c94d3dedce77a412e732834337..838545ce468d1bc9af34b8d451107f966fa5972f 100644 (file)
@@ -854,6 +854,18 @@ static int pcan_usb_probe(struct usb_interface *intf)
 /*
  * describe the PCAN-USB adapter
  */
+static const struct can_bittiming_const pcan_usb_const = {
+       .name = "pcan_usb",
+       .tseg1_min = 1,
+       .tseg1_max = 16,
+       .tseg2_min = 1,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 64,
+       .brp_inc = 1,
+};
+
 const struct peak_usb_adapter pcan_usb = {
        .name = "PCAN-USB",
        .device_id = PCAN_USB_PRODUCT_ID,
@@ -862,17 +874,7 @@ const struct peak_usb_adapter pcan_usb = {
        .clock = {
                .freq = PCAN_USB_CRYSTAL_HZ / 2 ,
        },
-       .bittiming_const = {
-               .name = "pcan_usb",
-               .tseg1_min = 1,
-               .tseg1_max = 16,
-               .tseg2_min = 1,
-               .tseg2_max = 8,
-               .sjw_max = 4,
-               .brp_min = 1,
-               .brp_max = 64,
-               .brp_inc = 1,
-       },
+       .bittiming_const = &pcan_usb_const,
 
        /* size of device private data */
        .sizeof_dev_private = sizeof(struct pcan_usb),
index 7921cff93a63b107c0ecc5cbadf77b1c6ab4b367..5a2e341a6d1ea7b2e2586414fa41592b7ad78099 100644 (file)
@@ -792,9 +792,9 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
        dev->ep_msg_out = peak_usb_adapter->ep_msg_out[ctrl_idx];
 
        dev->can.clock = peak_usb_adapter->clock;
-       dev->can.bittiming_const = &peak_usb_adapter->bittiming_const;
+       dev->can.bittiming_const = peak_usb_adapter->bittiming_const;
        dev->can.do_set_bittiming = peak_usb_set_bittiming;
-       dev->can.data_bittiming_const = &peak_usb_adapter->data_bittiming_const;
+       dev->can.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
        dev->can.do_set_data_bittiming = peak_usb_set_data_bittiming;
        dev->can.do_set_mode = peak_usb_set_mode;
        dev->can.do_get_berr_counter = peak_usb_adapter->do_get_berr_counter;
index 9e624f05ad4d99d377c3152138b20b82983c4e8f..506fe506c9d37fcb212196457d9db37f3a46cb2a 100644 (file)
@@ -48,8 +48,8 @@ struct peak_usb_adapter {
        u32 device_id;
        u32 ctrlmode_supported;
        struct can_clock clock;
-       const struct can_bittiming_const bittiming_const;
-       const struct can_bittiming_const data_bittiming_const;
+       const struct can_bittiming_const * const bittiming_const;
+       const struct can_bittiming_const * const data_bittiming_const;
        unsigned int ctrl_count;
 
        int (*intf_probe)(struct usb_interface *intf);
index 09d14e70abd746b7c17ff0cac6ee6832e9d8771f..ce44a033f63bb1456d44139b003c14cecb35b7e9 100644 (file)
@@ -990,6 +990,30 @@ static void pcan_usb_fd_free(struct peak_usb_device *dev)
 }
 
 /* describes the PCAN-USB FD adapter */
+static const struct can_bittiming_const pcan_usb_fd_const = {
+       .name = "pcan_usb_fd",
+       .tseg1_min = 1,
+       .tseg1_max = 64,
+       .tseg2_min = 1,
+       .tseg2_max = 16,
+       .sjw_max = 16,
+       .brp_min = 1,
+       .brp_max = 1024,
+       .brp_inc = 1,
+};
+
+static const struct can_bittiming_const pcan_usb_fd_data_const = {
+       .name = "pcan_usb_fd",
+       .tseg1_min = 1,
+       .tseg1_max = 16,
+       .tseg2_min = 1,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 1024,
+       .brp_inc = 1,
+};
+
 const struct peak_usb_adapter pcan_usb_fd = {
        .name = "PCAN-USB FD",
        .device_id = PCAN_USBFD_PRODUCT_ID,
@@ -999,28 +1023,8 @@ const struct peak_usb_adapter pcan_usb_fd = {
        .clock = {
                .freq = PCAN_UFD_CRYSTAL_HZ,
        },
-       .bittiming_const = {
-               .name = "pcan_usb_fd",
-               .tseg1_min = 1,
-               .tseg1_max = 64,
-               .tseg2_min = 1,
-               .tseg2_max = 16,
-               .sjw_max = 16,
-               .brp_min = 1,
-               .brp_max = 1024,
-               .brp_inc = 1,
-       },
-       .data_bittiming_const = {
-               .name = "pcan_usb_fd",
-               .tseg1_min = 1,
-               .tseg1_max = 16,
-               .tseg2_min = 1,
-               .tseg2_max = 8,
-               .sjw_max = 4,
-               .brp_min = 1,
-               .brp_max = 1024,
-               .brp_inc = 1,
-       },
+       .bittiming_const = &pcan_usb_fd_const,
+       .data_bittiming_const = &pcan_usb_fd_data_const,
 
        /* size of device private data */
        .sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
@@ -1058,6 +1062,30 @@ const struct peak_usb_adapter pcan_usb_fd = {
 };
 
 /* describes the PCAN-USB Pro FD adapter */
+static const struct can_bittiming_const pcan_usb_pro_fd_const = {
+       .name = "pcan_usb_pro_fd",
+       .tseg1_min = 1,
+       .tseg1_max = 64,
+       .tseg2_min = 1,
+       .tseg2_max = 16,
+       .sjw_max = 16,
+       .brp_min = 1,
+       .brp_max = 1024,
+       .brp_inc = 1,
+};
+
+static const struct can_bittiming_const pcan_usb_pro_fd_data_const = {
+       .name = "pcan_usb_pro_fd",
+       .tseg1_min = 1,
+       .tseg1_max = 16,
+       .tseg2_min = 1,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 1024,
+       .brp_inc = 1,
+};
+
 const struct peak_usb_adapter pcan_usb_pro_fd = {
        .name = "PCAN-USB Pro FD",
        .device_id = PCAN_USBPROFD_PRODUCT_ID,
@@ -1067,28 +1095,8 @@ const struct peak_usb_adapter pcan_usb_pro_fd = {
        .clock = {
                .freq = PCAN_UFD_CRYSTAL_HZ,
        },
-       .bittiming_const = {
-               .name = "pcan_usb_pro_fd",
-               .tseg1_min = 1,
-               .tseg1_max = 64,
-               .tseg2_min = 1,
-               .tseg2_max = 16,
-               .sjw_max = 16,
-               .brp_min = 1,
-               .brp_max = 1024,
-               .brp_inc = 1,
-       },
-       .data_bittiming_const = {
-               .name = "pcan_usb_pro_fd",
-               .tseg1_min = 1,
-               .tseg1_max = 16,
-               .tseg2_min = 1,
-               .tseg2_max = 8,
-               .sjw_max = 4,
-               .brp_min = 1,
-               .brp_max = 1024,
-               .brp_inc = 1,
-       },
+       .bittiming_const = &pcan_usb_pro_fd_const,
+       .data_bittiming_const = &pcan_usb_pro_fd_data_const,
 
        /* size of device private data */
        .sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
index 7d61b3279798b936f4a3238afb57c73437ba22f2..bbdd6058cd2f5af5465e8360456adeb88e668da4 100644 (file)
@@ -1004,6 +1004,18 @@ int pcan_usb_pro_probe(struct usb_interface *intf)
 /*
  * describe the PCAN-USB Pro adapter
  */
+static const struct can_bittiming_const pcan_usb_pro_const = {
+       .name = "pcan_usb_pro",
+       .tseg1_min = 1,
+       .tseg1_max = 16,
+       .tseg2_min = 1,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 1024,
+       .brp_inc = 1,
+};
+
 const struct peak_usb_adapter pcan_usb_pro = {
        .name = "PCAN-USB Pro",
        .device_id = PCAN_USBPRO_PRODUCT_ID,
@@ -1012,17 +1024,7 @@ const struct peak_usb_adapter pcan_usb_pro = {
        .clock = {
                .freq = PCAN_USBPRO_CRYSTAL_HZ,
        },
-       .bittiming_const = {
-               .name = "pcan_usb_pro",
-               .tseg1_min = 1,
-               .tseg1_max = 16,
-               .tseg2_min = 1,
-               .tseg2_max = 8,
-               .sjw_max = 4,
-               .brp_min = 1,
-               .brp_max = 1024,
-               .brp_inc = 1,
-       },
+       .bittiming_const = &pcan_usb_pro_const,
 
        /* size of device private data */
        .sizeof_dev_private = sizeof(struct pcan_usb_pro_device),
index 2d1ce3c5d0dd34c9fabb1399a32c49be744afdd1..753887d02b46abc66663a24a2ea3e4e396d6b881 100644 (file)
@@ -1763,16 +1763,9 @@ vortex_open(struct net_device *dev)
                        vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
                }
                if (i != RX_RING_SIZE) {
-                       int j;
                        pr_emerg("%s: no memory for rx ring\n", dev->name);
-                       for (j = 0; j < i; j++) {
-                               if (vp->rx_skbuff[j]) {
-                                       dev_kfree_skb(vp->rx_skbuff[j]);
-                                       vp->rx_skbuff[j] = NULL;
-                               }
-                       }
                        retval = -ENOMEM;
-                       goto err_free_irq;
+                       goto err_free_skb;
                }
                /* Wrap the ring. */
                vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
@@ -1782,7 +1775,13 @@ vortex_open(struct net_device *dev)
        if (!retval)
                goto out;
 
-err_free_irq:
+err_free_skb:
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               if (vp->rx_skbuff[i]) {
+                       dev_kfree_skb(vp->rx_skbuff[i]);
+                       vp->rx_skbuff[i] = NULL;
+               }
+       }
        free_irq(dev->irq, dev);
 err:
        if (vortex_debug > 1)
index c51014b0464f604c0f41118d8dff625e4993aa12..b52e0f63f9a3c7f719f734b308b49dd85db8f844 100644 (file)
@@ -65,7 +65,7 @@ obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
 obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
 obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/
 obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
-obj-$(CONFIG_SH_ETH) += renesas/
+obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/
 obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
 obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/
 obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/
index a626c4315a89b92560e96532ba1abeeedea27e99..cfa37041ab715db677f7d986bf45f51bbcae0444 100644 (file)
@@ -801,6 +801,9 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
 {
+       if (pdata->phy_dev)
+               phy_disconnect(pdata->phy_dev);
+
        mdiobus_unregister(pdata->mdio_bus);
        mdiobus_free(pdata->mdio_bus);
        pdata->mdio_bus = NULL;
index 299eb4315fe647ba8d67302649a2cf928a4d59d5..a02ea7f8fdae4897a70c4d4f92470136476e7eb0 100644 (file)
@@ -1277,9 +1277,10 @@ static int xgene_enet_remove(struct platform_device *pdev)
        mac_ops->tx_disable(pdata);
 
        xgene_enet_napi_del(pdata);
-       xgene_enet_mdio_remove(pdata);
-       xgene_enet_delete_desc_rings(pdata);
+       if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+               xgene_enet_mdio_remove(pdata);
        unregister_netdev(ndev);
+       xgene_enet_delete_desc_rings(pdata);
        pdata->port_ops->shutdown(pdata);
        free_netdev(ndev);
 
index a90d7364334f9dfa3687dc813e068508a342861c..f7fbdc9d132511b72df0db2ce0b92e4df0774c44 100644 (file)
@@ -262,9 +262,9 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        if (likely(skb)) {
                (*pkts_compl)++;
                (*bytes_compl) += skb->len;
+               dev_kfree_skb_any(skb);
        }
 
-       dev_kfree_skb_any(skb);
        tx_buf->first_bd = 0;
        tx_buf->skb = NULL;
 
index 76b9052a961c517978494199d74398264583508c..5907c821d131eed6fa5b6b0aa7a93dc41cca0d66 100644 (file)
@@ -1718,6 +1718,22 @@ static int bnx2x_nvram_write(struct bnx2x *bp, u32 offset, u8 *data_buf,
                offset += sizeof(u32);
                data_buf += sizeof(u32);
                written_so_far += sizeof(u32);
+
+               /* At end of each 4Kb page, release nvram lock to allow MFW
+                * chance to take it for its own use.
+                */
+               if ((cmd_flags & MCPR_NVM_COMMAND_LAST) &&
+                   (written_so_far < buf_size)) {
+                       DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
+                          "Releasing NVM lock after offset 0x%x\n",
+                          (u32)(offset - sizeof(u32)));
+                       bnx2x_release_nvram_lock(bp);
+                       usleep_range(1000, 2000);
+                       rc = bnx2x_acquire_nvram_lock(bp);
+                       if (rc)
+                               return rc;
+               }
+
                cmd_flags = 0;
        }
 
index 64c1e9db6b0b5420687c1c083cc20b8adb7de5bd..09ff09f828d08571a497787dd143bbd463ecd69e 100644 (file)
@@ -2126,6 +2126,8 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
        int ret = 0;
        int timeout = 0;
        u32 reg;
+       u32 dma_ctrl;
+       int i;
 
        /* Disable TDMA to stop add more frames in TX DMA */
        reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
@@ -2169,6 +2171,20 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
                ret = -ETIMEDOUT;
        }
 
+       dma_ctrl = 0;
+       for (i = 0; i < priv->hw_params->rx_queues; i++)
+               dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
+       reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
+       reg &= ~dma_ctrl;
+       bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+
+       dma_ctrl = 0;
+       for (i = 0; i < priv->hw_params->tx_queues; i++)
+               dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
+       reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+       reg &= ~dma_ctrl;
+       bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+
        return ret;
 }
 
@@ -2820,8 +2836,6 @@ static void bcmgenet_timeout(struct net_device *dev)
 
        netif_dbg(priv, tx_err, dev, "bcmgenet_timeout\n");
 
-       bcmgenet_disable_tx_napi(priv);
-
        for (q = 0; q < priv->hw_params->tx_queues; q++)
                bcmgenet_dump_tx_queue(&priv->tx_rings[q]);
        bcmgenet_dump_tx_queue(&priv->tx_rings[DESC_INDEX]);
@@ -2837,8 +2851,6 @@ static void bcmgenet_timeout(struct net_device *dev)
        bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
        bcmgenet_intrl2_1_writel(priv, int1_enable, INTRL2_CPU_MASK_CLEAR);
 
-       bcmgenet_enable_tx_napi(priv);
-
        dev->trans_start = jiffies;
 
        dev->stats.tx_errors++;
index 0612b19f6313bd3e6ffa205be2b543585262e31e..506047c386071db9472d60218faa004fe94849a8 100644 (file)
@@ -676,6 +676,7 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
                        if (!next_cmpl->valid)
                                break;
                }
+               packets++;
 
                /* TODO: BNA_CQ_EF_LOCAL ? */
                if (unlikely(flags & (BNA_CQ_EF_MAC_ERROR |
@@ -692,7 +693,6 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
                else
                        bnad_cq_setup_skb_frags(rcb, skb, sop_ci, nvecs, len);
 
-               packets++;
                rcb->rxq->rx_packets++;
                rcb->rxq->rx_bytes += totlen;
                ccb->bytes_per_intr += totlen;
index c4d6bbe9458dbfe9c726fdff1e9b6c4c64b8a33f..02e23e6f142487ddc8cc2a8d4e2c512cb7e6db62 100644 (file)
@@ -16,7 +16,6 @@ if NET_VENDOR_CAVIUM
 config THUNDER_NIC_PF
        tristate "Thunder Physical function driver"
        depends on 64BIT
-       default ARCH_THUNDER
        select THUNDER_NIC_BGX
        ---help---
          This driver supports Thunder's NIC physical function.
@@ -29,14 +28,12 @@ config THUNDER_NIC_PF
 config THUNDER_NIC_VF
        tristate "Thunder Virtual function driver"
        depends on 64BIT
-       default ARCH_THUNDER
        ---help---
          This driver supports Thunder's NIC virtual function
 
 config THUNDER_NIC_BGX
        tristate "Thunder MAC interface driver (BGX)"
        depends on 64BIT
-       default ARCH_THUNDER
        ---help---
          This driver supports programming and controlling of MAC
          interface from NIC physical function driver.
index a11485fbb33f2b7bcd6c973324ea41601dbaf575..c3c7db41819dfad26b521008c6c70148711ee019 100644 (file)
@@ -2332,10 +2332,11 @@ int t4_setup_debugfs(struct adapter *adap)
                                        EXT_MEM1_SIZE_G(size));
                }
        } else {
-               if (i & EXT_MEM_ENABLE_F)
+               if (i & EXT_MEM_ENABLE_F) {
                        size = t4_read_reg(adap, MA_EXT_MEMORY_BAR_A);
                        add_debugfs_mem(adap, "mc", MEM_MC,
                                        EXT_MEM_SIZE_G(size));
+               }
        }
 
        de = debugfs_create_file_size("flash", S_IRUSR, adap->debugfs_root, adap,
index 2716e6f30d9a0949633b40dc9864196c7465fa3a..00e3a6b6b82254269aa7e0bf5d165f13d358594f 100644 (file)
@@ -620,6 +620,11 @@ enum be_if_flags {
                                         BE_IF_FLAGS_VLAN_PROMISCUOUS |\
                                         BE_IF_FLAGS_MCAST_PROMISCUOUS)
 
+#define BE_IF_EN_FLAGS (BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |\
+                       BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_UNTAGGED)
+
+#define BE_IF_ALL_FILT_FLAGS   (BE_IF_EN_FLAGS | BE_IF_FLAGS_ALL_PROMISCUOUS)
+
 /* An RX interface is an object with one or more MAC addresses and
  * filtering capabilities. */
 struct be_cmd_req_if_create {
index 6f642426308c67399eac3abdb20ae6160ce41d2a..6ca693b03f33abbbdb6097544f2f4ee7f3928720 100644 (file)
@@ -273,6 +273,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
        if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
                return 0;
 
+       /* if device is not running, copy MAC to netdev->dev_addr */
+       if (!netif_running(netdev))
+               goto done;
+
        /* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
         * privilege or if PF did not provision the new MAC address.
         * On BE3, this cmd will always fail if the VF doesn't have the
@@ -307,9 +311,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
                status = -EPERM;
                goto err;
        }
-
-       memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-       dev_info(dev, "MAC address changed to %pM\n", mac);
+done:
+       ether_addr_copy(netdev->dev_addr, addr->sa_data);
+       dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
        return 0;
 err:
        dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data);
@@ -2447,10 +2451,24 @@ static void be_eq_clean(struct be_eq_obj *eqo)
        be_eq_notify(eqo->adapter, eqo->q.id, false, true, num, 0);
 }
 
-static void be_rx_cq_clean(struct be_rx_obj *rxo)
+/* Free posted rx buffers that were not used */
+static void be_rxq_clean(struct be_rx_obj *rxo)
 {
-       struct be_rx_page_info *page_info;
        struct be_queue_info *rxq = &rxo->q;
+       struct be_rx_page_info *page_info;
+
+       while (atomic_read(&rxq->used) > 0) {
+               page_info = get_rx_page_info(rxo);
+               put_page(page_info->page);
+               memset(page_info, 0, sizeof(*page_info));
+       }
+       BUG_ON(atomic_read(&rxq->used));
+       rxq->tail = 0;
+       rxq->head = 0;
+}
+
+static void be_rx_cq_clean(struct be_rx_obj *rxo)
+{
        struct be_queue_info *rx_cq = &rxo->cq;
        struct be_rx_compl_info *rxcp;
        struct be_adapter *adapter = rxo->adapter;
@@ -2487,16 +2505,6 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
 
        /* After cleanup, leave the CQ in unarmed state */
        be_cq_notify(adapter, rx_cq->id, false, 0);
-
-       /* Then free posted rx buffers that were not used */
-       while (atomic_read(&rxq->used) > 0) {
-               page_info = get_rx_page_info(rxo);
-               put_page(page_info->page);
-               memset(page_info, 0, sizeof(*page_info));
-       }
-       BUG_ON(atomic_read(&rxq->used));
-       rxq->tail = 0;
-       rxq->head = 0;
 }
 
 static void be_tx_compl_clean(struct be_adapter *adapter)
@@ -2576,8 +2584,8 @@ static void be_evt_queues_destroy(struct be_adapter *adapter)
                        be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ);
                        napi_hash_del(&eqo->napi);
                        netif_napi_del(&eqo->napi);
+                       free_cpumask_var(eqo->affinity_mask);
                }
-               free_cpumask_var(eqo->affinity_mask);
                be_queue_free(adapter, &eqo->q);
        }
 }
@@ -2594,13 +2602,7 @@ static int be_evt_queues_create(struct be_adapter *adapter)
 
        for_all_evt_queues(adapter, eqo, i) {
                int numa_node = dev_to_node(&adapter->pdev->dev);
-               if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL))
-                       return -ENOMEM;
-               cpumask_set_cpu(cpumask_local_spread(i, numa_node),
-                               eqo->affinity_mask);
-               netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
-                              BE_NAPI_WEIGHT);
-               napi_hash_add(&eqo->napi);
+
                aic = &adapter->aic_obj[i];
                eqo->adapter = adapter;
                eqo->idx = i;
@@ -2616,6 +2618,14 @@ static int be_evt_queues_create(struct be_adapter *adapter)
                rc = be_cmd_eq_create(adapter, eqo);
                if (rc)
                        return rc;
+
+               if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL))
+                       return -ENOMEM;
+               cpumask_set_cpu(cpumask_local_spread(i, numa_node),
+                               eqo->affinity_mask);
+               netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
+                              BE_NAPI_WEIGHT);
+               napi_hash_add(&eqo->napi);
        }
        return 0;
 }
@@ -3354,13 +3364,54 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
        for_all_rx_queues(adapter, rxo, i) {
                q = &rxo->q;
                if (q->created) {
+                       /* If RXQs are destroyed while in an "out of buffer"
+                        * state, there is a possibility of an HW stall on
+                        * Lancer. So, post 64 buffers to each queue to relieve
+                        * the "out of buffer" condition.
+                        * Make sure there's space in the RXQ before posting.
+                        */
+                       if (lancer_chip(adapter)) {
+                               be_rx_cq_clean(rxo);
+                               if (atomic_read(&q->used) == 0)
+                                       be_post_rx_frags(rxo, GFP_KERNEL,
+                                                        MAX_RX_POST);
+                       }
+
                        be_cmd_rxq_destroy(adapter, q);
                        be_rx_cq_clean(rxo);
+                       be_rxq_clean(rxo);
                }
                be_queue_free(adapter, q);
        }
 }
 
+static void be_disable_if_filters(struct be_adapter *adapter)
+{
+       be_cmd_pmac_del(adapter, adapter->if_handle,
+                       adapter->pmac_id[0], 0);
+
+       be_clear_uc_list(adapter);
+
+       /* The IFACE flags are enabled in the open path and cleared
+        * in the close path. When a VF gets detached from the host and
+        * assigned to a VM the following happens:
+        *      - VF's IFACE flags get cleared in the detach path
+        *      - IFACE create is issued by the VF in the attach path
+        * Due to a bug in the BE3/Skyhawk-R FW
+        * (Lancer FW doesn't have the bug), the IFACE capability flags
+        * specified along with the IFACE create cmd issued by a VF are not
+        * honoured by FW.  As a consequence, if a *new* driver
+        * (that enables/disables IFACE flags in open/close)
+        * is loaded in the host and an *old* driver is * used by a VM/VF,
+        * the IFACE gets created *without* the needed flags.
+        * To avoid this, disable RX-filter flags only for Lancer.
+        */
+       if (lancer_chip(adapter)) {
+               be_cmd_rx_filter(adapter, BE_IF_ALL_FILT_FLAGS, OFF);
+               adapter->if_flags &= ~BE_IF_ALL_FILT_FLAGS;
+       }
+}
+
 static int be_close(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
@@ -3373,6 +3424,8 @@ static int be_close(struct net_device *netdev)
        if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
                return 0;
 
+       be_disable_if_filters(adapter);
+
        be_roce_dev_close(adapter);
 
        if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
@@ -3392,7 +3445,6 @@ static int be_close(struct net_device *netdev)
        be_tx_compl_clean(adapter);
 
        be_rx_qs_destroy(adapter);
-       be_clear_uc_list(adapter);
 
        for_all_evt_queues(adapter, eqo, i) {
                if (msix_enabled(adapter))
@@ -3477,6 +3529,31 @@ static int be_rx_qs_create(struct be_adapter *adapter)
        return 0;
 }
 
+static int be_enable_if_filters(struct be_adapter *adapter)
+{
+       int status;
+
+       status = be_cmd_rx_filter(adapter, BE_IF_EN_FLAGS, ON);
+       if (status)
+               return status;
+
+       /* For BE3 VFs, the PF programs the initial MAC address */
+       if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
+               status = be_cmd_pmac_add(adapter, adapter->netdev->dev_addr,
+                                        adapter->if_handle,
+                                        &adapter->pmac_id[0], 0);
+               if (status)
+                       return status;
+       }
+
+       if (adapter->vlans_added)
+               be_vid_config(adapter);
+
+       be_set_rx_mode(adapter->netdev);
+
+       return 0;
+}
+
 static int be_open(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
@@ -3490,6 +3567,10 @@ static int be_open(struct net_device *netdev)
        if (status)
                goto err;
 
+       status = be_enable_if_filters(adapter);
+       if (status)
+               goto err;
+
        status = be_irq_register(adapter);
        if (status)
                goto err;
@@ -3686,16 +3767,6 @@ static void be_cancel_err_detection(struct be_adapter *adapter)
        }
 }
 
-static void be_mac_clear(struct be_adapter *adapter)
-{
-       if (adapter->pmac_id) {
-               be_cmd_pmac_del(adapter, adapter->if_handle,
-                               adapter->pmac_id[0], 0);
-               kfree(adapter->pmac_id);
-               adapter->pmac_id = NULL;
-       }
-}
-
 #ifdef CONFIG_BE2NET_VXLAN
 static void be_disable_vxlan_offloads(struct be_adapter *adapter)
 {
@@ -3770,8 +3841,8 @@ static int be_clear(struct be_adapter *adapter)
 #ifdef CONFIG_BE2NET_VXLAN
        be_disable_vxlan_offloads(adapter);
 #endif
-       /* delete the primary mac along with the uc-mac list */
-       be_mac_clear(adapter);
+       kfree(adapter->pmac_id);
+       adapter->pmac_id = NULL;
 
        be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
@@ -3782,25 +3853,11 @@ static int be_clear(struct be_adapter *adapter)
        return 0;
 }
 
-static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
-                       u32 cap_flags, u32 vf)
-{
-       u32 en_flags;
-
-       en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
-                  BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
-                  BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
-
-       en_flags &= cap_flags;
-
-       return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf);
-}
-
 static int be_vfs_if_create(struct be_adapter *adapter)
 {
        struct be_resources res = {0};
+       u32 cap_flags, en_flags, vf;
        struct be_vf_cfg *vf_cfg;
-       u32 cap_flags, vf;
        int status;
 
        /* If a FW profile exists, then cap_flags are updated */
@@ -3821,8 +3878,12 @@ static int be_vfs_if_create(struct be_adapter *adapter)
                        }
                }
 
-               status = be_if_create(adapter, &vf_cfg->if_handle,
-                                     cap_flags, vf + 1);
+               en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
+                                       BE_IF_FLAGS_BROADCAST |
+                                       BE_IF_FLAGS_MULTICAST |
+                                       BE_IF_FLAGS_PASS_L3L4_ERRORS);
+               status = be_cmd_if_create(adapter, cap_flags, en_flags,
+                                         &vf_cfg->if_handle, vf + 1);
                if (status)
                        return status;
        }
@@ -4194,15 +4255,8 @@ static int be_mac_setup(struct be_adapter *adapter)
 
                memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
                memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
-       } else {
-               /* Maybe the HW was reset; dev_addr must be re-programmed */
-               memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
        }
 
-       /* For BE3-R VFs, the PF programs the initial MAC address */
-       if (!(BEx_chip(adapter) && be_virtfn(adapter)))
-               be_cmd_pmac_add(adapter, mac, adapter->if_handle,
-                               &adapter->pmac_id[0], 0);
        return 0;
 }
 
@@ -4342,6 +4396,7 @@ static int be_func_init(struct be_adapter *adapter)
 static int be_setup(struct be_adapter *adapter)
 {
        struct device *dev = &adapter->pdev->dev;
+       u32 en_flags;
        int status;
 
        status = be_func_init(adapter);
@@ -4364,8 +4419,11 @@ static int be_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
-       status = be_if_create(adapter, &adapter->if_handle,
-                             be_if_cap_flags(adapter), 0);
+       /* will enable all the needed filter flags in be_open() */
+       en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
+       en_flags = en_flags & be_if_cap_flags(adapter);
+       status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
+                                 &adapter->if_handle, 0);
        if (status)
                goto err;
 
@@ -4391,11 +4449,6 @@ static int be_setup(struct be_adapter *adapter)
                dev_err(dev, "Please upgrade firmware to version >= 4.0\n");
        }
 
-       if (adapter->vlans_added)
-               be_vid_config(adapter);
-
-       be_set_rx_mode(adapter->netdev);
-
        status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
                                         adapter->rx_fc);
        if (status)
@@ -5121,7 +5174,7 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
        struct device *dev = &adapter->pdev->dev;
        int status;
 
-       if (lancer_chip(adapter) || BEx_chip(adapter))
+       if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
                return;
 
        if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
@@ -5168,7 +5221,7 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
 {
        struct be_adapter *adapter = netdev_priv(netdev);
 
-       if (lancer_chip(adapter) || BEx_chip(adapter))
+       if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
                return;
 
        if (adapter->vxlan_port != port)
index 32e3807c650ea7256b09f0c9e406a8219cb2bb78..b349e6f36ea75fa6a471d3c2a37a7bee21d8e59c 100644 (file)
@@ -1778,7 +1778,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
                return ret;
 
        fep->mii_timeout = 0;
-       init_completion(&fep->mdio_done);
+       reinit_completion(&fep->mdio_done);
 
        /* start a read op */
        writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
@@ -1817,7 +1817,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
                return ret;
 
        fep->mii_timeout = 0;
-       init_completion(&fep->mdio_done);
+       reinit_completion(&fep->mdio_done);
 
        /* start a write op */
        writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
@@ -3433,6 +3433,7 @@ fec_probe(struct platform_device *pdev)
 
        pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT);
        pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
 
index 56316db6c5a674fd1d17ef20e8db3747950cf71e..cf8e54652df95266e24a5d6d64ed67c00336f67b 100644 (file)
@@ -586,7 +586,8 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        frag = skb_shinfo(skb)->frags;
        while (nr_frags) {
                CBDC_SC(bdp,
-                       BD_ENET_TX_STATS | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+                       BD_ENET_TX_STATS | BD_ENET_TX_INTR | BD_ENET_TX_LAST |
+                       BD_ENET_TX_TC);
                CBDS_SC(bdp, BD_ENET_TX_READY);
 
                if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
index b34214e2df5f6e55bdbb29e6a8016c139e74345c..016743e355de31984d57904e802d69e6703ea5e4 100644 (file)
@@ -110,7 +110,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
 }
 
 #define FEC_NAPI_RX_EVENT_MSK  (FEC_ENET_RXF | FEC_ENET_RXB)
-#define FEC_NAPI_TX_EVENT_MSK  (FEC_ENET_TXF | FEC_ENET_TXB)
+#define FEC_NAPI_TX_EVENT_MSK  (FEC_ENET_TXF)
 #define FEC_RX_EVENT           (FEC_ENET_RXF)
 #define FEC_TX_EVENT           (FEC_ENET_TXF)
 #define FEC_ERR_EVENT_MSK      (FEC_ENET_HBERR | FEC_ENET_BABR | \
index 2b7610f341b09f4ff293f9916235030487fb2a80..10b3bbbbac8e10e89c47b2d50bb661cc80ad616b 100644 (file)
@@ -2102,6 +2102,11 @@ int startup_gfar(struct net_device *ndev)
        /* Start Rx/Tx DMA and enable the interrupts */
        gfar_start(priv);
 
+       /* force link state update after mac reset */
+       priv->oldlink = 0;
+       priv->oldspeed = 0;
+       priv->oldduplex = -1;
+
        phy_start(priv->phydev);
 
        enable_napi(priv);
index 3c0a8f825b630148c29b4cda6ca46b9797a668be..5b90fcf96265aec4a6daa1f28135ef2fa06a0752 100644 (file)
@@ -900,27 +900,6 @@ static int gfar_check_filer_hardware(struct gfar_private *priv)
        return 0;
 }
 
-static int gfar_comp_asc(const void *a, const void *b)
-{
-       return memcmp(a, b, 4);
-}
-
-static int gfar_comp_desc(const void *a, const void *b)
-{
-       return -memcmp(a, b, 4);
-}
-
-static void gfar_swap(void *a, void *b, int size)
-{
-       u32 *_a = a;
-       u32 *_b = b;
-
-       swap(_a[0], _b[0]);
-       swap(_a[1], _b[1]);
-       swap(_a[2], _b[2]);
-       swap(_a[3], _b[3]);
-}
-
 /* Write a mask to filer cache */
 static void gfar_set_mask(u32 mask, struct filer_table *tab)
 {
@@ -1270,310 +1249,6 @@ static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
        return 0;
 }
 
-/* Copy size filer entries */
-static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0],
-                                   struct gfar_filer_entry src[0], s32 size)
-{
-       while (size > 0) {
-               size--;
-               dst[size].ctrl = src[size].ctrl;
-               dst[size].prop = src[size].prop;
-       }
-}
-
-/* Delete the contents of the filer-table between start and end
- * and collapse them
- */
-static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab)
-{
-       int length;
-
-       if (end > MAX_FILER_CACHE_IDX || end < begin)
-               return -EINVAL;
-
-       end++;
-       length = end - begin;
-
-       /* Copy */
-       while (end < tab->index) {
-               tab->fe[begin].ctrl = tab->fe[end].ctrl;
-               tab->fe[begin++].prop = tab->fe[end++].prop;
-
-       }
-       /* Fill up with don't cares */
-       while (begin < tab->index) {
-               tab->fe[begin].ctrl = 0x60;
-               tab->fe[begin].prop = 0xFFFFFFFF;
-               begin++;
-       }
-
-       tab->index -= length;
-       return 0;
-}
-
-/* Make space on the wanted location */
-static int gfar_expand_filer_entries(u32 begin, u32 length,
-                                    struct filer_table *tab)
-{
-       if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX ||
-           begin > MAX_FILER_CACHE_IDX)
-               return -EINVAL;
-
-       gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]),
-                               tab->index - length + 1);
-
-       tab->index += length;
-       return 0;
-}
-
-static int gfar_get_next_cluster_start(int start, struct filer_table *tab)
-{
-       for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1);
-            start++) {
-               if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) ==
-                   (RQFCR_AND | RQFCR_CLE))
-                       return start;
-       }
-       return -1;
-}
-
-static int gfar_get_next_cluster_end(int start, struct filer_table *tab)
-{
-       for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1);
-            start++) {
-               if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) ==
-                   (RQFCR_CLE))
-                       return start;
-       }
-       return -1;
-}
-
-/* Uses hardwares clustering option to reduce
- * the number of filer table entries
- */
-static void gfar_cluster_filer(struct filer_table *tab)
-{
-       s32 i = -1, j, iend, jend;
-
-       while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) {
-               j = i;
-               while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) {
-                       /* The cluster entries self and the previous one
-                        * (a mask) must be identical!
-                        */
-                       if (tab->fe[i].ctrl != tab->fe[j].ctrl)
-                               break;
-                       if (tab->fe[i].prop != tab->fe[j].prop)
-                               break;
-                       if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl)
-                               break;
-                       if (tab->fe[i - 1].prop != tab->fe[j - 1].prop)
-                               break;
-                       iend = gfar_get_next_cluster_end(i, tab);
-                       jend = gfar_get_next_cluster_end(j, tab);
-                       if (jend == -1 || iend == -1)
-                               break;
-
-                       /* First we make some free space, where our cluster
-                        * element should be. Then we copy it there and finally
-                        * delete in from its old location.
-                        */
-                       if (gfar_expand_filer_entries(iend, (jend - j), tab) ==
-                           -EINVAL)
-                               break;
-
-                       gfar_copy_filer_entries(&(tab->fe[iend + 1]),
-                                               &(tab->fe[jend + 1]), jend - j);
-
-                       if (gfar_trim_filer_entries(jend - 1,
-                                                   jend + (jend - j),
-                                                   tab) == -EINVAL)
-                               return;
-
-                       /* Mask out cluster bit */
-                       tab->fe[iend].ctrl &= ~(RQFCR_CLE);
-               }
-       }
-}
-
-/* Swaps the masked bits of a1<>a2 and b1<>b2 */
-static void gfar_swap_bits(struct gfar_filer_entry *a1,
-                          struct gfar_filer_entry *a2,
-                          struct gfar_filer_entry *b1,
-                          struct gfar_filer_entry *b2, u32 mask)
-{
-       u32 temp[4];
-       temp[0] = a1->ctrl & mask;
-       temp[1] = a2->ctrl & mask;
-       temp[2] = b1->ctrl & mask;
-       temp[3] = b2->ctrl & mask;
-
-       a1->ctrl &= ~mask;
-       a2->ctrl &= ~mask;
-       b1->ctrl &= ~mask;
-       b2->ctrl &= ~mask;
-
-       a1->ctrl |= temp[1];
-       a2->ctrl |= temp[0];
-       b1->ctrl |= temp[3];
-       b2->ctrl |= temp[2];
-}
-
-/* Generate a list consisting of masks values with their start and
- * end of validity and block as indicator for parts belonging
- * together (glued by ANDs) in mask_table
- */
-static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table,
-                                   struct filer_table *tab)
-{
-       u32 i, and_index = 0, block_index = 1;
-
-       for (i = 0; i < tab->index; i++) {
-
-               /* LSByte of control = 0 sets a mask */
-               if (!(tab->fe[i].ctrl & 0xF)) {
-                       mask_table[and_index].mask = tab->fe[i].prop;
-                       mask_table[and_index].start = i;
-                       mask_table[and_index].block = block_index;
-                       if (and_index >= 1)
-                               mask_table[and_index - 1].end = i - 1;
-                       and_index++;
-               }
-               /* cluster starts and ends will be separated because they should
-                * hold their position
-                */
-               if (tab->fe[i].ctrl & RQFCR_CLE)
-                       block_index++;
-               /* A not set AND indicates the end of a depended block */
-               if (!(tab->fe[i].ctrl & RQFCR_AND))
-                       block_index++;
-       }
-
-       mask_table[and_index - 1].end = i - 1;
-
-       return and_index;
-}
-
-/* Sorts the entries of mask_table by the values of the masks.
- * Important: The 0xFF80 flags of the first and last entry of a
- * block must hold their position (which queue, CLusterEnable, ReJEct,
- * AND)
- */
-static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table,
-                                struct filer_table *temp_table, u32 and_index)
-{
-       /* Pointer to compare function (_asc or _desc) */
-       int (*gfar_comp)(const void *, const void *);
-
-       u32 i, size = 0, start = 0, prev = 1;
-       u32 old_first, old_last, new_first, new_last;
-
-       gfar_comp = &gfar_comp_desc;
-
-       for (i = 0; i < and_index; i++) {
-               if (prev != mask_table[i].block) {
-                       old_first = mask_table[start].start + 1;
-                       old_last = mask_table[i - 1].end;
-                       sort(mask_table + start, size,
-                            sizeof(struct gfar_mask_entry),
-                            gfar_comp, &gfar_swap);
-
-                       /* Toggle order for every block. This makes the
-                        * thing more efficient!
-                        */
-                       if (gfar_comp == gfar_comp_desc)
-                               gfar_comp = &gfar_comp_asc;
-                       else
-                               gfar_comp = &gfar_comp_desc;
-
-                       new_first = mask_table[start].start + 1;
-                       new_last = mask_table[i - 1].end;
-
-                       gfar_swap_bits(&temp_table->fe[new_first],
-                                      &temp_table->fe[old_first],
-                                      &temp_table->fe[new_last],
-                                      &temp_table->fe[old_last],
-                                      RQFCR_QUEUE | RQFCR_CLE |
-                                      RQFCR_RJE | RQFCR_AND);
-
-                       start = i;
-                       size = 0;
-               }
-               size++;
-               prev = mask_table[i].block;
-       }
-}
-
-/* Reduces the number of masks needed in the filer table to save entries
- * This is done by sorting the masks of a depended block. A depended block is
- * identified by gluing ANDs or CLE. The sorting order toggles after every
- * block. Of course entries in scope of a mask must change their location with
- * it.
- */
-static int gfar_optimize_filer_masks(struct filer_table *tab)
-{
-       struct filer_table *temp_table;
-       struct gfar_mask_entry *mask_table;
-
-       u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0;
-       s32 ret = 0;
-
-       /* We need a copy of the filer table because
-        * we want to change its order
-        */
-       temp_table = kmemdup(tab, sizeof(*temp_table), GFP_KERNEL);
-       if (temp_table == NULL)
-               return -ENOMEM;
-
-       mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1,
-                            sizeof(struct gfar_mask_entry), GFP_KERNEL);
-
-       if (mask_table == NULL) {
-               ret = -ENOMEM;
-               goto end;
-       }
-
-       and_index = gfar_generate_mask_table(mask_table, tab);
-
-       gfar_sort_mask_table(mask_table, temp_table, and_index);
-
-       /* Now we can copy the data from our duplicated filer table to
-        * the real one in the order the mask table says
-        */
-       for (i = 0; i < and_index; i++) {
-               size = mask_table[i].end - mask_table[i].start + 1;
-               gfar_copy_filer_entries(&(tab->fe[j]),
-                               &(temp_table->fe[mask_table[i].start]), size);
-               j += size;
-       }
-
-       /* And finally we just have to check for duplicated masks and drop the
-        * second ones
-        */
-       for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
-               if (tab->fe[i].ctrl == 0x80) {
-                       previous_mask = i++;
-                       break;
-               }
-       }
-       for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
-               if (tab->fe[i].ctrl == 0x80) {
-                       if (tab->fe[i].prop == tab->fe[previous_mask].prop) {
-                               /* Two identical ones found!
-                                * So drop the second one!
-                                */
-                               gfar_trim_filer_entries(i, i, tab);
-                       } else
-                               /* Not identical! */
-                               previous_mask = i;
-               }
-       }
-
-       kfree(mask_table);
-end:   kfree(temp_table);
-       return ret;
-}
-
 /* Write the bit-pattern from software's buffer to hardware registers */
 static int gfar_write_filer_table(struct gfar_private *priv,
                                  struct filer_table *tab)
@@ -1583,11 +1258,10 @@ static int gfar_write_filer_table(struct gfar_private *priv,
                return -EBUSY;
 
        /* Fill regular entries */
-       for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].prop);
-            i++)
+       for (; i < MAX_FILER_IDX && (tab->fe[i].ctrl | tab->fe[i].prop); i++)
                gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
        /* Fill the rest with fall-troughs */
-       for (; i < MAX_FILER_IDX - 1; i++)
+       for (; i < MAX_FILER_IDX; i++)
                gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
        /* Last entry must be default accept
         * because that's what people expect
@@ -1621,7 +1295,6 @@ static int gfar_process_filer_changes(struct gfar_private *priv)
 {
        struct ethtool_flow_spec_container *j;
        struct filer_table *tab;
-       s32 i = 0;
        s32 ret = 0;
 
        /* So index is set to zero, too! */
@@ -1646,17 +1319,6 @@ static int gfar_process_filer_changes(struct gfar_private *priv)
                }
        }
 
-       i = tab->index;
-
-       /* Optimizations to save entries */
-       gfar_cluster_filer(tab);
-       gfar_optimize_filer_masks(tab);
-
-       pr_debug("\tSummary:\n"
-                "\tData on hardware: %d\n"
-                "\tCompression rate: %d%%\n",
-                tab->index, 100 - (100 * tab->index) / i);
-
        /* Write everything to hardware */
        ret = gfar_write_filer_table(priv, tab);
        if (ret == -EBUSY) {
@@ -1722,13 +1384,14 @@ static int gfar_add_cls(struct gfar_private *priv,
        }
 
 process:
+       priv->rx_list.count++;
        ret = gfar_process_filer_changes(priv);
        if (ret)
                goto clean_list;
-       priv->rx_list.count++;
        return ret;
 
 clean_list:
+       priv->rx_list.count--;
        list_del(&temp->list);
 clean_mem:
        kfree(temp);
index 982fdcdc795b4752a2fbe65e71ed76ee197ad5de..b5b2925103ec10c1e835429c2ab7d2efee093838 100644 (file)
@@ -216,7 +216,7 @@ static void fm10k_reuse_rx_page(struct fm10k_ring *rx_ring,
 
 static inline bool fm10k_page_is_reserved(struct page *page)
 {
-       return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+       return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
 }
 
 static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer,
index 2f70a9b152bd1789349d9c4d995852e95be1e70d..830466c49987cfbf1ad25f6d9bc01e4f7f0d0454 100644 (file)
@@ -6566,7 +6566,7 @@ static void igb_reuse_rx_page(struct igb_ring *rx_ring,
 
 static inline bool igb_page_is_reserved(struct page *page)
 {
-       return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+       return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
 }
 
 static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,
index 9aa6104e34ea8e2bd93994e4d8291763014162b8..ae21e0b06c3ad40a54093c8966fcfa711f188cfb 100644 (file)
@@ -1832,7 +1832,7 @@ static void ixgbe_reuse_rx_page(struct ixgbe_ring *rx_ring,
 
 static inline bool ixgbe_page_is_reserved(struct page *page)
 {
-       return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+       return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
 }
 
 /**
index e71cdde9cb017aecab834d2f2d9c5d4821c3d42e..1d7b00b038a2ea8c3bdd9394ad3d4988ccee04c8 100644 (file)
@@ -765,7 +765,7 @@ static void ixgbevf_reuse_rx_page(struct ixgbevf_ring *rx_ring,
 
 static inline bool ixgbevf_page_is_reserved(struct page *page)
 {
-       return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+       return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
 }
 
 /**
index 3e8b1bfb1f2e316212bd9b60fa06522ca4dc68db..d9884fd15b453e2486177d58b7fc40bcd5aaf7cc 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/of_address.h>
 #include <linux/phy.h>
 #include <linux/clk.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
 #include <uapi/linux/ppp_defs.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 
 /* Coalescing */
 #define MVPP2_TXDONE_COAL_PKTS_THRESH  15
+#define MVPP2_TXDONE_HRTIMER_PERIOD_NS 1000000UL
 #define MVPP2_RX_COAL_PKTS             32
 #define MVPP2_RX_COAL_USEC             100
 
@@ -660,6 +663,14 @@ struct mvpp2_pcpu_stats {
        u64     tx_bytes;
 };
 
+/* Per-CPU port control */
+struct mvpp2_port_pcpu {
+       struct hrtimer tx_done_timer;
+       bool timer_scheduled;
+       /* Tasklet for egress finalization */
+       struct tasklet_struct tx_done_tasklet;
+};
+
 struct mvpp2_port {
        u8 id;
 
@@ -679,6 +690,9 @@ struct mvpp2_port {
        u32 pending_cause_rx;
        struct napi_struct napi;
 
+       /* Per-CPU port control */
+       struct mvpp2_port_pcpu __percpu *pcpu;
+
        /* Flags */
        unsigned long flags;
 
@@ -776,6 +790,9 @@ struct mvpp2_txq_pcpu {
        /* Array of transmitted skb */
        struct sk_buff **tx_skb;
 
+       /* Array of transmitted buffers' physical addresses */
+       dma_addr_t *tx_buffs;
+
        /* Index of last TX DMA descriptor that was inserted */
        int txq_put_index;
 
@@ -913,8 +930,6 @@ struct mvpp2_bm_pool {
        /* Occupied buffers indicator */
        atomic_t in_use;
        int in_use_thresh;
-
-       spinlock_t lock;
 };
 
 struct mvpp2_buff_hdr {
@@ -963,9 +978,13 @@ static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)
 }
 
 static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu,
-                             struct sk_buff *skb)
+                             struct sk_buff *skb,
+                             struct mvpp2_tx_desc *tx_desc)
 {
        txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
+       if (skb)
+               txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
+                                                        tx_desc->buf_phys_addr;
        txq_pcpu->txq_put_index++;
        if (txq_pcpu->txq_put_index == txq_pcpu->size)
                txq_pcpu->txq_put_index = 0;
@@ -3376,7 +3395,6 @@ static int mvpp2_bm_pool_create(struct platform_device *pdev,
        bm_pool->pkt_size = 0;
        bm_pool->buf_num = 0;
        atomic_set(&bm_pool->in_use, 0);
-       spin_lock_init(&bm_pool->lock);
 
        return 0;
 }
@@ -3647,7 +3665,6 @@ static struct mvpp2_bm_pool *
 mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
                  int pkt_size)
 {
-       unsigned long flags = 0;
        struct mvpp2_bm_pool *new_pool = &port->priv->bm_pools[pool];
        int num;
 
@@ -3656,8 +3673,6 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
                return NULL;
        }
 
-       spin_lock_irqsave(&new_pool->lock, flags);
-
        if (new_pool->type == MVPP2_BM_FREE)
                new_pool->type = type;
 
@@ -3686,8 +3701,6 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
                if (num != pkts_num) {
                        WARN(1, "pool %d: %d of %d allocated\n",
                             new_pool->id, num, pkts_num);
-                       /* We need to undo the bufs_add() allocations */
-                       spin_unlock_irqrestore(&new_pool->lock, flags);
                        return NULL;
                }
        }
@@ -3695,15 +3708,12 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
        mvpp2_bm_pool_bufsize_set(port->priv, new_pool,
                                  MVPP2_RX_BUF_SIZE(new_pool->pkt_size));
 
-       spin_unlock_irqrestore(&new_pool->lock, flags);
-
        return new_pool;
 }
 
 /* Initialize pools for swf */
 static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
 {
-       unsigned long flags = 0;
        int rxq;
 
        if (!port->pool_long) {
@@ -3714,9 +3724,7 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
                if (!port->pool_long)
                        return -ENOMEM;
 
-               spin_lock_irqsave(&port->pool_long->lock, flags);
                port->pool_long->port_map |= (1 << port->id);
-               spin_unlock_irqrestore(&port->pool_long->lock, flags);
 
                for (rxq = 0; rxq < rxq_number; rxq++)
                        mvpp2_rxq_long_pool_set(port, rxq, port->pool_long->id);
@@ -3730,9 +3738,7 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
                if (!port->pool_short)
                        return -ENOMEM;
 
-               spin_lock_irqsave(&port->pool_short->lock, flags);
                port->pool_short->port_map |= (1 << port->id);
-               spin_unlock_irqrestore(&port->pool_short->lock, flags);
 
                for (rxq = 0; rxq < rxq_number; rxq++)
                        mvpp2_rxq_short_pool_set(port, rxq,
@@ -3806,7 +3812,6 @@ static void mvpp2_interrupts_unmask(void *arg)
 
        mvpp2_write(port->priv, MVPP2_ISR_RX_TX_MASK_REG(port->id),
                    (MVPP2_CAUSE_MISC_SUM_MASK |
-                    MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK |
                     MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK));
 }
 
@@ -4382,23 +4387,6 @@ static void mvpp2_rx_time_coal_set(struct mvpp2_port *port,
        rxq->time_coal = usec;
 }
 
-/* Set threshold for TX_DONE pkts coalescing */
-static void mvpp2_tx_done_pkts_coal_set(void *arg)
-{
-       struct mvpp2_port *port = arg;
-       int queue;
-       u32 val;
-
-       for (queue = 0; queue < txq_number; queue++) {
-               struct mvpp2_tx_queue *txq = port->txqs[queue];
-
-               val = (txq->done_pkts_coal << MVPP2_TRANSMITTED_THRESH_OFFSET) &
-                      MVPP2_TRANSMITTED_THRESH_MASK;
-               mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
-               mvpp2_write(port->priv, MVPP2_TXQ_THRESH_REG, val);
-       }
-}
-
 /* Free Tx queue skbuffs */
 static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
                                struct mvpp2_tx_queue *txq,
@@ -4407,8 +4395,8 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
        int i;
 
        for (i = 0; i < num; i++) {
-               struct mvpp2_tx_desc *tx_desc = txq->descs +
-                                                       txq_pcpu->txq_get_index;
+               dma_addr_t buf_phys_addr =
+                                   txq_pcpu->tx_buffs[txq_pcpu->txq_get_index];
                struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
 
                mvpp2_txq_inc_get(txq_pcpu);
@@ -4416,8 +4404,8 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
                if (!skb)
                        continue;
 
-               dma_unmap_single(port->dev->dev.parent, tx_desc->buf_phys_addr,
-                                tx_desc->data_size, DMA_TO_DEVICE);
+               dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
+                                skb_headlen(skb), DMA_TO_DEVICE);
                dev_kfree_skb_any(skb);
        }
 }
@@ -4433,7 +4421,7 @@ static inline struct mvpp2_rx_queue *mvpp2_get_rx_queue(struct mvpp2_port *port,
 static inline struct mvpp2_tx_queue *mvpp2_get_tx_queue(struct mvpp2_port *port,
                                                        u32 cause)
 {
-       int queue = fls(cause >> 16) - 1;
+       int queue = fls(cause) - 1;
 
        return port->txqs[queue];
 }
@@ -4460,6 +4448,29 @@ static void mvpp2_txq_done(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
                        netif_tx_wake_queue(nq);
 }
 
+static unsigned int mvpp2_tx_done(struct mvpp2_port *port, u32 cause)
+{
+       struct mvpp2_tx_queue *txq;
+       struct mvpp2_txq_pcpu *txq_pcpu;
+       unsigned int tx_todo = 0;
+
+       while (cause) {
+               txq = mvpp2_get_tx_queue(port, cause);
+               if (!txq)
+                       break;
+
+               txq_pcpu = this_cpu_ptr(txq->pcpu);
+
+               if (txq_pcpu->count) {
+                       mvpp2_txq_done(port, txq, txq_pcpu);
+                       tx_todo += txq_pcpu->count;
+               }
+
+               cause &= ~(1 << txq->log_id);
+       }
+       return tx_todo;
+}
+
 /* Rx/Tx queue initialization/cleanup methods */
 
 /* Allocate and initialize descriptors for aggr TXQ */
@@ -4649,12 +4660,13 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
                txq_pcpu->tx_skb = kmalloc(txq_pcpu->size *
                                           sizeof(*txq_pcpu->tx_skb),
                                           GFP_KERNEL);
-               if (!txq_pcpu->tx_skb) {
-                       dma_free_coherent(port->dev->dev.parent,
-                                         txq->size * MVPP2_DESC_ALIGNED_SIZE,
-                                         txq->descs, txq->descs_phys);
-                       return -ENOMEM;
-               }
+               if (!txq_pcpu->tx_skb)
+                       goto error;
+
+               txq_pcpu->tx_buffs = kmalloc(txq_pcpu->size *
+                                            sizeof(dma_addr_t), GFP_KERNEL);
+               if (!txq_pcpu->tx_buffs)
+                       goto error;
 
                txq_pcpu->count = 0;
                txq_pcpu->reserved_num = 0;
@@ -4663,6 +4675,19 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
        }
 
        return 0;
+
+error:
+       for_each_present_cpu(cpu) {
+               txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+               kfree(txq_pcpu->tx_skb);
+               kfree(txq_pcpu->tx_buffs);
+       }
+
+       dma_free_coherent(port->dev->dev.parent,
+                         txq->size * MVPP2_DESC_ALIGNED_SIZE,
+                         txq->descs, txq->descs_phys);
+
+       return -ENOMEM;
 }
 
 /* Free allocated TXQ resources */
@@ -4675,6 +4700,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
        for_each_present_cpu(cpu) {
                txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
                kfree(txq_pcpu->tx_skb);
+               kfree(txq_pcpu->tx_buffs);
        }
 
        if (txq->descs)
@@ -4805,7 +4831,6 @@ static int mvpp2_setup_txqs(struct mvpp2_port *port)
                        goto err_cleanup;
        }
 
-       on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
        on_each_cpu(mvpp2_txq_sent_counter_clear, port, 1);
        return 0;
 
@@ -4887,6 +4912,49 @@ static void mvpp2_link_event(struct net_device *dev)
        }
 }
 
+static void mvpp2_timer_set(struct mvpp2_port_pcpu *port_pcpu)
+{
+       ktime_t interval;
+
+       if (!port_pcpu->timer_scheduled) {
+               port_pcpu->timer_scheduled = true;
+               interval = ktime_set(0, MVPP2_TXDONE_HRTIMER_PERIOD_NS);
+               hrtimer_start(&port_pcpu->tx_done_timer, interval,
+                             HRTIMER_MODE_REL_PINNED);
+       }
+}
+
+static void mvpp2_tx_proc_cb(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct mvpp2_port *port = netdev_priv(dev);
+       struct mvpp2_port_pcpu *port_pcpu = this_cpu_ptr(port->pcpu);
+       unsigned int tx_todo, cause;
+
+       if (!netif_running(dev))
+               return;
+       port_pcpu->timer_scheduled = false;
+
+       /* Process all the Tx queues */
+       cause = (1 << txq_number) - 1;
+       tx_todo = mvpp2_tx_done(port, cause);
+
+       /* Set the timer in case not all the packets were processed */
+       if (tx_todo)
+               mvpp2_timer_set(port_pcpu);
+}
+
+static enum hrtimer_restart mvpp2_hr_timer_cb(struct hrtimer *timer)
+{
+       struct mvpp2_port_pcpu *port_pcpu = container_of(timer,
+                                                        struct mvpp2_port_pcpu,
+                                                        tx_done_timer);
+
+       tasklet_schedule(&port_pcpu->tx_done_tasklet);
+
+       return HRTIMER_NORESTART;
+}
+
 /* Main RX/TX processing routines */
 
 /* Display more error info */
@@ -5144,11 +5212,11 @@ static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
                if (i == (skb_shinfo(skb)->nr_frags - 1)) {
                        /* Last descriptor */
                        tx_desc->command = MVPP2_TXD_L_DESC;
-                       mvpp2_txq_inc_put(txq_pcpu, skb);
+                       mvpp2_txq_inc_put(txq_pcpu, skb, tx_desc);
                } else {
                        /* Descriptor in the middle: Not First, Not Last */
                        tx_desc->command = 0;
-                       mvpp2_txq_inc_put(txq_pcpu, NULL);
+                       mvpp2_txq_inc_put(txq_pcpu, NULL, tx_desc);
                }
        }
 
@@ -5214,12 +5282,12 @@ static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
                /* First and Last descriptor */
                tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
                tx_desc->command = tx_cmd;
-               mvpp2_txq_inc_put(txq_pcpu, skb);
+               mvpp2_txq_inc_put(txq_pcpu, skb, tx_desc);
        } else {
                /* First but not Last */
                tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_PADDING_DISABLE;
                tx_desc->command = tx_cmd;
-               mvpp2_txq_inc_put(txq_pcpu, NULL);
+               mvpp2_txq_inc_put(txq_pcpu, NULL, tx_desc);
 
                /* Continue with other skb fragments */
                if (mvpp2_tx_frag_process(port, skb, aggr_txq, txq)) {
@@ -5255,6 +5323,17 @@ out:
                dev_kfree_skb_any(skb);
        }
 
+       /* Finalize TX processing */
+       if (txq_pcpu->count >= txq->done_pkts_coal)
+               mvpp2_txq_done(port, txq, txq_pcpu);
+
+       /* Set the timer in case not all frags were processed */
+       if (txq_pcpu->count <= frags && txq_pcpu->count > 0) {
+               struct mvpp2_port_pcpu *port_pcpu = this_cpu_ptr(port->pcpu);
+
+               mvpp2_timer_set(port_pcpu);
+       }
+
        return NETDEV_TX_OK;
 }
 
@@ -5268,10 +5347,11 @@ static inline void mvpp2_cause_error(struct net_device *dev, int cause)
                netdev_err(dev, "tx fifo underrun error\n");
 }
 
-static void mvpp2_txq_done_percpu(void *arg)
+static int mvpp2_poll(struct napi_struct *napi, int budget)
 {
-       struct mvpp2_port *port = arg;
-       u32 cause_rx_tx, cause_tx, cause_misc;
+       u32 cause_rx_tx, cause_rx, cause_misc;
+       int rx_done = 0;
+       struct mvpp2_port *port = netdev_priv(napi->dev);
 
        /* Rx/Tx cause register
         *
@@ -5285,7 +5365,7 @@ static void mvpp2_txq_done_percpu(void *arg)
         */
        cause_rx_tx = mvpp2_read(port->priv,
                                 MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
-       cause_tx = cause_rx_tx & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
+       cause_rx_tx &= ~MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
        cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK;
 
        if (cause_misc) {
@@ -5297,26 +5377,6 @@ static void mvpp2_txq_done_percpu(void *arg)
                            cause_rx_tx & ~MVPP2_CAUSE_MISC_SUM_MASK);
        }
 
-       /* Release TX descriptors */
-       if (cause_tx) {
-               struct mvpp2_tx_queue *txq = mvpp2_get_tx_queue(port, cause_tx);
-               struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
-
-               if (txq_pcpu->count)
-                       mvpp2_txq_done(port, txq, txq_pcpu);
-       }
-}
-
-static int mvpp2_poll(struct napi_struct *napi, int budget)
-{
-       u32 cause_rx_tx, cause_rx;
-       int rx_done = 0;
-       struct mvpp2_port *port = netdev_priv(napi->dev);
-
-       on_each_cpu(mvpp2_txq_done_percpu, port, 1);
-
-       cause_rx_tx = mvpp2_read(port->priv,
-                                MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
        cause_rx = cause_rx_tx & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK;
 
        /* Process RX packets */
@@ -5561,6 +5621,8 @@ err_cleanup_rxqs:
 static int mvpp2_stop(struct net_device *dev)
 {
        struct mvpp2_port *port = netdev_priv(dev);
+       struct mvpp2_port_pcpu *port_pcpu;
+       int cpu;
 
        mvpp2_stop_dev(port);
        mvpp2_phy_disconnect(port);
@@ -5569,6 +5631,13 @@ static int mvpp2_stop(struct net_device *dev)
        on_each_cpu(mvpp2_interrupts_mask, port, 1);
 
        free_irq(port->irq, port);
+       for_each_present_cpu(cpu) {
+               port_pcpu = per_cpu_ptr(port->pcpu, cpu);
+
+               hrtimer_cancel(&port_pcpu->tx_done_timer);
+               port_pcpu->timer_scheduled = false;
+               tasklet_kill(&port_pcpu->tx_done_tasklet);
+       }
        mvpp2_cleanup_rxqs(port);
        mvpp2_cleanup_txqs(port);
 
@@ -5784,7 +5853,6 @@ static int mvpp2_ethtool_set_coalesce(struct net_device *dev,
                txq->done_pkts_coal = c->tx_max_coalesced_frames;
        }
 
-       on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
        return 0;
 }
 
@@ -6035,6 +6103,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 {
        struct device_node *phy_node;
        struct mvpp2_port *port;
+       struct mvpp2_port_pcpu *port_pcpu;
        struct net_device *dev;
        struct resource *res;
        const char *dt_mac_addr;
@@ -6044,7 +6113,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        int features;
        int phy_mode;
        int priv_common_regs_num = 2;
-       int err, i;
+       int err, i, cpu;
 
        dev = alloc_etherdev_mqs(sizeof(struct mvpp2_port), txq_number,
                                 rxq_number);
@@ -6135,6 +6204,24 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        }
        mvpp2_port_power_up(port);
 
+       port->pcpu = alloc_percpu(struct mvpp2_port_pcpu);
+       if (!port->pcpu) {
+               err = -ENOMEM;
+               goto err_free_txq_pcpu;
+       }
+
+       for_each_present_cpu(cpu) {
+               port_pcpu = per_cpu_ptr(port->pcpu, cpu);
+
+               hrtimer_init(&port_pcpu->tx_done_timer, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_REL_PINNED);
+               port_pcpu->tx_done_timer.function = mvpp2_hr_timer_cb;
+               port_pcpu->timer_scheduled = false;
+
+               tasklet_init(&port_pcpu->tx_done_tasklet, mvpp2_tx_proc_cb,
+                            (unsigned long)dev);
+       }
+
        netif_napi_add(dev, &port->napi, mvpp2_poll, NAPI_POLL_WEIGHT);
        features = NETIF_F_SG | NETIF_F_IP_CSUM;
        dev->features = features | NETIF_F_RXCSUM;
@@ -6144,7 +6231,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        err = register_netdev(dev);
        if (err < 0) {
                dev_err(&pdev->dev, "failed to register netdev\n");
-               goto err_free_txq_pcpu;
+               goto err_free_port_pcpu;
        }
        netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
 
@@ -6153,6 +6240,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        priv->port_list[id] = port;
        return 0;
 
+err_free_port_pcpu:
+       free_percpu(port->pcpu);
 err_free_txq_pcpu:
        for (i = 0; i < txq_number; i++)
                free_percpu(port->txqs[i]->pcpu);
@@ -6171,6 +6260,7 @@ static void mvpp2_port_remove(struct mvpp2_port *port)
        int i;
 
        unregister_netdev(port->dev);
+       free_percpu(port->pcpu);
        free_percpu(port->stats);
        for (i = 0; i < txq_number; i++)
                free_percpu(port->txqs[i]->pcpu);
index afad529838de748efc9f9253c6fde42abbe954a3..06e3e1e54c35d6078321d792d1e0e537ec95a207 100644 (file)
@@ -391,6 +391,8 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        /* disable cmdif checksum */
        MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0);
 
+       MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12);
+
        err = set_caps(dev, set_ctx, set_sz);
 
 query_ex:
index f78909a00f150edfd76065b2b993d9660edaebdd..09d2e16fd6b00bfdd0c20fc10c64abd03c29a935 100644 (file)
@@ -952,9 +952,8 @@ static int ks8842_alloc_dma_bufs(struct net_device *netdev)
 
        sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev,
                tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE);
-       err = dma_mapping_error(adapter->dev,
-               sg_dma_address(&tx_ctl->sg));
-       if (err) {
+       if (dma_mapping_error(adapter->dev, sg_dma_address(&tx_ctl->sg))) {
+               err = -ENOMEM;
                sg_dma_address(&tx_ctl->sg) = 0;
                goto err;
        }
index 3df51faf18ae3ba8ce6bb7f49e6f51e4da1be738..f790f61ea78a2b4f1008da82eca29132ff5bdcc0 100644 (file)
@@ -4875,10 +4875,12 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
        case RTL_GIGA_MAC_VER_46:
        case RTL_GIGA_MAC_VER_47:
        case RTL_GIGA_MAC_VER_48:
+               RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
+               break;
        case RTL_GIGA_MAC_VER_49:
        case RTL_GIGA_MAC_VER_50:
        case RTL_GIGA_MAC_VER_51:
-               RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
+               RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
                break;
        default:
                RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
index 2d8578cade03790782af7e97a1f59f9848301ae6..2e7f9a2834be320eef4a7bed44d8c787f72f3e65 100644 (file)
@@ -4821,6 +4821,7 @@ static void rocker_remove_ports(const struct rocker *rocker)
                rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE,
                                   ROCKER_OP_FLAG_REMOVE);
                unregister_netdev(rocker_port->dev);
+               free_netdev(rocker_port->dev);
        }
        kfree(rocker->ports);
 }
index 605cc8948594626783e093db71d474d638a26bc1..b1a4ea21c91c13fa1fe8d7661cd589d1424cea30 100644 (file)
@@ -1282,7 +1282,12 @@ static size_t efx_ef10_update_stats_common(struct efx_nic *efx, u64 *full_stats,
                }
        }
 
-       if (core_stats) {
+       if (!core_stats)
+               return stats_count;
+
+       if (nic_data->datapath_caps &
+                       1 << MC_CMD_GET_CAPABILITIES_OUT_EVB_LBN) {
+               /* Use vadaptor stats. */
                core_stats->rx_packets = stats[EF10_STAT_rx_unicast] +
                                         stats[EF10_STAT_rx_multicast] +
                                         stats[EF10_STAT_rx_broadcast];
@@ -1302,6 +1307,26 @@ static size_t efx_ef10_update_stats_common(struct efx_nic *efx, u64 *full_stats,
                core_stats->rx_fifo_errors = stats[EF10_STAT_rx_overflow];
                core_stats->rx_errors = core_stats->rx_crc_errors;
                core_stats->tx_errors = stats[EF10_STAT_tx_bad];
+       } else {
+               /* Use port stats. */
+               core_stats->rx_packets = stats[EF10_STAT_port_rx_packets];
+               core_stats->tx_packets = stats[EF10_STAT_port_tx_packets];
+               core_stats->rx_bytes = stats[EF10_STAT_port_rx_bytes];
+               core_stats->tx_bytes = stats[EF10_STAT_port_tx_bytes];
+               core_stats->rx_dropped = stats[EF10_STAT_port_rx_nodesc_drops] +
+                                        stats[GENERIC_STAT_rx_nodesc_trunc] +
+                                        stats[GENERIC_STAT_rx_noskb_drops];
+               core_stats->multicast = stats[EF10_STAT_port_rx_multicast];
+               core_stats->rx_length_errors =
+                               stats[EF10_STAT_port_rx_gtjumbo] +
+                               stats[EF10_STAT_port_rx_length_error];
+               core_stats->rx_crc_errors = stats[EF10_STAT_port_rx_bad];
+               core_stats->rx_frame_errors =
+                               stats[EF10_STAT_port_rx_align_error];
+               core_stats->rx_fifo_errors = stats[EF10_STAT_port_rx_overflow];
+               core_stats->rx_errors = (core_stats->rx_length_errors +
+                                        core_stats->rx_crc_errors +
+                                        core_stats->rx_frame_errors);
        }
 
        return stats_count;
index 7e3129e7f143a9990c89780a8e6638f8182e4892..f0e4bb4e3ec59f9695957dee9dec55a02d450da8 100644 (file)
@@ -42,7 +42,7 @@
 #define NSS_COMMON_CLK_DIV_MASK                        0x7f
 
 #define NSS_COMMON_CLK_SRC_CTRL                        0x14
-#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x)      (1 << x)
+#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x)      (x)
 /* Mode is coded on 1 bit but is different depending on the MAC ID:
  * MAC0: QSGMII=0 RGMII=1
  * MAC1: QSGMII=0 SGMII=0 RGMII=1
@@ -291,7 +291,7 @@ static void *ipq806x_gmac_setup(struct platform_device *pdev)
 
        /* Configure the clock src according to the mode */
        regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
-       val &= ~NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
+       val &= ~(1 << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id));
        switch (gmac->phy_mode) {
        case PHY_INTERFACE_MODE_RGMII:
                val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
index a8a730641bbb14e723f841b2b3c13454b53a5491..bb1bb72121c0474b8c1898540a28d21264479d6a 100644 (file)
@@ -85,7 +85,6 @@ struct netcp_intf {
        struct list_head        rxhook_list_head;
        unsigned int            rx_queue_id;
        void                    *rx_fdq[KNAV_DMA_FDQ_PER_CHAN];
-       u32                     rx_buffer_sizes[KNAV_DMA_FDQ_PER_CHAN];
        struct napi_struct      rx_napi;
        struct napi_struct      tx_napi;
 
index 9749dfd78c434992f4041effc3c9a7314bdace3d..4755838c6137b462d6de262b38beadacdf099e98 100644 (file)
@@ -34,6 +34,7 @@
 #define NETCP_SOP_OFFSET       (NET_IP_ALIGN + NET_SKB_PAD)
 #define NETCP_NAPI_WEIGHT      64
 #define NETCP_TX_TIMEOUT       (5 * HZ)
+#define NETCP_PACKET_SIZE      (ETH_FRAME_LEN + ETH_FCS_LEN)
 #define NETCP_MIN_PACKET_SIZE  ETH_ZLEN
 #define NETCP_MAX_MCAST_ADDR   16
 
@@ -804,30 +805,28 @@ static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
        if (likely(fdq == 0)) {
                unsigned int primary_buf_len;
                /* Allocate a primary receive queue entry */
-               buf_len = netcp->rx_buffer_sizes[0] + NETCP_SOP_OFFSET;
+               buf_len = NETCP_PACKET_SIZE + NETCP_SOP_OFFSET;
                primary_buf_len = SKB_DATA_ALIGN(buf_len) +
                                SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
-               if (primary_buf_len <= PAGE_SIZE) {
-                       bufptr = netdev_alloc_frag(primary_buf_len);
-                       pad[1] = primary_buf_len;
-               } else {
-                       bufptr = kmalloc(primary_buf_len, GFP_ATOMIC |
-                                        GFP_DMA32 | __GFP_COLD);
-                       pad[1] = 0;
-               }
+               bufptr = netdev_alloc_frag(primary_buf_len);
+               pad[1] = primary_buf_len;
 
                if (unlikely(!bufptr)) {
-                       dev_warn_ratelimited(netcp->ndev_dev, "Primary RX buffer alloc failed\n");
+                       dev_warn_ratelimited(netcp->ndev_dev,
+                                            "Primary RX buffer alloc failed\n");
                        goto fail;
                }
                dma = dma_map_single(netcp->dev, bufptr, buf_len,
                                     DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(netcp->dev, dma)))
+                       goto fail;
+
                pad[0] = (u32)bufptr;
 
        } else {
                /* Allocate a secondary receive queue entry */
-               page = alloc_page(GFP_ATOMIC | GFP_DMA32 | __GFP_COLD);
+               page = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_COLD);
                if (unlikely(!page)) {
                        dev_warn_ratelimited(netcp->ndev_dev, "Secondary page alloc failed\n");
                        goto fail;
@@ -1010,7 +1009,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp)
 
        /* Map the linear buffer */
        dma_addr = dma_map_single(dev, skb->data, pkt_len, DMA_TO_DEVICE);
-       if (unlikely(!dma_addr)) {
+       if (unlikely(dma_mapping_error(dev, dma_addr))) {
                dev_err(netcp->ndev_dev, "Failed to map skb buffer\n");
                return NULL;
        }
@@ -1546,8 +1545,8 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
        knav_queue_disable_notify(netcp->rx_queue);
 
        /* open Rx FDQs */
-       for (i = 0; i < KNAV_DMA_FDQ_PER_CHAN &&
-            netcp->rx_queue_depths[i] && netcp->rx_buffer_sizes[i]; ++i) {
+       for (i = 0; i < KNAV_DMA_FDQ_PER_CHAN && netcp->rx_queue_depths[i];
+            ++i) {
                snprintf(name, sizeof(name), "rx-fdq-%s-%d", ndev->name, i);
                netcp->rx_fdq[i] = knav_queue_open(name, KNAV_QUEUE_GP, 0);
                if (IS_ERR_OR_NULL(netcp->rx_fdq[i])) {
@@ -1941,14 +1940,6 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
                netcp->rx_queue_depths[0] = 128;
        }
 
-       ret = of_property_read_u32_array(node_interface, "rx-buffer-size",
-                                        netcp->rx_buffer_sizes,
-                                        KNAV_DMA_FDQ_PER_CHAN);
-       if (ret) {
-               dev_err(dev, "missing \"rx-buffer-size\" parameter\n");
-               netcp->rx_buffer_sizes[0] = 1536;
-       }
-
        ret = of_property_read_u32_array(node_interface, "rx-pool", temp, 2);
        if (ret < 0) {
                dev_err(dev, "missing \"rx-pool\" parameter\n");
index 2ffbf13471d09ad4c27d8c70fbb4dd3145befa75..216bfd350169a9da723035876d152e89b17c8432 100644 (file)
@@ -728,11 +728,12 @@ static int mkiss_open(struct tty_struct *tty)
        dev->type = ARPHRD_AX25;
 
        /* Perform the low-level AX25 initialization. */
-       if ((err = ax_open(ax->dev))) {
+       err = ax_open(ax->dev);
+       if (err)
                goto out_free_netdev;
-       }
 
-       if (register_netdev(dev))
+       err = register_netdev(dev);
+       if (err)
                goto out_free_buffers;
 
        /* after register_netdev() - because else printk smashes the kernel */
index 1960b46add65b3b89f122cc401c872050cebdbe4..d7a65247f95258f8a37c3375eb9309ff7ac4f697 100644 (file)
@@ -290,6 +290,15 @@ struct phy_device *fixed_phy_register(unsigned int irq,
                return ERR_PTR(-EINVAL);
        }
 
+       /* propagate the fixed link values to struct phy_device */
+       phy->link = status->link;
+       if (status->link) {
+               phy->speed = status->speed;
+               phy->duplex = status->duplex;
+               phy->pause = status->pause;
+               phy->asym_pause = status->asym_pause;
+       }
+
        of_node_get(np);
        phy->dev.of_node = np;
 
index b2197b506acbe86f3540d5ae1d8334129c2bbe57..34fe339f4e801c14376dce3073524eaaa4034512 100644 (file)
@@ -811,6 +811,7 @@ void phy_state_machine(struct work_struct *work)
        bool needs_aneg = false, do_suspend = false;
        enum phy_state old_state;
        int err = 0;
+       int old_link;
 
        mutex_lock(&phydev->lock);
 
@@ -896,11 +897,18 @@ void phy_state_machine(struct work_struct *work)
                phydev->adjust_link(phydev->attached_dev);
                break;
        case PHY_RUNNING:
-               /* Only register a CHANGE if we are
-                * polling or ignoring interrupts
+               /* Only register a CHANGE if we are polling or ignoring
+                * interrupts and link changed since latest checking.
                 */
-               if (!phy_interrupt_is_valid(phydev))
-                       phydev->state = PHY_CHANGELINK;
+               if (!phy_interrupt_is_valid(phydev)) {
+                       old_link = phydev->link;
+                       err = phy_read_status(phydev);
+                       if (err)
+                               break;
+
+                       if (old_link != phydev->link)
+                               phydev->state = PHY_CHANGELINK;
+               }
                break;
        case PHY_CHANGELINK:
                err = phy_read_status(phydev);
@@ -1030,10 +1038,14 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
        int value = -1;
 
        if (phydrv->read_mmd_indirect == NULL) {
-               mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+               struct mii_bus *bus = phydev->bus;
+
+               mutex_lock(&bus->mdio_lock);
+               mmd_phy_indirect(bus, prtad, devad, addr);
 
                /* Read the content of the MMD's selected register */
-               value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA);
+               value = bus->read(bus, addr, MII_MMD_DATA);
+               mutex_unlock(&bus->mdio_lock);
        } else {
                value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
        }
@@ -1063,10 +1075,14 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
        struct phy_driver *phydrv = phydev->drv;
 
        if (phydrv->write_mmd_indirect == NULL) {
-               mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+               struct mii_bus *bus = phydev->bus;
+
+               mutex_lock(&bus->mdio_lock);
+               mmd_phy_indirect(bus, prtad, devad, addr);
 
                /* Write the data into MMD's selected register */
-               phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data);
+               bus->write(bus, addr, MII_MMD_DATA, data);
+               mutex_unlock(&bus->mdio_lock);
        } else {
                phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
        }
index 0302483de24066a64446699cb360b2fb2ad6a890..55f01788df5ec3beb734938e48cb620c3aeedd3d 100644 (file)
@@ -176,7 +176,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
        if (c45_ids)
                dev->c45_ids = *c45_ids;
        dev->bus = bus;
-       dev->dev.parent = bus->parent;
+       dev->dev.parent = &bus->dev;
        dev->dev.bus = &mdio_bus_type;
        dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
        dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
index c0f6479e19d48e51fd76c3bbce161ffdd7846842..70b08958763a129fff47ad00a1db130c1334f254 100644 (file)
@@ -91,19 +91,18 @@ static int lan911x_config_init(struct phy_device *phydev)
 }
 
 /*
- * The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
- * other in order to set the ENERGYON bit and exit EDPD mode.  If a link partner
- * does send the pulses within this interval, the PHY will remained powered
- * down.
- *
- * This workaround will manually toggle the PHY on/off upon calls to read_status
- * in order to generate link test pulses if the link is down.  If a link partner
- * is present, it will respond to the pulses, which will cause the ENERGYON bit
- * to be set and will cause the EDPD mode to be exited.
+ * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
+ * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
+ * unstable detection of plugging in Ethernet cable.
+ * This workaround disables Energy Detect Power-Down mode and waiting for
+ * response on link pulses to detect presence of plugged Ethernet cable.
+ * The Energy Detect Power-Down mode is enabled again in the end of procedure to
+ * save approximately 220 mW of power if cable is unplugged.
  */
 static int lan87xx_read_status(struct phy_device *phydev)
 {
        int err = genphy_read_status(phydev);
+       int i;
 
        if (!phydev->link) {
                /* Disable EDPD to wake up PHY */
@@ -116,8 +115,16 @@ static int lan87xx_read_status(struct phy_device *phydev)
                if (rc < 0)
                        return rc;
 
-               /* Sleep 64 ms to allow ~5 link test pulses to be sent */
-               msleep(64);
+               /* Wait max 640 ms to detect energy */
+               for (i = 0; i < 64; i++) {
+                       /* Sleep to allow link test pulses to be sent */
+                       msleep(10);
+                       rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+                       if (rc < 0)
+                               return rc;
+                       if (rc & MII_LAN83C185_ENERGYON)
+                               break;
+               }
 
                /* Re-enable EDPD */
                rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
@@ -191,7 +198,7 @@ static struct phy_driver smsc_phy_driver[] = {
 
        /* basic functions */
        .config_aneg    = genphy_config_aneg,
-       .read_status    = genphy_read_status,
+       .read_status    = lan87xx_read_status,
        .config_init    = smsc_phy_config_init,
        .soft_reset     = smsc_phy_reset,
 
index 9d15566521a719b525a28a009f1d999c91a00da2..fa8f5046afe90627242f6d2d523178da653c9427 100644 (file)
@@ -269,9 +269,9 @@ static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
 static void ppp_ccp_closed(struct ppp *ppp);
 static struct compressor *find_compressor(int type);
 static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
-static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
+static struct ppp *ppp_create_interface(struct net *net, int unit,
+                                       struct file *file, int *retp);
 static void init_ppp_file(struct ppp_file *pf, int kind);
-static void ppp_shutdown_interface(struct ppp *ppp);
 static void ppp_destroy_interface(struct ppp *ppp);
 static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
 static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
@@ -392,8 +392,10 @@ static int ppp_release(struct inode *unused, struct file *file)
                file->private_data = NULL;
                if (pf->kind == INTERFACE) {
                        ppp = PF_TO_PPP(pf);
+                       rtnl_lock();
                        if (file == ppp->owner)
-                               ppp_shutdown_interface(ppp);
+                               unregister_netdevice(ppp->dev);
+                       rtnl_unlock();
                }
                if (atomic_dec_and_test(&pf->refcnt)) {
                        switch (pf->kind) {
@@ -593,8 +595,10 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                mutex_lock(&ppp_mutex);
                if (pf->kind == INTERFACE) {
                        ppp = PF_TO_PPP(pf);
+                       rtnl_lock();
                        if (file == ppp->owner)
-                               ppp_shutdown_interface(ppp);
+                               unregister_netdevice(ppp->dev);
+                       rtnl_unlock();
                }
                if (atomic_long_read(&file->f_count) < 2) {
                        ppp_release(NULL, file);
@@ -838,11 +842,10 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
                /* Create a new ppp unit */
                if (get_user(unit, p))
                        break;
-               ppp = ppp_create_interface(net, unit, &err);
+               ppp = ppp_create_interface(net, unit, file, &err);
                if (!ppp)
                        break;
                file->private_data = &ppp->file;
-               ppp->owner = file;
                err = -EFAULT;
                if (put_user(ppp->file.index, p))
                        break;
@@ -916,6 +919,16 @@ static __net_init int ppp_init_net(struct net *net)
 static __net_exit void ppp_exit_net(struct net *net)
 {
        struct ppp_net *pn = net_generic(net, ppp_net_id);
+       struct ppp *ppp;
+       LIST_HEAD(list);
+       int id;
+
+       rtnl_lock();
+       idr_for_each_entry(&pn->units_idr, ppp, id)
+               unregister_netdevice_queue(ppp->dev, &list);
+
+       unregister_netdevice_many(&list);
+       rtnl_unlock();
 
        idr_destroy(&pn->units_idr);
 }
@@ -1088,8 +1101,28 @@ static int ppp_dev_init(struct net_device *dev)
        return 0;
 }
 
+static void ppp_dev_uninit(struct net_device *dev)
+{
+       struct ppp *ppp = netdev_priv(dev);
+       struct ppp_net *pn = ppp_pernet(ppp->ppp_net);
+
+       ppp_lock(ppp);
+       ppp->closing = 1;
+       ppp_unlock(ppp);
+
+       mutex_lock(&pn->all_ppp_mutex);
+       unit_put(&pn->units_idr, ppp->file.index);
+       mutex_unlock(&pn->all_ppp_mutex);
+
+       ppp->owner = NULL;
+
+       ppp->file.dead = 1;
+       wake_up_interruptible(&ppp->file.rwait);
+}
+
 static const struct net_device_ops ppp_netdev_ops = {
        .ndo_init        = ppp_dev_init,
+       .ndo_uninit      = ppp_dev_uninit,
        .ndo_start_xmit  = ppp_start_xmit,
        .ndo_do_ioctl    = ppp_net_ioctl,
        .ndo_get_stats64 = ppp_get_stats64,
@@ -2667,8 +2700,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
  * or if there is already a unit with the requested number.
  * unit == -1 means allocate a new number.
  */
-static struct ppp *
-ppp_create_interface(struct net *net, int unit, int *retp)
+static struct ppp *ppp_create_interface(struct net *net, int unit,
+                                       struct file *file, int *retp)
 {
        struct ppp *ppp;
        struct ppp_net *pn;
@@ -2688,6 +2721,7 @@ ppp_create_interface(struct net *net, int unit, int *retp)
        ppp->mru = PPP_MRU;
        init_ppp_file(&ppp->file, INTERFACE);
        ppp->file.hdrlen = PPP_HDRLEN - 2;      /* don't count proto bytes */
+       ppp->owner = file;
        for (i = 0; i < NUM_NP; ++i)
                ppp->npmode[i] = NPMODE_PASS;
        INIT_LIST_HEAD(&ppp->channels);
@@ -2775,34 +2809,6 @@ init_ppp_file(struct ppp_file *pf, int kind)
        init_waitqueue_head(&pf->rwait);
 }
 
-/*
- * Take down a ppp interface unit - called when the owning file
- * (the one that created the unit) is closed or detached.
- */
-static void ppp_shutdown_interface(struct ppp *ppp)
-{
-       struct ppp_net *pn;
-
-       pn = ppp_pernet(ppp->ppp_net);
-       mutex_lock(&pn->all_ppp_mutex);
-
-       /* This will call dev_close() for us. */
-       ppp_lock(ppp);
-       if (!ppp->closing) {
-               ppp->closing = 1;
-               ppp_unlock(ppp);
-               unregister_netdev(ppp->dev);
-               unit_put(&pn->units_idr, ppp->file.index);
-       } else
-               ppp_unlock(ppp);
-
-       ppp->file.dead = 1;
-       ppp->owner = NULL;
-       wake_up_interruptible(&ppp->file.rwait);
-
-       mutex_unlock(&pn->all_ppp_mutex);
-}
-
 /*
  * Free the memory used by a ppp unit.  This is only called once
  * there are no channels connected to the unit and no file structs
index dac7a0d9bb46e5d9d2385250f990a2a0acf5996c..01f08a7751f7aeb9c39be52a7766ec2800885fc8 100644 (file)
@@ -396,7 +396,7 @@ static int rionet_close(struct net_device *ndev)
        return 0;
 }
 
-static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
+static void rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
 {
        struct rio_dev *rdev = to_rio_dev(dev);
        unsigned char netid = rdev->net->hport->id;
@@ -416,8 +416,6 @@ static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
                        }
                }
        }
-
-       return 0;
 }
 
 static void rionet_get_drvinfo(struct net_device *ndev,
index 9d43460ce3c71f0b54c69b84fa5a0ec8b7341d5f..64a60afbe50cc4ca0ff12b65ad6331a5fcc5e3a7 100644 (file)
@@ -785,6 +785,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81a4, 8)},    /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81a8, 8)},    /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81a9, 8)},    /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},    /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
        {QMI_FIXED_INTF(0x03f0, 0x581d, 4)},    /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
 
        /* 4. Gobi 1000 devices */
index 3c86b107275a899f3748e4cfee82ab2bb43aff6b..e0498571ae267c1d74dc3a65ed6d59c54cb92d1a 100644 (file)
@@ -778,7 +778,7 @@ int usbnet_stop (struct net_device *net)
 {
        struct usbnet           *dev = netdev_priv(net);
        struct driver_info      *info = dev->driver_info;
-       int                     retval, pm;
+       int                     retval, pm, mpn;
 
        clear_bit(EVENT_DEV_OPEN, &dev->flags);
        netif_stop_queue (net);
@@ -809,6 +809,8 @@ int usbnet_stop (struct net_device *net)
 
        usbnet_purge_paused_rxq(dev);
 
+       mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags);
+
        /* deferred work (task, timer, softirq) must also stop.
         * can't flush_scheduled_work() until we drop rtnl (later),
         * else workers could deadlock; so make workers a NOP.
@@ -819,8 +821,7 @@ int usbnet_stop (struct net_device *net)
        if (!pm)
                usb_autopm_put_interface(dev->intf);
 
-       if (info->manage_power &&
-           !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags))
+       if (info->manage_power && mpn)
                info->manage_power(dev, 0);
        else
                usb_autopm_put_interface(dev->intf);
index 7fbca37a1adffe5d46d3603e9fd44d4dbd16d331..237f8e5e493ddaae958684e8ed411c6f7f2363d6 100644 (file)
@@ -1756,9 +1756,9 @@ static int virtnet_probe(struct virtio_device *vdev)
        /* Do we support "hardware" checksums? */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
                /* This opens up the world of extra features. */
-               dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+               dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG;
                if (csum)
-                       dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+                       dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
 
                if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
                        dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
index 34c519eb1db5092a6e1bd17e02b9a3e53a5c5cb2..5bc4b1ed67b39fa6761abb4027191bcd4977ccaa 100644 (file)
@@ -2216,6 +2216,8 @@ static int vxlan_open(struct net_device *dev)
 
        if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
                ret = vxlan_igmp_join(vxlan);
+               if (ret == -EADDRINUSE)
+                       ret = 0;
                if (ret) {
                        vxlan_sock_release(vs);
                        return ret;
index 7193b7304fdd3ed4b69c0125732d4a024d4a4b36..848ea6a399f236b14cc5d9a79dd38038e0331aec 100644 (file)
@@ -589,7 +589,8 @@ static int cosa_probe(int base, int irq, int dma)
                chan->netdev->base_addr = chan->cosa->datareg;
                chan->netdev->irq = chan->cosa->irq;
                chan->netdev->dma = chan->cosa->dma;
-               if (register_hdlc_device(chan->netdev)) {
+               err = register_hdlc_device(chan->netdev);
+               if (err) {
                        netdev_warn(chan->netdev,
                                    "register_hdlc_device() failed\n");
                        free_netdev(chan->netdev);
index 25d1cbd34306e03ea4827e09509c345d11b5a1df..b2f0d245bcf3a0e71fb96797c47f71ad0ca736db 100644 (file)
@@ -3728,7 +3728,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
                switch (phy->rev) {
                case 6:
                case 5:
-                       if (sprom->fem.ghz5.extpa_gain == 3)
+                       if (sprom->fem.ghz2.extpa_gain == 3)
                                return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
                        /* fall through */
                case 4:
index 5000bfcded617f32ca177ae7a0711f13a3ce65d3..5514ad6d4e54373d2a48564ec790489dfe1808dc 100644 (file)
@@ -1023,7 +1023,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
        cmd->scan_priority =
                iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
 
-       if (iwl_mvm_scan_total_iterations(params) == 0)
+       if (iwl_mvm_scan_total_iterations(params) == 1)
                cmd->ooc_priority =
                        iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
        else
index 6203c4ad9bba5d8ce3bb2f46f832c3bb4ebe85fc..9e144e71da0b5980264702a6210684cfa34edab5 100644 (file)
@@ -478,10 +478,16 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
                if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
                        iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
                                          APMG_PCIDEV_STT_VAL_WAKE_ME);
-               else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+               else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+                       iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+                                   CSR_RESET_LINK_PWR_MGMT_DISABLED);
                        iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
                                    CSR_HW_IF_CONFIG_REG_PREPARE |
                                    CSR_HW_IF_CONFIG_REG_ENABLE_PME);
+                       mdelay(1);
+                       iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+                                     CSR_RESET_LINK_PWR_MGMT_DISABLED);
+               }
                mdelay(5);
        }
 
@@ -575,6 +581,10 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
        if (ret >= 0)
                return 0;
 
+       iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+                   CSR_RESET_LINK_PWR_MGMT_DISABLED);
+       msleep(1);
+
        for (iter = 0; iter < 10; iter++) {
                /* If HW is not ready, prepare the conditions to check again */
                iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
@@ -582,8 +592,10 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
 
                do {
                        ret = iwl_pcie_set_hw_ready(trans);
-                       if (ret >= 0)
-                               return 0;
+                       if (ret >= 0) {
+                               ret = 0;
+                               goto out;
+                       }
 
                        usleep_range(200, 1000);
                        t += 200;
@@ -593,6 +605,10 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
 
        IWL_ERR(trans, "Couldn't prepare the card\n");
 
+out:
+       iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+                     CSR_RESET_LINK_PWR_MGMT_DISABLED);
+
        return ret;
 }
 
index 2b86c2135de36f627b397add88628bc47aa37271..607acb53c847558793d47a528d0830f9c79c8cbf 100644 (file)
@@ -1875,8 +1875,19 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 
        /* start timer if queue currently empty */
        if (q->read_ptr == q->write_ptr) {
-               if (txq->wd_timeout)
-                       mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
+               if (txq->wd_timeout) {
+                       /*
+                        * If the TXQ is active, then set the timer, if not,
+                        * set the timer in remainder so that the timer will
+                        * be armed with the right value when the station will
+                        * wake up.
+                        */
+                       if (!txq->frozen)
+                               mod_timer(&txq->stuck_timer,
+                                         jiffies + txq->wd_timeout);
+                       else
+                               txq->frozen_expiry_remainder = txq->wd_timeout;
+               }
                IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id);
                iwl_trans_pcie_ref(trans);
        }
index b6cc9ff47fc2e59b3cc92fe4002f05e59d981e56..1c6788aecc62658fe2cc7c4961415ef4715c8dde 100644 (file)
@@ -172,6 +172,7 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
                (struct rsi_91x_sdiodev *)adapter->rsi_dev;
        u32 len;
        u32 num_blocks;
+       const u8 *fw;
        const struct firmware *fw_entry = NULL;
        u32 block_size = dev->tx_blk_size;
        int status = 0;
@@ -200,6 +201,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
                return status;
        }
 
+       /* Copy firmware into DMA-accessible memory */
+       fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+       if (!fw)
+               return -ENOMEM;
        len = fw_entry->size;
 
        if (len % 4)
@@ -210,7 +215,8 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
        rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
        rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
 
-       status = rsi_copy_to_card(common, fw_entry->data, len, num_blocks);
+       status = rsi_copy_to_card(common, fw, len, num_blocks);
+       kfree(fw);
        release_firmware(fw_entry);
        return status;
 }
index 1106ce76707e1095fd523c5c541fa3740e9c9496..30c2cf7fa93b0c6015d22236c3a9189b462cb064 100644 (file)
@@ -146,7 +146,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
                return status;
        }
 
+       /* Copy firmware into DMA-accessible memory */
        fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+       if (!fw)
+               return -ENOMEM;
        len = fw_entry->size;
 
        if (len % 4)
@@ -158,6 +161,7 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
        rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
 
        status = rsi_copy_to_card(common, fw, len, num_blocks);
+       kfree(fw);
        release_firmware(fw_entry);
        return status;
 }
index 3b3a88b53b119909112a806ee71ab4d4bfa67a79..585d0883c7e58760eed503de64ced513c8331c82 100644 (file)
@@ -1015,9 +1015,12 @@ static void send_beacon_frame(struct ieee80211_hw *hw,
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+       struct rtl_tcb_desc tcb_desc;
 
-       if (skb)
-               rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, NULL);
+       if (skb) {
+               memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
+               rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc);
+       }
 }
 
 static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
index 1017f02d7bf7520868b25330493822e08f7826a0..7bf88d9dcdc3fc4732170c121ef78d5a85ca3fa9 100644 (file)
@@ -385,6 +385,7 @@ module_param_named(debug, rtl8723be_mod_params.debug, int, 0444);
 module_param_named(ips, rtl8723be_mod_params.inactiveps, bool, 0444);
 module_param_named(swlps, rtl8723be_mod_params.swctrl_lps, bool, 0444);
 module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444);
+module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444);
 module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog,
                   bool, 0444);
 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
index 1a83e190fc15e4158b5e441cc267ad149d465abe..28577a31549d1569032d63457464fe11fdf44d32 100644 (file)
@@ -61,6 +61,12 @@ void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue,
 void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
 {
        atomic_dec(&queue->inflight_packets);
+
+       /* Wake the dealloc thread _after_ decrementing inflight_packets so
+        * that if kthread_stop() has already been called, the dealloc thread
+        * does not wait forever with nothing to wake it.
+        */
+       wake_up(&queue->dealloc_wq);
 }
 
 int xenvif_schedulable(struct xenvif *vif)
index 7d50711476fe1e88debca95beb790d770261f036..3f44b522b8311a2c64eba48e6a9b7217ea0cb3a7 100644 (file)
@@ -810,23 +810,17 @@ static inline struct sk_buff *xenvif_alloc_skb(unsigned int size)
 static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *queue,
                                                        struct sk_buff *skb,
                                                        struct xen_netif_tx_request *txp,
-                                                       struct gnttab_map_grant_ref *gop)
+                                                       struct gnttab_map_grant_ref *gop,
+                                                       unsigned int frag_overflow,
+                                                       struct sk_buff *nskb)
 {
        struct skb_shared_info *shinfo = skb_shinfo(skb);
        skb_frag_t *frags = shinfo->frags;
        u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
        int start;
        pending_ring_idx_t index;
-       unsigned int nr_slots, frag_overflow = 0;
+       unsigned int nr_slots;
 
-       /* At this point shinfo->nr_frags is in fact the number of
-        * slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
-        */
-       if (shinfo->nr_frags > MAX_SKB_FRAGS) {
-               frag_overflow = shinfo->nr_frags - MAX_SKB_FRAGS;
-               BUG_ON(frag_overflow > MAX_SKB_FRAGS);
-               shinfo->nr_frags = MAX_SKB_FRAGS;
-       }
        nr_slots = shinfo->nr_frags;
 
        /* Skip first skb fragment if it is on same page as header fragment. */
@@ -841,13 +835,6 @@ static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *que
        }
 
        if (frag_overflow) {
-               struct sk_buff *nskb = xenvif_alloc_skb(0);
-               if (unlikely(nskb == NULL)) {
-                       if (net_ratelimit())
-                               netdev_err(queue->vif->dev,
-                                          "Can't allocate the frag_list skb.\n");
-                       return NULL;
-               }
 
                shinfo = skb_shinfo(nskb);
                frags = shinfo->frags;
@@ -1175,9 +1162,10 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                                     unsigned *copy_ops,
                                     unsigned *map_ops)
 {
-       struct gnttab_map_grant_ref *gop = queue->tx_map_ops, *request_gop;
-       struct sk_buff *skb;
+       struct gnttab_map_grant_ref *gop = queue->tx_map_ops;
+       struct sk_buff *skb, *nskb;
        int ret;
+       unsigned int frag_overflow;
 
        while (skb_queue_len(&queue->tx_queue) < budget) {
                struct xen_netif_tx_request txreq;
@@ -1265,6 +1253,29 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                        break;
                }
 
+               skb_shinfo(skb)->nr_frags = ret;
+               if (data_len < txreq.size)
+                       skb_shinfo(skb)->nr_frags++;
+               /* At this point shinfo->nr_frags is in fact the number of
+                * slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
+                */
+               frag_overflow = 0;
+               nskb = NULL;
+               if (skb_shinfo(skb)->nr_frags > MAX_SKB_FRAGS) {
+                       frag_overflow = skb_shinfo(skb)->nr_frags - MAX_SKB_FRAGS;
+                       BUG_ON(frag_overflow > MAX_SKB_FRAGS);
+                       skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
+                       nskb = xenvif_alloc_skb(0);
+                       if (unlikely(nskb == NULL)) {
+                               kfree_skb(skb);
+                               xenvif_tx_err(queue, &txreq, idx);
+                               if (net_ratelimit())
+                                       netdev_err(queue->vif->dev,
+                                                  "Can't allocate the frag_list skb.\n");
+                               break;
+                       }
+               }
+
                if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
                        struct xen_netif_extra_info *gso;
                        gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
@@ -1272,6 +1283,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                        if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
                                /* Failure in xenvif_set_skb_gso is fatal. */
                                kfree_skb(skb);
+                               kfree_skb(nskb);
                                break;
                        }
                }
@@ -1294,9 +1306,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                (*copy_ops)++;
 
-               skb_shinfo(skb)->nr_frags = ret;
                if (data_len < txreq.size) {
-                       skb_shinfo(skb)->nr_frags++;
                        frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
                                             pending_idx);
                        xenvif_tx_create_map_op(queue, pending_idx, &txreq, gop);
@@ -1310,13 +1320,8 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                queue->pending_cons++;
 
-               request_gop = xenvif_get_requests(queue, skb, txfrags, gop);
-               if (request_gop == NULL) {
-                       kfree_skb(skb);
-                       xenvif_tx_err(queue, &txreq, idx);
-                       break;
-               }
-               gop = request_gop;
+               gop = xenvif_get_requests(queue, skb, txfrags, gop,
+                                         frag_overflow, nskb);
 
                __skb_queue_tail(&queue->tx_queue, skb);
 
@@ -1536,7 +1541,6 @@ void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success)
                smp_wmb();
                queue->dealloc_prod++;
        } while (ubuf);
-       wake_up(&queue->dealloc_wq);
        spin_unlock_irqrestore(&queue->callback_lock, flags);
 
        if (likely(zerocopy_success))
index 2b77ccf77f81b8c1495e3b8a052ba5d1deb574cc..754a9bb0f58d2fed40b9fd5bbc16dc52ba313ccc 100644 (file)
@@ -355,7 +355,8 @@ static int nfc_mei_phy_enable(void *phy_id)
                goto err;
        }
 
-       r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy);
+       r = mei_cl_register_event_cb(phy->device, BIT(MEI_CL_EVENT_RX),
+                                    nfc_mei_event_cb, phy);
        if (r) {
                pr_err("Event cb registration failed %d\n", r);
                goto err;
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
new file mode 100644 (file)
index 0000000..8db2978
--- /dev/null
@@ -0,0 +1,39 @@
+menuconfig NVMEM
+       tristate "NVMEM Support"
+       select REGMAP
+       help
+         Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES...
+
+         This framework is designed to provide a generic interface to NVMEM
+         from both the Linux Kernel and the userspace.
+
+         This driver can also be built as a module. If so, the module
+         will be called nvmem_core.
+
+         If unsure, say no.
+
+if NVMEM
+
+config QCOM_QFPROM
+       tristate "QCOM QFPROM Support"
+       depends on ARCH_QCOM || COMPILE_TEST
+       select REGMAP_MMIO
+       help
+         Say y here to enable QFPROM support. The QFPROM provides access
+         functions for QFPROM data to rest of the drivers via nvmem interface.
+
+         This driver can also be built as a module. If so, the module
+         will be called nvmem_qfprom.
+
+config NVMEM_SUNXI_SID
+       tristate "Allwinner SoCs SID support"
+       depends on ARCH_SUNXI
+       select REGMAP_MMIO
+       help
+         This is a driver for the 'security ID' available on various Allwinner
+         devices.
+
+         This driver can also be built as a module. If so, the module
+         will be called nvmem_sunxi_sid.
+
+endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
new file mode 100644 (file)
index 0000000..4328b93
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for nvmem drivers.
+#
+
+obj-$(CONFIG_NVMEM)            += nvmem_core.o
+nvmem_core-y                   := core.o
+
+# Devices
+obj-$(CONFIG_QCOM_QFPROM)      += nvmem_qfprom.o
+nvmem_qfprom-y                 := qfprom.o
+obj-$(CONFIG_NVMEM_SUNXI_SID)  += nvmem_sunxi_sid.o
+nvmem_sunxi_sid-y              := sunxi_sid.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
new file mode 100644 (file)
index 0000000..d3c6676
--- /dev/null
@@ -0,0 +1,1083 @@
+/*
+ * nvmem framework core.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+struct nvmem_device {
+       const char              *name;
+       struct regmap           *regmap;
+       struct module           *owner;
+       struct device           dev;
+       int                     stride;
+       int                     word_size;
+       int                     ncells;
+       int                     id;
+       int                     users;
+       size_t                  size;
+       bool                    read_only;
+};
+
+struct nvmem_cell {
+       const char              *name;
+       int                     offset;
+       int                     bytes;
+       int                     bit_offset;
+       int                     nbits;
+       struct nvmem_device     *nvmem;
+       struct list_head        node;
+};
+
+static DEFINE_MUTEX(nvmem_mutex);
+static DEFINE_IDA(nvmem_ida);
+
+static LIST_HEAD(nvmem_cells);
+static DEFINE_MUTEX(nvmem_cells_mutex);
+
+#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+                                   struct bin_attribute *attr,
+                                   char *buf, loff_t pos, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nvmem_device *nvmem = to_nvmem_device(dev);
+       int rc;
+
+       /* Stop the user from reading */
+       if (pos > nvmem->size)
+               return 0;
+
+       if (pos + count > nvmem->size)
+               count = nvmem->size - pos;
+
+       count = round_down(count, nvmem->word_size);
+
+       rc = regmap_raw_read(nvmem->regmap, pos, buf, count);
+
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       return count;
+}
+
+static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
+                                    struct bin_attribute *attr,
+                                    char *buf, loff_t pos, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nvmem_device *nvmem = to_nvmem_device(dev);
+       int rc;
+
+       /* Stop the user from writing */
+       if (pos > nvmem->size)
+               return 0;
+
+       if (pos + count > nvmem->size)
+               count = nvmem->size - pos;
+
+       count = round_down(count, nvmem->word_size);
+
+       rc = regmap_raw_write(nvmem->regmap, pos, buf, count);
+
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       return count;
+}
+
+/* default read/write permissions */
+static struct bin_attribute bin_attr_rw_nvmem = {
+       .attr   = {
+               .name   = "nvmem",
+               .mode   = S_IWUSR | S_IRUGO,
+       },
+       .read   = bin_attr_nvmem_read,
+       .write  = bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_rw_attributes[] = {
+       &bin_attr_rw_nvmem,
+       NULL,
+};
+
+static const struct attribute_group nvmem_bin_rw_group = {
+       .bin_attrs      = nvmem_bin_rw_attributes,
+};
+
+static const struct attribute_group *nvmem_rw_dev_groups[] = {
+       &nvmem_bin_rw_group,
+       NULL,
+};
+
+/* read only permission */
+static struct bin_attribute bin_attr_ro_nvmem = {
+       .attr   = {
+               .name   = "nvmem",
+               .mode   = S_IRUGO,
+       },
+       .read   = bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_attributes[] = {
+       &bin_attr_ro_nvmem,
+       NULL,
+};
+
+static const struct attribute_group nvmem_bin_ro_group = {
+       .bin_attrs      = nvmem_bin_ro_attributes,
+};
+
+static const struct attribute_group *nvmem_ro_dev_groups[] = {
+       &nvmem_bin_ro_group,
+       NULL,
+};
+
+static void nvmem_release(struct device *dev)
+{
+       struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+       ida_simple_remove(&nvmem_ida, nvmem->id);
+       kfree(nvmem);
+}
+
+static const struct device_type nvmem_provider_type = {
+       .release        = nvmem_release,
+};
+
+static struct bus_type nvmem_bus_type = {
+       .name           = "nvmem",
+};
+
+static int of_nvmem_match(struct device *dev, void *nvmem_np)
+{
+       return dev->of_node == nvmem_np;
+}
+
+static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
+{
+       struct device *d;
+
+       if (!nvmem_np)
+               return NULL;
+
+       d = bus_find_device(&nvmem_bus_type, NULL, nvmem_np, of_nvmem_match);
+
+       if (!d)
+               return NULL;
+
+       return to_nvmem_device(d);
+}
+
+static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
+{
+       struct nvmem_cell *p;
+
+       list_for_each_entry(p, &nvmem_cells, node)
+               if (p && !strcmp(p->name, cell_id))
+                       return p;
+
+       return NULL;
+}
+
+static void nvmem_cell_drop(struct nvmem_cell *cell)
+{
+       mutex_lock(&nvmem_cells_mutex);
+       list_del(&cell->node);
+       mutex_unlock(&nvmem_cells_mutex);
+       kfree(cell);
+}
+
+static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
+{
+       struct nvmem_cell *cell;
+       struct list_head *p, *n;
+
+       list_for_each_safe(p, n, &nvmem_cells) {
+               cell = list_entry(p, struct nvmem_cell, node);
+               if (cell->nvmem == nvmem)
+                       nvmem_cell_drop(cell);
+       }
+}
+
+static void nvmem_cell_add(struct nvmem_cell *cell)
+{
+       mutex_lock(&nvmem_cells_mutex);
+       list_add_tail(&cell->node, &nvmem_cells);
+       mutex_unlock(&nvmem_cells_mutex);
+}
+
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+                                  const struct nvmem_cell_info *info,
+                                  struct nvmem_cell *cell)
+{
+       cell->nvmem = nvmem;
+       cell->offset = info->offset;
+       cell->bytes = info->bytes;
+       cell->name = info->name;
+
+       cell->bit_offset = info->bit_offset;
+       cell->nbits = info->nbits;
+
+       if (cell->nbits)
+               cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+                                          BITS_PER_BYTE);
+
+       if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+               dev_err(&nvmem->dev,
+                       "cell %s unaligned to nvmem stride %d\n",
+                       cell->name, nvmem->stride);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int nvmem_add_cells(struct nvmem_device *nvmem,
+                          const struct nvmem_config *cfg)
+{
+       struct nvmem_cell **cells;
+       const struct nvmem_cell_info *info = cfg->cells;
+       int i, rval;
+
+       cells = kcalloc(cfg->ncells, sizeof(*cells), GFP_KERNEL);
+       if (!cells)
+               return -ENOMEM;
+
+       for (i = 0; i < cfg->ncells; i++) {
+               cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
+               if (!cells[i]) {
+                       rval = -ENOMEM;
+                       goto err;
+               }
+
+               rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
+               if (IS_ERR_VALUE(rval)) {
+                       kfree(cells[i]);
+                       goto err;
+               }
+
+               nvmem_cell_add(cells[i]);
+       }
+
+       nvmem->ncells = cfg->ncells;
+       /* remove tmp array */
+       kfree(cells);
+
+       return 0;
+err:
+       while (--i)
+               nvmem_cell_drop(cells[i]);
+
+       return rval;
+}
+
+/**
+ * nvmem_register() - Register a nvmem device for given nvmem_config.
+ * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
+ *
+ * @config: nvmem device configuration with which nvmem device is created.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
+ * on success.
+ */
+
+struct nvmem_device *nvmem_register(const struct nvmem_config *config)
+{
+       struct nvmem_device *nvmem;
+       struct device_node *np;
+       struct regmap *rm;
+       int rval;
+
+       if (!config->dev)
+               return ERR_PTR(-EINVAL);
+
+       rm = dev_get_regmap(config->dev, NULL);
+       if (!rm) {
+               dev_err(config->dev, "Regmap not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
+       if (!nvmem)
+               return ERR_PTR(-ENOMEM);
+
+       rval  = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
+       if (rval < 0) {
+               kfree(nvmem);
+               return ERR_PTR(rval);
+       }
+
+       nvmem->id = rval;
+       nvmem->regmap = rm;
+       nvmem->owner = config->owner;
+       nvmem->stride = regmap_get_reg_stride(rm);
+       nvmem->word_size = regmap_get_val_bytes(rm);
+       nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
+       nvmem->dev.type = &nvmem_provider_type;
+       nvmem->dev.bus = &nvmem_bus_type;
+       nvmem->dev.parent = config->dev;
+       np = config->dev->of_node;
+       nvmem->dev.of_node = np;
+       dev_set_name(&nvmem->dev, "%s%d",
+                    config->name ? : "nvmem", config->id);
+
+       nvmem->read_only = of_property_read_bool(np, "read-only") |
+                          config->read_only;
+
+       nvmem->dev.groups = nvmem->read_only ? nvmem_ro_dev_groups :
+                                              nvmem_rw_dev_groups;
+
+       device_initialize(&nvmem->dev);
+
+       dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
+
+       rval = device_add(&nvmem->dev);
+       if (rval) {
+               ida_simple_remove(&nvmem_ida, nvmem->id);
+               kfree(nvmem);
+               return ERR_PTR(rval);
+       }
+
+       if (config->cells)
+               nvmem_add_cells(nvmem, config);
+
+       return nvmem;
+}
+EXPORT_SYMBOL_GPL(nvmem_register);
+
+/**
+ * nvmem_unregister() - Unregister previously registered nvmem device
+ *
+ * @nvmem: Pointer to previously registered nvmem device.
+ *
+ * Return: Will be an negative on error or a zero on success.
+ */
+int nvmem_unregister(struct nvmem_device *nvmem)
+{
+       mutex_lock(&nvmem_mutex);
+       if (nvmem->users) {
+               mutex_unlock(&nvmem_mutex);
+               return -EBUSY;
+       }
+       mutex_unlock(&nvmem_mutex);
+
+       nvmem_device_remove_all_cells(nvmem);
+       device_del(&nvmem->dev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+static struct nvmem_device *__nvmem_device_get(struct device_node *np,
+                                              struct nvmem_cell **cellp,
+                                              const char *cell_id)
+{
+       struct nvmem_device *nvmem = NULL;
+
+       mutex_lock(&nvmem_mutex);
+
+       if (np) {
+               nvmem = of_nvmem_find(np);
+               if (!nvmem) {
+                       mutex_unlock(&nvmem_mutex);
+                       return ERR_PTR(-EPROBE_DEFER);
+               }
+       } else {
+               struct nvmem_cell *cell = nvmem_find_cell(cell_id);
+
+               if (cell) {
+                       nvmem = cell->nvmem;
+                       *cellp = cell;
+               }
+
+               if (!nvmem) {
+                       mutex_unlock(&nvmem_mutex);
+                       return ERR_PTR(-ENOENT);
+               }
+       }
+
+       nvmem->users++;
+       mutex_unlock(&nvmem_mutex);
+
+       if (!try_module_get(nvmem->owner)) {
+               dev_err(&nvmem->dev,
+                       "could not increase module refcount for cell %s\n",
+                       nvmem->name);
+
+               mutex_lock(&nvmem_mutex);
+               nvmem->users--;
+               mutex_unlock(&nvmem_mutex);
+
+               return ERR_PTR(-EINVAL);
+       }
+
+       return nvmem;
+}
+
+static void __nvmem_device_put(struct nvmem_device *nvmem)
+{
+       module_put(nvmem->owner);
+       mutex_lock(&nvmem_mutex);
+       nvmem->users--;
+       mutex_unlock(&nvmem_mutex);
+}
+
+static int nvmem_match(struct device *dev, void *data)
+{
+       return !strcmp(dev_name(dev), data);
+}
+
+static struct nvmem_device *nvmem_find(const char *name)
+{
+       struct device *d;
+
+       d = bus_find_device(&nvmem_bus_type, NULL, (void *)name, nvmem_match);
+
+       if (!d)
+               return NULL;
+
+       return to_nvmem_device(d);
+}
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+/**
+ * of_nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev node: Device tree node that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.
+ */
+struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
+{
+
+       struct device_node *nvmem_np;
+       int index;
+
+       index = of_property_match_string(np, "nvmem-names", id);
+
+       nvmem_np = of_parse_phandle(np, "nvmem", index);
+       if (!nvmem_np)
+               return ERR_PTR(-EINVAL);
+
+       return __nvmem_device_get(nvmem_np, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(of_nvmem_device_get);
+#endif
+
+/**
+ * nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev : Device that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.
+ */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
+{
+       if (dev->of_node) { /* try dt first */
+               struct nvmem_device *nvmem;
+
+               nvmem = of_nvmem_device_get(dev->of_node, dev_name);
+
+               if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
+                       return nvmem;
+
+       }
+
+       return nvmem_find(dev_name);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_get);
+
+static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
+{
+       struct nvmem_device **nvmem = res;
+
+       if (WARN_ON(!nvmem || !*nvmem))
+               return 0;
+
+       return *nvmem == data;
+}
+
+static void devm_nvmem_device_release(struct device *dev, void *res)
+{
+       nvmem_device_put(*(struct nvmem_device **)res);
+}
+
+/**
+ * devm_nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
+ * that needs to be released.
+ */
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
+{
+       int ret;
+
+       ret = devres_release(dev, devm_nvmem_device_release,
+                            devm_nvmem_device_match, nvmem);
+
+       WARN_ON(ret);
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
+
+/**
+ * nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device that needs to be released.
+ */
+void nvmem_device_put(struct nvmem_device *nvmem)
+{
+       __nvmem_device_put(nvmem);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_put);
+
+/**
+ * devm_nvmem_device_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem name in nvmems property.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
+ * on success.  The nvmem_cell will be freed by the automatically once the
+ * device is freed.
+ */
+struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
+{
+       struct nvmem_device **ptr, *nvmem;
+
+       ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       nvmem = nvmem_device_get(dev, id);
+       if (!IS_ERR(nvmem)) {
+               *ptr = nvmem;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return nvmem;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
+static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
+{
+       struct nvmem_cell *cell = NULL;
+       struct nvmem_device *nvmem;
+
+       nvmem = __nvmem_device_get(NULL, &cell, cell_id);
+       if (IS_ERR(nvmem))
+               return ERR_CAST(nvmem);
+
+       return cell;
+}
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+/**
+ * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name from nvmem-cell-names property.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+                                           const char *name)
+{
+       struct device_node *cell_np, *nvmem_np;
+       struct nvmem_cell *cell;
+       struct nvmem_device *nvmem;
+       const __be32 *addr;
+       int rval, len, index;
+
+       index = of_property_match_string(np, "nvmem-cell-names", name);
+
+       cell_np = of_parse_phandle(np, "nvmem-cells", index);
+       if (!cell_np)
+               return ERR_PTR(-EINVAL);
+
+       nvmem_np = of_get_next_parent(cell_np);
+       if (!nvmem_np)
+               return ERR_PTR(-EINVAL);
+
+       nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+       if (IS_ERR(nvmem))
+               return ERR_CAST(nvmem);
+
+       addr = of_get_property(cell_np, "reg", &len);
+       if (!addr || (len < 2 * sizeof(u32))) {
+               dev_err(&nvmem->dev, "nvmem: invalid reg on %s\n",
+                       cell_np->full_name);
+               rval  = -EINVAL;
+               goto err_mem;
+       }
+
+       cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+       if (!cell) {
+               rval = -ENOMEM;
+               goto err_mem;
+       }
+
+       cell->nvmem = nvmem;
+       cell->offset = be32_to_cpup(addr++);
+       cell->bytes = be32_to_cpup(addr);
+       cell->name = cell_np->name;
+
+       addr = of_get_property(cell_np, "bits", &len);
+       if (addr && len == (2 * sizeof(u32))) {
+               cell->bit_offset = be32_to_cpup(addr++);
+               cell->nbits = be32_to_cpup(addr);
+       }
+
+       if (cell->nbits)
+               cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+                                          BITS_PER_BYTE);
+
+       if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+                       dev_err(&nvmem->dev,
+                               "cell %s unaligned to nvmem stride %d\n",
+                               cell->name, nvmem->stride);
+               rval  = -EINVAL;
+               goto err_sanity;
+       }
+
+       nvmem_cell_add(cell);
+
+       return cell;
+
+err_sanity:
+       kfree(cell);
+
+err_mem:
+       __nvmem_device_put(nvmem);
+
+       return ERR_PTR(rval);
+}
+EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+#endif
+
+/**
+ * nvmem_cell_get() - Get nvmem cell of device form a given cell name
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name to get.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
+{
+       struct nvmem_cell *cell;
+
+       if (dev->of_node) { /* try dt first */
+               cell = of_nvmem_cell_get(dev->of_node, cell_id);
+               if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
+                       return cell;
+       }
+
+       return nvmem_cell_get_from_list(cell_id);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_get);
+
+static void devm_nvmem_cell_release(struct device *dev, void *res)
+{
+       nvmem_cell_put(*(struct nvmem_cell **)res);
+}
+
+/**
+ * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem id in nvmem-names property.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell.  The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
+{
+       struct nvmem_cell **ptr, *cell;
+
+       ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       cell = nvmem_cell_get(dev, id);
+       if (!IS_ERR(cell)) {
+               *ptr = cell;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return cell;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
+
+static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
+{
+       struct nvmem_cell **c = res;
+
+       if (WARN_ON(!c || !*c))
+               return 0;
+
+       return *c == data;
+}
+
+/**
+ * devm_nvmem_cell_put() - Release previously allocated nvmem cell
+ * from devm_nvmem_cell_get.
+ *
+ * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get()
+ */
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
+{
+       int ret;
+
+       ret = devres_release(dev, devm_nvmem_cell_release,
+                               devm_nvmem_cell_match, cell);
+
+       WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_nvmem_cell_put);
+
+/**
+ * nvmem_cell_put() - Release previously allocated nvmem cell.
+ *
+ * @cell: Previously allocated nvmem cell by nvmem_cell_get()
+ */
+void nvmem_cell_put(struct nvmem_cell *cell)
+{
+       struct nvmem_device *nvmem = cell->nvmem;
+
+       __nvmem_device_put(nvmem);
+       nvmem_cell_drop(cell);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell,
+                                                   void *buf)
+{
+       u8 *p, *b;
+       int i, bit_offset = cell->bit_offset;
+
+       p = b = buf;
+       if (bit_offset) {
+               /* First shift */
+               *b++ >>= bit_offset;
+
+               /* setup rest of the bytes if any */
+               for (i = 1; i < cell->bytes; i++) {
+                       /* Get bits from next byte and shift them towards msb */
+                       *p |= *b << (BITS_PER_BYTE - bit_offset);
+
+                       p = b;
+                       *b++ >>= bit_offset;
+               }
+
+               /* result fits in less bytes */
+               if (cell->bytes != DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE))
+                       *p-- = 0;
+       }
+       /* clear msb bits if any leftover in the last byte */
+       *p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
+}
+
+static int __nvmem_cell_read(struct nvmem_device *nvmem,
+                     struct nvmem_cell *cell,
+                     void *buf, size_t *len)
+{
+       int rc;
+
+       rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       /* shift bits in-place */
+       if (cell->bit_offset || cell->bit_offset)
+               nvmem_shift_read_buffer_in_place(cell, buf);
+
+       *len = cell->bytes;
+
+       return 0;
+}
+
+/**
+ * nvmem_cell_read() - Read a given nvmem cell
+ *
+ * @cell: nvmem cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a char * buffer on success.
+ * The buffer should be freed by the consumer with a kfree().
+ */
+void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+{
+       struct nvmem_device *nvmem = cell->nvmem;
+       u8 *buf;
+       int rc;
+
+       if (!nvmem || !nvmem->regmap)
+               return ERR_PTR(-EINVAL);
+
+       buf = kzalloc(cell->bytes, GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       rc = __nvmem_cell_read(nvmem, cell, buf, len);
+       if (IS_ERR_VALUE(rc)) {
+               kfree(buf);
+               return ERR_PTR(rc);
+       }
+
+       return buf;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
+                                                   u8 *_buf, int len)
+{
+       struct nvmem_device *nvmem = cell->nvmem;
+       int i, rc, nbits, bit_offset = cell->bit_offset;
+       u8 v, *p, *buf, *b, pbyte, pbits;
+
+       nbits = cell->nbits;
+       buf = kzalloc(cell->bytes, GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       memcpy(buf, _buf, len);
+       p = b = buf;
+
+       if (bit_offset) {
+               pbyte = *b;
+               *b <<= bit_offset;
+
+               /* setup the first byte with lsb bits from nvmem */
+               rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1);
+               *b++ |= GENMASK(bit_offset - 1, 0) & v;
+
+               /* setup rest of the byte if any */
+               for (i = 1; i < cell->bytes; i++) {
+                       /* Get last byte bits and shift them towards lsb */
+                       pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
+                       pbyte = *b;
+                       p = b;
+                       *b <<= bit_offset;
+                       *b++ |= pbits;
+               }
+       }
+
+       /* if it's not end on byte boundary */
+       if ((nbits + bit_offset) % BITS_PER_BYTE) {
+               /* setup the last byte with msb bits from nvmem */
+               rc = regmap_raw_read(nvmem->regmap,
+                                   cell->offset + cell->bytes - 1, &v, 1);
+               *p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
+
+       }
+
+       return buf;
+}
+
+/**
+ * nvmem_cell_write() - Write to a given nvmem cell
+ *
+ * @cell: nvmem cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to nvmem cell.
+ *
+ * Return: length of bytes written or negative on failure.
+ */
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
+{
+       struct nvmem_device *nvmem = cell->nvmem;
+       int rc;
+
+       if (!nvmem || !nvmem->regmap || nvmem->read_only ||
+           (cell->bit_offset == 0 && len != cell->bytes))
+               return -EINVAL;
+
+       if (cell->bit_offset || cell->nbits) {
+               buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+               if (IS_ERR(buf))
+                       return PTR_ERR(buf);
+       }
+
+       rc = regmap_raw_write(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+       /* free the tmp buffer */
+       if (cell->bit_offset)
+               kfree(buf);
+
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
+/**
+ * nvmem_device_cell_read() - Read a given nvmem device and cell
+ *
+ * @nvmem: nvmem device to read from.
+ * @info: nvmem cell info to be read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * Return: length of successful bytes read on success and negative
+ * error code on error.
+ */
+ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+                          struct nvmem_cell_info *info, void *buf)
+{
+       struct nvmem_cell cell;
+       int rc;
+       ssize_t len;
+
+       if (!nvmem || !nvmem->regmap)
+               return -EINVAL;
+
+       rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
+
+/**
+ * nvmem_device_cell_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @info: nvmem cell info to be written
+ * @buf: buffer to be written to cell.
+ *
+ * Return: length of bytes written or negative error code on failure.
+ * */
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+                           struct nvmem_cell_info *info, void *buf)
+{
+       struct nvmem_cell cell;
+       int rc;
+
+       if (!nvmem || !nvmem->regmap)
+               return -EINVAL;
+
+       rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       return nvmem_cell_write(&cell, buf, cell.bytes);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
+/**
+ * nvmem_device_read() - Read from a given nvmem device
+ *
+ * @nvmem: nvmem device to read from.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * Return: length of successful bytes read on success and negative
+ * error code on error.
+ */
+int nvmem_device_read(struct nvmem_device *nvmem,
+                     unsigned int offset,
+                     size_t bytes, void *buf)
+{
+       int rc;
+
+       if (!nvmem || !nvmem->regmap)
+               return -EINVAL;
+
+       rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
+
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+       return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_read);
+
+/**
+ * nvmem_device_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to write.
+ * @buf: buffer to be written.
+ *
+ * Return: length of bytes written or negative error code on failure.
+ * */
+int nvmem_device_write(struct nvmem_device *nvmem,
+                      unsigned int offset,
+                      size_t bytes, void *buf)
+{
+       int rc;
+
+       if (!nvmem || !nvmem->regmap)
+               return -EINVAL;
+
+       rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
+
+       if (IS_ERR_VALUE(rc))
+               return rc;
+
+
+       return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_write);
+
+static int __init nvmem_init(void)
+{
+       return bus_register(&nvmem_bus_type);
+}
+
+static void __exit nvmem_exit(void)
+{
+       bus_unregister(&nvmem_bus_type);
+}
+
+subsys_initcall(nvmem_init);
+module_exit(nvmem_exit);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("nvmem Driver Core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
new file mode 100644 (file)
index 0000000..afb67e7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct regmap_config qfprom_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 8,
+       .reg_stride = 1,
+};
+
+static struct nvmem_config econfig = {
+       .name = "qfprom",
+       .owner = THIS_MODULE,
+};
+
+static int qfprom_remove(struct platform_device *pdev)
+{
+       struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+       return nvmem_unregister(nvmem);
+}
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct nvmem_device *nvmem;
+       struct regmap *regmap;
+       void __iomem *base;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       qfprom_regmap_config.max_register = resource_size(res) - 1;
+
+       regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(dev, "regmap init failed\n");
+               return PTR_ERR(regmap);
+       }
+       econfig.dev = dev;
+       nvmem = nvmem_register(&econfig);
+       if (IS_ERR(nvmem))
+               return PTR_ERR(nvmem);
+
+       platform_set_drvdata(pdev, nvmem);
+
+       return 0;
+}
+
+static const struct of_device_id qfprom_of_match[] = {
+       { .compatible = "qcom,qfprom",},
+       {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, qfprom_of_match);
+
+static struct platform_driver qfprom_driver = {
+       .probe = qfprom_probe,
+       .remove = qfprom_remove,
+       .driver = {
+               .name = "qcom,qfprom",
+               .of_match_table = qfprom_of_match,
+       },
+};
+module_platform_driver(qfprom_driver);
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm QFPROM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
new file mode 100644 (file)
index 0000000..14777dd
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Allwinner sunXi SoCs Security ID support.
+ *
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+
+static struct nvmem_config econfig = {
+       .name = "sunxi-sid",
+       .read_only = true,
+       .owner = THIS_MODULE,
+};
+
+struct sunxi_sid {
+       void __iomem            *base;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
+                             const unsigned int offset)
+{
+       u32 sid_key;
+
+       sid_key = ioread32be(sid->base + round_down(offset, 4));
+       sid_key >>= (offset % 4) * 8;
+
+       return sid_key; /* Only return the last byte */
+}
+
+static int sunxi_sid_read(void *context,
+                           const void *reg, size_t reg_size,
+                           void *val, size_t val_size)
+{
+       struct sunxi_sid *sid = context;
+       unsigned int offset = *(u32 *)reg;
+       u8 *buf = val;
+
+       while (val_size) {
+               *buf++ = sunxi_sid_read_byte(sid, offset);
+               val_size--;
+               offset++;
+       }
+
+       return 0;
+}
+
+static int sunxi_sid_write(void *context, const void *data, size_t count)
+{
+       /* Unimplemented, dummy to keep regmap core happy */
+       return 0;
+}
+
+static struct regmap_bus sunxi_sid_bus = {
+       .read = sunxi_sid_read,
+       .write = sunxi_sid_write,
+       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+       .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
+{
+       return false;
+}
+
+static struct regmap_config sunxi_sid_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 8,
+       .reg_stride = 1,
+       .writeable_reg = sunxi_sid_writeable_reg,
+};
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       struct nvmem_device *nvmem;
+       struct regmap *regmap;
+       struct sunxi_sid *sid;
+       int i, size;
+       char *randomness;
+
+       sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
+       if (!sid)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       sid->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(sid->base))
+               return PTR_ERR(sid->base);
+
+       size = resource_size(res) - 1;
+       sunxi_sid_regmap_config.max_register = size;
+
+       regmap = devm_regmap_init(dev, &sunxi_sid_bus, sid,
+                                 &sunxi_sid_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(dev, "regmap init failed\n");
+               return PTR_ERR(regmap);
+       }
+
+       econfig.dev = dev;
+       nvmem = nvmem_register(&econfig);
+       if (IS_ERR(nvmem))
+               return PTR_ERR(nvmem);
+
+       randomness = kzalloc(sizeof(u8) * size, GFP_KERNEL);
+       for (i = 0; i < size; i++)
+               randomness[i] = sunxi_sid_read_byte(sid, i);
+
+       add_device_randomness(randomness, size);
+       kfree(randomness);
+
+       platform_set_drvdata(pdev, nvmem);
+
+       return 0;
+}
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+       struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+       return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+       { .compatible = "allwinner,sun4i-a10-sid" },
+       { .compatible = "allwinner,sun7i-a20-sid" },
+       {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static struct platform_driver sunxi_sid_driver = {
+       .probe = sunxi_sid_probe,
+       .remove = sunxi_sid_remove,
+       .driver = {
+               .name = "eeprom-sunxi-sid",
+               .of_match_table = sunxi_sid_of_match,
+       },
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
index a0580afe1713a5f58db5e96da635028856200a08..baec33c4e6981ffdb19df8d767f5aff8cb72bb77 100644 (file)
@@ -560,9 +560,6 @@ dino_fixup_bus(struct pci_bus *bus)
        } else if (bus->parent) {
                int i;
 
-               pci_read_bridge_bases(bus);
-
-
                for(i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
                        if((bus->self->resource[i].flags & 
                            (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
index dceb9ddfd99af6d754b0190fe2eb99431f64f4a6..901e1a3fa4e2689e6cfd31a01d01a80520dc3a22 100644 (file)
@@ -693,7 +693,6 @@ lba_fixup_bus(struct pci_bus *bus)
        if (bus->parent) {
                int i;
                /* PCI-PCI Bridge */
-               pci_read_bridge_bases(bus);
                for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++)
                        pci_claim_bridge_resource(bus->self, i);
        } else {
index 73de4efcbe6edc85c8f3fb54e0c925a7ab30492b..944f50015ed07b41b2de0da464812910c411cc1a 100644 (file)
@@ -2,7 +2,7 @@
 # PCI configuration
 #
 config PCI_BUS_ADDR_T_64BIT
-       def_bool y if (ARCH_DMA_ADDR_T_64BIT || 64BIT)
+       def_bool y if (ARCH_DMA_ADDR_T_64BIT || (64BIT && !PARISC))
        depends on PCI
 
 config PCI_MSI
index 73e4af400a5a6bc2d4985c1550228ecbf90b45ab..be3f631c3f75067103857635e6126a2b9c600a05 100644 (file)
@@ -33,6 +33,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 #
 obj-$(CONFIG_ALPHA) += setup-irq.o
 obj-$(CONFIG_ARM) += setup-irq.o
+obj-$(CONFIG_ARM64) += setup-irq.o
 obj-$(CONFIG_UNICORE32) += setup-irq.o
 obj-$(CONFIG_SUPERH) += setup-irq.o
 obj-$(CONFIG_MIPS) += setup-irq.o
index d9b64a175990cfc4b9bc93c339ae3270b8dcb025..769f7e35f1a2efecabd75b731465e29e71a4fd62 100644 (file)
@@ -439,6 +439,56 @@ static const struct pci_vpd_ops pci_vpd_pci22_ops = {
        .release = pci_vpd_pci22_release,
 };
 
+static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
+                              void *arg)
+{
+       struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+       ssize_t ret;
+
+       if (!tdev)
+               return -ENODEV;
+
+       ret = pci_read_vpd(tdev, pos, count, arg);
+       pci_dev_put(tdev);
+       return ret;
+}
+
+static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
+                               const void *arg)
+{
+       struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+       ssize_t ret;
+
+       if (!tdev)
+               return -ENODEV;
+
+       ret = pci_write_vpd(tdev, pos, count, arg);
+       pci_dev_put(tdev);
+       return ret;
+}
+
+static const struct pci_vpd_ops pci_vpd_f0_ops = {
+       .read = pci_vpd_f0_read,
+       .write = pci_vpd_f0_write,
+       .release = pci_vpd_pci22_release,
+};
+
+static int pci_vpd_f0_dev_check(struct pci_dev *dev)
+{
+       struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+       int ret = 0;
+
+       if (!tdev)
+               return -ENODEV;
+       if (!tdev->vpd || !tdev->multifunction ||
+           dev->class != tdev->class || dev->vendor != tdev->vendor ||
+           dev->device != tdev->device)
+               ret = -ENODEV;
+
+       pci_dev_put(tdev);
+       return ret;
+}
+
 int pci_vpd_pci22_init(struct pci_dev *dev)
 {
        struct pci_vpd_pci22 *vpd;
@@ -447,12 +497,21 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
        cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
        if (!cap)
                return -ENODEV;
+       if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
+               int ret = pci_vpd_f0_dev_check(dev);
+
+               if (ret)
+                       return ret;
+       }
        vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
        if (!vpd)
                return -ENOMEM;
 
        vpd->base.len = PCI_VPD_PCI22_SIZE;
-       vpd->base.ops = &pci_vpd_pci22_ops;
+       if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
+               vpd->base.ops = &pci_vpd_f0_ops;
+       else
+               vpd->base.ops = &pci_vpd_pci22_ops;
        mutex_init(&vpd->lock);
        vpd->cap = cap;
        vpd->busy = false;
@@ -531,6 +590,14 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
        return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
 }
 
+static bool pcie_downstream_port(const struct pci_dev *dev)
+{
+       int type = pci_pcie_type(dev);
+
+       return type == PCI_EXP_TYPE_ROOT_PORT ||
+              type == PCI_EXP_TYPE_DOWNSTREAM;
+}
+
 bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
 {
        int type = pci_pcie_type(dev);
@@ -546,10 +613,7 @@ bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
 
 static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
 {
-       int type = pci_pcie_type(dev);
-
-       return (type == PCI_EXP_TYPE_ROOT_PORT ||
-               type == PCI_EXP_TYPE_DOWNSTREAM) &&
+       return pcie_downstream_port(dev) &&
               pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
 }
 
@@ -628,10 +692,9 @@ int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
         * State bit in the Slot Status register of Downstream Ports,
         * which must be hardwired to 1b.  (PCIe Base Spec 3.0, sec 7.8)
         */
-       if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA &&
-                pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+       if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
+           pos == PCI_EXP_SLTSTA)
                *val = PCI_EXP_SLTSTA_PDS;
-       }
 
        return 0;
 }
@@ -657,10 +720,9 @@ int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
                return ret;
        }
 
-       if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL &&
-                pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+       if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
+           pos == PCI_EXP_SLTSTA)
                *val = PCI_EXP_SLTSTA_PDS;
-       }
 
        return 0;
 }
index a8099d4d0c9ddb335e80fddabdf1d0a2daa04e53..eeb9fb2b47aa07f01381a7cd82b2c73f93206fed 100644 (file)
 
 #include "pci.h"
 
-static int ats_alloc_one(struct pci_dev *dev, int ps)
+void pci_ats_init(struct pci_dev *dev)
 {
        int pos;
-       u16 cap;
-       struct pci_ats *ats;
 
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
        if (!pos)
-               return -ENODEV;
-
-       ats = kzalloc(sizeof(*ats), GFP_KERNEL);
-       if (!ats)
-               return -ENOMEM;
-
-       ats->pos = pos;
-       ats->stu = ps;
-       pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
-       ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
-                                           PCI_ATS_MAX_QDEP;
-       dev->ats = ats;
-
-       return 0;
-}
+               return;
 
-static void ats_free_one(struct pci_dev *dev)
-{
-       kfree(dev->ats);
-       dev->ats = NULL;
+       dev->ats_cap = pos;
 }
 
 /**
@@ -56,43 +37,36 @@ static void ats_free_one(struct pci_dev *dev)
  */
 int pci_enable_ats(struct pci_dev *dev, int ps)
 {
-       int rc;
        u16 ctrl;
+       struct pci_dev *pdev;
 
-       BUG_ON(dev->ats && dev->ats->is_enabled);
-
-       if (ps < PCI_ATS_MIN_STU)
+       if (!dev->ats_cap)
                return -EINVAL;
 
-       if (dev->is_physfn || dev->is_virtfn) {
-               struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
-
-               mutex_lock(&pdev->sriov->lock);
-               if (pdev->ats)
-                       rc = pdev->ats->stu == ps ? 0 : -EINVAL;
-               else
-                       rc = ats_alloc_one(pdev, ps);
-
-               if (!rc)
-                       pdev->ats->ref_cnt++;
-               mutex_unlock(&pdev->sriov->lock);
-               if (rc)
-                       return rc;
-       }
+       if (WARN_ON(dev->ats_enabled))
+               return -EBUSY;
 
-       if (!dev->is_physfn) {
-               rc = ats_alloc_one(dev, ps);
-               if (rc)
-                       return rc;
-       }
+       if (ps < PCI_ATS_MIN_STU)
+               return -EINVAL;
 
+       /*
+        * Note that enabling ATS on a VF fails unless it's already enabled
+        * with the same STU on the PF.
+        */
        ctrl = PCI_ATS_CTRL_ENABLE;
-       if (!dev->is_virtfn)
-               ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
-       pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
-       dev->ats->is_enabled = 1;
+       if (dev->is_virtfn) {
+               pdev = pci_physfn(dev);
+               if (pdev->ats_stu != ps)
+                       return -EINVAL;
+
+               atomic_inc(&pdev->ats_ref_cnt);  /* count enabled VFs */
+       } else {
+               dev->ats_stu = ps;
+               ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU);
+       }
+       pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
 
+       dev->ats_enabled = 1;
        return 0;
 }
 EXPORT_SYMBOL_GPL(pci_enable_ats);
@@ -103,28 +77,25 @@ EXPORT_SYMBOL_GPL(pci_enable_ats);
  */
 void pci_disable_ats(struct pci_dev *dev)
 {
+       struct pci_dev *pdev;
        u16 ctrl;
 
-       BUG_ON(!dev->ats || !dev->ats->is_enabled);
-
-       pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
-       ctrl &= ~PCI_ATS_CTRL_ENABLE;
-       pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
-
-       dev->ats->is_enabled = 0;
+       if (WARN_ON(!dev->ats_enabled))
+               return;
 
-       if (dev->is_physfn || dev->is_virtfn) {
-               struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
+       if (atomic_read(&dev->ats_ref_cnt))
+               return;         /* VFs still enabled */
 
-               mutex_lock(&pdev->sriov->lock);
-               pdev->ats->ref_cnt--;
-               if (!pdev->ats->ref_cnt)
-                       ats_free_one(pdev);
-               mutex_unlock(&pdev->sriov->lock);
+       if (dev->is_virtfn) {
+               pdev = pci_physfn(dev);
+               atomic_dec(&pdev->ats_ref_cnt);
        }
 
-       if (!dev->is_physfn)
-               ats_free_one(dev);
+       pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, &ctrl);
+       ctrl &= ~PCI_ATS_CTRL_ENABLE;
+       pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
+
+       dev->ats_enabled = 0;
 }
 EXPORT_SYMBOL_GPL(pci_disable_ats);
 
@@ -132,16 +103,13 @@ void pci_restore_ats_state(struct pci_dev *dev)
 {
        u16 ctrl;
 
-       if (!pci_ats_enabled(dev))
+       if (!dev->ats_enabled)
                return;
-       if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS))
-               BUG();
 
        ctrl = PCI_ATS_CTRL_ENABLE;
        if (!dev->is_virtfn)
-               ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU);
-
-       pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+               ctrl |= PCI_ATS_CTRL_STU(dev->ats_stu - PCI_ATS_MIN_STU);
+       pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
 }
 EXPORT_SYMBOL_GPL(pci_restore_ats_state);
 
@@ -159,23 +127,16 @@ EXPORT_SYMBOL_GPL(pci_restore_ats_state);
  */
 int pci_ats_queue_depth(struct pci_dev *dev)
 {
-       int pos;
        u16 cap;
 
+       if (!dev->ats_cap)
+               return -EINVAL;
+
        if (dev->is_virtfn)
                return 0;
 
-       if (dev->ats)
-               return dev->ats->qdep;
-
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
-       if (!pos)
-               return -ENODEV;
-
-       pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
-
-       return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
-                                      PCI_ATS_MAX_QDEP;
+       pci_read_config_word(dev, dev->ats_cap + PCI_ATS_CAP, &cap);
+       return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) : PCI_ATS_MAX_QDEP;
 }
 EXPORT_SYMBOL_GPL(pci_ats_queue_depth);
 
index c132bddc03f380a96a3c0acb5691a44df8fd2fa7..1272b8002884bd4e19ac8ab8aee0bdaef833080c 100644 (file)
@@ -53,7 +53,7 @@ config PCI_RCAR_GEN2_PCIE
 
 config PCI_HOST_GENERIC
        bool "Generic PCI host controller"
-       depends on ARM && OF
+       depends on (ARM || ARM64) && OF
        help
          Say Y here if you want to support a simple generic PCI host
          controller, such as the one emulated by kvmtool.
@@ -135,7 +135,7 @@ config PCIE_IPROC_PLATFORM
          through the generic platform bus interface
 
 config PCIE_IPROC_BCMA
-       bool "Broadcom iProc PCIe BCMA bus driver"
+       tristate "Broadcom iProc PCIe BCMA bus driver"
        depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST)
        select PCIE_IPROC
        select BCMA
index 80db09e47800dffb017d64177fe00775539d27b0..199e29a044cdf26c8194a2475e06034640859265 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_gpio.h>
 #include <linux/pci.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
@@ -83,6 +84,17 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
        writel(value, pcie->base + offset);
 }
 
+static inline u32 dra7xx_pcie_readl_rc(struct pcie_port *pp, u32 offset)
+{
+       return readl(pp->dbi_base + offset);
+}
+
+static inline void dra7xx_pcie_writel_rc(struct pcie_port *pp, u32 offset,
+                                        u32 value)
+{
+       writel(value, pp->dbi_base + offset);
+}
+
 static int dra7xx_pcie_link_up(struct pcie_port *pp)
 {
        struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
@@ -155,7 +167,6 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -325,6 +336,9 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
        char name[10];
+       int gpio_sel;
+       enum of_gpio_flags flags;
+       unsigned long gpio_flags;
 
        dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
        if (!dra7xx)
@@ -382,9 +396,25 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 
        pm_runtime_enable(dev);
        ret = pm_runtime_get_sync(dev);
-       if (IS_ERR_VALUE(ret)) {
+       if (ret < 0) {
                dev_err(dev, "pm_runtime_get_sync failed\n");
-               goto err_phy;
+               goto err_get_sync;
+       }
+
+       gpio_sel = of_get_gpio_flags(dev->of_node, 0, &flags);
+       if (gpio_is_valid(gpio_sel)) {
+               gpio_flags = (flags & OF_GPIO_ACTIVE_LOW) ?
+                               GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+               ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags,
+                                           "pcie_reset");
+               if (ret) {
+                       dev_err(&pdev->dev, "gpio%d request failed, ret %d\n",
+                               gpio_sel, ret);
+                       goto err_gpio;
+               }
+       } else if (gpio_sel == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto err_gpio;
        }
 
        reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
@@ -395,12 +425,14 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 
        ret = dra7xx_add_pcie_port(dra7xx, pdev);
        if (ret < 0)
-               goto err_add_port;
+               goto err_gpio;
 
        return 0;
 
-err_add_port:
+err_gpio:
        pm_runtime_put(dev);
+
+err_get_sync:
        pm_runtime_disable(dev);
 
 err_phy:
@@ -431,6 +463,85 @@ static int __exit dra7xx_pcie_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int dra7xx_pcie_suspend(struct device *dev)
+{
+       struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+       struct pcie_port *pp = &dra7xx->pp;
+       u32 val;
+
+       /* clear MSE */
+       val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
+       val &= ~PCI_COMMAND_MEMORY;
+       dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
+
+       return 0;
+}
+
+static int dra7xx_pcie_resume(struct device *dev)
+{
+       struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+       struct pcie_port *pp = &dra7xx->pp;
+       u32 val;
+
+       /* set MSE */
+       val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
+       val |= PCI_COMMAND_MEMORY;
+       dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
+
+       return 0;
+}
+
+static int dra7xx_pcie_suspend_noirq(struct device *dev)
+{
+       struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+       int count = dra7xx->phy_count;
+
+       while (count--) {
+               phy_power_off(dra7xx->phy[count]);
+               phy_exit(dra7xx->phy[count]);
+       }
+
+       return 0;
+}
+
+static int dra7xx_pcie_resume_noirq(struct device *dev)
+{
+       struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
+       int phy_count = dra7xx->phy_count;
+       int ret;
+       int i;
+
+       for (i = 0; i < phy_count; i++) {
+               ret = phy_init(dra7xx->phy[i]);
+               if (ret < 0)
+                       goto err_phy;
+
+               ret = phy_power_on(dra7xx->phy[i]);
+               if (ret < 0) {
+                       phy_exit(dra7xx->phy[i]);
+                       goto err_phy;
+               }
+       }
+
+       return 0;
+
+err_phy:
+       while (--i >= 0) {
+               phy_power_off(dra7xx->phy[i]);
+               phy_exit(dra7xx->phy[i]);
+       }
+
+       return ret;
+}
+#endif
+
+static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume)
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq,
+                                     dra7xx_pcie_resume_noirq)
+};
+
 static const struct of_device_id of_dra7xx_pcie_match[] = {
        { .compatible = "ti,dra7-pcie", },
        {},
@@ -442,6 +553,7 @@ static struct platform_driver dra7xx_pcie_driver = {
        .driver = {
                .name   = "dra7-pcie",
                .of_match_table = of_dra7xx_pcie_match,
+               .pm     = &dra7xx_pcie_pm_ops,
        },
 };
 
index ba46e581db99925f9deaf3a392fff4d42d72a8e4..265dd25169bff9d2edfe827cd9321442d7c1e47d 100644 (file)
@@ -38,7 +38,16 @@ struct gen_pci_cfg_windows {
        const struct gen_pci_cfg_bus_ops        *ops;
 };
 
+/*
+ * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
+ * sysdata.  Add pci_sys_data as the first element in struct gen_pci so
+ * that when we use a gen_pci pointer as sysdata, it is also a pointer to
+ * a struct pci_sys_data.
+ */
 struct gen_pci {
+#ifdef CONFIG_ARM
+       struct pci_sys_data                     sys;
+#endif
        struct pci_host_bridge                  host;
        struct gen_pci_cfg_windows              cfg;
        struct list_head                        resources;
@@ -48,8 +57,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
                                             unsigned int devfn,
                                             int where)
 {
-       struct pci_sys_data *sys = bus->sysdata;
-       struct gen_pci *pci = sys->private_data;
+       struct gen_pci *pci = bus->sysdata;
        resource_size_t idx = bus->number - pci->cfg.bus_range->start;
 
        return pci->cfg.win[idx] + ((devfn << 8) | where);
@@ -64,8 +72,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
                                              unsigned int devfn,
                                              int where)
 {
-       struct pci_sys_data *sys = bus->sysdata;
-       struct gen_pci *pci = sys->private_data;
+       struct gen_pci *pci = bus->sysdata;
        resource_size_t idx = bus->number - pci->cfg.bus_range->start;
 
        return pci->cfg.win[idx] + ((devfn << 12) | where);
@@ -198,13 +205,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
        return 0;
 }
 
-static int gen_pci_setup(int nr, struct pci_sys_data *sys)
-{
-       struct gen_pci *pci = sys->private_data;
-       list_splice_init(&pci->resources, &sys->resources);
-       return 1;
-}
-
 static int gen_pci_probe(struct platform_device *pdev)
 {
        int err;
@@ -214,13 +214,7 @@ static int gen_pci_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
        struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
-       struct hw_pci hw = {
-               .nr_controllers = 1,
-               .private_data   = (void **)&pci,
-               .setup          = gen_pci_setup,
-               .map_irq        = of_irq_parse_and_map_pci,
-               .ops            = &gen_pci_ops,
-       };
+       struct pci_bus *bus, *child;
 
        if (!pci)
                return -ENOMEM;
@@ -258,7 +252,27 @@ static int gen_pci_probe(struct platform_device *pdev)
                return err;
        }
 
-       pci_common_init_dev(dev, &hw);
+       /* Do not reassign resources if probe only */
+       if (!pci_has_flag(PCI_PROBE_ONLY))
+               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+
+       bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources);
+       if (!bus) {
+               dev_err(dev, "Scanning rootbus failed");
+               return -ENODEV;
+       }
+
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
+               pci_bus_size_bridges(bus);
+               pci_bus_assign_resources(bus);
+
+               list_for_each_entry(child, &bus->children, node)
+                       pcie_bus_configure_settings(child);
+       }
+
+       pci_bus_add_devices(bus);
        return 0;
 }
 
index 233a196c6e6661c8dc9aea975a5cf15bf253c2fb..8f3a9813c4e55a5f16ee48e3b54ccd1ec4985702 100644 (file)
@@ -117,11 +117,7 @@ static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
        val = addr << PCIE_PHY_CTRL_DATA_LOC;
        writel(val, dbi_base + PCIE_PHY_CTRL);
 
-       ret = pcie_phy_poll_ack(dbi_base, 0);
-       if (ret)
-               return ret;
-
-       return 0;
+       return pcie_phy_poll_ack(dbi_base, 0);
 }
 
 /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
@@ -148,11 +144,7 @@ static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
        /* deassert Read signal */
        writel(0x00, dbi_base + PCIE_PHY_CTRL);
 
-       ret = pcie_phy_poll_ack(dbi_base, 0);
-       if (ret)
-               return ret;
-
-       return 0;
+       return pcie_phy_poll_ack(dbi_base, 0);
 }
 
 static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
index f34892e0edb4f973e4dd3e9ab39b24cf0c2f0716..f1d0749ebbf066d99e02c73a8c609aaf55b4baa4 100644 (file)
@@ -196,7 +196,6 @@ static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
        irq_set_chip_and_handler(irq, &ks_dw_pcie_msi_irq_chip,
                                 handle_level_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -277,7 +276,6 @@ static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
        irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
                                 handle_level_irq);
        irq_set_chip_data(irq, d->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
index 70aa09556ec5ce3b5866766b7c7fec7bab332b19..67ec5e1c99dbbb75a6f14943b25539ca50dc0f1e 100644 (file)
@@ -879,6 +879,7 @@ static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
                return;
 
        pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
+       of_node_put(msi_node);
 
        if (pcie->msi)
                pcie->msi->dev = &pcie->pdev->dev;
index 10c05718dbfdcb27c31617b6b6ea725ff9d437d7..81df0c1fe063ff164aef16eb2cfc449539a8a107 100644 (file)
@@ -1248,7 +1248,6 @@ static int tegra_msi_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &tegra_msi_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        tegra_cpuidle_pcie_irqs_in_use();
 
index 2d31d4d6fd08dffa41adad3f887b1b130585ff63..398c9bfe13a92166f747d67fcc676eb42eadeec3 100644 (file)
@@ -223,7 +223,6 @@ static int xgene_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
        irq_domain_set_info(domain, virq, msi_irq,
                            &xgene_msi_bottom_irq_chip, domain->host_data,
                            handle_simple_irq, NULL, NULL);
-       set_irq_flags(virq, IRQF_VALID);
 
        return 0;
 }
@@ -582,7 +581,6 @@ error:
 static struct platform_driver xgene_msi_driver = {
        .driver = {
                .name = "xgene-msi",
-               .owner = THIS_MODULE,
                .of_match_table = xgene_msi_match_table,
        },
        .probe = xgene_msi_probe,
index a9dfb70d623ae0acbb54d96ada58a68ecc3074fe..0236ab9d5720133b57536c916591aab580157b28 100644 (file)
@@ -321,8 +321,16 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
                                return ret;
                        break;
                case IORESOURCE_MEM:
-                       xgene_pcie_setup_ob_reg(port, res, OMR1BARL, res->start,
-                                               res->start - window->offset);
+                       if (res->flags & IORESOURCE_PREFETCH)
+                               xgene_pcie_setup_ob_reg(port, res, OMR2BARL,
+                                                       res->start,
+                                                       res->start -
+                                                       window->offset);
+                       else
+                               xgene_pcie_setup_ob_reg(port, res, OMR1BARL,
+                                                       res->start,
+                                                       res->start -
+                                                       window->offset);
                        break;
                case IORESOURCE_BUS:
                        break;
@@ -514,6 +522,7 @@ static int xgene_pcie_msi_enable(struct pci_bus *bus)
        if (!bus->msi)
                return -ENODEV;
 
+       of_node_put(msi_node);
        bus->msi->dev = &bus->dev;
        return 0;
 }
index 69486be7181e18287a8a8bd421055b902233e3c4..8d52ce73f84262a4835557d952ddd709693fcef3 100644 (file)
@@ -350,7 +350,6 @@ static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -388,7 +387,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
                addrp = of_get_address(np, index, NULL, NULL);
                pp->cfg0_mod_base = of_read_number(addrp, ns);
                pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
-       } else {
+       } else if (!pp->va_cfg0_base) {
                dev_err(pp->dev, "missing *config* reg space\n");
        }
 
@@ -526,7 +525,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
 
 #ifdef CONFIG_PCI_MSI
        dw_pcie_msi_chip.dev = pp->dev;
-       dw_pci.msi_ctrl = &dw_pcie_msi_chip;
 #endif
 
        dw_pci.nr_controllers = 1;
@@ -708,8 +706,15 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
        struct pcie_port *pp = sys_to_pcie(sys);
 
        pp->root_bus_nr = sys->busnr;
-       bus = pci_scan_root_bus(pp->dev, sys->busnr,
-                                 &dw_pcie_ops, sys, &sys->resources);
+
+       if (IS_ENABLED(CONFIG_PCI_MSI))
+               bus = pci_scan_root_bus_msi(pp->dev, sys->busnr, &dw_pcie_ops,
+                                           sys, &sys->resources,
+                                           &dw_pcie_msi_chip);
+       else
+               bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
+                                       sys, &sys->resources);
+
        if (!bus)
                return NULL;
 
index d77481ea553e08de04527f885df842e3dc2f8d84..fe2efb141a9bd3b74c22af5764ead81dcfc2ce6d 100644 (file)
 #define SYS_RC_INTX_EN               0x330
 #define SYS_RC_INTX_MASK             0xf
 
-static inline struct iproc_pcie *sys_to_pcie(struct pci_sys_data *sys)
+static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
 {
-       return sys->private_data;
+       struct iproc_pcie *pcie;
+#ifdef CONFIG_ARM
+       struct pci_sys_data *sys = bus->sysdata;
+
+       pcie = sys->private_data;
+#else
+       pcie = bus->sysdata;
+#endif
+       return pcie;
 }
 
 /**
@@ -71,8 +79,7 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
                                            unsigned int devfn,
                                            int where)
 {
-       struct pci_sys_data *sys = bus->sysdata;
-       struct iproc_pcie *pcie = sys_to_pcie(sys);
+       struct iproc_pcie *pcie = iproc_data(bus);
        unsigned slot = PCI_SLOT(devfn);
        unsigned fn = PCI_FUNC(devfn);
        unsigned busno = bus->number;
@@ -186,32 +193,34 @@ static void iproc_pcie_enable(struct iproc_pcie *pcie)
 int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
 {
        int ret;
+       void *sysdata;
        struct pci_bus *bus;
 
        if (!pcie || !pcie->dev || !pcie->base)
                return -EINVAL;
 
-       if (pcie->phy) {
-               ret = phy_init(pcie->phy);
-               if (ret) {
-                       dev_err(pcie->dev, "unable to initialize PCIe PHY\n");
-                       return ret;
-               }
-
-               ret = phy_power_on(pcie->phy);
-               if (ret) {
-                       dev_err(pcie->dev, "unable to power on PCIe PHY\n");
-                       goto err_exit_phy;
-               }
+       ret = phy_init(pcie->phy);
+       if (ret) {
+               dev_err(pcie->dev, "unable to initialize PCIe PHY\n");
+               return ret;
+       }
 
+       ret = phy_power_on(pcie->phy);
+       if (ret) {
+               dev_err(pcie->dev, "unable to power on PCIe PHY\n");
+               goto err_exit_phy;
        }
 
        iproc_pcie_reset(pcie);
 
+#ifdef CONFIG_ARM
        pcie->sysdata.private_data = pcie;
+       sysdata = &pcie->sysdata;
+#else
+       sysdata = pcie;
+#endif
 
-       bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops,
-                                 &pcie->sysdata, res);
+       bus = pci_create_root_bus(pcie->dev, 0, &iproc_pcie_ops, sysdata, res);
        if (!bus) {
                dev_err(pcie->dev, "unable to create PCI root bus\n");
                ret = -ENOMEM;
@@ -229,7 +238,9 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
 
        pci_scan_child_bus(bus);
        pci_assign_unassigned_bus_resources(bus);
+#ifdef CONFIG_ARM
        pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
+#endif
        pci_bus_add_devices(bus);
 
        return 0;
@@ -239,12 +250,9 @@ err_rm_root_bus:
        pci_remove_root_bus(bus);
 
 err_power_off_phy:
-       if (pcie->phy)
-               phy_power_off(pcie->phy);
+       phy_power_off(pcie->phy);
 err_exit_phy:
-       if (pcie->phy)
-               phy_exit(pcie->phy);
-
+       phy_exit(pcie->phy);
        return ret;
 }
 EXPORT_SYMBOL(iproc_pcie_setup);
@@ -254,10 +262,8 @@ int iproc_pcie_remove(struct iproc_pcie *pcie)
        pci_stop_root_bus(pcie->root_bus);
        pci_remove_root_bus(pcie->root_bus);
 
-       if (pcie->phy) {
-               phy_power_off(pcie->phy);
-               phy_exit(pcie->phy);
-       }
+       phy_power_off(pcie->phy);
+       phy_exit(pcie->phy);
 
        return 0;
 }
index ba0a108309ccf584446947120be074fed83883ba..c9e4c10a462e80897eafec3fbbf3ba119c2307e3 100644 (file)
@@ -21,7 +21,7 @@
  * @dev: pointer to device data structure
  * @base: PCIe host controller I/O register base
  * @resources: linked list of all PCI resources
- * @sysdata: Per PCI controller data
+ * @sysdata: Per PCI controller data (ARM-specific)
  * @root_bus: pointer to root bus
  * @phy: optional PHY device that controls the Serdes
  * @irqs: interrupt IDs
@@ -29,7 +29,9 @@
 struct iproc_pcie {
        struct device *dev;
        void __iomem *base;
+#ifdef CONFIG_ARM
        struct pci_sys_data sysdata;
+#endif
        struct pci_bus *root_bus;
        struct phy *phy;
        int irqs[IPROC_PCIE_MAX_NUM_IRQS];
index c086210f2ffd1d0962ff253e98d06946e4236e89..7678fe0820d712d00fe189e8bf3d0651d4277ae9 100644 (file)
@@ -664,7 +664,6 @@ static int rcar_msi_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &rcar_msi_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
index c49fbdc0f6e461df57f4c23fe963eeb6d6ab904c..98d2683181bc5fbbbff05b89170d864c02e12cb3 100644 (file)
@@ -223,8 +223,7 @@ static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
        status = readl(&app_reg->int_sts);
 
        if (status & MSI_CTRL_INT) {
-               if (!IS_ENABLED(CONFIG_PCI_MSI))
-                       BUG();
+               BUG_ON(!IS_ENABLED(CONFIG_PCI_MSI));
                dw_handle_msi_irq(pp);
        }
 
index f1a06a091ccb578359656b1d9c4b32c0e99b2d99..1aeaa914bd3034e0b42823b6ba593ad047b917fc 100644 (file)
@@ -338,7 +338,6 @@ static int xilinx_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &xilinx_msi_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -377,7 +376,6 @@ static int xilinx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
        irq_set_chip_data(irq, domain->host_data);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -449,14 +447,17 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
                        return IRQ_HANDLED;
                }
 
-               /* Clear interrupt FIFO register 1 */
-               pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
-                          XILINX_PCIE_REG_RPIFR1);
+               if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) {
+                       /* Clear interrupt FIFO register 1 */
+                       pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
+                                  XILINX_PCIE_REG_RPIFR1);
 
-               /* Handle INTx Interrupt */
-               val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
-                       XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
-               generic_handle_irq(irq_find_mapping(port->irq_domain, val));
+                       /* Handle INTx Interrupt */
+                       val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
+                               XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
+                       generic_handle_irq(irq_find_mapping(port->irq_domain,
+                                                           val));
+               }
        }
 
        if (status & XILINX_PCIE_INTR_MSI) {
@@ -647,9 +648,15 @@ static struct pci_bus *xilinx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
        struct pci_bus *bus;
 
        port->root_busno = sys->busnr;
-       bus = pci_scan_root_bus(port->dev, sys->busnr, &xilinx_pcie_ops,
-                               sys, &sys->resources);
 
+       if (IS_ENABLED(CONFIG_PCI_MSI))
+               bus = pci_scan_root_bus_msi(port->dev, sys->busnr,
+                                           &xilinx_pcie_ops, sys,
+                                           &sys->resources,
+                                           &xilinx_pcie_msi_chip);
+       else
+               bus = pci_scan_root_bus(port->dev, sys->busnr,
+                                       &xilinx_pcie_ops, sys, &sys->resources);
        return bus;
 }
 
@@ -847,7 +854,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_PCI_MSI
        xilinx_pcie_msi_chip.dev = port->dev;
-       hw.msi_ctrl = &xilinx_pcie_msi_chip;
 #endif
        pci_common_init_dev(dev, &hw);
 
index 56d8486dc16704d1f93726d03131cbedfe0b4bed..d1fab97d6b01ff4cb2900ac1336ed0ae69852a39 100644 (file)
@@ -83,12 +83,12 @@ GET_STATUS(attention_status, u8)
 GET_STATUS(latch_status, u8)
 GET_STATUS(adapter_status, u8)
 
-static ssize_t power_read_file(struct pci_slot *slot, char *buf)
+static ssize_t power_read_file(struct pci_slot *pci_slot, char *buf)
 {
        int retval;
        u8 value;
 
-       retval = get_power_status(slot->hotplug, &value);
+       retval = get_power_status(pci_slot->hotplug, &value);
        if (retval)
                return retval;
 
@@ -140,22 +140,22 @@ static struct pci_slot_attribute hotplug_slot_attr_power = {
        .store = power_write_file
 };
 
-static ssize_t attention_read_file(struct pci_slot *slot, char *buf)
+static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf)
 {
        int retval;
        u8 value;
 
-       retval = get_attention_status(slot->hotplug, &value);
+       retval = get_attention_status(pci_slot->hotplug, &value);
        if (retval)
                return retval;
 
        return sprintf(buf, "%d\n", value);
 }
 
-static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,
+static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf,
                                    size_t count)
 {
-       struct hotplug_slot_ops *ops = slot->hotplug->ops;
+       struct hotplug_slot_ops *ops = pci_slot->hotplug->ops;
        unsigned long lattention;
        u8 attention;
        int retval = 0;
@@ -169,7 +169,7 @@ static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,
                goto exit;
        }
        if (ops->set_attention_status)
-               retval = ops->set_attention_status(slot->hotplug, attention);
+               retval = ops->set_attention_status(pci_slot->hotplug, attention);
        module_put(ops->owner);
 
 exit:
@@ -184,12 +184,12 @@ static struct pci_slot_attribute hotplug_slot_attr_attention = {
        .store = attention_write_file
 };
 
-static ssize_t latch_read_file(struct pci_slot *slot, char *buf)
+static ssize_t latch_read_file(struct pci_slot *pci_slot, char *buf)
 {
        int retval;
        u8 value;
 
-       retval = get_latch_status(slot->hotplug, &value);
+       retval = get_latch_status(pci_slot->hotplug, &value);
        if (retval)
                return retval;
 
@@ -201,12 +201,12 @@ static struct pci_slot_attribute hotplug_slot_attr_latch = {
        .show = latch_read_file,
 };
 
-static ssize_t presence_read_file(struct pci_slot *slot, char *buf)
+static ssize_t presence_read_file(struct pci_slot *pci_slot, char *buf)
 {
        int retval;
        u8 value;
 
-       retval = get_adapter_status(slot->hotplug, &value);
+       retval = get_adapter_status(pci_slot->hotplug, &value);
        if (retval)
                return retval;
 
@@ -307,43 +307,43 @@ static bool has_test_file(struct pci_slot *pci_slot)
        return false;
 }
 
-static int fs_add_slot(struct pci_slot *slot)
+static int fs_add_slot(struct pci_slot *pci_slot)
 {
        int retval = 0;
 
        /* Create symbolic link to the hotplug driver module */
-       pci_hp_create_module_link(slot);
+       pci_hp_create_module_link(pci_slot);
 
-       if (has_power_file(slot)) {
-               retval = sysfs_create_file(&slot->kobj,
+       if (has_power_file(pci_slot)) {
+               retval = sysfs_create_file(&pci_slot->kobj,
                                           &hotplug_slot_attr_power.attr);
                if (retval)
                        goto exit_power;
        }
 
-       if (has_attention_file(slot)) {
-               retval = sysfs_create_file(&slot->kobj,
+       if (has_attention_file(pci_slot)) {
+               retval = sysfs_create_file(&pci_slot->kobj,
                                           &hotplug_slot_attr_attention.attr);
                if (retval)
                        goto exit_attention;
        }
 
-       if (has_latch_file(slot)) {
-               retval = sysfs_create_file(&slot->kobj,
+       if (has_latch_file(pci_slot)) {
+               retval = sysfs_create_file(&pci_slot->kobj,
                                           &hotplug_slot_attr_latch.attr);
                if (retval)
                        goto exit_latch;
        }
 
-       if (has_adapter_file(slot)) {
-               retval = sysfs_create_file(&slot->kobj,
+       if (has_adapter_file(pci_slot)) {
+               retval = sysfs_create_file(&pci_slot->kobj,
                                           &hotplug_slot_attr_presence.attr);
                if (retval)
                        goto exit_adapter;
        }
 
-       if (has_test_file(slot)) {
-               retval = sysfs_create_file(&slot->kobj,
+       if (has_test_file(pci_slot)) {
+               retval = sysfs_create_file(&pci_slot->kobj,
                                           &hotplug_slot_attr_test.attr);
                if (retval)
                        goto exit_test;
@@ -352,45 +352,45 @@ static int fs_add_slot(struct pci_slot *slot)
        goto exit;
 
 exit_test:
-       if (has_adapter_file(slot))
-               sysfs_remove_file(&slot->kobj,
+       if (has_adapter_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj,
                                  &hotplug_slot_attr_presence.attr);
 exit_adapter:
-       if (has_latch_file(slot))
-               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+       if (has_latch_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
 exit_latch:
-       if (has_attention_file(slot))
-               sysfs_remove_file(&slot->kobj,
+       if (has_attention_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj,
                                  &hotplug_slot_attr_attention.attr);
 exit_attention:
-       if (has_power_file(slot))
-               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+       if (has_power_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
 exit_power:
-       pci_hp_remove_module_link(slot);
+       pci_hp_remove_module_link(pci_slot);
 exit:
        return retval;
 }
 
-static void fs_remove_slot(struct pci_slot *slot)
+static void fs_remove_slot(struct pci_slot *pci_slot)
 {
-       if (has_power_file(slot))
-               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+       if (has_power_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
 
-       if (has_attention_file(slot))
-               sysfs_remove_file(&slot->kobj,
+       if (has_attention_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj,
                                  &hotplug_slot_attr_attention.attr);
 
-       if (has_latch_file(slot))
-               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+       if (has_latch_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
 
-       if (has_adapter_file(slot))
-               sysfs_remove_file(&slot->kobj,
+       if (has_adapter_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj,
                                  &hotplug_slot_attr_presence.attr);
 
-       if (has_test_file(slot))
-               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+       if (has_test_file(pci_slot))
+               sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_test.attr);
 
-       pci_hp_remove_module_link(slot);
+       pci_hp_remove_module_link(pci_slot);
 }
 
 static struct hotplug_slot *get_slot_from_name(const char *name)
@@ -467,37 +467,37 @@ EXPORT_SYMBOL_GPL(__pci_hp_register);
 
 /**
  * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
- * @hotplug: pointer to the &struct hotplug_slot to deregister
+ * @slot: pointer to the &struct hotplug_slot to deregister
  *
  * The @slot must have been registered with the pci hotplug subsystem
  * previously with a call to pci_hp_register().
  *
  * Returns 0 if successful, anything else for an error.
  */
-int pci_hp_deregister(struct hotplug_slot *hotplug)
+int pci_hp_deregister(struct hotplug_slot *slot)
 {
        struct hotplug_slot *temp;
-       struct pci_slot *slot;
+       struct pci_slot *pci_slot;
 
-       if (!hotplug)
+       if (!slot)
                return -ENODEV;
 
        mutex_lock(&pci_hp_mutex);
-       temp = get_slot_from_name(hotplug_slot_name(hotplug));
-       if (temp != hotplug) {
+       temp = get_slot_from_name(hotplug_slot_name(slot));
+       if (temp != slot) {
                mutex_unlock(&pci_hp_mutex);
                return -ENODEV;
        }
 
-       list_del(&hotplug->slot_list);
+       list_del(&slot->slot_list);
 
-       slot = hotplug->pci_slot;
-       fs_remove_slot(slot);
-       dbg("Removed slot %s from the list\n", hotplug_slot_name(hotplug));
+       pci_slot = slot->pci_slot;
+       fs_remove_slot(pci_slot);
+       dbg("Removed slot %s from the list\n", hotplug_slot_name(slot));
 
-       hotplug->release(hotplug);
-       slot->hotplug = NULL;
-       pci_destroy_slot(slot);
+       slot->release(slot);
+       pci_slot->hotplug = NULL;
+       pci_destroy_slot(pci_slot);
        mutex_unlock(&pci_hp_mutex);
 
        return 0;
@@ -506,7 +506,7 @@ EXPORT_SYMBOL_GPL(pci_hp_deregister);
 
 /**
  * pci_hp_change_slot_info - changes the slot's information structure in the core
- * @hotplug: pointer to the slot whose info has changed
+ * @slot: pointer to the slot whose info has changed
  * @info: pointer to the info copy into the slot's info structure
  *
  * @slot must have been registered with the pci
@@ -514,13 +514,13 @@ EXPORT_SYMBOL_GPL(pci_hp_deregister);
  *
  * Returns 0 if successful, anything else for an error.
  */
-int pci_hp_change_slot_info(struct hotplug_slot *hotplug,
+int pci_hp_change_slot_info(struct hotplug_slot *slot,
                            struct hotplug_slot_info *info)
 {
-       if (!hotplug || !info)
+       if (!slot || !info)
                return -ENODEV;
 
-       memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
+       memcpy(slot->info, info, sizeof(struct hotplug_slot_info));
 
        return 0;
 }
index 57cd1327346f816ad2e1aed45fdc484ea5d8fba9..62d6fe6c37145c5c35c62a4746093f486edd3457 100644 (file)
@@ -101,18 +101,12 @@ struct controller {
        unsigned int power_fault_detected;
 };
 
-#define INT_BUTTON_IGNORE              0
 #define INT_PRESENCE_ON                        1
 #define INT_PRESENCE_OFF               2
-#define INT_SWITCH_CLOSE               3
-#define INT_SWITCH_OPEN                        4
-#define INT_POWER_FAULT                        5
-#define INT_POWER_FAULT_CLEAR          6
-#define INT_BUTTON_PRESS               7
-#define INT_BUTTON_RELEASE             8
-#define INT_BUTTON_CANCEL              9
-#define INT_LINK_UP                    10
-#define INT_LINK_DOWN                  11
+#define INT_POWER_FAULT                        3
+#define INT_BUTTON_PRESS               4
+#define INT_LINK_UP                    5
+#define INT_LINK_DOWN                  6
 
 #define STATIC_STATE                   0
 #define BLINKINGON_STATE               1
index 2913f7e68a10bdee3eefe169576dd7347965e31c..5c24e938042fd6bccb4e207d58dcb988d7c62611 100644 (file)
@@ -109,21 +109,23 @@ static int pcie_poll_cmd(struct controller *ctrl, int timeout)
        struct pci_dev *pdev = ctrl_dev(ctrl);
        u16 slot_status;
 
-       pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
-       if (slot_status & PCI_EXP_SLTSTA_CC) {
-               pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
-                                          PCI_EXP_SLTSTA_CC);
-               return 1;
-       }
-       while (timeout > 0) {
-               msleep(10);
-               timeout -= 10;
+       while (true) {
                pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
+               if (slot_status == (u16) ~0) {
+                       ctrl_info(ctrl, "%s: no response from device\n",
+                                 __func__);
+                       return 0;
+               }
+
                if (slot_status & PCI_EXP_SLTSTA_CC) {
                        pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
                                                   PCI_EXP_SLTSTA_CC);
                        return 1;
                }
+               if (timeout < 0)
+                       break;
+               msleep(10);
+               timeout -= 10;
        }
        return 0;       /* timeout */
 }
@@ -190,6 +192,11 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd,
        pcie_wait_cmd(ctrl);
 
        pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
+       if (slot_ctrl == (u16) ~0) {
+               ctrl_info(ctrl, "%s: no response from device\n", __func__);
+               goto out;
+       }
+
        slot_ctrl &= ~mask;
        slot_ctrl |= (cmd & mask);
        ctrl->cmd_busy = 1;
@@ -205,6 +212,7 @@ static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd,
        if (wait)
                pcie_wait_cmd(ctrl);
 
+out:
        mutex_unlock(&ctrl->ctrl_lock);
 }
 
@@ -535,7 +543,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        struct pci_dev *dev;
        struct slot *slot = ctrl->slot;
        u16 detected, intr_loc;
-       u8 open, present;
+       u8 present;
        bool link;
 
        /*
@@ -546,9 +554,14 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        intr_loc = 0;
        do {
                pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected);
+               if (detected == (u16) ~0) {
+                       ctrl_info(ctrl, "%s: no response from device\n",
+                                 __func__);
+                       return IRQ_HANDLED;
+               }
 
                detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
-                            PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
+                            PCI_EXP_SLTSTA_PDC |
                             PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
                detected &= ~intr_loc;
                intr_loc |= detected;
@@ -581,15 +594,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
        if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
                return IRQ_HANDLED;
 
-       /* Check MRL Sensor Changed */
-       if (intr_loc & PCI_EXP_SLTSTA_MRLSC) {
-               pciehp_get_latch_status(slot, &open);
-               ctrl_info(ctrl, "Latch %s on Slot(%s)\n",
-                         open ? "open" : "close", slot_name(slot));
-               pciehp_queue_interrupt_event(slot, open ? INT_SWITCH_OPEN :
-                                            INT_SWITCH_CLOSE);
-       }
-
        /* Check Attention Button Pressed */
        if (intr_loc & PCI_EXP_SLTSTA_ABP) {
                ctrl_info(ctrl, "Button pressed on Slot(%s)\n",
@@ -649,13 +653,11 @@ void pcie_enable_notification(struct controller *ctrl)
                cmd |= PCI_EXP_SLTCTL_ABPE;
        else
                cmd |= PCI_EXP_SLTCTL_PDCE;
-       if (MRL_SENS(ctrl))
-               cmd |= PCI_EXP_SLTCTL_MRLSCE;
        if (!pciehp_poll_mode)
                cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE;
 
        mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
-               PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
+               PCI_EXP_SLTCTL_PFDE |
                PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
                PCI_EXP_SLTCTL_DLLSCE);
 
index f66be868ad2122efdb40e742f8ecb9fc43cbc508..2f9b1c0d1f961cb961d3320011a5b40afa1bb917 100644 (file)
@@ -77,24 +77,9 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
 
 /* Arch hooks */
 
-struct msi_controller * __weak pcibios_msi_controller(struct pci_dev *dev)
-{
-       return NULL;
-}
-
-static struct msi_controller *pci_msi_controller(struct pci_dev *dev)
-{
-       struct msi_controller *msi_ctrl = dev->bus->msi;
-
-       if (msi_ctrl)
-               return msi_ctrl;
-
-       return pcibios_msi_controller(dev);
-}
-
 int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-       struct msi_controller *chip = pci_msi_controller(dev);
+       struct msi_controller *chip = dev->bus->msi;
        int err;
 
        if (!chip || !chip->setup_irq)
@@ -665,6 +650,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
        pci_msi_set_enable(dev, 1);
        dev->msi_enabled = 1;
 
+       pcibios_free_irq(dev);
        dev->irq = entry->irq;
        return 0;
 }
@@ -792,9 +778,9 @@ static int msix_capability_init(struct pci_dev *dev,
        /* Set MSI-X enabled bits and unmask the function */
        pci_intx_for_msi(dev, 0);
        dev->msix_enabled = 1;
-
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
 
+       pcibios_free_irq(dev);
        return 0;
 
 out_avail:
@@ -909,6 +895,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
 
        /* Restore dev->irq to its default pin-assertion irq */
        dev->irq = desc->msi_attrib.default_irq;
+       pcibios_alloc_irq(dev);
 }
 
 void pci_disable_msi(struct pci_dev *dev)
@@ -1009,6 +996,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
        pci_intx_for_msi(dev, 1);
        dev->msix_enabled = 0;
+       pcibios_alloc_irq(dev);
 }
 
 void pci_disable_msix(struct pci_dev *dev)
index 314a625b78d6360093eff3be221ffc04193b771e..a32ba753e4135862825c60690f83f1f9b145fa07 100644 (file)
@@ -594,7 +594,7 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
 /**
  * pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI
  * @pdev: the PCI device whose delay is to be updated
- * @adev: the companion ACPI device of this PCI device
+ * @handle: ACPI handle of this device
  *
  * Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
  * control method of either the device itself or the PCI host bridge.
index 3cb2210de5530e3edffd3286df3a66f455f6b2ec..52a880ca1768362ec41399e8df11c3504a28a107 100644 (file)
@@ -388,18 +388,31 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
        return error;
 }
 
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+       return 0;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
+
 static int pci_device_probe(struct device *dev)
 {
-       int error = 0;
-       struct pci_driver *drv;
-       struct pci_dev *pci_dev;
+       int error;
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct pci_driver *drv = to_pci_driver(dev->driver);
+
+       error = pcibios_alloc_irq(pci_dev);
+       if (error < 0)
+               return error;
 
-       drv = to_pci_driver(dev->driver);
-       pci_dev = to_pci_dev(dev);
        pci_dev_get(pci_dev);
        error = __pci_device_probe(drv, pci_dev);
-       if (error)
+       if (error) {
+               pcibios_free_irq(pci_dev);
                pci_dev_put(pci_dev);
+       }
 
        return error;
 }
@@ -415,6 +428,7 @@ static int pci_device_remove(struct device *dev)
                        drv->remove(pci_dev);
                        pm_runtime_put_noidle(dev);
                }
+               pcibios_free_irq(pci_dev);
                pci_dev->driver = NULL;
        }
 
index 0008c950452c31e71f8f591354449980893e58f6..cc76238c86fbb6c503feb74262d317b9df09dffd 100644 (file)
@@ -81,7 +81,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
 unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
 unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
 
-enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
+enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
 
 /*
  * The default CLS is used if arch didn't set CLS explicitly and not
@@ -140,7 +140,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
 EXPORT_SYMBOL_GPL(pci_ioremap_bar);
 #endif
 
-#define PCI_FIND_CAP_TTL       48
 
 static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
                                   u8 pos, int cap, int *ttl)
@@ -196,8 +195,6 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,
                return PCI_CAPABILITY_LIST;
        case PCI_HEADER_TYPE_CARDBUS:
                return PCI_CB_CAPABILITY_LIST;
-       default:
-               return 0;
        }
 
        return 0;
@@ -972,7 +969,7 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        struct pci_cap_saved_state *save_state;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
-       if (pos <= 0)
+       if (!pos)
                return 0;
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
@@ -995,7 +992,7 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
-       if (!save_state || pos <= 0)
+       if (!save_state || !pos)
                return;
        cap = (u16 *)&save_state->cap.data[0];
 
@@ -1092,6 +1089,9 @@ void pci_restore_state(struct pci_dev *dev)
 
        pci_restore_pcix_state(dev);
        pci_restore_msi_state(dev);
+
+       /* Restore ACS and IOV configuration state */
+       pci_enable_acs(dev);
        pci_restore_iov_state(dev);
 
        dev->state_saved = false;
@@ -2159,7 +2159,7 @@ static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
        else
                pos = pci_find_capability(dev, cap);
 
-       if (pos <= 0)
+       if (!pos)
                return 0;
 
        save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
index 4ff0ff1c4088ff68f8ca7bb515e54ad382e74680..24ba9dc8910a2ccf7c8735d7c8601e147ad13cb1 100644 (file)
@@ -4,6 +4,8 @@
 #define PCI_CFG_SPACE_SIZE     256
 #define PCI_CFG_SPACE_EXP_SIZE 4096
 
+#define PCI_FIND_CAP_TTL       48
+
 extern const unsigned char pcie_link_speed[];
 
 bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
index 2f0ce668a775eda0ccc15ea6bbfeea133ac6c823..88122dc2e1b1375f1715f8b8ca431673cee8d3e9 100644 (file)
@@ -448,7 +448,7 @@ static int resume_iter(struct device *dev, void *data)
 }
 
 /**
- * pcie_port_device_suspend - resume port services associated with a PCIe port
+ * pcie_port_device_resume - resume port services associated with a PCIe port
  * @dev: PCI Express port to handle
  */
 int pcie_port_device_resume(struct device *dev)
index cefd636681b6418ce75376879dc26fe3891bc47d..04cfc60f786070617e06dfdd692129cbac841ee3 100644 (file)
@@ -826,6 +826,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                        child->bridge_ctl = bctl;
                }
 
+               /* Read and initialize bridge resources */
+               pci_read_bridge_bases(child);
+
                cmax = pci_scan_child_bus(child);
                if (cmax > subordinate)
                        dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
@@ -886,6 +889,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 
                if (!is_cardbus) {
                        child->bridge_ctl = bctl;
+
+                       /* Read and initialize bridge resources */
+                       pci_read_bridge_bases(child);
                        max = pci_scan_child_bus(child);
                } else {
                        /*
@@ -997,7 +1003,12 @@ void set_pcie_port_type(struct pci_dev *pdev)
        else if (type == PCI_EXP_TYPE_UPSTREAM ||
                 type == PCI_EXP_TYPE_DOWNSTREAM) {
                parent = pci_upstream_bridge(pdev);
-               if (!parent->has_secondary_link)
+
+               /*
+                * Usually there's an upstream device (Root Port or Switch
+                * Downstream Port), but we can't assume one exists.
+                */
+               if (parent && !parent->has_secondary_link)
                        pdev->has_secondary_link = 1;
        }
 }
@@ -1103,7 +1114,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
 
 #define LEGACY_IO_RESOURCE     (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
 
-static void pci_msi_setup_pci_dev(struct pci_dev *dev)
+void pci_msi_setup_pci_dev(struct pci_dev *dev)
 {
        /*
         * Disable the MSI hardware to avoid screaming interrupts
@@ -1133,7 +1144,6 @@ int pci_setup_device(struct pci_dev *dev)
 {
        u32 class;
        u8 hdr_type;
-       struct pci_slot *slot;
        int pos = 0;
        struct pci_bus_region region;
        struct resource *res;
@@ -1149,10 +1159,7 @@ int pci_setup_device(struct pci_dev *dev)
        dev->error_state = pci_channel_io_normal;
        set_pcie_port_type(dev);
 
-       list_for_each_entry(slot, &dev->bus->slots, list)
-               if (PCI_SLOT(dev->devfn) == slot->number)
-                       dev->slot = slot;
-
+       pci_dev_assign_slot(dev);
        /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
           set this higher, assuming the system even supports it.  */
        dev->dma_mask = 0xffffffff;
@@ -1268,13 +1275,51 @@ int pci_setup_device(struct pci_dev *dev)
        bad:
                dev_err(&dev->dev, "ignoring class %#08x (doesn't match header type %02x)\n",
                        dev->class, dev->hdr_type);
-               dev->class = PCI_CLASS_NOT_DEFINED;
+               dev->class = PCI_CLASS_NOT_DEFINED << 8;
        }
 
        /* We found a fine healthy device, go go go... */
        return 0;
 }
 
+static void pci_configure_mps(struct pci_dev *dev)
+{
+       struct pci_dev *bridge = pci_upstream_bridge(dev);
+       int mps, p_mps, rc;
+
+       if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge))
+               return;
+
+       mps = pcie_get_mps(dev);
+       p_mps = pcie_get_mps(bridge);
+
+       if (mps == p_mps)
+               return;
+
+       if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
+               dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
+                        mps, pci_name(bridge), p_mps);
+               return;
+       }
+
+       /*
+        * Fancier MPS configuration is done later by
+        * pcie_bus_configure_settings()
+        */
+       if (pcie_bus_config != PCIE_BUS_DEFAULT)
+               return;
+
+       rc = pcie_set_mps(dev, p_mps);
+       if (rc) {
+               dev_warn(&dev->dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
+                        p_mps);
+               return;
+       }
+
+       dev_info(&dev->dev, "Max Payload Size set to %d (was %d, max %d)\n",
+                p_mps, mps, 128 << dev->pcie_mpss);
+}
+
 static struct hpp_type0 pci_default_type0 = {
        .revision = 1,
        .cache_line_size = 8,
@@ -1396,6 +1441,8 @@ static void pci_configure_device(struct pci_dev *dev)
        struct hotplug_params hpp;
        int ret;
 
+       pci_configure_mps(dev);
+
        memset(&hpp, 0, sizeof(hpp));
        ret = pci_get_hp_params(dev, &hpp);
        if (ret)
@@ -1540,6 +1587,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
        /* Single Root I/O Virtualization */
        pci_iov_init(dev);
 
+       /* Address Translation Services */
+       pci_ats_init(dev);
+
        /* Enable ACS P2P upstream forwarding */
        pci_enable_acs(dev);
 }
@@ -1791,22 +1841,6 @@ static void pcie_write_mrrs(struct pci_dev *dev)
                dev_err(&dev->dev, "MRRS was unable to be configured with a safe value.  If problems are experienced, try running with pci=pcie_bus_safe\n");
 }
 
-static void pcie_bus_detect_mps(struct pci_dev *dev)
-{
-       struct pci_dev *bridge = dev->bus->self;
-       int mps, p_mps;
-
-       if (!bridge)
-               return;
-
-       mps = pcie_get_mps(dev);
-       p_mps = pcie_get_mps(bridge);
-
-       if (mps != p_mps)
-               dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
-                        mps, pci_name(bridge), p_mps);
-}
-
 static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
 {
        int mps, orig_mps;
@@ -1814,10 +1848,9 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
        if (!pci_is_pcie(dev))
                return 0;
 
-       if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
-               pcie_bus_detect_mps(dev);
+       if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
+           pcie_bus_config == PCIE_BUS_DEFAULT)
                return 0;
-       }
 
        mps = 128 << *(u8 *)data;
        orig_mps = pcie_get_mps(dev);
@@ -2096,8 +2129,9 @@ void pci_bus_release_busn_res(struct pci_bus *b)
                        res, ret ? "can not be" : "is");
 }
 
-struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
-               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
+               struct pci_ops *ops, void *sysdata,
+               struct list_head *resources, struct msi_controller *msi)
 {
        struct resource_entry *window;
        bool found = false;
@@ -2114,6 +2148,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
        if (!b)
                return NULL;
 
+       b->msi = msi;
+
        if (!found) {
                dev_info(&b->dev,
                 "No busn resource found for root bus, will use [bus %02x-ff]\n",
@@ -2128,6 +2164,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 
        return b;
 }
+
+struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
+               struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+       return pci_scan_root_bus_msi(parent, bus, ops, sysdata, resources,
+                                    NULL);
+}
 EXPORT_SYMBOL(pci_scan_root_bus);
 
 struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
index e9fd0e90fa3b5c6656f7d8939a522add97c29b06..6a30252cd79f20f24e604965a9a023f2ff08478f 100644 (file)
@@ -163,7 +163,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,        PCI_DEVICE_ID_INTEL_82439TX,    quirk_
  *     VIA Apollo KT133 needs PCI latency patch
  *     Made according to a windows driver based patch by George E. Breese
  *     see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
- *     and http://www.georgebreese.com/net/software/#PCI
  *     Also see http://www.au-ja.org/review-kt133a-1-en.phtml for
  *     the info on which Mr Breese based his work.
  *
@@ -424,10 +423,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,        PCI_DEVICE_ID_ATI_RS100,   quirk_ati_
  */
 static void quirk_amd_nl_class(struct pci_dev *pdev)
 {
-       /*
-        * Use 'USB Device' (0x0c03fe) instead of PCI header provided
-        */
-       pdev->class = 0x0c03fe;
+       u32 class = pdev->class;
+
+       /* Use "USB Device (not host controller)" class */
+       pdev->class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe;
+       dev_info(&pdev->dev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
+                class, pdev->class);
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB,
                quirk_amd_nl_class);
@@ -1569,6 +1570,18 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
 
 #endif
 
+static void quirk_jmicron_async_suspend(struct pci_dev *dev)
+{
+       if (dev->multifunction) {
+               device_disable_async_suspend(&dev->dev);
+               dev_info(&dev->dev, "async suspend disabled to avoid multi-function power-on ordering issue\n");
+       }
+}
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, 8, quirk_jmicron_async_suspend);
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0, quirk_jmicron_async_suspend);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x2362, quirk_jmicron_async_suspend);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_JMICRON, 0x236f, quirk_jmicron_async_suspend);
+
 #ifdef CONFIG_X86_IO_APIC
 static void quirk_alder_ioapic(struct pci_dev *pdev)
 {
@@ -1894,6 +1907,15 @@ static void quirk_netmos(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
                         PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
 
+static void quirk_f0_vpd_link(struct pci_dev *dev)
+{
+       if (!dev->multifunction || !PCI_FUNC(dev->devfn))
+               return;
+       dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+                             PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
+
 static void quirk_e100_interrupt(struct pci_dev *dev)
 {
        u16 command, pmcsr;
@@ -1986,14 +2008,18 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
 
 static void fixup_rev1_53c810(struct pci_dev *dev)
 {
-       /* rev 1 ncr53c810 chips don't set the class at all which means
+       u32 class = dev->class;
+
+       /*
+        * rev 1 ncr53c810 chips don't set the class at all which means
         * they don't get their resources remapped. Fix that here.
         */
+       if (class)
+               return;
 
-       if (dev->class == PCI_CLASS_NOT_DEFINED) {
-               dev_info(&dev->dev, "NCR 53c810 rev 1 detected; setting PCI class\n");
-               dev->class = PCI_CLASS_STORAGE_SCSI;
-       }
+       dev->class = PCI_CLASS_STORAGE_SCSI << 8;
+       dev_info(&dev->dev, "NCR 53c810 rev 1 PCI class overridden (%#08x -> %#08x)\n",
+                class, dev->class);
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
 
@@ -2241,7 +2267,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
  * return 1 if a HT MSI capability is found and enabled */
 static int msi_ht_cap_enabled(struct pci_dev *dev)
 {
-       int pos, ttl = 48;
+       int pos, ttl = PCI_FIND_CAP_TTL;
 
        pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
        while (pos && ttl--) {
@@ -2300,7 +2326,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
 /* Force enable MSI mapping capability on HT bridges */
 static void ht_enable_msi_mapping(struct pci_dev *dev)
 {
-       int pos, ttl = 48;
+       int pos, ttl = PCI_FIND_CAP_TTL;
 
        pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
        while (pos && ttl--) {
@@ -2379,7 +2405,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
 
 static int ht_check_msi_mapping(struct pci_dev *dev)
 {
-       int pos, ttl = 48;
+       int pos, ttl = PCI_FIND_CAP_TTL;
        int found = 0;
 
        /* check if there is HT MSI cap or enabled on this device */
@@ -2504,7 +2530,7 @@ out:
 
 static void ht_disable_msi_mapping(struct pci_dev *dev)
 {
-       int pos, ttl = 48;
+       int pos, ttl = PCI_FIND_CAP_TTL;
 
        pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
        while (pos && ttl--) {
@@ -2829,12 +2855,15 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
 
 static void fixup_ti816x_class(struct pci_dev *dev)
 {
+       u32 class = dev->class;
+
        /* TI 816x devices do not have class code set when in PCIe boot mode */
-       dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
-       dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+       dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8;
+       dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n",
+                class, dev->class);
 }
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
-                                PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class);
+                             PCI_CLASS_NOT_DEFINED, 8, fixup_ti816x_class);
 
 /* Some PCIe devices do not work reliably with the claimed maximum
  * payload size supported.
@@ -2862,7 +2891,8 @@ static void quirk_intel_mc_errata(struct pci_dev *dev)
        int err;
        u16 rcc;
 
-       if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
+       if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
+           pcie_bus_config == PCIE_BUS_DEFAULT)
                return;
 
        /* Intel errata specifies bits to change but does not say what they are.
@@ -3028,7 +3058,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
-
+/* Intel Cherrytrail devices do not need 10ms d3_delay */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2280, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b0, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b8, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22d8, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22dc, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
 /*
  * Some devices may pass our check in pci_intx_mask_supported if
  * PCI_COMMAND_INTX_DISABLE works though they actually do not properly
@@ -3326,28 +3365,6 @@ fs_initcall_sync(pci_apply_final_quirks);
  * reset a single function if other methods (e.g. FLR, PM D0->D3) are
  * not available.
  */
-static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
-{
-       int pos;
-
-       /* only implement PCI_CLASS_SERIAL_USB at present */
-       if (dev->class == PCI_CLASS_SERIAL_USB) {
-               pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
-               if (!pos)
-                       return -ENOTTY;
-
-               if (probe)
-                       return 0;
-
-               pci_write_config_byte(dev, pos + 0x4, 1);
-               msleep(100);
-
-               return 0;
-       } else {
-               return -ENOTTY;
-       }
-}
-
 static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
 {
        /*
@@ -3506,8 +3523,6 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
                reset_ivb_igd },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
                reset_ivb_igd },
-       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
-               reset_intel_generic_dev },
        { PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
                reset_chelsio_generic_dev },
        { 0 }
@@ -3654,6 +3669,28 @@ DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
 /* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */
 DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
 
+/*
+ * Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
+ * class code.  Fix it.
+ */
+static void quirk_tw686x_class(struct pci_dev *pdev)
+{
+       u32 class = pdev->class;
+
+       /* Use "Multimedia controller" class */
+       pdev->class = (PCI_CLASS_MULTIMEDIA_OTHER << 8) | 0x01;
+       dev_info(&pdev->dev, "TW686x PCI class overridden (%#08x -> %#08x)\n",
+                class, pdev->class);
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6864, PCI_CLASS_NOT_DEFINED, 8,
+                             quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6865, PCI_CLASS_NOT_DEFINED, 8,
+                             quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6868, PCI_CLASS_NOT_DEFINED, 8,
+                             quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, PCI_CLASS_NOT_DEFINED, 8,
+                             quirk_tw686x_class);
+
 /*
  * AMD has indicated that the devices below do not support peer-to-peer
  * in any system where they are found in the southbridge with an AMD
@@ -3848,6 +3885,9 @@ static const struct pci_dev_acs_enabled {
        { PCI_VENDOR_ID_INTEL, 0x105F, pci_quirk_mf_endpoint_acs },
        { PCI_VENDOR_ID_INTEL, 0x1060, pci_quirk_mf_endpoint_acs },
        { PCI_VENDOR_ID_INTEL, 0x10D9, pci_quirk_mf_endpoint_acs },
+       /* I219 */
+       { PCI_VENDOR_ID_INTEL, 0x15b7, pci_quirk_mf_endpoint_acs },
+       { PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs },
        /* Intel PCH root ports */
        { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
        { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
@@ -4008,3 +4048,88 @@ void pci_dev_specific_enable_acs(struct pci_dev *dev)
                }
        }
 }
+
+/*
+ * The PCI capabilities list for Intel DH895xCC VFs (device id 0x0443) with
+ * QuickAssist Technology (QAT) is prematurely terminated in hardware.  The
+ * Next Capability pointer in the MSI Capability Structure should point to
+ * the PCIe Capability Structure but is incorrectly hardwired as 0 terminating
+ * the list.
+ */
+static void quirk_intel_qat_vf_cap(struct pci_dev *pdev)
+{
+       int pos, i = 0;
+       u8 next_cap;
+       u16 reg16, *cap;
+       struct pci_cap_saved_state *state;
+
+       /* Bail if the hardware bug is fixed */
+       if (pdev->pcie_cap || pci_find_capability(pdev, PCI_CAP_ID_EXP))
+               return;
+
+       /* Bail if MSI Capability Structure is not found for some reason */
+       pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       if (!pos)
+               return;
+
+       /*
+        * Bail if Next Capability pointer in the MSI Capability Structure
+        * is not the expected incorrect 0x00.
+        */
+       pci_read_config_byte(pdev, pos + 1, &next_cap);
+       if (next_cap)
+               return;
+
+       /*
+        * PCIe Capability Structure is expected to be at 0x50 and should
+        * terminate the list (Next Capability pointer is 0x00).  Verify
+        * Capability Id and Next Capability pointer is as expected.
+        * Open-code some of set_pcie_port_type() and pci_cfg_space_size_ext()
+        * to correctly set kernel data structures which have already been
+        * set incorrectly due to the hardware bug.
+        */
+       pos = 0x50;
+       pci_read_config_word(pdev, pos, &reg16);
+       if (reg16 == (0x0000 | PCI_CAP_ID_EXP)) {
+               u32 status;
+#ifndef PCI_EXP_SAVE_REGS
+#define PCI_EXP_SAVE_REGS     7
+#endif
+               int size = PCI_EXP_SAVE_REGS * sizeof(u16);
+
+               pdev->pcie_cap = pos;
+               pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
+               pdev->pcie_flags_reg = reg16;
+               pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
+               pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
+
+               pdev->cfg_size = PCI_CFG_SPACE_EXP_SIZE;
+               if (pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &status) !=
+                   PCIBIOS_SUCCESSFUL || (status == 0xffffffff))
+                       pdev->cfg_size = PCI_CFG_SPACE_SIZE;
+
+               if (pci_find_saved_cap(pdev, PCI_CAP_ID_EXP))
+                       return;
+
+               /*
+                * Save PCIE cap
+                */
+               state = kzalloc(sizeof(*state) + size, GFP_KERNEL);
+               if (!state)
+                       return;
+
+               state->cap.cap_nr = PCI_CAP_ID_EXP;
+               state->cap.cap_extended = 0;
+               state->cap.size = size;
+               cap = (u16 *)&state->cap.data[0];
+               pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap[i++]);
+               pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &cap[i++]);
+               pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &cap[i++]);
+               pcie_capability_read_word(pdev, PCI_EXP_RTCTL,  &cap[i++]);
+               pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &cap[i++]);
+               pcie_capability_read_word(pdev, PCI_EXP_LNKCTL2, &cap[i++]);
+               pcie_capability_read_word(pdev, PCI_EXP_SLTCTL2, &cap[i++]);
+               hlist_add_head(&state->next, &pdev->saved_cap_space);
+       }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap);
index 396c200b9ddb3b6d534e571f1827819e221c65e8..429d34c348b9fbddc373e22876ad4f5017788a8d 100644 (file)
@@ -14,6 +14,7 @@
 
 struct kset *pci_slots_kset;
 EXPORT_SYMBOL_GPL(pci_slots_kset);
+static DEFINE_MUTEX(pci_slot_mutex);
 
 static ssize_t pci_slot_attr_show(struct kobject *kobj,
                                        struct attribute *attr, char *buf)
@@ -106,9 +107,11 @@ static void pci_slot_release(struct kobject *kobj)
        dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n",
                slot->number, pci_slot_name(slot));
 
+       down_read(&pci_bus_sem);
        list_for_each_entry(dev, &slot->bus->devices, bus_list)
                if (PCI_SLOT(dev->devfn) == slot->number)
                        dev->slot = NULL;
+       up_read(&pci_bus_sem);
 
        list_del(&slot->list);
 
@@ -191,12 +194,22 @@ static int rename_slot(struct pci_slot *slot, const char *name)
        return result;
 }
 
+void pci_dev_assign_slot(struct pci_dev *dev)
+{
+       struct pci_slot *slot;
+
+       mutex_lock(&pci_slot_mutex);
+       list_for_each_entry(slot, &dev->bus->slots, list)
+               if (PCI_SLOT(dev->devfn) == slot->number)
+                       dev->slot = slot;
+       mutex_unlock(&pci_slot_mutex);
+}
+
 static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr)
 {
        struct pci_slot *slot;
-       /*
-        * We already hold pci_bus_sem so don't worry
-        */
+
+       /* We already hold pci_slot_mutex */
        list_for_each_entry(slot, &parent->slots, list)
                if (slot->number == slot_nr) {
                        kobject_get(&slot->kobj);
@@ -253,7 +266,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
        int err = 0;
        char *slot_name = NULL;
 
-       down_write(&pci_bus_sem);
+       mutex_lock(&pci_slot_mutex);
 
        if (slot_nr == -1)
                goto placeholder;
@@ -301,16 +314,18 @@ placeholder:
        INIT_LIST_HEAD(&slot->list);
        list_add(&slot->list, &parent->slots);
 
+       down_read(&pci_bus_sem);
        list_for_each_entry(dev, &parent->devices, bus_list)
                if (PCI_SLOT(dev->devfn) == slot_nr)
                        dev->slot = slot;
+       up_read(&pci_bus_sem);
 
        dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n",
                slot_nr, pci_slot_name(slot));
 
 out:
        kfree(slot_name);
-       up_write(&pci_bus_sem);
+       mutex_unlock(&pci_slot_mutex);
        return slot;
 err:
        kfree(slot);
@@ -332,9 +347,9 @@ void pci_destroy_slot(struct pci_slot *slot)
        dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n",
                slot->number, atomic_read(&slot->kobj.kref.refcount) - 1);
 
-       down_write(&pci_bus_sem);
+       mutex_lock(&pci_slot_mutex);
        kobject_put(&slot->kobj);
-       up_write(&pci_bus_sem);
+       mutex_unlock(&pci_slot_mutex);
 }
 EXPORT_SYMBOL_GPL(pci_destroy_slot);
 
index 6b8dd162f644214ba24fd666b5aa6c94467d964d..47da573d0babd8bb9805c8cdb9a9d40323567bf8 100644 (file)
@@ -54,6 +54,17 @@ config PHY_EXYNOS_MIPI_VIDEO
          Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
          and EXYNOS SoCs.
 
+config PHY_LPC18XX_USB_OTG
+       tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
+       depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
+       depends on MFD_SYSCON
+       select GENERIC_PHY
+       help
+         Enable this to support NXP LPC18xx/43xx internal USB OTG PHY.
+
+         This driver is need for USB0 support on LPC18xx/43xx and takes
+         care of enabling and clock setup.
+
 config PHY_PXA_28NM_HSIC
        tristate "Marvell USB HSIC 28nm PHY Driver"
        depends on HAS_IOMEM
@@ -199,6 +210,8 @@ config PHY_SUN4I_USB
        tristate "Allwinner sunxi SoC USB PHY driver"
        depends on ARCH_SUNXI && HAS_IOMEM && OF
        depends on RESET_CONTROLLER
+       depends on EXTCON
+       depends on POWER_SUPPLY
        select GENERIC_PHY
        help
          Enable this to support the transceiver that is part of Allwinner
index f344e1b2e825c2fe5124270beb0561672a5c6ccf..a5b18c18fc12d78fce9c19021a0847f49ece504b 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)        += phy-armada375-usb2.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)                += phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)      += phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)    += phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_LPC18XX_USB_OTG)      += phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_PXA_28NM_USB2)                += phy-pxa-28nm-usb2.o
 obj-$(CONFIG_PHY_PXA_28NM_HSIC)                += phy-pxa-28nm-hsic.o
 obj-$(CONFIG_PHY_MVEBU_SATA)           += phy-mvebu-sata.o
index 8ccc3952c13dca6287b04a6b62fe50d1ceb076d6..1a3db288c0a9ac81ade8eadab50429931c1898af 100644 (file)
@@ -51,7 +51,7 @@ static int armada375_usb_phy_init(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops armada375_usb_phy_ops = {
+static const struct phy_ops armada375_usb_phy_ops = {
        .init = armada375_usb_phy_init,
        .owner = THIS_MODULE,
 };
@@ -149,7 +149,6 @@ static struct platform_driver armada375_usb_phy_driver = {
        .driver = {
                .of_match_table = of_usb_cluster_table,
                .name  = "armada-375-usb-cluster",
-               .owner = THIS_MODULE,
        }
 };
 module_platform_driver(armada375_usb_phy_driver);
index ef2dc1aab2b9b5ed03cf0511da89c6da1f78393d..7b67fe49e30bf7187cfc8ee24cad70a0dafedfd1 100644 (file)
@@ -91,7 +91,7 @@ static int bcm_kona_usb_phy_power_off(struct phy *gphy)
        return 0;
 }
 
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
        .init           = bcm_kona_usb_phy_init,
        .power_on       = bcm_kona_usb_phy_power_on,
        .power_off      = bcm_kona_usb_phy_power_off,
index 6f3e06d687de99260b0300e10d0864387d740177..0062027afb1ef90335ae46782dba06448949b989 100644 (file)
@@ -176,7 +176,7 @@ static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
        return priv->phys[i]->phy;
 }
 
-static struct phy_ops phy_berlin_sata_ops = {
+static const struct phy_ops phy_berlin_sata_ops = {
        .power_on       = phy_berlin_sata_power_on,
        .power_off      = phy_berlin_sata_power_off,
        .owner          = THIS_MODULE,
index 335e06d66ed9a5100cbdda511e6c206238651814..797ba17c404f74053c460c4c7e5a9724d4e8bb5b 100644 (file)
@@ -147,12 +147,12 @@ static int phy_berlin_usb_power_on(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops phy_berlin_usb_ops = {
+static const struct phy_ops phy_berlin_usb_ops = {
        .power_on       = phy_berlin_usb_power_on,
        .owner          = THIS_MODULE,
 };
 
-static const struct of_device_id phy_berlin_sata_of_match[] = {
+static const struct of_device_id phy_berlin_usb_of_match[] = {
        {
                .compatible = "marvell,berlin2-usb-phy",
                .data = &phy_berlin_pll_dividers[0],
@@ -163,12 +163,12 @@ static const struct of_device_id phy_berlin_sata_of_match[] = {
        },
        { },
 };
-MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
+MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);
 
 static int phy_berlin_usb_probe(struct platform_device *pdev)
 {
        const struct of_device_id *match =
-               of_match_device(phy_berlin_sata_of_match, &pdev->dev);
+               of_match_device(phy_berlin_usb_of_match, &pdev->dev);
        struct phy_berlin_usb_priv *priv;
        struct resource *res;
        struct phy *phy;
@@ -207,9 +207,8 @@ static struct platform_driver phy_berlin_usb_driver = {
        .probe  = phy_berlin_usb_probe,
        .driver = {
                .name           = "phy-berlin-usb",
-               .owner          = THIS_MODULE,
-               .of_match_table = phy_berlin_sata_of_match,
-        },
+               .of_match_table = phy_berlin_usb_of_match,
+       },
 };
 module_platform_driver(phy_berlin_usb_driver);
 
index b7e303d28caff3d5eeb4cceade89c6a66047fdfa..8a2cb16a1937d20e88b045868beec28db966be5c 100644 (file)
@@ -122,7 +122,7 @@ static int brcm_sata_phy_init(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops phy_ops_28nm = {
+static const struct phy_ops phy_ops_28nm = {
        .init           = brcm_sata_phy_init,
        .owner          = THIS_MODULE,
 };
index 7b42555ddd51aac0d44714ef2254278d3fe59215..b4bbef664d206b4a73cd665986bd12eb988de285 100644 (file)
@@ -113,7 +113,7 @@ static int dm816x_usb_phy_init(struct phy *x)
        return 0;
 }
 
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
        .init           = dm816x_usb_phy_init,
        .owner          = THIS_MODULE,
 };
index 179cbf9451aacf1aca440e46eb05493f41037e48..34b06154e5d959b8b2b0f429e62dd9ae0355151f 100644 (file)
@@ -48,7 +48,7 @@ static int exynos_dp_video_phy_power_off(struct phy *phy)
                                  EXYNOS5_PHY_ENABLE, 0);
 }
 
-static struct phy_ops exynos_dp_video_phy_ops = {
+static const struct phy_ops exynos_dp_video_phy_ops = {
        .power_on       = exynos_dp_video_phy_power_on,
        .power_off      = exynos_dp_video_phy_power_off,
        .owner          = THIS_MODULE,
index df7519a39ba0b15fd9181a3c3c9bcba17fcd34e9..2a54caba93b4021a5b48c44100ec42e9baf45da4 100644 (file)
@@ -124,7 +124,7 @@ static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
        return state->phys[args->args[0]].phy;
 }
 
-static struct phy_ops exynos_mipi_video_phy_ops = {
+static const struct phy_ops exynos_mipi_video_phy_ops = {
        .power_on       = exynos_mipi_video_phy_power_on,
        .power_off      = exynos_mipi_video_phy_power_off,
        .owner          = THIS_MODULE,
index d72ef15b0d68d575917fc6293e8e9bf6fc0e5342..20696f53303f0798059f45273cf817cb936ea415 100644 (file)
@@ -537,7 +537,7 @@ static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
        return phy_drd->phys[args->args[0]].phy;
 }
 
-static struct phy_ops exynos5_usbdrd_phy_ops = {
+static const struct phy_ops exynos5_usbdrd_phy_ops = {
        .init           = exynos5_usbdrd_phy_init,
        .exit           = exynos5_usbdrd_phy_exit,
        .power_on       = exynos5_usbdrd_phy_power_on,
index bc858cc800a12bbbedad8bf18586cd9d9ee1ef78..60e13afcd9b849c568c15c543a3564fa9b5b1571 100644 (file)
@@ -154,7 +154,7 @@ static int exynos_sata_phy_init(struct phy *phy)
        return ret;
 }
 
-static struct phy_ops exynos_sata_phy_ops = {
+static const struct phy_ops exynos_sata_phy_ops = {
        .init           = exynos_sata_phy_init,
        .power_on       = exynos_sata_phy_power_on,
        .power_off      = exynos_sata_phy_power_off,
index d6b22659cac11cfb4187cf9347ac86774f79de5e..e5ab3aa78b9d2420a3564f802630c33b1036ce53 100644 (file)
@@ -129,7 +129,7 @@ static int hix5hd2_sata_phy_init(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops hix5hd2_sata_phy_ops = {
+static const struct phy_ops hix5hd2_sata_phy_ops = {
        .init           = hix5hd2_sata_phy_init,
        .owner          = THIS_MODULE,
 };
diff --git a/drivers/phy/phy-lpc18xx-usb-otg.c b/drivers/phy/phy-lpc18xx-usb-otg.c
new file mode 100644 (file)
index 0000000..3b7a71e
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * PHY driver for NXP LPC18xx/43xx internal USB OTG PHY
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* USB OTG PHY register offset and bit in CREG */
+#define LPC18XX_CREG_CREG0             0x004
+#define LPC18XX_CREG_CREG0_USB0PHY     BIT(5)
+
+struct lpc18xx_usb_otg_phy {
+       struct phy *phy;
+       struct clk *clk;
+       struct regmap *reg;
+};
+
+static int lpc18xx_usb_otg_phy_init(struct phy *phy)
+{
+       struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+       int ret;
+
+       /* The PHY must be clocked at 480 MHz */
+       ret = clk_set_rate(lpc->clk, 480000000);
+       if (ret)
+               return ret;
+
+       return clk_prepare(lpc->clk);
+}
+
+static int lpc18xx_usb_otg_phy_exit(struct phy *phy)
+{
+       struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+
+       clk_unprepare(lpc->clk);
+
+       return 0;
+}
+
+static int lpc18xx_usb_otg_phy_power_on(struct phy *phy)
+{
+       struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+       int ret;
+
+       ret = clk_enable(lpc->clk);
+       if (ret)
+               return ret;
+
+       /* The bit in CREG is cleared to enable the PHY */
+       return regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0,
+                                 LPC18XX_CREG_CREG0_USB0PHY, 0);
+}
+
+static int lpc18xx_usb_otg_phy_power_off(struct phy *phy)
+{
+       struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+       int ret;
+
+       ret = regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0,
+                                LPC18XX_CREG_CREG0_USB0PHY,
+                                LPC18XX_CREG_CREG0_USB0PHY);
+       if (ret)
+               return ret;
+
+       clk_disable(lpc->clk);
+
+       return 0;
+}
+
+static const struct phy_ops lpc18xx_usb_otg_phy_ops = {
+       .init           = lpc18xx_usb_otg_phy_init,
+       .exit           = lpc18xx_usb_otg_phy_exit,
+       .power_on       = lpc18xx_usb_otg_phy_power_on,
+       .power_off      = lpc18xx_usb_otg_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int lpc18xx_usb_otg_phy_probe(struct platform_device *pdev)
+{
+       struct phy_provider *phy_provider;
+       struct lpc18xx_usb_otg_phy *lpc;
+
+       lpc = devm_kzalloc(&pdev->dev, sizeof(*lpc), GFP_KERNEL);
+       if (!lpc)
+               return -ENOMEM;
+
+       lpc->reg = syscon_node_to_regmap(pdev->dev.of_node->parent);
+       if (IS_ERR(lpc->reg)) {
+               dev_err(&pdev->dev, "failed to get syscon\n");
+               return PTR_ERR(lpc->reg);
+       }
+
+       lpc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(lpc->clk)) {
+               dev_err(&pdev->dev, "failed to get clock\n");
+               return PTR_ERR(lpc->clk);
+       }
+
+       lpc->phy = devm_phy_create(&pdev->dev, NULL, &lpc18xx_usb_otg_phy_ops);
+       if (IS_ERR(lpc->phy)) {
+               dev_err(&pdev->dev, "failed to create PHY\n");
+               return PTR_ERR(lpc->phy);
+       }
+
+       phy_set_drvdata(lpc->phy, lpc);
+
+       phy_provider = devm_of_phy_provider_register(&pdev->dev,
+                                                    of_phy_simple_xlate);
+
+       return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id lpc18xx_usb_otg_phy_match[] = {
+       { .compatible = "nxp,lpc1850-usb-otg-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_usb_otg_phy_match);
+
+static struct platform_driver lpc18xx_usb_otg_phy_driver = {
+       .probe          = lpc18xx_usb_otg_phy_probe,
+       .driver         = {
+               .name   = "lpc18xx-usb-otg-phy",
+               .of_match_table = lpc18xx_usb_otg_phy_match,
+       },
+};
+module_platform_driver(lpc18xx_usb_otg_phy_driver);
+
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_DESCRIPTION("NXP LPC18xx/43xx USB OTG PHY driver");
+MODULE_LICENSE("GPL v2");
index 5e257ef7ac050a55bc09d6ce853aa6d2a37cf52e..c47b56b4a2b8892810f00179a53e9eceba7c612c 100644 (file)
@@ -1132,7 +1132,7 @@ static struct phy *miphy28lp_xlate(struct device *dev,
        return miphy_phy->phy;
 }
 
-static struct phy_ops miphy28lp_ops = {
+static const struct phy_ops miphy28lp_ops = {
        .init = miphy28lp_init,
        .owner = THIS_MODULE,
 };
@@ -1268,7 +1268,6 @@ static struct platform_driver miphy28lp_driver = {
        .probe = miphy28lp_probe,
        .driver = {
                .name = "miphy28lp-phy",
-               .owner = THIS_MODULE,
                .of_match_table = miphy28lp_of_match,
        }
 };
index 0ff354d6e1831b3f9a970ae8d6f30a4c0fa466da..00a686a073ed6ee804ea96ebcdb0ef3813482a85 100644 (file)
@@ -510,7 +510,7 @@ static struct phy *miphy365x_xlate(struct device *dev,
        return miphy_phy->phy;
 }
 
-static struct phy_ops miphy365x_ops = {
+static const struct phy_ops miphy365x_ops = {
        .init           = miphy365x_init,
        .owner          = THIS_MODULE,
 };
index 03b94f92e6f17b319c68a58f03ac8cf91ef0be75..768ce92e81ce7634f767612a99f37025185422db 100644 (file)
@@ -75,7 +75,7 @@ static int phy_mvebu_sata_power_off(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops phy_mvebu_sata_ops = {
+static const struct phy_ops phy_mvebu_sata_ops = {
        .power_on       = phy_mvebu_sata_power_on,
        .power_off      = phy_mvebu_sata_power_off,
        .owner          = THIS_MODULE,
index c1a468686bdc72433b7596512cb70852f3ef2420..0fe80589ffbea0cef4c00e85d242934c1dcb3f69 100644 (file)
@@ -137,7 +137,7 @@ static int omap_usb_init(struct phy *x)
        return 0;
 }
 
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
        .init           = omap_usb_init,
        .power_on       = omap_usb_power_on,
        .power_off      = omap_usb_power_off,
index 4b243f7a10e4a9bb3e9e237e1a25dcb5f80b7b52..69ce2afac0150fb580630921ed4f9892d58dab77 100644 (file)
@@ -204,7 +204,7 @@ static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
        return 0;
 }
 
-static struct phy_ops qcom_apq8064_sata_phy_ops = {
+static const struct phy_ops qcom_apq8064_sata_phy_ops = {
        .init           = qcom_apq8064_sata_phy_init,
        .exit           = qcom_apq8064_sata_phy_exit,
        .owner          = THIS_MODULE,
index 6f2fe26279165ff1b8e26821cfd243d0ab79a214..0ad127cc9298b10cb99988b7f40c7aa264bc1f47 100644 (file)
@@ -126,7 +126,7 @@ static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
        return 0;
 }
 
-static struct phy_ops qcom_ipq806x_sata_phy_ops = {
+static const struct phy_ops qcom_ipq806x_sata_phy_ops = {
        .init           = qcom_ipq806x_sata_phy_init,
        .exit           = qcom_ipq806x_sata_phy_exit,
        .owner          = THIS_MODULE,
index 591a39175e8a2357cd0f138cda151850a91963ea..2bd5ce43a7240d66429ed781b4780c33210897a0 100644 (file)
@@ -150,7 +150,7 @@ int ufs_qcom_phy_remove(struct phy *generic_phy,
                       struct ufs_qcom_phy *ufs_qcom_phy);
 struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
                        struct ufs_qcom_phy *common_cfg,
-                       struct phy_ops *ufs_qcom_phy_gen_ops,
+                       const struct phy_ops *ufs_qcom_phy_gen_ops,
                        struct ufs_qcom_phy_specific_ops *phy_spec_ops);
 int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
                        struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A,
index f5fc50a9fce782036357bbd8f536ea08c209ee10..56631e77c11d7fb2ebd5e978869797d910b5daaf 100644 (file)
@@ -115,7 +115,7 @@ static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
        return err;
 }
 
-static struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
+static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
        .init           = ufs_qcom_phy_qmp_14nm_init,
        .exit           = ufs_qcom_phy_exit,
        .power_on       = ufs_qcom_phy_power_on,
@@ -191,7 +191,6 @@ static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = {
        .driver = {
                .of_match_table = ufs_qcom_phy_qmp_14nm_of_match,
                .name = "ufs_qcom_phy_qmp_14nm",
-               .owner = THIS_MODULE,
        },
 };
 
index 8332f96b2c4a7c7496e9ae3f987f6f404fd7faea..b16ea77d07b923c1a29f57def315bcdc032a9d40 100644 (file)
@@ -171,7 +171,7 @@ static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
        return err;
 }
 
-static struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
+static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
        .init           = ufs_qcom_phy_qmp_20nm_init,
        .exit           = ufs_qcom_phy_exit,
        .power_on       = ufs_qcom_phy_power_on,
@@ -247,7 +247,6 @@ static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = {
        .driver = {
                .of_match_table = ufs_qcom_phy_qmp_20nm_of_match,
                .name = "ufs_qcom_phy_qmp_20nm",
-               .owner = THIS_MODULE,
        },
 };
 
index f9c618f0ab6e4fe120462616b2c84ba0d9fe30a6..49a1ed0cef56fe7cbf9aed102b47149415f021f0 100644 (file)
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
 
 struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
                                struct ufs_qcom_phy *common_cfg,
-                               struct phy_ops *ufs_qcom_phy_gen_ops,
+                               const struct phy_ops *ufs_qcom_phy_gen_ops,
                                struct ufs_qcom_phy_specific_ops *phy_spec_ops)
 {
        int err;
index 39d9b299543572f01a3712b85e18c07a1bef605d..6e0d9fa8e1d13f8d1ad0eec73b1040f594637df7 100644 (file)
@@ -184,7 +184,7 @@ static int rcar_gen2_phy_power_off(struct phy *p)
        return 0;
 }
 
-static struct phy_ops rcar_gen2_phy_ops = {
+static const struct phy_ops rcar_gen2_phy_ops = {
        .init           = rcar_gen2_phy_init,
        .exit           = rcar_gen2_phy_exit,
        .power_on       = rcar_gen2_phy_power_on,
index 7d4c33643768808780f71455900bc7dd51329103..5a5c073e72fe1ee6115bea310890b646b6b40a69 100644 (file)
@@ -84,7 +84,7 @@ static int rockchip_usb_phy_power_on(struct phy *_phy)
        return 0;
 }
 
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
        .power_on       = rockchip_usb_phy_power_on,
        .power_off      = rockchip_usb_phy_power_off,
        .owner          = THIS_MODULE,
@@ -146,7 +146,6 @@ static struct platform_driver rockchip_usb_driver = {
        .probe          = rockchip_usb_phy_probe,
        .driver         = {
                .name   = "rockchip-usb-phy",
-               .owner  = THIS_MODULE,
                .of_match_table = rockchip_usb_phy_dt_ids,
        },
 };
index 55b6994932e37f0b3d5d14c72cb1ff7df4807f85..f278a9c547e199c6228081f3445133dcdd9cda46 100644 (file)
@@ -71,7 +71,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops samsung_usb2_phy_ops = {
+static const struct phy_ops samsung_usb2_phy_ops = {
        .power_on       = samsung_usb2_phy_power_on,
        .power_off      = samsung_usb2_phy_power_off,
        .owner          = THIS_MODULE,
index 45d0005b2203f14777fff62f8ba30cffe4d779fc..ed67e98e54ca6560e567d4b3944d674651538681 100644 (file)
@@ -179,7 +179,7 @@ static const struct of_device_id spear1310_miphy_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
 
-static struct phy_ops spear1310_miphy_ops = {
+static const struct phy_ops spear1310_miphy_ops = {
        .init = spear1310_miphy_init,
        .exit = spear1310_miphy_exit,
        .owner = THIS_MODULE,
index 494240da4a398e4554f60a3c960df6234dbb8d84..97280c0cf6128c2a0339a27e7f207702ffe6762e 100644 (file)
@@ -189,7 +189,7 @@ static const struct of_device_id spear1340_miphy_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
 
-static struct phy_ops spear1340_miphy_ops = {
+static const struct phy_ops spear1340_miphy_ops = {
        .init = spear1340_miphy_init,
        .exit = spear1340_miphy_exit,
        .owner = THIS_MODULE,
index c093b472b57dadee94b832a989f5495a07dc98f2..0ac74639ad0244aa81e9f4878c58c5d6aff39841 100644 (file)
@@ -112,7 +112,7 @@ static int stih41x_usb_phy_power_off(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops stih41x_usb_phy_ops = {
+static const struct phy_ops stih41x_usb_phy_ops = {
        .init           = stih41x_usb_phy_init,
        .power_on       = stih41x_usb_phy_power_on,
        .power_off      = stih41x_usb_phy_power_off,
index 2dad7e820ff0b16b7447b708f0c147b2e0289f02..731b395d6e6a1621ee7fc36055b6c1a5f7367780 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Allwinner sun4i USB phy driver
  *
- * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
  *
  * Based on code from
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/extcon.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/phy/phy.h>
 #include <linux/phy/phy-sun4i-usb.h>
 #include <linux/platform_device.h>
+#include <linux/power_supply.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
+#include <linux/workqueue.h>
 
 #define REG_ISCR                       0x00
-#define REG_PHYCTL                     0x04
+#define REG_PHYCTL_A10                 0x04
 #define REG_PHYBIST                    0x08
 #define REG_PHYTUNE                    0x0c
+#define REG_PHYCTL_A33                 0x10
 
 #define PHYCTL_DATA                    BIT(7)
 
 #define SUNXI_AHB_INCRX_ALIGN_EN       BIT(8)
 #define SUNXI_ULPI_BYPASS_EN           BIT(0)
 
+/* ISCR, Interface Status and Control bits */
+#define ISCR_ID_PULLUP_EN              (1 << 17)
+#define ISCR_DPDM_PULLUP_EN    (1 << 16)
+/* sunxi has the phy id/vbus pins not connected, so we use the force bits */
+#define ISCR_FORCE_ID_MASK     (3 << 14)
+#define ISCR_FORCE_ID_LOW              (2 << 14)
+#define ISCR_FORCE_ID_HIGH     (3 << 14)
+#define ISCR_FORCE_VBUS_MASK   (3 << 12)
+#define ISCR_FORCE_VBUS_LOW    (2 << 12)
+#define ISCR_FORCE_VBUS_HIGH   (3 << 12)
+
 /* Common Control Bits for Both PHYs */
 #define PHY_PLL_BW                     0x03
 #define PHY_RES45_CAL_EN               0x0c
 
 #define MAX_PHYS                       3
 
+/*
+ * Note do not raise the debounce time, we must report Vusb high within 100ms
+ * otherwise we get Vbus errors
+ */
+#define DEBOUNCE_TIME                  msecs_to_jiffies(50)
+#define POLL_TIME                      msecs_to_jiffies(250)
+
 struct sun4i_usb_phy_data {
        void __iomem *base;
        struct mutex mutex;
        int num_phys;
        u32 disc_thresh;
+       bool has_a33_phyctl;
        struct sun4i_usb_phy {
                struct phy *phy;
                void __iomem *pmu;
                struct regulator *vbus;
                struct reset_control *reset;
                struct clk *clk;
+               bool regulator_on;
                int index;
        } phys[MAX_PHYS];
+       /* phy0 / otg related variables */
+       struct extcon_dev *extcon;
+       bool phy0_init;
+       bool phy0_poll;
+       struct gpio_desc *id_det_gpio;
+       struct gpio_desc *vbus_det_gpio;
+       struct power_supply *vbus_power_supply;
+       struct notifier_block vbus_power_nb;
+       bool vbus_power_nb_registered;
+       int id_det_irq;
+       int vbus_det_irq;
+       int id_det;
+       int vbus_det;
+       struct delayed_work detect;
 };
 
 #define to_sun4i_usb_phy_data(phy) \
        container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
 
+static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+       u32 iscr;
+
+       iscr = readl(data->base + REG_ISCR);
+       iscr &= ~clr;
+       iscr |= set;
+       writel(iscr, data->base + REG_ISCR);
+}
+
+static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
+{
+       if (val)
+               val = ISCR_FORCE_ID_HIGH;
+       else
+               val = ISCR_FORCE_ID_LOW;
+
+       sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
+}
+
+static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
+{
+       if (val)
+               val = ISCR_FORCE_VBUS_HIGH;
+       else
+               val = ISCR_FORCE_VBUS_LOW;
+
+       sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
+}
+
 static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
                                int len)
 {
        struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
        u32 temp, usbc_bit = BIT(phy->index * 2);
+       void *phyctl;
        int i;
 
        mutex_lock(&phy_data->mutex);
 
+       if (phy_data->has_a33_phyctl) {
+               phyctl = phy_data->base + REG_PHYCTL_A33;
+               /* A33 needs us to set phyctl to 0 explicitly */
+               writel(0, phyctl);
+       } else {
+               phyctl = phy_data->base + REG_PHYCTL_A10;
+       }
+
        for (i = 0; i < len; i++) {
-               temp = readl(phy_data->base + REG_PHYCTL);
+               temp = readl(phyctl);
 
                /* clear the address portion */
                temp &= ~(0xff << 8);
 
                /* set the address */
                temp |= ((addr + i) << 8);
-               writel(temp, phy_data->base + REG_PHYCTL);
+               writel(temp, phyctl);
 
                /* set the data bit and clear usbc bit*/
-               temp = readb(phy_data->base + REG_PHYCTL);
+               temp = readb(phyctl);
                if (data & 0x1)
                        temp |= PHYCTL_DATA;
                else
                        temp &= ~PHYCTL_DATA;
                temp &= ~usbc_bit;
-               writeb(temp, phy_data->base + REG_PHYCTL);
+               writeb(temp, phyctl);
 
                /* pulse usbc_bit */
-               temp = readb(phy_data->base + REG_PHYCTL);
+               temp = readb(phyctl);
                temp |= usbc_bit;
-               writeb(temp, phy_data->base + REG_PHYCTL);
+               writeb(temp, phyctl);
 
-               temp = readb(phy_data->base + REG_PHYCTL);
+               temp = readb(phyctl);
                temp &= ~usbc_bit;
-               writeb(temp, phy_data->base + REG_PHYCTL);
+               writeb(temp, phyctl);
 
                data >>= 1;
        }
@@ -171,12 +253,39 @@ static int sun4i_usb_phy_init(struct phy *_phy)
 
        sun4i_usb_phy_passby(phy, 1);
 
+       if (phy->index == 0) {
+               data->phy0_init = true;
+
+               /* Enable pull-ups */
+               sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
+               sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
+
+               if (data->id_det_gpio) {
+                       /* OTG mode, force ISCR and cable state updates */
+                       data->id_det = -1;
+                       data->vbus_det = -1;
+                       queue_delayed_work(system_wq, &data->detect, 0);
+               } else {
+                       /* Host only mode */
+                       sun4i_usb_phy0_set_id_detect(_phy, 0);
+                       sun4i_usb_phy0_set_vbus_detect(_phy, 1);
+               }
+       }
+
        return 0;
 }
 
 static int sun4i_usb_phy_exit(struct phy *_phy)
 {
        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+       if (phy->index == 0) {
+               /* Disable pull-ups */
+               sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
+               sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
+               data->phy0_init = false;
+       }
 
        sun4i_usb_phy_passby(phy, 0);
        reset_control_assert(phy->reset);
@@ -185,23 +294,74 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
        return 0;
 }
 
+static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
+{
+       if (data->vbus_det_gpio)
+               return gpiod_get_value_cansleep(data->vbus_det_gpio);
+
+       if (data->vbus_power_supply) {
+               union power_supply_propval val;
+               int r;
+
+               r = power_supply_get_property(data->vbus_power_supply,
+                                             POWER_SUPPLY_PROP_PRESENT, &val);
+               if (r == 0)
+                       return val.intval;
+       }
+
+       /* Fallback: report vbus as high */
+       return 1;
+}
+
+static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
+{
+       return data->vbus_det_gpio || data->vbus_power_supply;
+}
+
 static int sun4i_usb_phy_power_on(struct phy *_phy)
 {
        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-       int ret = 0;
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+       int ret;
+
+       if (!phy->vbus || phy->regulator_on)
+               return 0;
+
+       /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
+       if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) &&
+                               data->vbus_det)
+               return 0;
+
+       ret = regulator_enable(phy->vbus);
+       if (ret)
+               return ret;
+
+       phy->regulator_on = true;
 
-       if (phy->vbus)
-               ret = regulator_enable(phy->vbus);
+       /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
+       if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll)
+               mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
 
-       return ret;
+       return 0;
 }
 
 static int sun4i_usb_phy_power_off(struct phy *_phy)
 {
        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+       if (!phy->vbus || !phy->regulator_on)
+               return 0;
+
+       regulator_disable(phy->vbus);
+       phy->regulator_on = false;
 
-       if (phy->vbus)
-               regulator_disable(phy->vbus);
+       /*
+        * phy0 vbus typically slowly discharges, sometimes this causes the
+        * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
+        */
+       if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll)
+               mod_delayed_work(system_wq, &data->detect, POLL_TIME);
 
        return 0;
 }
@@ -214,7 +374,7 @@ void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled)
 }
 EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect);
 
-static struct phy_ops sun4i_usb_phy_ops = {
+static const struct phy_ops sun4i_usb_phy_ops = {
        .init           = sun4i_usb_phy_init,
        .exit           = sun4i_usb_phy_exit,
        .power_on       = sun4i_usb_phy_power_on,
@@ -222,6 +382,95 @@ static struct phy_ops sun4i_usb_phy_ops = {
        .owner          = THIS_MODULE,
 };
 
+static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
+{
+       struct sun4i_usb_phy_data *data =
+               container_of(work, struct sun4i_usb_phy_data, detect.work);
+       struct phy *phy0 = data->phys[0].phy;
+       int id_det, vbus_det, id_notify = 0, vbus_notify = 0;
+
+       id_det = gpiod_get_value_cansleep(data->id_det_gpio);
+       vbus_det = sun4i_usb_phy0_get_vbus_det(data);
+
+       mutex_lock(&phy0->mutex);
+
+       if (!data->phy0_init) {
+               mutex_unlock(&phy0->mutex);
+               return;
+       }
+
+       if (id_det != data->id_det) {
+               /*
+                * When a host cable (id == 0) gets plugged in on systems
+                * without vbus detection report vbus low for long enough for
+                * the musb-ip to end the current device session.
+                */
+               if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 0) {
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+                       msleep(200);
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+               }
+               sun4i_usb_phy0_set_id_detect(phy0, id_det);
+               data->id_det = id_det;
+               id_notify = 1;
+       }
+
+       if (vbus_det != data->vbus_det) {
+               sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
+               data->vbus_det = vbus_det;
+               vbus_notify = 1;
+       }
+
+       mutex_unlock(&phy0->mutex);
+
+       if (id_notify) {
+               extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
+                                       !id_det);
+               /*
+                * When a host cable gets unplugged (id == 1) on systems
+                * without vbus detection report vbus low for long enough to
+                * the musb-ip to end the current host session.
+                */
+               if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) {
+                       mutex_lock(&phy0->mutex);
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+                       msleep(1000);
+                       sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+                       mutex_unlock(&phy0->mutex);
+               }
+       }
+
+       if (vbus_notify)
+               extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
+
+       if (data->phy0_poll)
+               queue_delayed_work(system_wq, &data->detect, POLL_TIME);
+}
+
+static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
+{
+       struct sun4i_usb_phy_data *data = dev_id;
+
+       /* vbus or id changed, let the pins settle and then scan them */
+       mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+       return IRQ_HANDLED;
+}
+
+static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
+                                     unsigned long val, void *v)
+{
+       struct sun4i_usb_phy_data *data =
+               container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
+       struct power_supply *psy = v;
+
+       /* Properties on the vbus_power_supply changed, scan vbus_det */
+       if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
+               mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+       return NOTIFY_OK;
+}
+
 static struct phy *sun4i_usb_phy_xlate(struct device *dev,
                                        struct of_phandle_args *args)
 {
@@ -233,6 +482,29 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
        return data->phys[args->args[0]].phy;
 }
 
+static int sun4i_usb_phy_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+       if (data->vbus_power_nb_registered)
+               power_supply_unreg_notifier(&data->vbus_power_nb);
+       if (data->id_det_irq >= 0)
+               devm_free_irq(dev, data->id_det_irq, data);
+       if (data->vbus_det_irq >= 0)
+               devm_free_irq(dev, data->vbus_det_irq, data);
+
+       cancel_delayed_work_sync(&data->detect);
+
+       return 0;
+}
+
+static const unsigned int sun4i_usb_phy0_cable[] = {
+       EXTCON_USB,
+       EXTCON_USB_HOST,
+       EXTCON_NONE,
+};
+
 static int sun4i_usb_phy_probe(struct platform_device *pdev)
 {
        struct sun4i_usb_phy_data *data;
@@ -241,35 +513,87 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
        struct phy_provider *phy_provider;
        bool dedicated_clocks;
        struct resource *res;
-       int i;
+       int i, ret;
 
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
        mutex_init(&data->mutex);
+       INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
+       dev_set_drvdata(dev, data);
 
-       if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy"))
+       if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
+           of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
+           of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
                data->num_phys = 2;
        else
                data->num_phys = 3;
 
-       if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy") ||
-           of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
-               data->disc_thresh = 3;
-       else
+       if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
+           of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy"))
                data->disc_thresh = 2;
+       else
+               data->disc_thresh = 3;
 
-       if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
+       if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") ||
+           of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
+           of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
                dedicated_clocks = true;
        else
                dedicated_clocks = false;
 
+       if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
+               data->has_a33_phyctl = true;
+
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
        data->base = devm_ioremap_resource(dev, res);
        if (IS_ERR(data->base))
                return PTR_ERR(data->base);
 
+       data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN);
+       if (IS_ERR(data->id_det_gpio)) {
+               if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               data->id_det_gpio = NULL;
+       }
+
+       data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN);
+       if (IS_ERR(data->vbus_det_gpio)) {
+               if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               data->vbus_det_gpio = NULL;
+       }
+
+       if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
+               data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
+                                                    "usb0_vbus_power-supply");
+               if (IS_ERR(data->vbus_power_supply))
+                       return PTR_ERR(data->vbus_power_supply);
+
+               if (!data->vbus_power_supply)
+                       return -EPROBE_DEFER;
+       }
+
+       /* vbus_det without id_det makes no sense, and is not supported */
+       if (sun4i_usb_phy0_have_vbus_det(data) && !data->id_det_gpio) {
+               dev_err(dev, "usb0_id_det missing or invalid\n");
+               return -ENODEV;
+       }
+
+       if (data->id_det_gpio) {
+               data->extcon = devm_extcon_dev_allocate(dev,
+                                                       sun4i_usb_phy0_cable);
+               if (IS_ERR(data->extcon))
+                       return PTR_ERR(data->extcon);
+
+               ret = devm_extcon_dev_register(dev, data->extcon);
+               if (ret) {
+                       dev_err(dev, "failed to register extcon: %d\n", ret);
+                       return ret;
+               }
+       }
+
        for (i = 0; i < data->num_phys; i++) {
                struct sun4i_usb_phy *phy = data->phys + i;
                char name[16];
@@ -319,10 +643,54 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
                phy_set_drvdata(phy->phy, &data->phys[i]);
        }
 
-       dev_set_drvdata(dev, data);
+       data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
+       data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
+       if ((data->id_det_gpio && data->id_det_irq < 0) ||
+           (data->vbus_det_gpio && data->vbus_det_irq < 0))
+               data->phy0_poll = true;
+
+       if (data->id_det_irq >= 0) {
+               ret = devm_request_irq(dev, data->id_det_irq,
+                               sun4i_usb_phy0_id_vbus_det_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               "usb0-id-det", data);
+               if (ret) {
+                       dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (data->vbus_det_irq >= 0) {
+               ret = devm_request_irq(dev, data->vbus_det_irq,
+                               sun4i_usb_phy0_id_vbus_det_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               "usb0-vbus-det", data);
+               if (ret) {
+                       dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
+                       data->vbus_det_irq = -1;
+                       sun4i_usb_phy_remove(pdev); /* Stop detect work */
+                       return ret;
+               }
+       }
+
+       if (data->vbus_power_supply) {
+               data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
+               data->vbus_power_nb.priority = 0;
+               ret = power_supply_reg_notifier(&data->vbus_power_nb);
+               if (ret) {
+                       sun4i_usb_phy_remove(pdev); /* Stop detect work */
+                       return ret;
+               }
+               data->vbus_power_nb_registered = true;
+       }
+
        phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+       if (IS_ERR(phy_provider)) {
+               sun4i_usb_phy_remove(pdev); /* Stop detect work */
+               return PTR_ERR(phy_provider);
+       }
 
-       return PTR_ERR_OR_ZERO(phy_provider);
+       return 0;
 }
 
 static const struct of_device_id sun4i_usb_phy_of_match[] = {
@@ -330,12 +698,15 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
        { .compatible = "allwinner,sun5i-a13-usb-phy" },
        { .compatible = "allwinner,sun6i-a31-usb-phy" },
        { .compatible = "allwinner,sun7i-a20-usb-phy" },
+       { .compatible = "allwinner,sun8i-a23-usb-phy" },
+       { .compatible = "allwinner,sun8i-a33-usb-phy" },
        { },
 };
 MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
 
 static struct platform_driver sun4i_usb_phy_driver = {
        .probe  = sun4i_usb_phy_probe,
+       .remove = sun4i_usb_phy_remove,
        .driver = {
                .of_match_table = sun4i_usb_phy_of_match,
                .name  = "sun4i-usb-phy",
index 0095914a662c05916db38d1693ab1fa189a45a04..ac4f31abefe33e45a4b1cdf5636c7c1ba05f716d 100644 (file)
@@ -114,7 +114,7 @@ static int sun9i_usb_phy_exit(struct phy *_phy)
        return 0;
 }
 
-static struct phy_ops sun9i_usb_phy_ops = {
+static const struct phy_ops sun9i_usb_phy_ops = {
        .init           = sun9i_usb_phy_init,
        .exit           = sun9i_usb_phy_exit,
        .owner          = THIS_MODULE,
index 08020dc2c7c8c3496987589841fc0ddb0b1c9ff7..93bc1120af12844ca17cd53e7869dba0676b438b 100644 (file)
@@ -298,7 +298,7 @@ static int ti_pipe3_exit(struct phy *x)
 
        return 0;
 }
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
        .init           = ti_pipe3_init,
        .exit           = ti_pipe3_exit,
        .power_on       = ti_pipe3_power_on,
index 07efdd318bdc9215d4de464aa3a19f7cc22ec612..2535d792d57af69277460ed4bc51beb39065d1d5 100644 (file)
@@ -53,7 +53,7 @@ static int tusb1210_power_off(struct phy *phy)
        return 0;
 }
 
-static struct phy_ops phy_ops = {
+static const struct phy_ops phy_ops = {
        .power_on = tusb1210_power_on,
        .power_off = tusb1210_power_off,
        .owner = THIS_MODULE,
index ac49fb6285eeecfd4a6db6df0dd28965b55483a6..f2ebe490a4bc590aa381247c9bfbd1a12fecc11b 100644 (file)
@@ -5,7 +5,7 @@
  * and it's controller, which is always the parent.
  */
 static inline struct phy
-*ulpi_phy_create(struct ulpi *ulpi, struct phy_ops *ops)
+*ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops)
 {
        struct phy *phy;
        int ret;
index 08beeed5485d3067be3093633a1d3173ffab44c2..f8758d6febf818a7101d6019a55e389af315cea5 100644 (file)
@@ -333,7 +333,7 @@ config CHARGER_LP8788
 
 config CHARGER_GPIO
        tristate "GPIO charger"
-       depends on GPIOLIB
+       depends on GPIOLIB || COMPILE_TEST
        help
          Say Y to include support for chargers which report their online status
          through a GPIO pin.
@@ -391,26 +391,30 @@ config CHARGER_BQ2415X
 
 config CHARGER_BQ24190
        tristate "TI BQ24190 battery charger driver"
-       depends on I2C && GPIOLIB
+       depends on I2C
+       depends on GPIOLIB || COMPILE_TEST
        help
          Say Y to enable support for the TI BQ24190 battery charger.
 
 config CHARGER_BQ24257
        tristate "TI BQ24257 battery charger driver"
-       depends on I2C && GPIOLIB
+       depends on I2C
+       depends on GPIOLIB || COMPILE_TEST
        depends on REGMAP_I2C
        help
          Say Y to enable support for the TI BQ24257 battery charger.
 
 config CHARGER_BQ24735
        tristate "TI BQ24735 battery charger support"
-       depends on I2C && GPIOLIB
+       depends on I2C
+       depends on GPIOLIB || COMPILE_TEST
        help
          Say Y to enable support for the TI BQ24735 battery charger.
 
 config CHARGER_BQ25890
        tristate "TI BQ25890 battery charger driver"
-       depends on I2C && GPIOLIB
+       depends on I2C
+       depends on GPIOLIB || COMPILE_TEST
        select REGMAP_I2C
        help
          Say Y to enable support for the TI BQ25890 battery charger.
@@ -462,7 +466,8 @@ config BATTERY_RT5033
 
 config CHARGER_RT9455
        tristate "Richtek RT9455 battery charger driver"
-       depends on I2C && GPIOLIB
+       depends on I2C
+       depends on GPIOLIB || COMPILE_TEST
        select REGMAP_I2C
        help
          Say Y to enable support for Richtek RT9455 battery charger.
index e98dcb661cc9bfd2730eb966978488513f5e2deb..ec212b5be755c68cf28313fafe24910c2d0cfc03 100644 (file)
@@ -170,7 +170,7 @@ struct bq2415x_device {
        struct power_supply *charger;
        struct power_supply_desc charger_desc;
        struct delayed_work work;
-       struct power_supply *notify_psy;
+       struct device_node *notify_node;
        struct notifier_block nb;
        enum bq2415x_mode reported_mode;/* mode reported by hook function */
        enum bq2415x_mode mode;         /* currently configured mode */
@@ -792,22 +792,47 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
 
 }
 
+static bool bq2415x_update_reported_mode(struct bq2415x_device *bq, int mA)
+{
+       enum bq2415x_mode mode;
+
+       if (mA == 0)
+               mode = BQ2415X_MODE_OFF;
+       else if (mA < 500)
+               mode = BQ2415X_MODE_NONE;
+       else if (mA < 1800)
+               mode = BQ2415X_MODE_HOST_CHARGER;
+       else
+               mode = BQ2415X_MODE_DEDICATED_CHARGER;
+
+       if (bq->reported_mode == mode)
+               return false;
+
+       bq->reported_mode = mode;
+       return true;
+}
+
 static int bq2415x_notifier_call(struct notifier_block *nb,
                unsigned long val, void *v)
 {
        struct bq2415x_device *bq =
                container_of(nb, struct bq2415x_device, nb);
        struct power_supply *psy = v;
-       enum bq2415x_mode mode;
        union power_supply_propval prop;
        int ret;
-       int mA;
 
        if (val != PSY_EVENT_PROP_CHANGED)
                return NOTIFY_OK;
 
-       if (psy != bq->notify_psy)
-               return NOTIFY_OK;
+       /* Ignore event if it was not send by notify_node/notify_device */
+       if (bq->notify_node) {
+               if (!psy->dev.parent ||
+                   psy->dev.parent->of_node != bq->notify_node)
+                       return NOTIFY_OK;
+       } else if (bq->init_data.notify_device) {
+               if (strcmp(psy->desc->name, bq->init_data.notify_device) != 0)
+                       return NOTIFY_OK;
+       }
 
        dev_dbg(bq->dev, "notifier call was called\n");
 
@@ -816,22 +841,9 @@ static int bq2415x_notifier_call(struct notifier_block *nb,
        if (ret != 0)
                return NOTIFY_OK;
 
-       mA = prop.intval;
-
-       if (mA == 0)
-               mode = BQ2415X_MODE_OFF;
-       else if (mA < 500)
-               mode = BQ2415X_MODE_NONE;
-       else if (mA < 1800)
-               mode = BQ2415X_MODE_HOST_CHARGER;
-       else
-               mode = BQ2415X_MODE_DEDICATED_CHARGER;
-
-       if (bq->reported_mode == mode)
+       if (!bq2415x_update_reported_mode(bq, prop.intval))
                return NOTIFY_OK;
 
-       bq->reported_mode = mode;
-
        /* if automode is not enabled do not tell about reported_mode */
        if (bq->automode < 1)
                return NOTIFY_OK;
@@ -1536,6 +1548,8 @@ static int bq2415x_probe(struct i2c_client *client,
        struct device_node *np = client->dev.of_node;
        struct bq2415x_platform_data *pdata = client->dev.platform_data;
        const struct acpi_device_id *acpi_id = NULL;
+       struct power_supply *notify_psy = NULL;
+       union power_supply_propval prop;
 
        if (!np && !pdata && !ACPI_HANDLE(&client->dev)) {
                dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n");
@@ -1569,25 +1583,6 @@ static int bq2415x_probe(struct i2c_client *client,
                goto error_2;
        }
 
-       if (np) {
-               bq->notify_psy = power_supply_get_by_phandle(np,
-                                               "ti,usb-charger-detection");
-
-               if (IS_ERR(bq->notify_psy)) {
-                       dev_info(&client->dev,
-                                "no 'ti,usb-charger-detection' property (err=%ld)\n",
-                               PTR_ERR(bq->notify_psy));
-                       bq->notify_psy = NULL;
-               } else if (!bq->notify_psy) {
-                       ret = -EPROBE_DEFER;
-                       goto error_2;
-               }
-       } else if (pdata && pdata->notify_device) {
-               bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
-       } else {
-               bq->notify_psy = NULL;
-       }
-
        i2c_set_clientdata(client, bq);
 
        bq->id = num;
@@ -1607,32 +1602,35 @@ static int bq2415x_probe(struct i2c_client *client,
                                               "ti,current-limit",
                                               &bq->init_data.current_limit);
                if (ret)
-                       goto error_3;
+                       goto error_2;
                ret = device_property_read_u32(bq->dev,
                                        "ti,weak-battery-voltage",
                                        &bq->init_data.weak_battery_voltage);
                if (ret)
-                       goto error_3;
+                       goto error_2;
                ret = device_property_read_u32(bq->dev,
                                "ti,battery-regulation-voltage",
                                &bq->init_data.battery_regulation_voltage);
                if (ret)
-                       goto error_3;
+                       goto error_2;
                ret = device_property_read_u32(bq->dev,
                                               "ti,charge-current",
                                               &bq->init_data.charge_current);
                if (ret)
-                       goto error_3;
+                       goto error_2;
                ret = device_property_read_u32(bq->dev,
                                "ti,termination-current",
                                &bq->init_data.termination_current);
                if (ret)
-                       goto error_3;
+                       goto error_2;
                ret = device_property_read_u32(bq->dev,
                                               "ti,resistor-sense",
                                               &bq->init_data.resistor_sense);
                if (ret)
-                       goto error_3;
+                       goto error_2;
+               if (np)
+                       bq->notify_node = of_parse_phandle(np,
+                                               "ti,usb-charger-detection", 0);
        } else {
                memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
        }
@@ -1642,56 +1640,72 @@ static int bq2415x_probe(struct i2c_client *client,
        ret = bq2415x_power_supply_init(bq);
        if (ret) {
                dev_err(bq->dev, "failed to register power supply: %d\n", ret);
-               goto error_3;
+               goto error_2;
        }
 
        ret = bq2415x_sysfs_init(bq);
        if (ret) {
                dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
-               goto error_4;
+               goto error_3;
        }
 
        ret = bq2415x_set_defaults(bq);
        if (ret) {
                dev_err(bq->dev, "failed to set default values: %d\n", ret);
-               goto error_5;
+               goto error_4;
        }
 
-       if (bq->notify_psy) {
+       if (bq->notify_node || bq->init_data.notify_device) {
                bq->nb.notifier_call = bq2415x_notifier_call;
                ret = power_supply_reg_notifier(&bq->nb);
                if (ret) {
                        dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
-                       goto error_6;
+                       goto error_4;
                }
 
-               /* Query for initial reported_mode and set it */
-               bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED,
-                                     bq->notify_psy);
-               bq2415x_set_mode(bq, bq->reported_mode);
-
                bq->automode = 1;
-               dev_info(bq->dev, "automode enabled\n");
+               dev_info(bq->dev, "automode supported, waiting for events\n");
        } else {
                bq->automode = -1;
                dev_info(bq->dev, "automode not supported\n");
        }
 
+       /* Query for initial reported_mode and set it */
+       if (bq->nb.notifier_call) {
+               if (np) {
+                       notify_psy = power_supply_get_by_phandle(np,
+                                               "ti,usb-charger-detection");
+                       if (IS_ERR(notify_psy))
+                               notify_psy = NULL;
+               } else if (bq->init_data.notify_device) {
+                       notify_psy = power_supply_get_by_name(
+                                               bq->init_data.notify_device);
+               }
+       }
+       if (notify_psy) {
+               ret = power_supply_get_property(notify_psy,
+                                       POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
+               power_supply_put(notify_psy);
+
+               if (ret == 0) {
+                       bq2415x_update_reported_mode(bq, prop.intval);
+                       bq2415x_set_mode(bq, bq->reported_mode);
+               }
+       }
+
        INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work);
        bq2415x_set_autotimer(bq, 1);
 
        dev_info(bq->dev, "driver registered\n");
        return 0;
 
-error_6:
-error_5:
-       bq2415x_sysfs_exit(bq);
 error_4:
-       bq2415x_power_supply_exit(bq);
+       bq2415x_sysfs_exit(bq);
 error_3:
-       if (bq->notify_psy)
-               power_supply_put(bq->notify_psy);
+       bq2415x_power_supply_exit(bq);
 error_2:
+       if (bq->notify_node)
+               of_node_put(bq->notify_node);
        kfree(name);
 error_1:
        mutex_lock(&bq2415x_id_mutex);
@@ -1707,10 +1721,11 @@ static int bq2415x_remove(struct i2c_client *client)
 {
        struct bq2415x_device *bq = i2c_get_clientdata(client);
 
-       if (bq->notify_psy) {
+       if (bq->nb.notifier_call)
                power_supply_unreg_notifier(&bq->nb);
-               power_supply_put(bq->notify_psy);
-       }
+
+       if (bq->notify_node)
+               of_node_put(bq->notify_node);
 
        bq2415x_sysfs_exit(bq);
        bq2415x_power_supply_exit(bq);
index 052db78c373650979f620cd031cf7f7b0fa067b7..469a452cbe1004025d86326222671f11e0674b52 100644 (file)
@@ -902,7 +902,7 @@ static int bq24190_charger_property_is_writeable(struct power_supply *psy,
 }
 
 static enum power_supply_property bq24190_charger_properties[] = {
-       POWER_SUPPLY_PROP_TYPE,
+       POWER_SUPPLY_PROP_CHARGE_TYPE,
        POWER_SUPPLY_PROP_HEALTH,
        POWER_SUPPLY_PROP_ONLINE,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
@@ -1515,6 +1515,7 @@ static const struct i2c_device_id bq24190_i2c_ids[] = {
        { "bq24190", BQ24190_REG_VPRS_PN_24190 },
        { },
 };
+MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
 
 #ifdef CONFIG_OF
 static const struct of_device_id bq24190_of_match[] = {
@@ -1534,7 +1535,6 @@ static struct i2c_driver bq24190_driver = {
        .id_table       = bq24190_i2c_ids,
        .driver = {
                .name           = "bq24190-charger",
-               .owner          = THIS_MODULE,
                .pm             = &bq24190_pm_ops,
                .of_match_table = of_match_ptr(bq24190_of_match),
        },
index 961a189300275a3d65b5885ab5d647822059ba4c..eb2b3689de975ac1b670b2a2226b82734b7fc58e 100644 (file)
@@ -267,8 +267,9 @@ static int bq24735_charger_probe(struct i2c_client *client,
 
        name = (char *)charger->pdata->name;
        if (!name) {
-               name = kasprintf(GFP_KERNEL, "bq24735@%s",
-                                dev_name(&client->dev));
+               name = devm_kasprintf(&client->dev, GFP_KERNEL,
+                                     "bq24735@%s",
+                                     dev_name(&client->dev));
                if (!name) {
                        dev_err(&client->dev, "Failed to alloc device name\n");
                        return -ENOMEM;
@@ -296,23 +297,21 @@ static int bq24735_charger_probe(struct i2c_client *client,
        if (ret < 0) {
                dev_err(&client->dev, "Failed to read manufacturer id : %d\n",
                        ret);
-               goto err_free_name;
+               return ret;
        } else if (ret != 0x0040) {
                dev_err(&client->dev,
                        "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret);
-               ret = -ENODEV;
-               goto err_free_name;
+               return -ENODEV;
        }
 
        ret = bq24735_read_word(client, BQ24735_DEVICE_ID);
        if (ret < 0) {
                dev_err(&client->dev, "Failed to read device id : %d\n", ret);
-               goto err_free_name;
+               return ret;
        } else if (ret != 0x000B) {
                dev_err(&client->dev,
                        "device id mismatch. 0x000b != 0x%04x\n", ret);
-               ret = -ENODEV;
-               goto err_free_name;
+               return -ENODEV;
        }
 
        if (gpio_is_valid(charger->pdata->status_gpio)) {
@@ -331,7 +330,7 @@ static int bq24735_charger_probe(struct i2c_client *client,
        ret = bq24735_config_charger(charger);
        if (ret < 0) {
                dev_err(&client->dev, "failed in configuring charger");
-               goto err_free_name;
+               return ret;
        }
 
        /* check for AC adapter presence */
@@ -339,17 +338,17 @@ static int bq24735_charger_probe(struct i2c_client *client,
                ret = bq24735_enable_charging(charger);
                if (ret < 0) {
                        dev_err(&client->dev, "Failed to enable charging\n");
-                       goto err_free_name;
+                       return ret;
                }
        }
 
-       charger->charger = power_supply_register(&client->dev, supply_desc,
-                                                &psy_cfg);
+       charger->charger = devm_power_supply_register(&client->dev, supply_desc,
+                                                     &psy_cfg);
        if (IS_ERR(charger->charger)) {
                ret = PTR_ERR(charger->charger);
                dev_err(&client->dev, "Failed to register power supply: %d\n",
                        ret);
-               goto err_free_name;
+               return ret;
        }
 
        if (client->irq) {
@@ -364,33 +363,10 @@ static int bq24735_charger_probe(struct i2c_client *client,
                        dev_err(&client->dev,
                                "Unable to register IRQ %d err %d\n",
                                client->irq, ret);
-                       goto err_unregister_supply;
+                       return ret;
                }
        }
 
-       return 0;
-err_unregister_supply:
-       power_supply_unregister(charger->charger);
-err_free_name:
-       if (name != charger->pdata->name)
-               kfree(name);
-
-       return ret;
-}
-
-static int bq24735_charger_remove(struct i2c_client *client)
-{
-       struct bq24735 *charger = i2c_get_clientdata(client);
-
-       if (charger->client->irq)
-               devm_free_irq(&charger->client->dev, charger->client->irq,
-                             &charger->charger);
-
-       power_supply_unregister(charger->charger);
-
-       if (charger->charger_desc.name != charger->pdata->name)
-               kfree(charger->charger_desc.name);
-
        return 0;
 }
 
@@ -409,11 +385,9 @@ MODULE_DEVICE_TABLE(of, bq24735_match_ids);
 static struct i2c_driver bq24735_charger_driver = {
        .driver = {
                .name = "bq24735-charger",
-               .owner = THIS_MODULE,
                .of_match_table = bq24735_match_ids,
        },
        .probe = bq24735_charger_probe,
-       .remove = bq24735_charger_remove,
        .id_table = bq24735_charger_id,
 };
 
index b6b98378faa32b50c0e1900c76ca4e26da3bd6c1..8287261fd978895afca216d993537c7f55ea1dee 100644 (file)
 
 #include <linux/power/bq27x00_battery.h>
 
-#define DRIVER_VERSION                 "1.2.0"
-
-#define BQ27x00_REG_TEMP               0x06
-#define BQ27x00_REG_VOLT               0x08
-#define BQ27x00_REG_AI                 0x14
-#define BQ27x00_REG_FLAGS              0x0A
-#define BQ27x00_REG_TTE                        0x16
-#define BQ27x00_REG_TTF                        0x18
-#define BQ27x00_REG_TTECP              0x26
-#define BQ27x00_REG_NAC                        0x0C /* Nominal available capacity */
-#define BQ27x00_REG_LMD                        0x12 /* Last measured discharge */
-#define BQ27x00_REG_CYCT               0x2A /* Cycle count total */
-#define BQ27x00_REG_AE                 0x22 /* Available energy */
-#define BQ27x00_POWER_AVG              0x24
-
-#define BQ27000_REG_RSOC               0x0B /* Relative State-of-Charge */
-#define BQ27000_REG_ILMD               0x76 /* Initial last measured discharge */
-#define BQ27000_FLAG_EDVF              BIT(0) /* Final End-of-Discharge-Voltage flag */
-#define BQ27000_FLAG_EDV1              BIT(1) /* First End-of-Discharge-Voltage flag */
-#define BQ27000_FLAG_CI                        BIT(4) /* Capacity Inaccurate flag */
-#define BQ27000_FLAG_FC                        BIT(5)
-#define BQ27000_FLAG_CHGS              BIT(7) /* Charge state flag */
-
-#define BQ27500_REG_SOC                        0x2C
-#define BQ27500_REG_DCAP               0x3C /* Design capacity */
-#define BQ27500_FLAG_DSC               BIT(0)
-#define BQ27500_FLAG_SOCF              BIT(1) /* State-of-Charge threshold final */
-#define BQ27500_FLAG_SOC1              BIT(2) /* State-of-Charge threshold 1 */
-#define BQ27500_FLAG_FC                        BIT(9)
-#define BQ27500_FLAG_OTC               BIT(15)
-
-#define BQ27742_POWER_AVG              0x76
-
-#define BQ27510_REG_SOC                        0x20
-#define BQ27510_REG_DCAP               0x2E /* Design capacity */
-#define BQ27510_REG_CYCT               0x1E /* Cycle count total */
+#define DRIVER_VERSION         "1.2.0"
+
+#define BQ27XXX_MANUFACTURER   "Texas Instruments"
+
+#define BQ27x00_REG_TEMP       0x06
+#define BQ27x00_REG_VOLT       0x08
+#define BQ27x00_REG_AI         0x14
+#define BQ27x00_REG_FLAGS      0x0A
+#define BQ27x00_REG_TTE                0x16
+#define BQ27x00_REG_TTF                0x18
+#define BQ27x00_REG_TTECP      0x26
+#define BQ27x00_REG_NAC                0x0C /* Nominal available capacity */
+#define BQ27x00_REG_LMD                0x12 /* Last measured discharge */
+#define BQ27x00_REG_CYCT       0x2A /* Cycle count total */
+#define BQ27x00_REG_AE         0x22 /* Available energy */
+#define BQ27x00_POWER_AVG      0x24
+
+#define BQ27000_REG_RSOC       0x0B /* Relative State-of-Charge */
+#define BQ27000_REG_ILMD       0x76 /* Initial last measured discharge */
+#define BQ27000_FLAG_EDVF      BIT(0) /* Final End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_EDV1      BIT(1) /* First End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_CI                BIT(4) /* Capacity Inaccurate flag */
+#define BQ27000_FLAG_FC                BIT(5)
+#define BQ27000_FLAG_CHGS      BIT(7) /* Charge state flag */
+
+#define BQ27500_REG_SOC                0x2C
+#define BQ27500_REG_DCAP       0x3C /* Design capacity */
+#define BQ27500_FLAG_DSC       BIT(0)
+#define BQ27500_FLAG_SOCF      BIT(1) /* State-of-Charge threshold final */
+#define BQ27500_FLAG_SOC1      BIT(2) /* State-of-Charge threshold 1 */
+#define BQ27500_FLAG_FC                BIT(9)
+#define BQ27500_FLAG_OTC       BIT(15)
+
+#define BQ27742_POWER_AVG      0x76
+
+#define BQ27510_REG_SOC                0x20
+#define BQ27510_REG_DCAP       0x2E /* Design capacity */
+#define BQ27510_REG_CYCT       0x1E /* Cycle count total */
 
 /* bq27425 register addresses are same as bq27x00 addresses minus 4 */
-#define BQ27425_REG_OFFSET             0x04
+#define BQ27425_REG_OFFSET     0x04
 #define BQ27425_REG_SOC                (0x1C + BQ27425_REG_OFFSET)
-#define BQ27425_REG_DCAP               (0x3C + BQ27425_REG_OFFSET)
+#define BQ27425_REG_DCAP       (0x3C + BQ27425_REG_OFFSET)
 
 #define BQ27000_RS                     20 /* Resistor sense */
 #define BQ27x00_POWER_CONSTANT         (256 * 29200 / 1000)
@@ -106,7 +108,7 @@ struct bq27x00_reg_cache {
 };
 
 struct bq27x00_device_info {
-       struct device           *dev;
+       struct device           *dev;
        int                     id;
        enum bq27x00_chip       chip;
 
@@ -142,6 +144,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
        POWER_SUPPLY_PROP_ENERGY_NOW,
        POWER_SUPPLY_PROP_POWER_AVG,
        POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
 static enum power_supply_property bq27425_battery_props[] = {
@@ -156,6 +159,7 @@ static enum power_supply_property bq27425_battery_props[] = {
        POWER_SUPPLY_PROP_CHARGE_FULL,
        POWER_SUPPLY_PROP_CHARGE_NOW,
        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+       POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
 static enum power_supply_property bq27742_battery_props[] = {
@@ -174,6 +178,7 @@ static enum power_supply_property bq27742_battery_props[] = {
        POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_POWER_AVG,
        POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
 static enum power_supply_property bq27510_battery_props[] = {
@@ -192,19 +197,20 @@ static enum power_supply_property bq27510_battery_props[] = {
        POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_POWER_AVG,
        POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
 static unsigned int poll_interval = 360;
 module_param(poll_interval, uint, 0644);
-MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
-                               "0 disables polling");
+MODULE_PARM_DESC(poll_interval,
+                "battery poll interval in seconds - 0 disables polling");
 
 /*
  * Common code for BQ27x00 devices
  */
 
 static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
-               bool single)
+                              bool single)
 {
        if (di->chip == BQ27425)
                return di->bus.read(di, reg - BQ27425_REG_OFFSET, single);
@@ -313,8 +319,9 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
                        ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false);
                else
                        ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
-       } else
+       } else {
                ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
+       }
 
        if (ilmd < 0) {
                dev_dbg(di->dev, "error reading initial last measured discharge\n");
@@ -445,7 +452,7 @@ static int bq27x00_battery_read_health(struct bq27x00_device_info *di)
                return tval;
        }
 
-       if ((di->chip == BQ27500)) {
+       if (di->chip == BQ27500) {
                if (tval & BQ27500_FLAG_SOCF)
                        tval = POWER_SUPPLY_HEALTH_DEAD;
                else if (tval & BQ27500_FLAG_OTC)
@@ -559,7 +566,7 @@ static void bq27x00_battery_poll(struct work_struct *work)
  * Or 0 if something fails.
  */
 static int bq27x00_battery_current(struct bq27x00_device_info *di,
-       union power_supply_propval *val)
+                                  union power_supply_propval *val)
 {
        int curr;
        int flags;
@@ -587,7 +594,7 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
 }
 
 static int bq27x00_battery_status(struct bq27x00_device_info *di,
-       union power_supply_propval *val)
+                                 union power_supply_propval *val)
 {
        int status;
 
@@ -615,7 +622,7 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
 }
 
 static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
-       union power_supply_propval *val)
+                                         union power_supply_propval *val)
 {
        int level;
 
@@ -649,7 +656,7 @@ static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
  * Or < 0 if something fails.
  */
 static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
-       union power_supply_propval *val)
+                                  union power_supply_propval *val)
 {
        int volt;
 
@@ -665,7 +672,7 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
 }
 
 static int bq27x00_simple_value(int value,
-       union power_supply_propval *val)
+                               union power_supply_propval *val)
 {
        if (value < 0)
                return value;
@@ -749,6 +756,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_HEALTH:
                ret = bq27x00_simple_value(di->cache.health, val);
                break;
+       case POWER_SUPPLY_PROP_MANUFACTURER:
+               val->strval = BQ27XXX_MANUFACTURER;
+               break;
        default:
                return -EINVAL;
        }
@@ -827,7 +837,6 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
        mutex_destroy(&di->lock);
 }
 
-
 /* i2c specific code */
 #ifdef CONFIG_BATTERY_BQ27X00_I2C
 
@@ -888,14 +897,12 @@ static int bq27x00_battery_probe(struct i2c_client *client,
 
        name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
        if (!name) {
-               dev_err(&client->dev, "failed to allocate device name\n");
                retval = -ENOMEM;
                goto batt_failed;
        }
 
        di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
        if (!di) {
-               dev_err(&client->dev, "failed to allocate device info data\n");
                retval = -ENOMEM;
                goto batt_failed;
        }
@@ -956,8 +963,9 @@ static struct i2c_driver bq27x00_battery_driver = {
 static inline int bq27x00_battery_i2c_init(void)
 {
        int ret = i2c_add_driver(&bq27x00_battery_driver);
+
        if (ret)
-               printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n");
+               pr_err("Unable to register BQ27x00 i2c driver\n");
 
        return ret;
 }
@@ -978,7 +986,7 @@ static inline void bq27x00_battery_i2c_exit(void) {};
 #ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
 
 static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
-                       bool single)
+                                bool single)
 {
        struct device *dev = di->dev;
        struct bq27000_platform_data *pdata = dev->platform_data;
@@ -1028,10 +1036,8 @@ static int bq27000_battery_probe(struct platform_device *pdev)
        }
 
        di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
-       if (!di) {
-               dev_err(&pdev->dev, "failed to allocate device info data\n");
+       if (!di)
                return -ENOMEM;
-       }
 
        platform_set_drvdata(pdev, di);
 
@@ -1064,8 +1070,9 @@ static struct platform_driver bq27000_battery_driver = {
 static inline int bq27x00_battery_platform_init(void)
 {
        int ret = platform_driver_register(&bq27000_battery_driver);
+
        if (ret)
-               printk(KERN_ERR "Unable to register BQ27000 platform driver\n");
+               pr_err("Unable to register BQ27000 platform driver\n");
 
        return ret;
 }
index a7a0427343f3ef563fd9d6264165e27edf1e0ef2..d3743d0ad55bdcb5af7db6cc41b728b994f1840e 100644 (file)
@@ -637,10 +637,6 @@ static ssize_t ds2780_read_param_eeprom_bin(struct file *filp,
        struct power_supply *psy = to_power_supply(dev);
        struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
 
-       count = min_t(loff_t, count,
-               DS2780_EEPROM_BLOCK1_END -
-               DS2780_EEPROM_BLOCK1_START + 1 - off);
-
        return ds2780_read_block(dev_info, buf,
                                DS2780_EEPROM_BLOCK1_START + off, count);
 }
@@ -655,10 +651,6 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
        struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
        int ret;
 
-       count = min_t(loff_t, count,
-               DS2780_EEPROM_BLOCK1_END -
-               DS2780_EEPROM_BLOCK1_START + 1 - off);
-
        ret = ds2780_write(dev_info, buf,
                                DS2780_EEPROM_BLOCK1_START + off, count);
        if (ret < 0)
@@ -676,7 +668,7 @@ static struct bin_attribute ds2780_param_eeprom_bin_attr = {
                .name = "param_eeprom",
                .mode = S_IRUGO | S_IWUSR,
        },
-       .size = DS2780_EEPROM_BLOCK1_END - DS2780_EEPROM_BLOCK1_START + 1,
+       .size = DS2780_PARAM_EEPROM_SIZE,
        .read = ds2780_read_param_eeprom_bin,
        .write = ds2780_write_param_eeprom_bin,
 };
@@ -690,10 +682,6 @@ static ssize_t ds2780_read_user_eeprom_bin(struct file *filp,
        struct power_supply *psy = to_power_supply(dev);
        struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
 
-       count = min_t(loff_t, count,
-               DS2780_EEPROM_BLOCK0_END -
-               DS2780_EEPROM_BLOCK0_START + 1 - off);
-
        return ds2780_read_block(dev_info, buf,
                                DS2780_EEPROM_BLOCK0_START + off, count);
 }
@@ -708,10 +696,6 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
        struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
        int ret;
 
-       count = min_t(loff_t, count,
-               DS2780_EEPROM_BLOCK0_END -
-               DS2780_EEPROM_BLOCK0_START + 1 - off);
-
        ret = ds2780_write(dev_info, buf,
                                DS2780_EEPROM_BLOCK0_START + off, count);
        if (ret < 0)
@@ -729,7 +713,7 @@ static struct bin_attribute ds2780_user_eeprom_bin_attr = {
                .name = "user_eeprom",
                .mode = S_IRUGO | S_IWUSR,
        },
-       .size = DS2780_EEPROM_BLOCK0_END - DS2780_EEPROM_BLOCK0_START + 1,
+       .size = DS2780_USER_EEPROM_SIZE,
        .read = ds2780_read_user_eeprom_bin,
        .write = ds2780_write_user_eeprom_bin,
 };
index 56d583dae9087c89742bf25e4d0a61364d4f5885..c3680024f3992af41f7a4ff8a5598b628df67c43 100644 (file)
@@ -639,8 +639,6 @@ static ssize_t ds2781_read_param_eeprom_bin(struct file *filp,
        struct power_supply *psy = to_power_supply(dev);
        struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
 
-       count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off);
-
        return ds2781_read_block(dev_info, buf,
                                DS2781_EEPROM_BLOCK1_START + off, count);
 }
@@ -655,8 +653,6 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp,
        struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
        int ret;
 
-       count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off);
-
        ret = ds2781_write(dev_info, buf,
                                DS2781_EEPROM_BLOCK1_START + off, count);
        if (ret < 0)
@@ -688,8 +684,6 @@ static ssize_t ds2781_read_user_eeprom_bin(struct file *filp,
        struct power_supply *psy = to_power_supply(dev);
        struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
 
-       count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off);
-
        return ds2781_read_block(dev_info, buf,
                                DS2781_EEPROM_BLOCK0_START + off, count);
 
@@ -705,8 +699,6 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp,
        struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
        int ret;
 
-       count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off);
-
        ret = ds2781_write(dev_info, buf,
                                DS2781_EEPROM_BLOCK0_START + off, count);
        if (ret < 0)
index daeb0860736c1d5a954eda63f1a87d716c1b6832..4adf2ba021ceb2a2f99510d4ed28bfbae51617c4 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/swab.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/idr.h>
 #include <linux/power_supply.h>
 #include <linux/slab.h>
 
@@ -63,15 +62,11 @@ struct ltc294x_info {
        struct power_supply_desc supply_desc;   /* Supply description */
        struct delayed_work work;       /* Work scheduler */
        int num_regs;   /* Number of registers (chip type) */
-       int id;         /* Identifier of ltc294x chip */
        int charge;     /* Last charge register content */
        int r_sense;    /* mOhm */
        int Qlsb;       /* nAh */
 };
 
-static DEFINE_IDR(ltc294x_id);
-static DEFINE_MUTEX(ltc294x_lock);
-
 static inline int convert_bin_to_uAh(
        const struct ltc294x_info *info, int Q)
 {
@@ -371,10 +366,6 @@ static int ltc294x_i2c_remove(struct i2c_client *client)
 
        cancel_delayed_work(&info->work);
        power_supply_unregister(info->supply);
-       kfree(info->supply_desc.name);
-       mutex_lock(&ltc294x_lock);
-       idr_remove(&ltc294x_id, info->id);
-       mutex_unlock(&ltc294x_lock);
        return 0;
 }
 
@@ -384,44 +375,28 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
        struct power_supply_config psy_cfg = {};
        struct ltc294x_info *info;
        int ret;
-       int num;
        u32 prescaler_exp;
        s32 r_sense;
        struct device_node *np;
 
-       mutex_lock(&ltc294x_lock);
-       ret = idr_alloc(&ltc294x_id, client, 0, 0, GFP_KERNEL);
-       mutex_unlock(&ltc294x_lock);
-       if (ret < 0)
-               goto fail_id;
-
-       num = ret;
-
        info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
-       if (info == NULL) {
-               ret = -ENOMEM;
-               goto fail_info;
-       }
+       if (info == NULL)
+               return -ENOMEM;
 
        i2c_set_clientdata(client, info);
 
-       info->num_regs = id->driver_data;
-       info->supply_desc.name = kasprintf(GFP_KERNEL, "%s-%d", client->name,
-                                          num);
-       if (!info->supply_desc.name) {
-               ret = -ENOMEM;
-               goto fail_name;
-       }
-
        np = of_node_get(client->dev.of_node);
 
+       info->num_regs = id->driver_data;
+       info->supply_desc.name = np->name;
+
        /* r_sense can be negative, when sense+ is connected to the battery
         * instead of the sense-. This results in reversed measurements. */
        ret = of_property_read_u32(np, "lltc,resistor-sense", &r_sense);
        if (ret < 0) {
                dev_err(&client->dev,
                        "Could not find lltc,resistor-sense in devicetree\n");
-               goto fail_name;
+               return ret;
        }
        info->r_sense = r_sense;
 
@@ -446,7 +421,6 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
        }
 
        info->client = client;
-       info->id = num;
        info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY;
        info->supply_desc.properties = ltc294x_properties;
        if (info->num_regs >= LTC294X_REG_TEMPERATURE_LSB)
@@ -473,31 +447,19 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
        ret = ltc294x_reset(info, prescaler_exp);
        if (ret < 0) {
                dev_err(&client->dev, "Communication with chip failed\n");
-               goto fail_comm;
+               return ret;
        }
 
        info->supply = power_supply_register(&client->dev, &info->supply_desc,
                                             &psy_cfg);
        if (IS_ERR(info->supply)) {
                dev_err(&client->dev, "failed to register ltc2941\n");
-               ret = PTR_ERR(info->supply);
-               goto fail_register;
+               return PTR_ERR(info->supply);
        } else {
                schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ);
        }
 
        return 0;
-
-fail_register:
-       kfree(info->supply_desc.name);
-fail_comm:
-fail_name:
-fail_info:
-       mutex_lock(&ltc294x_lock);
-       idr_remove(&ltc294x_id, num);
-       mutex_unlock(&ltc294x_lock);
-fail_id:
-       return ret;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 754879eb59f67b878fc70b6b19dc10935c15d257..060cab5ae3aa2de0f91e2d6b376e2daa7b2b1863 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/power_supply.h>
 #include <linux/regmap.h>
 #include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
 
 #define MAX77693_CHARGER_NAME                          "max77693-charger"
index a944338a39de406d80d932c31babebbb50731318..9e29b1321648d12bf55cbc6f423be199826bf4d2 100644 (file)
@@ -521,11 +521,6 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj,
        int ret;
        int i;
 
-       if (off >= EEPROM_SIZE)
-               return 0;
-       if (off + count > EEPROM_SIZE)
-               count = EEPROM_SIZE - off;
-
        for (i = 0; i < count; i++) {
                ec_byte = EEPROM_START + off + i;
                ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1);
@@ -545,7 +540,7 @@ static struct bin_attribute olpc_bat_eeprom = {
                .name = "eeprom",
                .mode = S_IRUGO,
        },
-       .size = 0,
+       .size = EEPROM_SIZE,
        .read = olpc_bat_eeprom_read,
 };
 
index cc0893ffbf7e66bc2d107b4ea708d04cf09a87b1..3a45cc0c4dceb13e46e7ea9a92d8c1a3f10ac2f9 100644 (file)
@@ -1244,7 +1244,6 @@ static struct i2c_driver pm2xxx_charger_driver = {
        .remove = pm2xxx_wall_charger_remove,
        .driver = {
                .name = "pm2xxx-wall_charger",
-               .owner = THIS_MODULE,
                .pm = PM2XXX_PM_OPS,
        },
        .id_table = pm2xxx_id,
index 17d93a73c5136e53ab2955d7aba02a7ef0c85d1f..5a0189bf19bb145faccce601478910906b5ef839 100644 (file)
@@ -166,5 +166,12 @@ config POWER_RESET_RMOBILE
        help
          Reboot support for Renesas R-Mobile and SH-Mobile SoCs.
 
+config POWER_RESET_ZX
+       tristate "ZTE SoCs reset driver"
+       depends on ARCH_ZX || COMPILE_TEST
+       depends on HAS_IOMEM
+       help
+         Reboot support for ZTE SoCs.
+
 endif
 
index dbe06c368743220ede4be9dbb9c2dfb814205bdc..096fa67047f6ed62ac74397cfea552cb571a0ec3 100644 (file)
@@ -19,3 +19,4 @@ obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o
 obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o
 obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o
 obj-$(CONFIG_POWER_RESET_RMOBILE) += rmobile-reset.o
+obj-$(CONFIG_POWER_RESET_ZX) += zx-reboot.o
index 36dc52fb2ec8ba9aace408546359dc0879db40f2..c378d4ec826f4248155cb9f786697caba7e307ad 100644 (file)
@@ -123,6 +123,15 @@ static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode,
        return NOTIFY_DONE;
 }
 
+static int sama5d3_restart(struct notifier_block *this, unsigned long mode,
+                          void *cmd)
+{
+       writel(cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST),
+              at91_rstc_base);
+
+       return NOTIFY_DONE;
+}
+
 static void __init at91_reset_status(struct platform_device *pdev)
 {
        u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
@@ -155,13 +164,13 @@ static void __init at91_reset_status(struct platform_device *pdev)
 static const struct of_device_id at91_ramc_of_match[] = {
        { .compatible = "atmel,at91sam9260-sdramc", },
        { .compatible = "atmel,at91sam9g45-ddramc", },
-       { .compatible = "atmel,sama5d3-ddramc", },
        { /* sentinel */ }
 };
 
 static const struct of_device_id at91_reset_of_match[] = {
        { .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart },
        { .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
+       { .compatible = "atmel,sama5d3-rstc", .data = sama5d3_restart },
        { /* sentinel */ }
 };
 
@@ -181,13 +190,16 @@ static int at91_reset_of_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       for_each_matching_node(np, at91_ramc_of_match) {
-               at91_ramc_base[idx] = of_iomap(np, 0);
-               if (!at91_ramc_base[idx]) {
-                       dev_err(&pdev->dev, "Could not map ram controller address\n");
-                       return -ENODEV;
+       if (!of_device_is_compatible(pdev->dev.of_node, "atmel,sama5d3-rstc")) {
+               /* we need to shutdown the ddr controller, so get ramc base */
+               for_each_matching_node(np, at91_ramc_of_match) {
+                       at91_ramc_base[idx] = of_iomap(np, 0);
+                       if (!at91_ramc_base[idx]) {
+                               dev_err(&pdev->dev, "Could not map ram controller address\n");
+                               return -ENODEV;
+                       }
+                       idx++;
                }
-               idx++;
        }
 
        match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
diff --git a/drivers/power/reset/zx-reboot.c b/drivers/power/reset/zx-reboot.c
new file mode 100644 (file)
index 0000000..a5b0096
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * ZTE zx296702 SoC reset code
+ *
+ * Copyright (c) 2015 Linaro Ltd.
+ *
+ * Author: Jun Nie <jun.nie@linaro.org>
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+static void __iomem *base;
+static void __iomem *pcu_base;
+
+static int zx_restart_handler(struct notifier_block *this,
+                             unsigned long mode, void *cmd)
+{
+       writel_relaxed(1, base + 0xb0);
+       writel_relaxed(1, pcu_base + 0x34);
+
+       mdelay(50);
+       pr_emerg("Unable to restart system\n");
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block zx_restart_nb = {
+       .notifier_call = zx_restart_handler,
+       .priority = 128,
+};
+
+static int zx_reboot_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int err;
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               WARN(1, "failed to map base address");
+               return -ENODEV;
+       }
+
+       np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu");
+       pcu_base = of_iomap(np, 0);
+       if (!pcu_base) {
+               iounmap(base);
+               WARN(1, "failed to map pcu_base address");
+               return -ENODEV;
+       }
+
+       err = register_restart_handler(&zx_restart_nb);
+       if (err)
+               dev_err(&pdev->dev, "Register restart handler failed(err=%d)\n",
+                       err);
+
+       return err;
+}
+
+static const struct of_device_id zx_reboot_of_match[] = {
+       { .compatible = "zte,sysctrl" },
+       {}
+};
+
+static struct platform_driver zx_reboot_driver = {
+       .probe = zx_reboot_probe,
+       .driver = {
+               .name = "zx-reboot",
+               .of_match_table = zx_reboot_of_match,
+       },
+};
+module_platform_driver(zx_reboot_driver);
index a7a6877b4e1660fdf39841e4491c07be2d903a57..bcdd8304849291e6f1ddcbcfa0725cc4e05ce47e 100644 (file)
@@ -165,7 +165,7 @@ static const struct i2c_device_id rt5033_battery_id[] = {
        { "rt5033-battery", },
        { }
 };
-MODULE_DEVICE_TABLE(platform, rt5033_battery_id);
+MODULE_DEVICE_TABLE(i2c, rt5033_battery_id);
 
 static struct i2c_driver rt5033_battery_driver = {
        .driver = {
index 08baac6e3adaa187a7393375a19aa3b3ec772737..a49a9d44bdda84dce49166280c12bbd7fb125bf6 100644 (file)
@@ -973,7 +973,6 @@ static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info,
 
        if (irq2 & GET_MASK(F_CHRVPI)) {
                dev_dbg(dev, "Charger fault occurred\n");
-               alert_userspace = true;
                /*
                 * CHRVPI bit is set in 2 cases:
                 * 1. when the power source is connected to the charger.
@@ -981,6 +980,9 @@ static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info,
                 * To identify the case, PWR_RDY bit is checked. Because
                 * PWR_RDY bit is set / cleared after CHRVPI interrupt is
                 * triggered, it is used delayed_work to later read PWR_RDY bit.
+                * Also, do not set to true alert_userspace, because there is no
+                * need to notify userspace when CHRVPI interrupt has occurred.
+                * Userspace will be notified after PWR_RDY bit is read.
                 */
                queue_delayed_work(system_power_efficient_wq,
                                   &info->pwr_rdy_work,
@@ -1178,7 +1180,7 @@ static irqreturn_t rt9455_irq_handler_thread(int irq, void *data)
                /*
                 * Sometimes, an interrupt occurs while rt9455_probe() function
                 * is executing and power_supply_register() is not yet called.
-                * Do not call power_supply_charged() in this case.
+                * Do not call power_supply_changed() in this case.
                 */
                if (info->charger)
                        power_supply_changed(info->charger);
@@ -1478,6 +1480,11 @@ static void rt9455_pwr_rdy_work_callback(struct work_struct *work)
                                   RT9455_MAX_CHARGING_TIME * HZ);
                break;
        }
+       /*
+        * Notify userspace that the charger has been either connected to or
+        * disconnected from the power source.
+        */
+       power_supply_changed(info->charger);
 }
 
 static void rt9455_max_charging_time_work_callback(struct work_struct *work)
@@ -1533,6 +1540,11 @@ static void rt9455_batt_presence_work_callback(struct work_struct *work)
                        if (ret)
                                dev_err(dev, "Failed to unmask BATAB interrupt\n");
                }
+               /*
+                * Notify userspace that the battery is now connected to the
+                * charger.
+                */
+               power_supply_changed(info->charger);
        }
 }
 
index ac6206951d5842235cdf167a69bca0f93c6b5bd3..af9383d23d122e36b99efb8868f9c84790f17267 100644 (file)
@@ -215,7 +215,7 @@ static int rx51_battery_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, di);
 
        di->dev = &pdev->dev;
-       di->bat_desc.name = dev_name(&pdev->dev);
+       di->bat_desc.name = "rx51-battery";
        di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
        di->bat_desc.properties = rx51_battery_props;
        di->bat_desc.num_properties = ARRAY_SIZE(rx51_battery_props);
index 022b8910e443510fdf1320891af7566e1db24b6f..f4f2c1f76c326d9093c9d9ea7587dd189aed5182 100644 (file)
 #include <linux/power_supply.h>
 #include <linux/notifier.h>
 #include <linux/usb/otg.h>
-#include <linux/regulator/machine.h>
+#include <linux/i2c/twl4030-madc.h>
 
+#define TWL4030_BCIMDEN                0x00
+#define TWL4030_BCIMDKEY       0x01
 #define TWL4030_BCIMSTATEC     0x02
 #define TWL4030_BCIICHG                0x08
 #define TWL4030_BCIVAC         0x0a
 #define TWL4030_BCIMFSTS4      0x10
 #define TWL4030_BCICTL1                0x23
 #define TWL4030_BB_CFG         0x12
+#define TWL4030_BCIIREF1       0x27
+#define TWL4030_BCIIREF2       0x28
+#define TWL4030_BCIMFKEY       0x11
+#define TWL4030_BCIMFEN3       0x14
+#define TWL4030_BCIMFTH8       0x1d
+#define TWL4030_BCIMFTH9       0x1e
+#define TWL4030_BCIWDKEY       0x21
 
 #define TWL4030_BCIMFSTS1      0x01
 
 #define TWL4030_BCIAUTOWEN     BIT(5)
 #define TWL4030_CONFIG_DONE    BIT(4)
+#define TWL4030_CVENAC         BIT(2)
 #define TWL4030_BCIAUTOUSB     BIT(1)
 #define TWL4030_BCIAUTOAC      BIT(0)
 #define TWL4030_CGAIN          BIT(5)
 #define TWL4030_MSTATEC_COMPLETE1      0x0b
 #define TWL4030_MSTATEC_COMPLETE4      0x0e
 
+#if IS_ENABLED(CONFIG_TWL4030_MADC)
+/*
+ * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
+ * then AC is available.
+ */
+static inline int ac_available(void)
+{
+       return twl4030_get_madc_conversion(11) > 4500;
+}
+#else
+static inline int ac_available(void)
+{
+       return 0;
+}
+#endif
 static bool allow_usb;
 module_param(allow_usb, bool, 0644);
 MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
@@ -94,12 +119,39 @@ struct twl4030_bci {
        struct work_struct      work;
        int                     irq_chg;
        int                     irq_bci;
-       struct regulator        *usb_reg;
        int                     usb_enabled;
 
+       /*
+        * ichg_* and *_cur values in uA. If any are 'large', we set
+        * CGAIN to '1' which doubles the range for half the
+        * precision.
+        */
+       unsigned int            ichg_eoc, ichg_lo, ichg_hi;
+       unsigned int            usb_cur, ac_cur;
+       bool                    ac_is_active;
+       int                     usb_mode, ac_mode; /* charging mode requested */
+#define        CHARGE_OFF      0
+#define        CHARGE_AUTO     1
+#define        CHARGE_LINEAR   2
+
+       /* When setting the USB current we slowly increase the
+        * requested current until target is reached or the voltage
+        * drops below 4.75V.  In the latter case we step back one
+        * step.
+        */
+       unsigned int            usb_cur_target;
+       struct delayed_work     current_worker;
+#define        USB_CUR_STEP    20000   /* 20mA at a time */
+#define        USB_MIN_VOLT    4750000 /* 4.75V */
+#define        USB_CUR_DELAY   msecs_to_jiffies(100)
+#define        USB_MAX_CURRENT 1700000 /* TWL4030 caps at 1.7A */
+
        unsigned long           event;
 };
 
+/* strings for 'usb_mode' values */
+static char *modes[] = { "off", "auto", "continuous" };
+
 /*
  * clear and set bits on an given register on a given module
  */
@@ -180,27 +232,233 @@ static int twl4030_is_battery_present(struct twl4030_bci *bci)
 }
 
 /*
- * Check if VBUS power is present
+ * TI provided formulas:
+ * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
+ * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
+ * Here we use integer approximation of:
+ * CGAIN == 0: val * 1.6618 - 0.85 * 1000
+ * CGAIN == 1: (val * 1.6618 - 0.85 * 1000) * 2
+ */
+/*
+ * convert twl register value for currents into uA
+ */
+static int regval2ua(int regval, bool cgain)
+{
+       if (cgain)
+               return (regval * 16618 - 8500 * 1000) / 5;
+       else
+               return (regval * 16618 - 8500 * 1000) / 10;
+}
+
+/*
+ * convert uA currents into twl register value
  */
-static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
+static int ua2regval(int ua, bool cgain)
 {
        int ret;
-       u8 hwsts;
+       if (cgain)
+               ua /= 2;
+       ret = (ua * 10 + 8500 * 1000) / 16618;
+       /* rounding problems */
+       if (ret < 512)
+               ret = 512;
+       return ret;
+}
 
-       ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &hwsts,
-                             TWL4030_PM_MASTER_STS_HW_CONDITIONS);
-       if (ret < 0)
-               return 0;
+static int twl4030_charger_update_current(struct twl4030_bci *bci)
+{
+       int status;
+       int cur;
+       unsigned reg, cur_reg;
+       u8 bcictl1, oldreg, fullreg;
+       bool cgain = false;
+       u8 boot_bci;
 
-       dev_dbg(bci->dev, "check_vbus: HW_CONDITIONS %02x\n", hwsts);
+       /*
+        * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
+        * and AC is enabled, set current for 'ac'
+        */
+       if (ac_available()) {
+               cur = bci->ac_cur;
+               bci->ac_is_active = true;
+       } else {
+               cur = bci->usb_cur;
+               bci->ac_is_active = false;
+               if (cur > bci->usb_cur_target) {
+                       cur = bci->usb_cur_target;
+                       bci->usb_cur = cur;
+               }
+               if (cur < bci->usb_cur_target)
+                       schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
+       }
+
+       /* First, check thresholds and see if cgain is needed */
+       if (bci->ichg_eoc >= 200000)
+               cgain = true;
+       if (bci->ichg_lo >= 400000)
+               cgain = true;
+       if (bci->ichg_hi >= 820000)
+               cgain = true;
+       if (cur > 852000)
+               cgain = true;
+
+       status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+       if (status < 0)
+               return status;
+       if (twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &boot_bci,
+                           TWL4030_PM_MASTER_BOOT_BCI) < 0)
+               boot_bci = 0;
+       boot_bci &= 7;
+
+       if ((!!cgain) != !!(bcictl1 & TWL4030_CGAIN))
+               /* Need to turn for charging while we change the
+                * CGAIN bit.  Leave it off while everything is
+                * updated.
+                */
+               twl4030_clear_set_boot_bci(boot_bci, 0);
+
+       /*
+        * For ichg_eoc, the hardware only supports reg values matching
+        * 100XXXX000, and requires the XXXX be stored in the high nibble
+        * of TWL4030_BCIMFTH8.
+        */
+       reg = ua2regval(bci->ichg_eoc, cgain);
+       if (reg > 0x278)
+               reg = 0x278;
+       if (reg < 0x200)
+               reg = 0x200;
+       reg = (reg >> 3) & 0xf;
+       fullreg = reg << 4;
+
+       /*
+        * For ichg_lo, reg value must match 10XXXX0000.
+        * XXXX is stored in low nibble of TWL4030_BCIMFTH8.
+        */
+       reg = ua2regval(bci->ichg_lo, cgain);
+       if (reg > 0x2F0)
+               reg = 0x2F0;
+       if (reg < 0x200)
+               reg = 0x200;
+       reg = (reg >> 4) & 0xf;
+       fullreg |= reg;
+
+       /* ichg_eoc and ichg_lo live in same register */
+       status = twl4030_bci_read(TWL4030_BCIMFTH8, &oldreg);
+       if (status < 0)
+               return status;
+       if (oldreg != fullreg) {
+               status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xF4,
+                                         TWL4030_BCIMFKEY);
+               if (status < 0)
+                       return status;
+               twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                                fullreg, TWL4030_BCIMFTH8);
+       }
 
-       /* in case we also have STS_USB_ID, VBUS is driven by TWL itself */
-       if ((hwsts & TWL4030_STS_VBUS) && !(hwsts & TWL4030_STS_USB_ID))
-               return 1;
+       /* ichg_hi threshold must be 1XXXX01100 (I think) */
+       reg = ua2regval(bci->ichg_hi, cgain);
+       if (reg > 0x3E0)
+               reg = 0x3E0;
+       if (reg < 0x200)
+               reg = 0x200;
+       fullreg = (reg >> 5) & 0xF;
+       fullreg <<= 4;
+       status = twl4030_bci_read(TWL4030_BCIMFTH9, &oldreg);
+       if (status < 0)
+               return status;
+       if ((oldreg & 0xF0) != fullreg) {
+               fullreg |= (oldreg & 0x0F);
+               status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+                                         TWL4030_BCIMFKEY);
+               if (status < 0)
+                       return status;
+               twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                                fullreg, TWL4030_BCIMFTH9);
+       }
 
+       /*
+        * And finally, set the current.  This is stored in
+        * two registers.
+        */
+       reg = ua2regval(cur, cgain);
+       /* we have only 10 bits */
+       if (reg > 0x3ff)
+               reg = 0x3ff;
+       status = twl4030_bci_read(TWL4030_BCIIREF1, &oldreg);
+       if (status < 0)
+               return status;
+       cur_reg = oldreg;
+       status = twl4030_bci_read(TWL4030_BCIIREF2, &oldreg);
+       if (status < 0)
+               return status;
+       cur_reg |= oldreg << 8;
+       if (reg != oldreg) {
+               /* disable write protection for one write access for
+                * BCIIREF */
+               status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+                                         TWL4030_BCIMFKEY);
+               if (status < 0)
+                       return status;
+               status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                                         (reg & 0x100) ? 3 : 2,
+                                         TWL4030_BCIIREF2);
+               if (status < 0)
+                       return status;
+               /* disable write protection for one write access for
+                * BCIIREF */
+               status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
+                                         TWL4030_BCIMFKEY);
+               if (status < 0)
+                       return status;
+               status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                                         reg & 0xff,
+                                         TWL4030_BCIIREF1);
+       }
+       if ((!!cgain) != !!(bcictl1 & TWL4030_CGAIN)) {
+               /* Flip CGAIN and re-enable charging */
+               bcictl1 ^= TWL4030_CGAIN;
+               twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
+                                bcictl1, TWL4030_BCICTL1);
+               twl4030_clear_set_boot_bci(0, boot_bci);
+       }
        return 0;
 }
 
+static int twl4030_charger_get_current(void);
+
+static void twl4030_current_worker(struct work_struct *data)
+{
+       int v, curr;
+       int res;
+       struct twl4030_bci *bci = container_of(data, struct twl4030_bci,
+                                              current_worker.work);
+
+       res = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
+       if (res < 0)
+               v = 0;
+       else
+               /* BCIVBUS uses ADCIN8, 7/1023 V/step */
+               v = res * 6843;
+       curr = twl4030_charger_get_current();
+
+       dev_dbg(bci->dev, "v=%d cur=%d limit=%d target=%d\n", v, curr,
+               bci->usb_cur, bci->usb_cur_target);
+
+       if (v < USB_MIN_VOLT) {
+               /* Back up and stop adjusting. */
+               bci->usb_cur -= USB_CUR_STEP;
+               bci->usb_cur_target = bci->usb_cur;
+       } else if (bci->usb_cur >= bci->usb_cur_target ||
+                  bci->usb_cur + USB_CUR_STEP > USB_MAX_CURRENT) {
+               /* Reached target and voltage is OK - stop */
+               return;
+       } else {
+               bci->usb_cur += USB_CUR_STEP;
+               schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
+       }
+       twl4030_charger_update_current(bci);
+}
+
 /*
  * Enable/Disable USB Charge functionality.
  */
@@ -208,45 +466,60 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 {
        int ret;
 
-       if (enable) {
-               /* Check for USB charger connected */
-               if (!twl4030_bci_have_vbus(bci))
-                       return -ENODEV;
+       if (bci->usb_mode == CHARGE_OFF)
+               enable = false;
+       if (enable && !IS_ERR_OR_NULL(bci->transceiver)) {
 
-               /*
-                * Until we can find out what current the device can provide,
-                * require a module param to enable USB charging.
-                */
-               if (!allow_usb) {
-                       dev_warn(bci->dev, "USB charging is disabled.\n");
-                       return -EACCES;
-               }
+               twl4030_charger_update_current(bci);
 
-               /* Need to keep regulator on */
+               /* Need to keep phy powered */
                if (!bci->usb_enabled) {
-                       ret = regulator_enable(bci->usb_reg);
-                       if (ret) {
-                               dev_err(bci->dev,
-                                       "Failed to enable regulator\n");
-                               return ret;
-                       }
+                       pm_runtime_get_sync(bci->transceiver->dev);
                        bci->usb_enabled = 1;
                }
 
-               /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
-               ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
-               if (ret < 0)
-                       return ret;
+               if (bci->usb_mode == CHARGE_AUTO)
+                       /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
+                       ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
 
                /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
                ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0,
                        TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
+               if (bci->usb_mode == CHARGE_LINEAR) {
+                       twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0);
+                       /* Watch dog key: WOVF acknowledge */
+                       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33,
+                                              TWL4030_BCIWDKEY);
+                       /* 0x24 + EKEY6: off mode */
+                       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+                                              TWL4030_BCIMDKEY);
+                       /* EKEY2: Linear charge: USB path */
+                       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x26,
+                                              TWL4030_BCIMDKEY);
+                       /* WDKEY5: stop watchdog count */
+                       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf3,
+                                              TWL4030_BCIWDKEY);
+                       /* enable MFEN3 access */
+                       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x9c,
+                                              TWL4030_BCIMFKEY);
+                        /* ICHGEOCEN - end-of-charge monitor (current < 80mA)
+                         *                      (charging continues)
+                         * ICHGLOWEN - current level monitor (charge continues)
+                         * don't monitor over-current or heat save
+                         */
+                       ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xf0,
+                                              TWL4030_BCIMFEN3);
+               }
        } else {
                ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
+               ret |= twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x2a,
+                                       TWL4030_BCIMDKEY);
                if (bci->usb_enabled) {
-                       regulator_disable(bci->usb_reg);
+                       pm_runtime_mark_last_busy(bci->transceiver->dev);
+                       pm_runtime_put_autosuspend(bci->transceiver->dev);
                        bci->usb_enabled = 0;
                }
+               bci->usb_cur = 0;
        }
 
        return ret;
@@ -255,10 +528,13 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
 /*
  * Enable/Disable AC Charge funtionality.
  */
-static int twl4030_charger_enable_ac(bool enable)
+static int twl4030_charger_enable_ac(struct twl4030_bci *bci, bool enable)
 {
        int ret;
 
+       if (bci->ac_mode == CHARGE_OFF)
+               enable = false;
+
        if (enable)
                ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
        else
@@ -318,6 +594,9 @@ static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
        struct twl4030_bci *bci = arg;
 
        dev_dbg(bci->dev, "CHG_PRES irq\n");
+       /* reset current on each 'plug' event */
+       bci->ac_cur = 500000;
+       twl4030_charger_update_current(bci);
        power_supply_changed(bci->ac);
        power_supply_changed(bci->usb);
 
@@ -350,6 +629,7 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
                power_supply_changed(bci->ac);
                power_supply_changed(bci->usb);
        }
+       twl4030_charger_update_current(bci);
 
        /* various monitoring events, for now we just log them here */
        if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
@@ -370,6 +650,63 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
+/*
+ * Provide "max_current" attribute in sysfs.
+ */
+static ssize_t
+twl4030_bci_max_current_store(struct device *dev, struct device_attribute *attr,
+       const char *buf, size_t n)
+{
+       struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+       int cur = 0;
+       int status = 0;
+       status = kstrtoint(buf, 10, &cur);
+       if (status)
+               return status;
+       if (cur < 0)
+               return -EINVAL;
+       if (dev == &bci->ac->dev)
+               bci->ac_cur = cur;
+       else
+               bci->usb_cur_target = cur;
+
+       twl4030_charger_update_current(bci);
+       return n;
+}
+
+/*
+ * sysfs max_current show
+ */
+static ssize_t twl4030_bci_max_current_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       int status = 0;
+       int cur = -1;
+       u8 bcictl1;
+       struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+
+       if (dev == &bci->ac->dev) {
+               if (!bci->ac_is_active)
+                       cur = bci->ac_cur;
+       } else {
+               if (bci->ac_is_active)
+                       cur = bci->usb_cur_target;
+       }
+       if (cur < 0) {
+               cur = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
+               if (cur < 0)
+                       return cur;
+               status = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+               if (status < 0)
+                       return status;
+               cur = regval2ua(cur, bcictl1 & TWL4030_CGAIN);
+       }
+       return scnprintf(buf, PAGE_SIZE, "%u\n", cur);
+}
+
+static DEVICE_ATTR(max_current, 0644, twl4030_bci_max_current_show,
+                       twl4030_bci_max_current_store);
+
 static void twl4030_bci_usb_work(struct work_struct *data)
 {
        struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
@@ -392,6 +729,12 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 
        dev_dbg(bci->dev, "OTG notify %lu\n", val);
 
+       /* reset current on each 'plug' event */
+       if (allow_usb)
+               bci->usb_cur_target = 500000;
+       else
+               bci->usb_cur_target = 100000;
+
        bci->event = val;
        schedule_work(&bci->work);
 
@@ -399,13 +742,66 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
 }
 
 /*
- * TI provided formulas:
- * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
- * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
- * Here we use integer approximation of:
- * CGAIN == 0: val * 1.6618 - 0.85
- * CGAIN == 1: (val * 1.6618 - 0.85) * 2
+ * sysfs charger enabled store
+ */
+static ssize_t
+twl4030_bci_mode_store(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t n)
+{
+       struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+       int mode;
+       int status;
+
+       if (sysfs_streq(buf, modes[0]))
+               mode = 0;
+       else if (sysfs_streq(buf, modes[1]))
+               mode = 1;
+       else if (sysfs_streq(buf, modes[2]))
+               mode = 2;
+       else
+               return -EINVAL;
+       if (dev == &bci->ac->dev) {
+               if (mode == 2)
+                       return -EINVAL;
+               twl4030_charger_enable_ac(bci, false);
+               bci->ac_mode = mode;
+               status = twl4030_charger_enable_ac(bci, true);
+       } else {
+               twl4030_charger_enable_usb(bci, false);
+               bci->usb_mode = mode;
+               status = twl4030_charger_enable_usb(bci, true);
+       }
+       return (status == 0) ? n : status;
+}
+
+/*
+ * sysfs charger enabled show
  */
+static ssize_t
+twl4030_bci_mode_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct twl4030_bci *bci = dev_get_drvdata(dev->parent);
+       int len = 0;
+       int i;
+       int mode = bci->usb_mode;
+
+       if (dev == &bci->ac->dev)
+               mode = bci->ac_mode;
+
+       for (i = 0; i < ARRAY_SIZE(modes); i++)
+               if (mode == i)
+                       len += snprintf(buf+len, PAGE_SIZE-len,
+                                       "[%s] ", modes[i]);
+               else
+                       len += snprintf(buf+len, PAGE_SIZE-len,
+                                       "%s ", modes[i]);
+       buf[len-1] = '\n';
+       return len;
+}
+static DEVICE_ATTR(mode, 0644, twl4030_bci_mode_show,
+                  twl4030_bci_mode_store);
+
 static int twl4030_charger_get_current(void)
 {
        int curr;
@@ -420,11 +816,7 @@ static int twl4030_charger_get_current(void)
        if (ret)
                return ret;
 
-       ret = (curr * 16618 - 850 * 10000) / 10;
-       if (bcictl1 & TWL4030_CGAIN)
-               ret *= 2;
-
-       return ret;
+       return regval2ua(curr, bcictl1 & TWL4030_CGAIN);
 }
 
 /*
@@ -476,6 +868,17 @@ static int twl4030_bci_get_property(struct power_supply *psy,
                is_charging = state & TWL4030_MSTATEC_USB;
        else
                is_charging = state & TWL4030_MSTATEC_AC;
+       if (!is_charging) {
+               u8 s;
+               twl4030_bci_read(TWL4030_BCIMDEN, &s);
+               if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
+                       is_charging = s & 1;
+               else
+                       is_charging = s & 2;
+               if (is_charging)
+                       /* A little white lie */
+                       state = TWL4030_MSTATEC_QUICK1;
+       }
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
@@ -574,20 +977,31 @@ static const struct power_supply_desc twl4030_bci_usb_desc = {
        .get_property   = twl4030_bci_get_property,
 };
 
-static int __init twl4030_bci_probe(struct platform_device *pdev)
+static int twl4030_bci_probe(struct platform_device *pdev)
 {
        struct twl4030_bci *bci;
        const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
        int ret;
        u32 reg;
 
-       bci = kzalloc(sizeof(*bci), GFP_KERNEL);
+       bci = devm_kzalloc(&pdev->dev, sizeof(*bci), GFP_KERNEL);
        if (bci == NULL)
                return -ENOMEM;
 
        if (!pdata)
                pdata = twl4030_bci_parse_dt(&pdev->dev);
 
+       bci->ichg_eoc = 80100; /* Stop charging when current drops to here */
+       bci->ichg_lo = 241000; /* Low threshold */
+       bci->ichg_hi = 500000; /* High threshold */
+       bci->ac_cur = 500000; /* 500mA */
+       if (allow_usb)
+               bci->usb_cur_target = 500000;  /* 500mA */
+       else
+               bci->usb_cur_target = 100000;  /* 100mA */
+       bci->usb_mode = CHARGE_AUTO;
+       bci->ac_mode = CHARGE_AUTO;
+
        bci->dev = &pdev->dev;
        bci->irq_chg = platform_get_irq(pdev, 0);
        bci->irq_bci = platform_get_irq(pdev, 1);
@@ -596,47 +1010,46 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        ret = twl4030_is_battery_present(bci);
        if  (ret) {
                dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
-               goto fail_no_battery;
+               return ret;
        }
 
        platform_set_drvdata(pdev, bci);
 
-       bci->ac = power_supply_register(&pdev->dev, &twl4030_bci_ac_desc,
-                                       NULL);
+       bci->ac = devm_power_supply_register(&pdev->dev, &twl4030_bci_ac_desc,
+                                            NULL);
        if (IS_ERR(bci->ac)) {
                ret = PTR_ERR(bci->ac);
                dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
-               goto fail_register_ac;
+               return ret;
        }
 
-       bci->usb_reg = regulator_get(bci->dev, "bci3v1");
-
-       bci->usb = power_supply_register(&pdev->dev, &twl4030_bci_usb_desc,
-                                        NULL);
+       bci->usb = devm_power_supply_register(&pdev->dev, &twl4030_bci_usb_desc,
+                                             NULL);
        if (IS_ERR(bci->usb)) {
                ret = PTR_ERR(bci->usb);
                dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
-               goto fail_register_usb;
+               return ret;
        }
 
-       ret = request_threaded_irq(bci->irq_chg, NULL,
+       ret = devm_request_threaded_irq(&pdev->dev, bci->irq_chg, NULL,
                        twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
                        bci);
        if (ret < 0) {
                dev_err(&pdev->dev, "could not request irq %d, status %d\n",
                        bci->irq_chg, ret);
-               goto fail_chg_irq;
+               return ret;
        }
 
-       ret = request_threaded_irq(bci->irq_bci, NULL,
+       ret = devm_request_threaded_irq(&pdev->dev, bci->irq_bci, NULL,
                        twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
        if (ret < 0) {
                dev_err(&pdev->dev, "could not request irq %d, status %d\n",
                        bci->irq_bci, ret);
-               goto fail_bci_irq;
+               return ret;
        }
 
        INIT_WORK(&bci->work, twl4030_bci_usb_work);
+       INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker);
 
        bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
        if (bci->dev->of_node) {
@@ -644,9 +1057,13 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
 
                phynode = of_find_compatible_node(bci->dev->of_node->parent,
                                                  NULL, "ti,twl4030-usb");
-               if (phynode)
+               if (phynode) {
                        bci->transceiver = devm_usb_get_phy_by_node(
                                bci->dev, phynode, &bci->usb_nb);
+                       if (IS_ERR(bci->transceiver) &&
+                           PTR_ERR(bci->transceiver) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+               }
        }
 
        /* Enable interrupts now. */
@@ -656,7 +1073,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
                               TWL4030_INTERRUPTS_BCIIMR1A);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
-               goto fail_unmask_interrupts;
+               return ret;
        }
 
        reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
@@ -665,8 +1082,23 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        if (ret < 0)
                dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
 
-       twl4030_charger_enable_ac(true);
-       twl4030_charger_enable_usb(bci, true);
+       twl4030_charger_update_current(bci);
+       if (device_create_file(&bci->usb->dev, &dev_attr_max_current))
+               dev_warn(&pdev->dev, "could not create sysfs file\n");
+       if (device_create_file(&bci->usb->dev, &dev_attr_mode))
+               dev_warn(&pdev->dev, "could not create sysfs file\n");
+       if (device_create_file(&bci->ac->dev, &dev_attr_mode))
+               dev_warn(&pdev->dev, "could not create sysfs file\n");
+       if (device_create_file(&bci->ac->dev, &dev_attr_max_current))
+               dev_warn(&pdev->dev, "could not create sysfs file\n");
+
+       twl4030_charger_enable_ac(bci, true);
+       if (!IS_ERR_OR_NULL(bci->transceiver))
+               twl4030_bci_usb_ncb(&bci->usb_nb,
+                                   bci->transceiver->last_event,
+                                   NULL);
+       else
+               twl4030_charger_enable_usb(bci, false);
        if (pdata)
                twl4030_charger_enable_backup(pdata->bb_uvolt,
                                              pdata->bb_uamp);
@@ -674,42 +1106,26 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
                twl4030_charger_enable_backup(0, 0);
 
        return 0;
-
-fail_unmask_interrupts:
-       free_irq(bci->irq_bci, bci);
-fail_bci_irq:
-       free_irq(bci->irq_chg, bci);
-fail_chg_irq:
-       power_supply_unregister(bci->usb);
-fail_register_usb:
-       power_supply_unregister(bci->ac);
-fail_register_ac:
-fail_no_battery:
-       kfree(bci);
-
-       return ret;
 }
 
 static int __exit twl4030_bci_remove(struct platform_device *pdev)
 {
        struct twl4030_bci *bci = platform_get_drvdata(pdev);
 
-       twl4030_charger_enable_ac(false);
+       twl4030_charger_enable_ac(bci, false);
        twl4030_charger_enable_usb(bci, false);
        twl4030_charger_enable_backup(0, 0);
 
+       device_remove_file(&bci->usb->dev, &dev_attr_max_current);
+       device_remove_file(&bci->usb->dev, &dev_attr_mode);
+       device_remove_file(&bci->ac->dev, &dev_attr_max_current);
+       device_remove_file(&bci->ac->dev, &dev_attr_mode);
        /* mask interrupts */
        twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
                         TWL4030_INTERRUPTS_BCIIMR1A);
        twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
                         TWL4030_INTERRUPTS_BCIIMR2A);
 
-       free_irq(bci->irq_bci, bci);
-       free_irq(bci->irq_chg, bci);
-       power_supply_unregister(bci->usb);
-       power_supply_unregister(bci->ac);
-       kfree(bci);
-
        return 0;
 }
 
@@ -720,14 +1136,14 @@ static const struct of_device_id twl_bci_of_match[] = {
 MODULE_DEVICE_TABLE(of, twl_bci_of_match);
 
 static struct platform_driver twl4030_bci_driver = {
+       .probe = twl4030_bci_probe,
        .driver = {
                .name   = "twl4030_bci",
                .of_match_table = of_match_ptr(twl_bci_of_match),
        },
        .remove = __exit_p(twl4030_bci_remove),
 };
-
-module_platform_driver_probe(twl4030_bci_driver, twl4030_bci_probe);
+module_platform_driver(twl4030_bci_driver);
 
 MODULE_AUTHOR("Gražvydas Ignotas");
 MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
index 7fd4f511d78fd6bdc685c857e280f1581d20b035..a62a89674fb5f6f82b8223067a6e1ff2b62ade21 100644 (file)
@@ -78,7 +78,6 @@ struct pm800_regulator_info {
 };
 
 struct pm800_regulators {
-       struct regulator_dev *regulators[PM800_ID_RG_MAX];
        struct pm80x_chip *chip;
        struct regmap *map;
 };
@@ -92,14 +91,16 @@ struct pm800_regulators {
  * not the constant voltage table.
  * n_volt - Number of available selectors
  */
-#define PM800_BUCK(vreg, ereg, ebit, amax, volt_ranges, n_volt)                \
+#define PM800_BUCK(match, vreg, ereg, ebit, amax, volt_ranges, n_volt) \
 {                                                                      \
        .desc   = {                                                     \
-               .name   = #vreg,                                        \
-               .ops    = &pm800_volt_range_ops,                        \
-               .type   = REGULATOR_VOLTAGE,                            \
-               .id     = PM800_ID_##vreg,                              \
-               .owner  = THIS_MODULE,                                  \
+               .name                   = #vreg,                        \
+               .of_match               = of_match_ptr(#match),         \
+               .regulators_node        = of_match_ptr("regulators"),   \
+               .ops                    = &pm800_volt_range_ops,        \
+               .type                   = REGULATOR_VOLTAGE,            \
+               .id                     = PM800_ID_##vreg,              \
+               .owner                  = THIS_MODULE,                  \
                .n_voltages             = n_volt,                       \
                .linear_ranges          = volt_ranges,                  \
                .n_linear_ranges        = ARRAY_SIZE(volt_ranges),      \
@@ -108,7 +109,7 @@ struct pm800_regulators {
                .enable_reg             = PM800_##ereg,                 \
                .enable_mask            = 1 << (ebit),                  \
        },                                                              \
-       .max_ua         = (amax),                                       \
+       .max_ua = (amax),                                               \
 }
 
 /*
@@ -120,22 +121,24 @@ struct pm800_regulators {
  * For all the LDOes, there are too many ranges. Using volt_table will be
  * simpler and faster.
  */
-#define PM800_LDO(vreg, ereg, ebit, amax, ldo_volt_table)              \
+#define PM800_LDO(match, vreg, ereg, ebit, amax, ldo_volt_table)       \
 {                                                                      \
        .desc   = {                                                     \
-               .name   = #vreg,                                        \
-               .ops    = &pm800_volt_table_ops,                        \
-               .type   = REGULATOR_VOLTAGE,                            \
-               .id     = PM800_ID_##vreg,                              \
-               .owner  = THIS_MODULE,                                  \
-               .n_voltages = ARRAY_SIZE(ldo_volt_table),               \
-               .vsel_reg       = PM800_##vreg##_VOUT,                  \
-               .vsel_mask      = 0xf,                                  \
-               .enable_reg     = PM800_##ereg,                         \
-               .enable_mask    = 1 << (ebit),                          \
-               .volt_table     = ldo_volt_table,                       \
+               .name                   = #vreg,                        \
+               .of_match               = of_match_ptr(#match),         \
+               .regulators_node        = of_match_ptr("regulators"),   \
+               .ops                    = &pm800_volt_table_ops,        \
+               .type                   = REGULATOR_VOLTAGE,            \
+               .id                     = PM800_ID_##vreg,              \
+               .owner                  = THIS_MODULE,                  \
+               .n_voltages             = ARRAY_SIZE(ldo_volt_table),   \
+               .vsel_reg               = PM800_##vreg##_VOUT,          \
+               .vsel_mask              = 0xf,                          \
+               .enable_reg             = PM800_##ereg,                 \
+               .enable_mask            = 1 << (ebit),                  \
+               .volt_table             = ldo_volt_table,               \
        },                                                              \
-       .max_ua         = (amax),                                       \
+       .max_ua = (amax),                                               \
 }
 
 /* Ranges are sorted in ascending order. */
@@ -178,122 +181,66 @@ static int pm800_get_current_limit(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops pm800_volt_range_ops = {
-       .list_voltage = regulator_list_voltage_linear_range,
-       .map_voltage = regulator_map_voltage_linear_range,
-       .set_voltage_sel = regulator_set_voltage_sel_regmap,
-       .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
-       .get_current_limit = pm800_get_current_limit,
+       .list_voltage           = regulator_list_voltage_linear_range,
+       .map_voltage            = regulator_map_voltage_linear_range,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .get_current_limit      = pm800_get_current_limit,
 };
 
 static struct regulator_ops pm800_volt_table_ops = {
-       .list_voltage = regulator_list_voltage_table,
-       .map_voltage = regulator_map_voltage_iterate,
-       .set_voltage_sel = regulator_set_voltage_sel_regmap,
-       .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
-       .get_current_limit = pm800_get_current_limit,
+       .list_voltage           = regulator_list_voltage_table,
+       .map_voltage            = regulator_map_voltage_iterate,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .get_current_limit      = pm800_get_current_limit,
 };
 
 /* The array is indexed by id(PM800_ID_XXX) */
 static struct pm800_regulator_info pm800_regulator_info[] = {
-       PM800_BUCK(BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55),
-       PM800_BUCK(BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73),
-       PM800_BUCK(BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73),
-       PM800_BUCK(BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73),
-       PM800_BUCK(BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73),
-
-       PM800_LDO(LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table),
-       PM800_LDO(LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table),
-       PM800_LDO(LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table),
-       PM800_LDO(LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table),
-       PM800_LDO(LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table),
-};
-
-#define PM800_REGULATOR_OF_MATCH(_name, _id)                           \
-       [PM800_ID_##_id] = {                                            \
-               .name = #_name,                                         \
-               .driver_data = &pm800_regulator_info[PM800_ID_##_id],   \
-       }
-
-static struct of_regulator_match pm800_regulator_matches[] = {
-       PM800_REGULATOR_OF_MATCH(buck1, BUCK1),
-       PM800_REGULATOR_OF_MATCH(buck2, BUCK2),
-       PM800_REGULATOR_OF_MATCH(buck3, BUCK3),
-       PM800_REGULATOR_OF_MATCH(buck4, BUCK4),
-       PM800_REGULATOR_OF_MATCH(buck5, BUCK5),
-       PM800_REGULATOR_OF_MATCH(ldo1, LDO1),
-       PM800_REGULATOR_OF_MATCH(ldo2, LDO2),
-       PM800_REGULATOR_OF_MATCH(ldo3, LDO3),
-       PM800_REGULATOR_OF_MATCH(ldo4, LDO4),
-       PM800_REGULATOR_OF_MATCH(ldo5, LDO5),
-       PM800_REGULATOR_OF_MATCH(ldo6, LDO6),
-       PM800_REGULATOR_OF_MATCH(ldo7, LDO7),
-       PM800_REGULATOR_OF_MATCH(ldo8, LDO8),
-       PM800_REGULATOR_OF_MATCH(ldo9, LDO9),
-       PM800_REGULATOR_OF_MATCH(ldo10, LDO10),
-       PM800_REGULATOR_OF_MATCH(ldo11, LDO11),
-       PM800_REGULATOR_OF_MATCH(ldo12, LDO12),
-       PM800_REGULATOR_OF_MATCH(ldo13, LDO13),
-       PM800_REGULATOR_OF_MATCH(ldo14, LDO14),
-       PM800_REGULATOR_OF_MATCH(ldo15, LDO15),
-       PM800_REGULATOR_OF_MATCH(ldo16, LDO16),
-       PM800_REGULATOR_OF_MATCH(ldo17, LDO17),
-       PM800_REGULATOR_OF_MATCH(ldo18, LDO18),
-       PM800_REGULATOR_OF_MATCH(ldo19, LDO19),
+       PM800_BUCK(buck1, BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55),
+       PM800_BUCK(buck2, BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73),
+       PM800_BUCK(buck3, BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73),
+       PM800_BUCK(buck4, BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73),
+       PM800_BUCK(buck5, BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73),
+
+       PM800_LDO(ldo1, LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table),
+       PM800_LDO(ldo2, LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table),
+       PM800_LDO(ldo3, LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo4, LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo5, LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo6, LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo7, LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo8, LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo9, LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo10, LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo11, LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo12, LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo13, LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo14, LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo15, LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo16, LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo17, LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table),
+       PM800_LDO(ldo18, LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table),
+       PM800_LDO(ldo19, LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table),
 };
 
-static int pm800_regulator_dt_init(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       int ret;
-
-       ret = of_regulator_match(&pdev->dev, np,
-                                pm800_regulator_matches,
-                                ARRAY_SIZE(pm800_regulator_matches));
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
 static int pm800_regulator_probe(struct platform_device *pdev)
 {
        struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm80x_platform_data *pdata = dev_get_platdata(pdev->dev.parent);
        struct pm800_regulators *pm800_data;
-       struct pm800_regulator_info *info;
        struct regulator_config config = { };
        struct regulator_init_data *init_data;
        int i, ret;
 
-       if (!pdata || pdata->num_regulators == 0) {
-               if (IS_ENABLED(CONFIG_OF)) {
-                       ret = pm800_regulator_dt_init(pdev);
-                       if (ret)
-                               return ret;
-               } else {
-                       return -ENODEV;
-               }
-       } else if (pdata->num_regulators) {
+       if (pdata && pdata->num_regulators) {
                unsigned int count = 0;
 
                /* Check whether num_regulator is valid. */
@@ -303,8 +250,6 @@ static int pm800_regulator_probe(struct platform_device *pdev)
                }
                if (count != pdata->num_regulators)
                        return -EINVAL;
-       } else {
-               return -EINVAL;
        }
 
        pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data),
@@ -317,30 +262,27 @@ static int pm800_regulator_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, pm800_data);
 
+       config.dev = chip->dev;
+       config.regmap = pm800_data->map;
        for (i = 0; i < PM800_ID_RG_MAX; i++) {
-               if (!pdata || pdata->num_regulators == 0)
-                       init_data = pm800_regulator_matches[i].init_data;
-               else
+               struct regulator_dev *regulator;
+
+               if (pdata && pdata->num_regulators) {
                        init_data = pdata->regulators[i];
-               if (!init_data)
-                       continue;
-               info = pm800_regulator_matches[i].driver_data;
-               config.dev = &pdev->dev;
-               config.init_data = init_data;
-               config.driver_data = info;
-               config.regmap = pm800_data->map;
-               config.of_node = pm800_regulator_matches[i].of_node;
-
-               pm800_data->regulators[i] =
-                               regulator_register(&info->desc, &config);
-               if (IS_ERR(pm800_data->regulators[i])) {
-                       ret = PTR_ERR(pm800_data->regulators[i]);
-                       dev_err(&pdev->dev, "Failed to register %s\n",
-                               info->desc.name);
+                       if (!init_data)
+                               continue;
 
-                       while (--i >= 0)
-                               regulator_unregister(pm800_data->regulators[i]);
+                       config.init_data = init_data;
+               }
+
+               config.driver_data = &pm800_regulator_info[i];
 
+               regulator = devm_regulator_register(&pdev->dev,
+                               &pm800_regulator_info[i].desc, &config);
+               if (IS_ERR(regulator)) {
+                       ret = PTR_ERR(regulator);
+                       dev_err(&pdev->dev, "Failed to register %s\n",
+                                       pm800_regulator_info[i].desc.name);
                        return ret;
                }
        }
@@ -348,23 +290,11 @@ static int pm800_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pm800_regulator_remove(struct platform_device *pdev)
-{
-       struct pm800_regulators *pm800_data = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < PM800_ID_RG_MAX; i++)
-               regulator_unregister(pm800_data->regulators[i]);
-
-       return 0;
-}
-
 static struct platform_driver pm800_regulator_driver = {
        .driver         = {
                .name   = "88pm80x-regulator",
        },
        .probe          = pm800_regulator_probe,
-       .remove         = pm800_regulator_remove,
 };
 
 module_platform_driver(pm800_regulator_driver);
index bef3bde6971b0425d2632b54d2f1bb447c643ce4..64bccff557be16fdf8f667d3bc518793a985cd52 100644 (file)
@@ -209,13 +209,13 @@ config REGULATOR_DA9210
          interface.
 
 config REGULATOR_DA9211
-       tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214 regulator"
+       tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214/DA9215 regulator"
        depends on I2C
        select REGMAP_I2C
        help
          Say y here to support for the Dialog Semiconductor DA9211/DA9212
-         /DA9213/DA9214.
-         The DA9211/DA9212/DA9213/DA9214 is a multi-phase synchronous
+         /DA9213/DA9214/DA9215.
+         The DA9211/DA9212/DA9213/DA9214/DA9215 is a multi-phase synchronous
          step down converter 12A or 16A DC-DC Buck controlled through an I2C
          interface.
 
@@ -407,13 +407,13 @@ config REGULATOR_MAX77686
          Exynos-4 chips to control VARM and VINT voltages.
 
 config REGULATOR_MAX77693
-       tristate "Maxim MAX77693 regulator"
-       depends on MFD_MAX77693
+       tristate "Maxim 77693/77843 regulator"
+       depends on (MFD_MAX77693 || MFD_MAX77843)
        help
-         This driver controls a Maxim 77693 regulator via I2C bus.
+         This driver controls a Maxim 77693/77843 regulators via I2C bus.
          The regulators include two LDOs, 'SAFEOUT1', 'SAFEOUT2'
          and one current regulator 'CHARGER'. This is suitable for
-         Exynos-4x12 chips.
+         Exynos-4x12 (MAX77693) or Exynos5433 (MAX77843) SoC chips.
 
 config REGULATOR_MAX77802
        tristate "Maxim 77802 regulator"
@@ -424,14 +424,6 @@ config REGULATOR_MAX77802
          Exynos5420/Exynos5800 SoCs to control various voltages.
          It includes support for control of voltage and ramp speed.
 
-config REGULATOR_MAX77843
-       tristate "Maxim 77843 regulator"
-       depends on MFD_MAX77843
-       help
-         This driver controls a Maxim 77843 regulator.
-         The regulator include two 'SAFEOUT' for USB(Universal Serial Bus)
-         This is suitable for Exynos5433 SoC chips.
-
 config REGULATOR_MC13XXX_CORE
        tristate
 
@@ -451,6 +443,15 @@ config REGULATOR_MC13892
          Say y here to support the regulators found on the Freescale MC13892
          PMIC.
 
+config REGULATOR_MT6311
+       tristate "MediaTek MT6311 PMIC"
+       depends on I2C
+       help
+         Say y here to select this option to enable the power regulator of
+         MediaTek MT6311 PMIC.
+         This driver supports the control of different power rails of device
+         through regulator interface.
+
 config REGULATOR_MT6397
        tristate "MediaTek MT6397 PMIC"
        depends on MFD_MT6397
@@ -522,6 +523,18 @@ config REGULATOR_QCOM_RPM
          Qualcomm RPM as a module. The module will be named
          "qcom_rpm-regulator".
 
+config REGULATOR_QCOM_SMD_RPM
+       tristate "Qualcomm SMD based RPM regulator driver"
+       depends on QCOM_SMD_RPM
+       help
+         If you say yes to this option, support will be included for the
+         regulators exposed by the Resource Power Manager found in Qualcomm
+         8974 based devices.
+
+         Say M here if you want to include support for the regulators on the
+         Qualcomm RPM as a module. The module will be named
+         "qcom_smd-regulator".
+
 config REGULATOR_QCOM_SPMI
        tristate "Qualcomm SPMI regulator driver"
        depends on SPMI || COMPILE_TEST
index 91bf76267404c9b8a9260dba5e0a0c8a793247e6..0f8174913c17bd0b23fb434af7e0a48206680e85 100644 (file)
@@ -56,12 +56,13 @@ obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
 obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o
 obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o
-obj-$(CONFIG_REGULATOR_MAX77843) += max77843.o
 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_MT6311) += mt6311-regulator.o
 obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
+obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
 obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
index 2ff73d72ca34aca4d332fa1c7967d35f24471de0..896db168e4bdba4ffd8e75375f42339506cfc0fc 100644 (file)
@@ -530,7 +530,6 @@ MODULE_DEVICE_TABLE(i2c, act8865_ids);
 static struct i2c_driver act8865_pmic_driver = {
        .driver = {
                .name   = "act8865",
-               .owner  = THIS_MODULE,
        },
        .probe          = act8865_pmic_probe,
        .id_table       = act8865_ids,
index 48016a050d5fb9b9c19981075755bd3831be0652..ea50a886ba6397f9dd185125d99f19e238357e6a 100644 (file)
@@ -275,4 +275,3 @@ module_exit(ad5398_exit);
 MODULE_DESCRIPTION("AD5398 and AD5821 current regulator driver");
 MODULE_AUTHOR("Sonic Zhang");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("i2c:ad5398-regulator");
index 646829132b5926ffeaf5e14a82d6296f1f32f159..01bf3476a79183714f62f67efcf5d8b17b70d497 100644 (file)
@@ -405,3 +405,4 @@ module_platform_driver(axp20x_regulator_driver);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
 MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
+MODULE_ALIAS("platform:axp20x-regulator");
index 78387a6cbae59e40a6fb05fc255647cacfe3209b..de9f272a0faf75d7562665aebba60444338f21c5 100644 (file)
@@ -111,6 +111,11 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                                          const char *supply_name);
 static void _regulator_put(struct regulator *regulator);
 
+static struct regulator_dev *dev_to_rdev(struct device *dev)
+{
+       return container_of(dev, struct regulator_dev, dev);
+}
+
 static const char *rdev_get_name(struct regulator_dev *rdev)
 {
        if (rdev->constraints && rdev->constraints->name)
@@ -296,7 +301,7 @@ static int regulator_check_drms(struct regulator_dev *rdev)
                return -ENODEV;
        }
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
-               rdev_err(rdev, "operation not allowed\n");
+               rdev_dbg(rdev, "operation not allowed\n");
                return -EPERM;
        }
        return 0;
@@ -641,6 +646,8 @@ static int drms_uA_update(struct regulator_dev *rdev)
        int current_uA = 0, output_uV, input_uV, err;
        unsigned int mode;
 
+       lockdep_assert_held_once(&rdev->mutex);
+
        /*
         * first check to see if we can set modes at all, otherwise just
         * tell the consumer everything is OK.
@@ -761,6 +768,8 @@ static int suspend_set_state(struct regulator_dev *rdev,
 /* locks held by caller */
 static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
 {
+       lockdep_assert_held_once(&rdev->mutex);
+
        if (!rdev->constraints)
                return -EINVAL;
 
@@ -1082,6 +1091,15 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                }
        }
 
+       if (rdev->constraints->over_current_protection
+               && ops->set_over_current_protection) {
+               ret = ops->set_over_current_protection(rdev);
+               if (ret < 0) {
+                       rdev_err(rdev, "failed to set over current protection\n");
+                       goto out;
+               }
+       }
+
        print_constraints(rdev);
        return 0;
 out:
@@ -1595,9 +1613,11 @@ static void _regulator_put(struct regulator *regulator)
 {
        struct regulator_dev *rdev;
 
-       if (regulator == NULL || IS_ERR(regulator))
+       if (IS_ERR_OR_NULL(regulator))
                return;
 
+       lockdep_assert_held_once(&regulator_list_mutex);
+
        rdev = regulator->rdev;
 
        debugfs_remove_recursive(regulator->debugfs);
@@ -1606,14 +1626,15 @@ static void _regulator_put(struct regulator *regulator)
        if (regulator->dev)
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
        mutex_lock(&rdev->mutex);
-       kfree(regulator->supply_name);
        list_del(&regulator->list);
-       kfree(regulator);
 
        rdev->open_count--;
        rdev->exclusive = 0;
        mutex_unlock(&rdev->mutex);
 
+       kfree(regulator->supply_name);
+       kfree(regulator);
+
        module_put(rdev->owner);
 }
 
@@ -1976,6 +1997,8 @@ static int _regulator_enable(struct regulator_dev *rdev)
 {
        int ret;
 
+       lockdep_assert_held_once(&rdev->mutex);
+
        /* check voltage and requested load before enabling */
        if (rdev->constraints &&
            (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
@@ -2076,6 +2099,8 @@ static int _regulator_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
 
+       lockdep_assert_held_once(&rdev->mutex);
+
        if (WARN(rdev->use_count <= 0,
                 "unbalanced disables for %s\n", rdev_get_name(rdev)))
                return -EIO;
@@ -2154,6 +2179,8 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
 
+       lockdep_assert_held_once(&rdev->mutex);
+
        ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
                        REGULATOR_EVENT_PRE_DISABLE, NULL);
        if (ret & NOTIFY_STOP_MASK)
@@ -2722,7 +2749,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
                goto out;
 
        /* If we're trying to set a range that overlaps the current voltage,
-        * return succesfully even though the regulator does not support
+        * return successfully even though the regulator does not support
         * changing the voltage.
         */
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
@@ -3450,6 +3477,8 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
+       lockdep_assert_held_once(&rdev->mutex);
+
        _notifier_call_chain(rdev, event, data);
        return NOTIFY_DONE;
 
@@ -3594,6 +3623,9 @@ static const struct attribute_group *regulator_dev_groups[] = {
 static void regulator_dev_release(struct device *dev)
 {
        struct regulator_dev *rdev = dev_get_drvdata(dev);
+
+       kfree(rdev->constraints);
+       of_node_put(rdev->dev.of_node);
        kfree(rdev);
 }
 
@@ -3824,11 +3856,9 @@ void regulator_unregister(struct regulator_dev *rdev)
        WARN_ON(rdev->open_count);
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
-       kfree(rdev->constraints);
+       mutex_unlock(&regulator_list_mutex);
        regulator_ena_gpio_free(rdev);
-       of_node_put(rdev->dev.of_node);
        device_unregister(&rdev->dev);
-       mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_unregister);
 
@@ -4147,13 +4177,57 @@ static int __init regulator_init(void)
 /* init early to allow our consumers to complete system booting */
 core_initcall(regulator_init);
 
-static int __init regulator_init_complete(void)
+static int __init regulator_late_cleanup(struct device *dev, void *data)
 {
-       struct regulator_dev *rdev;
-       const struct regulator_ops *ops;
-       struct regulation_constraints *c;
+       struct regulator_dev *rdev = dev_to_rdev(dev);
+       const struct regulator_ops *ops = rdev->desc->ops;
+       struct regulation_constraints *c = rdev->constraints;
        int enabled, ret;
 
+       if (c && c->always_on)
+               return 0;
+
+       if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
+               return 0;
+
+       mutex_lock(&rdev->mutex);
+
+       if (rdev->use_count)
+               goto unlock;
+
+       /* If we can't read the status assume it's on. */
+       if (ops->is_enabled)
+               enabled = ops->is_enabled(rdev);
+       else
+               enabled = 1;
+
+       if (!enabled)
+               goto unlock;
+
+       if (have_full_constraints()) {
+               /* We log since this may kill the system if it goes
+                * wrong. */
+               rdev_info(rdev, "disabling\n");
+               ret = _regulator_do_disable(rdev);
+               if (ret != 0)
+                       rdev_err(rdev, "couldn't disable: %d\n", ret);
+       } else {
+               /* The intention is that in future we will
+                * assume that full constraints are provided
+                * so warn even if we aren't going to do
+                * anything here.
+                */
+               rdev_warn(rdev, "incomplete constraints, leaving on\n");
+       }
+
+unlock:
+       mutex_unlock(&rdev->mutex);
+
+       return 0;
+}
+
+static int __init regulator_init_complete(void)
+{
        /*
         * Since DT doesn't provide an idiomatic mechanism for
         * enabling full constraints and since it's much more natural
@@ -4163,58 +4237,13 @@ static int __init regulator_init_complete(void)
        if (of_have_populated_dt())
                has_full_constraints = true;
 
-       mutex_lock(&regulator_list_mutex);
-
        /* If we have a full configuration then disable any regulators
         * we have permission to change the status for and which are
         * not in use or always_on.  This is effectively the default
         * for DT and ACPI as they have full constraints.
         */
-       list_for_each_entry(rdev, &regulator_list, list) {
-               ops = rdev->desc->ops;
-               c = rdev->constraints;
-
-               if (c && c->always_on)
-                       continue;
-
-               if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
-                       continue;
-
-               mutex_lock(&rdev->mutex);
-
-               if (rdev->use_count)
-                       goto unlock;
-
-               /* If we can't read the status assume it's on. */
-               if (ops->is_enabled)
-                       enabled = ops->is_enabled(rdev);
-               else
-                       enabled = 1;
-
-               if (!enabled)
-                       goto unlock;
-
-               if (have_full_constraints()) {
-                       /* We log since this may kill the system if it
-                        * goes wrong. */
-                       rdev_info(rdev, "disabling\n");
-                       ret = _regulator_do_disable(rdev);
-                       if (ret != 0)
-                               rdev_err(rdev, "couldn't disable: %d\n", ret);
-               } else {
-                       /* The intention is that in future we will
-                        * assume that full constraints are provided
-                        * so warn even if we aren't going to do
-                        * anything here.
-                        */
-                       rdev_warn(rdev, "incomplete constraints, leaving on\n");
-               }
-
-unlock:
-               mutex_unlock(&rdev->mutex);
-       }
-
-       mutex_unlock(&regulator_list_mutex);
+       class_for_each_device(&regulator_class, NULL, NULL,
+                             regulator_late_cleanup);
 
        return 0;
 }
index dd76da09b3c7ffbb7cb3abb972c887c684b1bff0..5638fe8d759d745e11e3c14fbb173f0a2efd1912 100644 (file)
@@ -818,7 +818,6 @@ static int da9062_regulator_probe(struct platform_device *pdev)
 static struct platform_driver da9062_regulator_driver = {
        .driver = {
                .name = "da9062-regulators",
-               .owner = THIS_MODULE,
        },
        .probe = da9062_regulator_probe,
 };
index f0489cb9018b4e7895937d330d077e100783fc16..b3517830edb6f0ea2139cbc5ebe902ce8cf8265d 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
@@ -120,6 +122,55 @@ static int da9210_get_current_limit(struct regulator_dev *rdev)
        return da9210_buck_limits[sel];
 }
 
+static irqreturn_t da9210_irq_handler(int irq, void *data)
+{
+       struct da9210 *chip = data;
+       unsigned int val, handled = 0;
+       int error, ret = IRQ_NONE;
+
+       error = regmap_read(chip->regmap, DA9210_REG_EVENT_B, &val);
+       if (error < 0)
+               goto error_i2c;
+
+       if (val & DA9210_E_OVCURR) {
+               regulator_notifier_call_chain(chip->rdev,
+                                             REGULATOR_EVENT_OVER_CURRENT,
+                                             NULL);
+               handled |= DA9210_E_OVCURR;
+       }
+       if (val & DA9210_E_NPWRGOOD) {
+               regulator_notifier_call_chain(chip->rdev,
+                                             REGULATOR_EVENT_UNDER_VOLTAGE,
+                                             NULL);
+               handled |= DA9210_E_NPWRGOOD;
+       }
+       if (val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT)) {
+               regulator_notifier_call_chain(chip->rdev,
+                                             REGULATOR_EVENT_OVER_TEMP, NULL);
+               handled |= val & (DA9210_E_TEMP_WARN | DA9210_E_TEMP_CRIT);
+       }
+       if (val & DA9210_E_VMAX) {
+               regulator_notifier_call_chain(chip->rdev,
+                                             REGULATOR_EVENT_REGULATION_OUT,
+                                             NULL);
+               handled |= DA9210_E_VMAX;
+       }
+       if (handled) {
+               /* Clear handled events */
+               error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled);
+               if (error < 0)
+                       goto error_i2c;
+
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+
+error_i2c:
+       dev_err(regmap_get_device(chip->regmap), "I2C error : %d\n", error);
+       return ret;
+}
+
 /*
  * I2C driver interface functions
  */
@@ -168,6 +219,30 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
        }
 
        chip->rdev = rdev;
+       if (i2c->irq) {
+               error = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+                                                 da9210_irq_handler,
+                                                 IRQF_TRIGGER_LOW |
+                                                 IRQF_ONESHOT | IRQF_SHARED,
+                                                 "da9210", chip);
+               if (error) {
+                       dev_err(&i2c->dev, "Failed to request IRQ%u: %d\n",
+                               i2c->irq, error);
+                       return error;
+               }
+
+               error = regmap_update_bits(chip->regmap, DA9210_REG_MASK_B,
+                                        DA9210_M_OVCURR | DA9210_M_NPWRGOOD |
+                                        DA9210_M_TEMP_WARN |
+                                        DA9210_M_TEMP_CRIT | DA9210_M_VMAX, 0);
+               if (error < 0) {
+                       dev_err(&i2c->dev, "Failed to update mask reg: %d\n",
+                               error);
+                       return error;
+               }
+       } else {
+               dev_warn(&i2c->dev, "No IRQ configured\n");
+       }
 
        i2c_set_clientdata(i2c, chip);
 
@@ -184,7 +259,6 @@ MODULE_DEVICE_TABLE(i2c, da9210_i2c_id);
 static struct i2c_driver da9210_regulator_driver = {
        .driver = {
                .name = "da9210",
-               .owner = THIS_MODULE,
        },
        .probe = da9210_i2c_probe,
        .id_table = da9210_i2c_id,
index df79e4b1946e7d6e966e5759e323f67fbacfb021..04ef65b7eb3d2e225e784f7f3fc166b12ecba522 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * da9211-regulator.c - Regulator device driver for DA9211/DA9213
- * Copyright (C) 2014  Dialog Semiconductor Ltd.
+ * da9211-regulator.c - Regulator device driver for DA9211/DA9213/DA9215
+ * Copyright (C) 2015  Dialog Semiconductor Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -32,6 +32,7 @@
 /* DEVICE IDs */
 #define DA9211_DEVICE_ID       0x22
 #define DA9213_DEVICE_ID       0x23
+#define DA9215_DEVICE_ID       0x24
 
 #define DA9211_BUCK_MODE_SLEEP 1
 #define DA9211_BUCK_MODE_SYNC  2
@@ -90,6 +91,13 @@ static const int da9213_current_limits[] = {
        3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000,
        4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000
 };
+/* Current limits for DA9215 buck (uA) indices
+ * corresponds with register values
+ */
+static const int da9215_current_limits[] = {
+       4000000, 4200000, 4400000, 4600000, 4800000, 5000000, 5200000, 5400000,
+       5600000, 5800000, 6000000, 6200000, 6400000, 6600000, 6800000, 7000000
+};
 
 static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev)
 {
@@ -157,6 +165,10 @@ static int da9211_set_current_limit(struct regulator_dev *rdev, int min,
                current_limits = da9213_current_limits;
                max_size = ARRAY_SIZE(da9213_current_limits)-1;
                break;
+       case DA9215:
+               current_limits = da9215_current_limits;
+               max_size = ARRAY_SIZE(da9215_current_limits)-1;
+               break;
        default:
                return -EINVAL;
        }
@@ -189,6 +201,9 @@ static int da9211_get_current_limit(struct regulator_dev *rdev)
        case DA9213:
                current_limits = da9213_current_limits;
                break;
+       case DA9215:
+               current_limits = da9215_current_limits;
+               break;
        default:
                return -EINVAL;
        }
@@ -350,13 +365,11 @@ static int da9211_regulator_init(struct da9211 *chip)
        /* If configuration for 1/2 bucks is different between platform data
         * and the register, driver should exit.
         */
-       if ((chip->pdata->num_buck == 2 && data == 0x40)
-               || (chip->pdata->num_buck == 1 && data == 0x00)) {
-               if (data == 0)
-                       chip->num_regulator = 1;
-               else
-                       chip->num_regulator = 2;
-       } else {
+       if (chip->pdata->num_buck == 1 && data == 0x00)
+               chip->num_regulator = 1;
+       else if (chip->pdata->num_buck == 2 && data != 0x00)
+               chip->num_regulator = 2;
+       else {
                dev_err(chip->dev, "Configuration is mismatched\n");
                return -EINVAL;
        }
@@ -438,6 +451,9 @@ static int da9211_i2c_probe(struct i2c_client *i2c,
        case DA9213_DEVICE_ID:
                chip->chip_id = DA9213;
                break;
+       case DA9215_DEVICE_ID:
+               chip->chip_id = DA9215;
+               break;
        default:
                dev_err(chip->dev, "Unsupported device id = 0x%x.\n", data);
                return -ENODEV;
@@ -478,6 +494,7 @@ static int da9211_i2c_probe(struct i2c_client *i2c,
 static const struct i2c_device_id da9211_i2c_id[] = {
        {"da9211", DA9211},
        {"da9213", DA9213},
+       {"da9215", DA9215},
        {},
 };
 MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
@@ -486,6 +503,7 @@ MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
 static const struct of_device_id da9211_dt_ids[] = {
        { .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] },
        { .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] },
+       { .compatible = "dlg,da9215", .data = &da9211_i2c_id[2] },
        {},
 };
 MODULE_DEVICE_TABLE(of, da9211_dt_ids);
@@ -494,7 +512,6 @@ MODULE_DEVICE_TABLE(of, da9211_dt_ids);
 static struct i2c_driver da9211_regulator_driver = {
        .driver = {
                .name = "da9211",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(da9211_dt_ids),
        },
        .probe = da9211_i2c_probe,
@@ -504,5 +521,5 @@ static struct i2c_driver da9211_regulator_driver = {
 module_i2c_driver(da9211_regulator_driver);
 
 MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
-MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213");
-MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213/DA9215");
+MODULE_LICENSE("GPL");
index 93fa9df2721c9d4d6f286f3d6ebc49bff228d98a..d6ad96fc64d33eae95ceb112a3970665f64876ec 100644 (file)
@@ -1,16 +1,16 @@
 /*
- * da9211-regulator.h - Regulator definitions for DA9211/DA9213
- * Copyright (C) 2014  Dialog Semiconductor Ltd.
+ * da9211-regulator.h - Regulator definitions for DA9211/DA9213/DA9215
+ * Copyright (C) 2015  Dialog Semiconductor Ltd.
  *
- * 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 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 library is distributed in the hope that it will be useful,
+ * 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
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __DA9211_REGISTERS_H__
index 42865681c00bfb18df9bc5085a0b84f6fd8a0851..4940e8287df68090104a78cc6239ab90e22423c6 100644 (file)
@@ -439,6 +439,7 @@ static const struct i2c_device_id fan53555_id[] = {
        },
        { },
 };
+MODULE_DEVICE_TABLE(i2c, fan53555_id);
 
 static struct i2c_driver fan53555_regulator_driver = {
        .driver = {
index 6e5da95fa025d4df8c8f3821230ec491be64bd22..4abd8e9c81e5893b4a84d3146db7131c8f42387a 100644 (file)
@@ -156,7 +156,6 @@ MODULE_DEVICE_TABLE(i2c, isl6271a_id);
 static struct i2c_driver isl6271a_i2c_driver = {
        .driver = {
                .name = "isl6271a",
-               .owner = THIS_MODULE,
        },
        .probe = isl6271a_probe,
        .id_table = isl6271a_id,
index 6e3a15fe00f1ce37d51d47d0c66ee26c39a8b367..257c1943e7534276a058c9e98f015c26eafeb0ee 100644 (file)
@@ -183,6 +183,7 @@ static const struct of_device_id isl9305_dt_ids[] = {
        { .compatible = "isil,isl9305h" },
        {},
 };
+MODULE_DEVICE_TABLE(of, isl9305_dt_ids);
 #endif
 
 static const struct i2c_device_id isl9305_i2c_id[] = {
@@ -195,7 +196,6 @@ MODULE_DEVICE_TABLE(i2c, isl9305_i2c_id);
 static struct i2c_driver isl9305_regulator_driver = {
        .driver = {
                .name = "isl9305",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(isl9305_dt_ids),
        },
        .probe = isl9305_i2c_probe,
index 66fd2330dca043a2627c8443f090ba5822f5de14..15c25c622edf69c60adc6ede42401675093b074c 100644 (file)
@@ -452,7 +452,6 @@ MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
 static struct i2c_driver lp3971_i2c_driver = {
        .driver = {
                .name = "LP3971",
-               .owner = THIS_MODULE,
        },
        .probe    = lp3971_i2c_probe,
        .id_table = lp3971_i2c_id,
index aea485afcc1a8a9983781320182ed9078ff9517c..3a7e96e2c7b3c93d9cfc910a080f664145c67ce6 100644 (file)
@@ -550,7 +550,6 @@ MODULE_DEVICE_TABLE(i2c, lp3972_i2c_id);
 static struct i2c_driver lp3972_i2c_driver = {
        .driver = {
                .name = "lp3972",
-               .owner = THIS_MODULE,
        },
        .probe    = lp3972_i2c_probe,
        .id_table = lp3972_i2c_id,
index 3de328ab41f3c69dde58349d6aa4fb0d18736617..e5af07208f9d382ad54fb2e35b358662fff35de8 100644 (file)
@@ -849,7 +849,7 @@ static struct lp872x_platform_data
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
-               goto out;
+               return ERR_PTR(-ENOMEM);
 
        of_property_read_u8(np, "ti,general-config", &pdata->general_config);
        if (of_find_property(np, "ti,update-config", NULL))
@@ -857,7 +857,7 @@ static struct lp872x_platform_data
 
        pdata->dvs = devm_kzalloc(dev, sizeof(struct lp872x_dvs), GFP_KERNEL);
        if (!pdata->dvs)
-               goto out;
+               return ERR_PTR(-ENOMEM);
 
        pdata->dvs->gpio = of_get_named_gpio(np, "ti,dvs-gpio", 0);
        of_property_read_u8(np, "ti,dvs-vsel", (u8 *)&pdata->dvs->vsel);
@@ -903,15 +903,21 @@ static struct lp872x_platform_data
 static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
        struct lp872x *lp;
+       struct lp872x_platform_data *pdata;
        int ret;
        const int lp872x_num_regulators[] = {
                [LP8720] = LP8720_NUM_REGULATORS,
                [LP8725] = LP8725_NUM_REGULATORS,
        };
 
-       if (cl->dev.of_node)
-               cl->dev.platform_data = lp872x_populate_pdata_from_dt(&cl->dev,
+       if (cl->dev.of_node) {
+               pdata = lp872x_populate_pdata_from_dt(&cl->dev,
                                              (enum lp872x_id)id->driver_data);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+       } else {
+               pdata = dev_get_platdata(&cl->dev);
+       }
 
        lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
        if (!lp)
@@ -927,7 +933,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
        }
 
        lp->dev = &cl->dev;
-       lp->pdata = dev_get_platdata(&cl->dev);
+       lp->pdata = pdata;
        lp->chipid = id->driver_data;
        i2c_set_clientdata(cl, lp);
 
@@ -955,7 +961,6 @@ MODULE_DEVICE_TABLE(i2c, lp872x_ids);
 static struct i2c_driver lp872x_driver = {
        .driver = {
                .name = "lp872x",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(lp872x_dt_ids),
        },
        .probe = lp872x_probe,
index 0ce8e4e0fa7308dfd5056a0553ad7b5d9050b4a3..972c386b269024180e512cab2c65da0e069817c6 100644 (file)
@@ -378,7 +378,7 @@ static bool ltc3589_volatile_reg(struct device *dev, unsigned int reg)
        return false;
 }
 
-static struct reg_default ltc3589_reg_defaults[] = {
+static const struct reg_default ltc3589_reg_defaults[] = {
        { LTC3589_SCR1,   0x00 },
        { LTC3589_OVEN,   0x00 },
        { LTC3589_SCR2,   0x00 },
@@ -542,7 +542,6 @@ MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id);
 static struct i2c_driver ltc3589_driver = {
        .driver = {
                .name = DRIVER_NAME,
-               .owner = THIS_MODULE,
        },
        .probe = ltc3589_probe,
        .id_table = ltc3589_i2c_id,
@@ -552,4 +551,3 @@ module_i2c_driver(ltc3589_driver);
 MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
 MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3589(-1,2)");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:ltc3589");
index d2a8c64cae42a9bc83890e922b7971781347ee62..2c1228d5796acb1df61cb12c161fc4ba8ed2f1b8 100644 (file)
@@ -304,7 +304,6 @@ static struct i2c_driver max1586_pmic_driver = {
        .probe = max1586_pmic_probe,
        .driver         = {
                .name   = "max1586",
-               .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(max1586_of_match),
        },
        .id_table       = max1586_id,
index 38722c8311a52bc04e1d4bac151fcc9bfec7d548..de730fd3f8a5df6cf7786be8f8b64c52b3786820 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * max77693.c - Regulator driver for the Maxim 77693
+ * max77693.c - Regulator driver for the Maxim 77693 and 77843
  *
- * Copyright (C) 2013 Samsung Electronics
+ * Copyright (C) 2013-2015 Samsung Electronics
  * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ * Krzysztof Kozlowski <k.kozlowski.k@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
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
+#include <linux/mfd/max77843-private.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regmap.h>
 
-#define CHGIN_ILIM_STEP_20mA                   20000
+/*
+ * ID for MAX77843 regulators.
+ * There is no need for such for MAX77693.
+ */
+enum max77843_regulator_type {
+       MAX77843_SAFEOUT1 = 0,
+       MAX77843_SAFEOUT2,
+       MAX77843_CHARGER,
+
+       MAX77843_NUM,
+};
+
+/* Register differences between chargers: MAX77693 and MAX77843 */
+struct chg_reg_data {
+       unsigned int linear_reg;
+       unsigned int linear_mask;
+       unsigned int uA_step;
+       unsigned int min_sel;
+};
 
 /*
- * CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA
+ * MAX77693 CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA
  * 0x00, 0x01, 0x2, 0x03       = 60 mA
  * 0x04 ~ 0x7E                 = (60 + (X - 3) * 20) mA
+ * Actually for MAX77693 the driver manipulates the maximum input current,
+ * not the fast charge current (output). This should be fixed.
+ *
+ * On MAX77843 the calculation formula is the same (except values).
+ * Fortunately it properly manipulates the fast charge current.
  */
 static int max77693_chg_get_current_limit(struct regulator_dev *rdev)
 {
+       const struct chg_reg_data *reg_data = rdev_get_drvdata(rdev);
        unsigned int chg_min_uA = rdev->constraints->min_uA;
        unsigned int chg_max_uA = rdev->constraints->max_uA;
        unsigned int reg, sel;
        unsigned int val;
        int ret;
 
-       ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, &reg);
+       ret = regmap_read(rdev->regmap, reg_data->linear_reg, &reg);
        if (ret < 0)
                return ret;
 
-       sel = reg & CHG_CNFG_09_CHGIN_ILIM_MASK;
+       sel = reg & reg_data->linear_mask;
 
        /* the first four codes for charger current are all 60mA */
-       if (sel <= 3)
+       if (sel <= reg_data->min_sel)
                sel = 0;
        else
-               sel -= 3;
+               sel -= reg_data->min_sel;
 
-       val = chg_min_uA + CHGIN_ILIM_STEP_20mA * sel;
+       val = chg_min_uA + reg_data->uA_step * sel;
        if (val > chg_max_uA)
                return -EINVAL;
 
@@ -70,23 +97,43 @@ static int max77693_chg_get_current_limit(struct regulator_dev *rdev)
 static int max77693_chg_set_current_limit(struct regulator_dev *rdev,
                                                int min_uA, int max_uA)
 {
+       const struct chg_reg_data *reg_data = rdev_get_drvdata(rdev);
        unsigned int chg_min_uA = rdev->constraints->min_uA;
        int sel = 0;
 
-       while (chg_min_uA + CHGIN_ILIM_STEP_20mA * sel < min_uA)
+       while (chg_min_uA + reg_data->uA_step * sel < min_uA)
                sel++;
 
-       if (chg_min_uA + CHGIN_ILIM_STEP_20mA * sel > max_uA)
+       if (chg_min_uA + reg_data->uA_step * sel > max_uA)
                return -EINVAL;
 
        /* the first four codes for charger current are all 60mA */
-       sel += 3;
+       sel += reg_data->min_sel;
 
-       return regmap_write(rdev->regmap,
-                               MAX77693_CHG_REG_CHG_CNFG_09, sel);
+       return regmap_write(rdev->regmap, reg_data->linear_reg, sel);
 }
 /* end of CHARGER regulator ops */
 
+/* Returns regmap suitable for given regulator on chosen device */
+static struct regmap *max77693_get_regmap(enum max77693_types type,
+                                         struct max77693_dev *max77693,
+                                         int reg_id)
+{
+       if (type == TYPE_MAX77693)
+               return max77693->regmap;
+
+       /* Else: TYPE_MAX77843 */
+       switch (reg_id) {
+       case MAX77843_SAFEOUT1:
+       case MAX77843_SAFEOUT2:
+               return max77693->regmap;
+       case MAX77843_CHARGER:
+               return max77693->regmap_chg;
+       default:
+               return max77693->regmap;
+       }
+}
+
 static const unsigned int max77693_safeout_table[] = {
        4850000,
        4900000,
@@ -111,7 +158,7 @@ static struct regulator_ops max77693_charger_ops = {
        .set_current_limit      = max77693_chg_set_current_limit,
 };
 
-#define regulator_desc_esafeout(_num)  {                       \
+#define max77693_regulator_desc_esafeout(_num) {               \
        .name           = "ESAFEOUT"#_num,                      \
        .id             = MAX77693_ESAFEOUT##_num,              \
        .of_match       = of_match_ptr("ESAFEOUT"#_num),        \
@@ -127,9 +174,9 @@ static struct regulator_ops max77693_charger_ops = {
        .enable_mask    = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \
 }
 
-static const struct regulator_desc regulators[] = {
-       regulator_desc_esafeout(1),
-       regulator_desc_esafeout(2),
+static const struct regulator_desc max77693_supported_regulators[] = {
+       max77693_regulator_desc_esafeout(1),
+       max77693_regulator_desc_esafeout(2),
        {
                .name = "CHARGER",
                .id = MAX77693_CHARGER,
@@ -145,18 +192,86 @@ static const struct regulator_desc regulators[] = {
        },
 };
 
+static const struct chg_reg_data max77693_chg_reg_data = {
+       .linear_reg     = MAX77693_CHG_REG_CHG_CNFG_09,
+       .linear_mask    = CHG_CNFG_09_CHGIN_ILIM_MASK,
+       .uA_step        = 20000,
+       .min_sel        = 3,
+};
+
+#define        max77843_regulator_desc_esafeout(num)   {                       \
+       .name           = "SAFEOUT" # num,                              \
+       .id             = MAX77843_SAFEOUT ## num,                      \
+       .ops            = &max77693_safeout_ops,                        \
+       .of_match       = of_match_ptr("SAFEOUT" # num),                \
+       .regulators_node = of_match_ptr("regulators"),                  \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .n_voltages     = ARRAY_SIZE(max77693_safeout_table),           \
+       .volt_table     = max77693_safeout_table,                       \
+       .enable_reg     = MAX77843_SYS_REG_SAFEOUTCTRL,                 \
+       .enable_mask    = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num,    \
+       .vsel_reg       = MAX77843_SYS_REG_SAFEOUTCTRL,                 \
+       .vsel_mask      = MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \
+}
+
+static const struct regulator_desc max77843_supported_regulators[] = {
+       [MAX77843_SAFEOUT1] = max77843_regulator_desc_esafeout(1),
+       [MAX77843_SAFEOUT2] = max77843_regulator_desc_esafeout(2),
+       [MAX77843_CHARGER] = {
+               .name           = "CHARGER",
+               .id             = MAX77843_CHARGER,
+               .ops            = &max77693_charger_ops,
+               .of_match       = of_match_ptr("CHARGER"),
+               .regulators_node = of_match_ptr("regulators"),
+               .type           = REGULATOR_CURRENT,
+               .owner          = THIS_MODULE,
+               .enable_reg     = MAX77843_CHG_REG_CHG_CNFG_00,
+               .enable_mask    = MAX77843_CHG_MASK,
+               .enable_val     = MAX77843_CHG_MASK,
+       },
+};
+
+static const struct chg_reg_data max77843_chg_reg_data = {
+       .linear_reg     = MAX77843_CHG_REG_CHG_CNFG_02,
+       .linear_mask    = MAX77843_CHG_FAST_CHG_CURRENT_MASK,
+       .uA_step        = MAX77843_CHG_FAST_CHG_CURRENT_STEP,
+       .min_sel        = 2,
+};
+
 static int max77693_pmic_probe(struct platform_device *pdev)
 {
+       enum max77693_types type = platform_get_device_id(pdev)->driver_data;
        struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       const struct regulator_desc *regulators;
+       unsigned int regulators_size;
        int i;
        struct regulator_config config = { };
 
        config.dev = iodev->dev;
-       config.regmap = iodev->regmap;
 
-       for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+       switch (type) {
+       case TYPE_MAX77693:
+               regulators = max77693_supported_regulators;
+               regulators_size = ARRAY_SIZE(max77693_supported_regulators);
+               config.driver_data = (void *)&max77693_chg_reg_data;
+               break;
+       case TYPE_MAX77843:
+               regulators = max77843_supported_regulators;
+               regulators_size = ARRAY_SIZE(max77843_supported_regulators);
+               config.driver_data = (void *)&max77843_chg_reg_data;
+               break;
+       default:
+               dev_err(&pdev->dev, "Unsupported device type: %u\n", type);
+               return -ENODEV;
+       }
+
+       for (i = 0; i < regulators_size; i++) {
                struct regulator_dev *rdev;
 
+               config.regmap = max77693_get_regmap(type, iodev,
+                                                   regulators[i].id);
+
                rdev = devm_regulator_register(&pdev->dev,
                                                &regulators[i], &config);
                if (IS_ERR(rdev)) {
@@ -170,7 +285,8 @@ static int max77693_pmic_probe(struct platform_device *pdev)
 }
 
 static const struct platform_device_id max77693_pmic_id[] = {
-       {"max77693-pmic", 0},
+       { "max77693-pmic", TYPE_MAX77693 },
+       { "max77843-regulator", TYPE_MAX77843 },
        {},
 };
 
@@ -184,8 +300,19 @@ static struct platform_driver max77693_pmic_driver = {
        .id_table = max77693_pmic_id,
 };
 
-module_platform_driver(max77693_pmic_driver);
+static int __init max77693_pmic_init(void)
+{
+       return platform_driver_register(&max77693_pmic_driver);
+}
+subsys_initcall(max77693_pmic_init);
+
+static void __exit max77693_pmic_cleanup(void)
+{
+       platform_driver_unregister(&max77693_pmic_driver);
+}
+module_exit(max77693_pmic_cleanup);
 
-MODULE_DESCRIPTION("MAXIM MAX77693 regulator driver");
+MODULE_DESCRIPTION("MAXIM 77693/77843 regulator driver");
 MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
+MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski.k@gmail.com>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max77843.c b/drivers/regulator/max77843.c
deleted file mode 100644 (file)
index f4fd0d3..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * max77843.c - Regulator driver for the Maxim MAX77843
- *
- * Copyright (C) 2015 Samsung Electronics
- * Author: Jaewon Kim <jaewon02.kim@samsung.com>
- * Author: Beomho Seo <beomho.seo@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/mfd/max77843-private.h>
-#include <linux/regulator/of_regulator.h>
-
-enum max77843_regulator_type {
-       MAX77843_SAFEOUT1 = 0,
-       MAX77843_SAFEOUT2,
-       MAX77843_CHARGER,
-
-       MAX77843_NUM,
-};
-
-static const unsigned int max77843_safeout_voltage_table[] = {
-       4850000,
-       4900000,
-       4950000,
-       3300000,
-};
-
-static int max77843_reg_get_current_limit(struct regulator_dev *rdev)
-{
-       struct regmap *regmap = rdev->regmap;
-       unsigned int chg_min_uA = rdev->constraints->min_uA;
-       unsigned int chg_max_uA = rdev->constraints->max_uA;
-       unsigned int val;
-       int ret;
-       unsigned int reg, sel;
-
-       ret = regmap_read(regmap, MAX77843_CHG_REG_CHG_CNFG_02, &reg);
-       if (ret) {
-               dev_err(&rdev->dev, "Failed to read charger register\n");
-               return ret;
-       }
-
-       sel = reg & MAX77843_CHG_FAST_CHG_CURRENT_MASK;
-
-       if (sel < 0x03)
-               sel = 0;
-       else
-               sel -= 2;
-
-       val = chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel;
-       if (val > chg_max_uA)
-               return -EINVAL;
-
-       return val;
-}
-
-static int max77843_reg_set_current_limit(struct regulator_dev *rdev,
-               int min_uA, int max_uA)
-{
-       struct regmap *regmap = rdev->regmap;
-       unsigned int chg_min_uA = rdev->constraints->min_uA;
-       int sel = 0;
-
-       while (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel < min_uA)
-               sel++;
-
-       if (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel > max_uA)
-               return -EINVAL;
-
-       sel += 2;
-
-       return regmap_write(regmap, MAX77843_CHG_REG_CHG_CNFG_02, sel);
-}
-
-static struct regulator_ops max77843_charger_ops = {
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
-       .disable                = regulator_disable_regmap,
-       .get_current_limit      = max77843_reg_get_current_limit,
-       .set_current_limit      = max77843_reg_set_current_limit,
-};
-
-static struct regulator_ops max77843_regulator_ops = {
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
-       .disable                = regulator_disable_regmap,
-       .list_voltage           = regulator_list_voltage_table,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-};
-
-#define        MAX77843_SAFEOUT(num)   { \
-       .name           = "SAFEOUT" # num, \
-       .id             = MAX77843_SAFEOUT ## num, \
-       .ops            = &max77843_regulator_ops, \
-       .of_match       = of_match_ptr("SAFEOUT" # num), \
-       .regulators_node = of_match_ptr("regulators"), \
-       .type           = REGULATOR_VOLTAGE, \
-       .owner          = THIS_MODULE, \
-       .n_voltages     = ARRAY_SIZE(max77843_safeout_voltage_table), \
-       .volt_table     = max77843_safeout_voltage_table, \
-       .enable_reg     = MAX77843_SYS_REG_SAFEOUTCTRL, \
-       .enable_mask    = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num, \
-       .vsel_reg       = MAX77843_SYS_REG_SAFEOUTCTRL, \
-       .vsel_mask      = MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \
-}
-
-static const struct regulator_desc max77843_supported_regulators[] = {
-       [MAX77843_SAFEOUT1] = MAX77843_SAFEOUT(1),
-       [MAX77843_SAFEOUT2] = MAX77843_SAFEOUT(2),
-       [MAX77843_CHARGER] = {
-               .name           = "CHARGER",
-               .id             = MAX77843_CHARGER,
-               .ops            = &max77843_charger_ops,
-               .of_match       = of_match_ptr("CHARGER"),
-               .regulators_node = of_match_ptr("regulators"),
-               .type           = REGULATOR_CURRENT,
-               .owner          = THIS_MODULE,
-               .enable_reg     = MAX77843_CHG_REG_CHG_CNFG_00,
-               .enable_mask    = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK,
-               .enable_val     = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK,
-       },
-};
-
-static struct regmap *max77843_get_regmap(struct max77843 *max77843, int reg_id)
-{
-       switch (reg_id) {
-       case MAX77843_SAFEOUT1:
-       case MAX77843_SAFEOUT2:
-               return max77843->regmap;
-       case MAX77843_CHARGER:
-               return max77843->regmap_chg;
-       default:
-               return max77843->regmap;
-       }
-}
-
-static int max77843_regulator_probe(struct platform_device *pdev)
-{
-       struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent);
-       struct regulator_config config = {};
-       int i;
-
-       config.dev = max77843->dev;
-       config.driver_data = max77843;
-
-       for (i = 0; i < ARRAY_SIZE(max77843_supported_regulators); i++) {
-               struct regulator_dev *regulator;
-
-               config.regmap = max77843_get_regmap(max77843,
-                               max77843_supported_regulators[i].id);
-
-               regulator = devm_regulator_register(&pdev->dev,
-                               &max77843_supported_regulators[i], &config);
-               if (IS_ERR(regulator)) {
-                       dev_err(&pdev->dev,
-                                       "Failed to regiser regulator-%d\n", i);
-                       return PTR_ERR(regulator);
-               }
-       }
-
-       return 0;
-}
-
-static const struct platform_device_id max77843_regulator_id[] = {
-       { "max77843-regulator", },
-       { /* sentinel */ },
-};
-
-static struct platform_driver max77843_regulator_driver = {
-       .driver = {
-               .name = "max77843-regulator",
-       },
-       .probe          = max77843_regulator_probe,
-       .id_table       = max77843_regulator_id,
-};
-
-static int __init max77843_regulator_init(void)
-{
-       return platform_driver_register(&max77843_regulator_driver);
-}
-subsys_initcall(max77843_regulator_init);
-
-static void __exit max77843_regulator_exit(void)
-{
-       platform_driver_unregister(&max77843_regulator_driver);
-}
-module_exit(max77843_regulator_exit);
-
-MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
-MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
-MODULE_DESCRIPTION("Maxim MAX77843 regulator driver");
-MODULE_LICENSE("GPL");
index 4071d74fa8288ce27d2cdd34505c006474e2f869..b87f62dd484e0a4ca349e5a9f7d5fbb34aaab349 100644 (file)
@@ -518,7 +518,6 @@ static struct i2c_driver max8660_driver = {
        .probe = max8660_probe,
        .driver         = {
                .name   = "max8660",
-               .owner  = THIS_MODULE,
        },
        .id_table       = max8660_id,
 };
index e94ddcf97722331e3cdde0645697169a35ba8c12..5b75b7c2e3ea441c266a13c367d555b08d46077d 100644 (file)
@@ -75,6 +75,7 @@
 #define MAX8973_DISCH_ENBABLE                          BIT(5)
 #define MAX8973_FT_ENABLE                              BIT(4)
 
+#define MAX8973_CKKADV_TRIP_MASK                       0xC
 #define MAX8973_CKKADV_TRIP_DISABLE                    0xC
 #define MAX8973_CKKADV_TRIP_75mV_PER_US                        0x0
 #define MAX8973_CKKADV_TRIP_150mV_PER_US               0x4
@@ -282,6 +283,55 @@ static int max8973_set_ramp_delay(struct regulator_dev *rdev,
        return ret;
 }
 
+static int max8973_set_current_limit(struct regulator_dev *rdev,
+               int min_ua, int max_ua)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       unsigned int val;
+       int ret;
+
+       if (max_ua <= 9000000)
+               val = MAX8973_CKKADV_TRIP_75mV_PER_US;
+       else if (max_ua <= 12000000)
+               val = MAX8973_CKKADV_TRIP_150mV_PER_US;
+       else
+               val = MAX8973_CKKADV_TRIP_DISABLE;
+
+       ret = regmap_update_bits(max->regmap, MAX8973_CONTROL2,
+                       MAX8973_CKKADV_TRIP_MASK, val);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d update failed: %d\n",
+                               MAX8973_CONTROL2, ret);
+               return ret;
+       }
+       return 0;
+}
+
+static int max8973_get_current_limit(struct regulator_dev *rdev)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       unsigned int control2;
+       int ret;
+
+       ret = regmap_read(max->regmap, MAX8973_CONTROL2, &control2);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d read failed: %d\n",
+                               MAX8973_CONTROL2, ret);
+               return ret;
+       }
+       switch (control2 & MAX8973_CKKADV_TRIP_MASK) {
+       case MAX8973_CKKADV_TRIP_DISABLE:
+               return 15000000;
+       case MAX8973_CKKADV_TRIP_150mV_PER_US:
+               return 12000000;
+       case MAX8973_CKKADV_TRIP_75mV_PER_US:
+               return 9000000;
+       default:
+               break;
+       }
+       return 9000000;
+}
+
 static const struct regulator_ops max8973_dcdc_ops = {
        .get_voltage_sel        = max8973_dcdc_get_voltage_sel,
        .set_voltage_sel        = max8973_dcdc_set_voltage_sel,
@@ -421,6 +471,8 @@ static struct max8973_regulator_platform_data *max8973_parse_dt(
        struct device_node *np = dev->of_node;
        int ret;
        u32 pval;
+       bool etr_enable;
+       bool etr_sensitivity_high;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
@@ -452,6 +504,23 @@ static struct max8973_regulator_platform_data *max8973_parse_dt(
        if (of_property_read_bool(np, "maxim,enable-bias-control"))
                pdata->control_flags  |= MAX8973_CONTROL_BIAS_ENABLE;
 
+       etr_enable = of_property_read_bool(np, "maxim,enable-etr");
+       etr_sensitivity_high = of_property_read_bool(np,
+                               "maxim,enable-high-etr-sensitivity");
+       if (etr_sensitivity_high)
+               etr_enable = true;
+
+       if (etr_enable) {
+               if (etr_sensitivity_high)
+                       pdata->control_flags |=
+                               MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US;
+               else
+                       pdata->control_flags |=
+                               MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US;
+       } else {
+               pdata->control_flags |= MAX8973_CONTROL_CLKADV_TRIP_DISABLED;
+       }
+
        return pdata;
 }
 
@@ -568,6 +637,15 @@ static int max8973_probe(struct i2c_client *client,
                        max->lru_index[i] = i;
                max->lru_index[0] = max->curr_vout_reg;
                max->lru_index[max->curr_vout_reg] = 0;
+       } else {
+               /*
+                * If there is no DVS GPIO, the VOUT register
+                * address is fixed.
+                */
+               max->ops.set_voltage_sel = regulator_set_voltage_sel_regmap;
+               max->ops.get_voltage_sel = regulator_get_voltage_sel_regmap;
+               max->desc.vsel_reg = max->curr_vout_reg;
+               max->desc.vsel_mask = MAX8973_VOUT_MASK;
        }
 
        if (pdata_from_dt)
@@ -613,6 +691,8 @@ static int max8973_probe(struct i2c_client *client,
                max->ops.enable = regulator_enable_regmap;
                max->ops.disable = regulator_disable_regmap;
                max->ops.is_enabled = regulator_is_enabled_regmap;
+               max->ops.set_current_limit = max8973_set_current_limit;
+               max->ops.get_current_limit = max8973_get_current_limit;
                break;
        default:
                break;
@@ -652,7 +732,6 @@ static struct i2c_driver max8973_i2c_driver = {
        .driver = {
                .name = "max8973",
                .of_match_table = of_max8973_match_tbl,
-               .owner = THIS_MODULE,
        },
        .probe = max8973_probe,
        .id_table = max8973_id,
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
new file mode 100644 (file)
index 0000000..02c4e5f
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Henry Chen <henryc.chen@mediatek.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.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/mt6311.h>
+#include <linux/slab.h>
+#include "mt6311-regulator.h"
+
+static const struct regmap_config mt6311_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MT6311_FQMTR_CON4,
+};
+
+/* Default limits measured in millivolts and milliamps */
+#define MT6311_MIN_UV          600000
+#define MT6311_MAX_UV          1393750
+#define MT6311_STEP_UV         6250
+
+static const struct regulator_linear_range buck_volt_range[] = {
+       REGULATOR_LINEAR_RANGE(MT6311_MIN_UV, 0, 0x7f, MT6311_STEP_UV),
+};
+
+static const struct regulator_ops mt6311_buck_ops = {
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_ops mt6311_ldo_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+};
+
+#define MT6311_BUCK(_id) \
+{\
+       .name = #_id,\
+       .ops = &mt6311_buck_ops,\
+       .of_match = of_match_ptr(#_id),\
+       .regulators_node = of_match_ptr("regulators"),\
+       .type = REGULATOR_VOLTAGE,\
+       .id = MT6311_ID_##_id,\
+       .n_voltages = (MT6311_MAX_UV - MT6311_MIN_UV) / MT6311_STEP_UV + 1,\
+       .min_uV = MT6311_MIN_UV,\
+       .uV_step = MT6311_STEP_UV,\
+       .owner = THIS_MODULE,\
+       .linear_ranges = buck_volt_range, \
+       .n_linear_ranges = ARRAY_SIZE(buck_volt_range), \
+       .enable_reg = MT6311_VDVFS11_CON9,\
+       .enable_mask = MT6311_PMIC_VDVFS11_EN_MASK,\
+       .vsel_reg = MT6311_VDVFS11_CON12,\
+       .vsel_mask = MT6311_PMIC_VDVFS11_VOSEL_MASK,\
+}
+
+#define MT6311_LDO(_id) \
+{\
+       .name = #_id,\
+       .ops = &mt6311_ldo_ops,\
+       .of_match = of_match_ptr(#_id),\
+       .regulators_node = of_match_ptr("regulators"),\
+       .type = REGULATOR_VOLTAGE,\
+       .id = MT6311_ID_##_id,\
+       .owner = THIS_MODULE,\
+       .enable_reg = MT6311_LDO_CON3,\
+       .enable_mask = MT6311_PMIC_RG_VBIASN_EN_MASK,\
+}
+
+static const struct regulator_desc mt6311_regulators[] = {
+       MT6311_BUCK(VDVFS),
+       MT6311_LDO(VBIASN),
+};
+
+/*
+ * I2C driver interface functions
+ */
+static int mt6311_i2c_probe(struct i2c_client *i2c,
+               const struct i2c_device_id *id)
+{
+       struct regulator_config config = { };
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       int i, ret;
+       unsigned int data;
+
+       regmap = devm_regmap_init_i2c(i2c, &mt6311_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       ret = regmap_read(regmap, MT6311_SWCID, &data);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read DEVICE_ID reg: %d\n", ret);
+               return ret;
+       }
+
+       switch (data) {
+       case MT6311_E1_CID_CODE:
+       case MT6311_E2_CID_CODE:
+       case MT6311_E3_CID_CODE:
+               break;
+       default:
+               dev_err(&i2c->dev, "Unsupported device id = 0x%x.\n", data);
+               return -ENODEV;
+       }
+
+       for (i = 0; i < MT6311_MAX_REGULATORS; i++) {
+               config.dev = &i2c->dev;
+               config.regmap = regmap;
+
+               rdev = devm_regulator_register(&i2c->dev,
+                       &mt6311_regulators[i], &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&i2c->dev,
+                               "Failed to register MT6311 regulator\n");
+                       return PTR_ERR(rdev);
+               }
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id mt6311_i2c_id[] = {
+       {"mt6311", 0},
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id mt6311_dt_ids[] = {
+       { .compatible = "mediatek,mt6311-regulator",
+         .data = &mt6311_i2c_id[0] },
+       {},
+};
+MODULE_DEVICE_TABLE(of, mt6311_dt_ids);
+#endif
+
+static struct i2c_driver mt6311_regulator_driver = {
+       .driver = {
+               .name = "mt6311",
+               .of_match_table = of_match_ptr(mt6311_dt_ids),
+       },
+       .probe = mt6311_i2c_probe,
+       .id_table = mt6311_i2c_id,
+};
+
+module_i2c_driver(mt6311_regulator_driver);
+
+MODULE_AUTHOR("Henry Chen <henryc.chen@mediatek.com>");
+MODULE_DESCRIPTION("Regulator device driver for Mediatek MT6311");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/mt6311-regulator.h b/drivers/regulator/mt6311-regulator.h
new file mode 100644 (file)
index 0000000..5218db4
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Henry Chen <henryc.chen@mediatek.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.
+ */
+
+#ifndef __MT6311_REGULATOR_H__
+#define __MT6311_REGULATOR_H__
+
+#define MT6311_SWCID              0x01
+
+#define MT6311_TOP_INT_CON        0x18
+#define MT6311_TOP_INT_MON        0x19
+
+#define MT6311_VDVFS11_CON0       0x87
+#define MT6311_VDVFS11_CON7       0x88
+#define MT6311_VDVFS11_CON8       0x89
+#define MT6311_VDVFS11_CON9       0x8A
+#define MT6311_VDVFS11_CON10      0x8B
+#define MT6311_VDVFS11_CON11      0x8C
+#define MT6311_VDVFS11_CON12      0x8D
+#define MT6311_VDVFS11_CON13      0x8E
+#define MT6311_VDVFS11_CON14      0x8F
+#define MT6311_VDVFS11_CON15      0x90
+#define MT6311_VDVFS11_CON16      0x91
+#define MT6311_VDVFS11_CON17      0x92
+#define MT6311_VDVFS11_CON18      0x93
+#define MT6311_VDVFS11_CON19      0x94
+
+#define MT6311_LDO_CON0           0xCC
+#define MT6311_LDO_OCFB0          0xCD
+#define MT6311_LDO_CON2           0xCE
+#define MT6311_LDO_CON3           0xCF
+#define MT6311_LDO_CON4           0xD0
+#define MT6311_FQMTR_CON0         0xD1
+#define MT6311_FQMTR_CON1         0xD2
+#define MT6311_FQMTR_CON2         0xD3
+#define MT6311_FQMTR_CON3         0xD4
+#define MT6311_FQMTR_CON4         0xD5
+
+#define MT6311_PMIC_RG_INT_POL_MASK                      0x1
+#define MT6311_PMIC_RG_INT_EN_MASK                       0x2
+#define MT6311_PMIC_RG_BUCK_OC_INT_STATUS_MASK           0x10
+
+#define MT6311_PMIC_VDVFS11_EN_CTRL_MASK                 0x1
+#define MT6311_PMIC_VDVFS11_VOSEL_CTRL_MASK              0x2
+#define MT6311_PMIC_VDVFS11_EN_SEL_MASK                  0x3
+#define MT6311_PMIC_VDVFS11_VOSEL_SEL_MASK               0xc
+#define MT6311_PMIC_VDVFS11_EN_MASK                      0x1
+#define MT6311_PMIC_VDVFS11_VOSEL_MASK                   0x7F
+#define MT6311_PMIC_VDVFS11_VOSEL_ON_MASK                0x7F
+#define MT6311_PMIC_VDVFS11_VOSEL_SLEEP_MASK             0x7F
+#define MT6311_PMIC_NI_VDVFS11_VOSEL_MASK                0x7F
+
+#define MT6311_PMIC_RG_VBIASN_EN_MASK                    0x1
+
+#endif
index b1c485b24ab246234edbab2dfb4217e4fe1df833..250700c853bfa524991f6721256fb02876f54799 100644 (file)
@@ -107,6 +107,9 @@ static void of_get_regulation_constraints(struct device_node *np,
        if (!of_property_read_u32(np, "regulator-system-load", &pval))
                constraints->system_load = pval;
 
+       constraints->over_current_protection = of_property_read_bool(np,
+                                       "regulator-over-current-protection");
+
        for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
                switch (i) {
                case PM_SUSPEND_MEM:
index bd2b75c0d1d1201663cc29fd2b26100de3671459..4fa7bcaf454e85e9c4d239c5b6214e340f873c19 100644 (file)
@@ -30,6 +30,7 @@
 struct pbias_reg_info {
        u32 enable;
        u32 enable_mask;
+       u32 disable_val;
        u32 vmode;
        unsigned int enable_time;
        char *name;
@@ -62,6 +63,7 @@ static const struct pbias_reg_info pbias_mmc_omap2430 = {
        .enable = BIT(1),
        .enable_mask = BIT(1),
        .vmode = BIT(0),
+       .disable_val = 0,
        .enable_time = 100,
        .name = "pbias_mmc_omap2430"
 };
@@ -77,6 +79,7 @@ static const struct pbias_reg_info pbias_sim_omap3 = {
 static const struct pbias_reg_info pbias_mmc_omap4 = {
        .enable = BIT(26) | BIT(22),
        .enable_mask = BIT(26) | BIT(25) | BIT(22),
+       .disable_val = BIT(25),
        .vmode = BIT(21),
        .enable_time = 100,
        .name = "pbias_mmc_omap4"
@@ -85,6 +88,7 @@ static const struct pbias_reg_info pbias_mmc_omap4 = {
 static const struct pbias_reg_info pbias_mmc_omap5 = {
        .enable = BIT(27) | BIT(26),
        .enable_mask = BIT(27) | BIT(25) | BIT(26),
+       .disable_val = BIT(25),
        .vmode = BIT(21),
        .enable_time = 100,
        .name = "pbias_mmc_omap5"
@@ -159,6 +163,7 @@ static int pbias_regulator_probe(struct platform_device *pdev)
                drvdata[data_idx].desc.enable_reg = res->start;
                drvdata[data_idx].desc.enable_mask = info->enable_mask;
                drvdata[data_idx].desc.enable_val = info->enable;
+               drvdata[data_idx].desc.disable_val = info->disable_val;
 
                cfg.init_data = pbias_matches[idx].init_data;
                cfg.driver_data = &drvdata[data_idx];
index 8cc8d1877c446a48737b5d337f9faf91dc6c37e1..2a44e5dd9c2a159b0efc5022fd205c34a9408e80 100644 (file)
@@ -643,7 +643,6 @@ static struct i2c_driver pfuze_driver = {
        .id_table = pfuze_device_id,
        .driver = {
                .name = "pfuze100-regulator",
-               .owner = THIS_MODULE,
                .of_match_table = pfuze_dt_ids,
        },
        .probe = pfuze100_regulator_probe,
@@ -653,4 +652,3 @@ module_i2c_driver(pfuze_driver);
 MODULE_AUTHOR("Robin Gong <b38343@freescale.com>");
 MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/PFUZE200 PMIC");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:pfuze100-regulator");
index ffa96124a5e7206f4f86f7025098a3744f9ec315..fc3166dfcbfaa455b5105ef8e7715d3e17c56d6b 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/pwm.h>
 
 struct pwm_regulator_data {
-       struct pwm_voltages *duty_cycle_table;
+       /*  Shared */
        struct pwm_device *pwm;
+
+       /* Voltage table */
+       struct pwm_voltages *duty_cycle_table;
        int state;
+
+       /* Continuous voltage */
+       int volt_uV;
 };
 
 struct pwm_voltages {
@@ -31,6 +38,9 @@ struct pwm_voltages {
        unsigned int dutycycle;
 };
 
+/**
+ * Voltage table call-backs
+ */
 static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
@@ -79,29 +89,129 @@ static int pwm_regulator_list_voltage(struct regulator_dev *rdev,
        return drvdata->duty_cycle_table[selector].uV;
 }
 
-static struct regulator_ops pwm_regulator_voltage_ops = {
+/**
+ * Continuous voltage call-backs
+ */
+static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, int req_uV)
+{
+       int min_uV = rdev->constraints->min_uV;
+       int max_uV = rdev->constraints->max_uV;
+       int diff = max_uV - min_uV;
+
+       return 100 - (((req_uV * 100) - (min_uV * 100)) / diff);
+}
+
+static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
+{
+       struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
+
+       return drvdata->volt_uV;
+}
+
+static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
+                                       int min_uV, int max_uV,
+                                       unsigned *selector)
+{
+       struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
+       unsigned int ramp_delay = rdev->constraints->ramp_delay;
+       unsigned int period = pwm_get_period(drvdata->pwm);
+       int duty_cycle;
+       int ret;
+
+       duty_cycle = pwm_voltage_to_duty_cycle_percentage(rdev, min_uV);
+
+       ret = pwm_config(drvdata->pwm, (period / 100) * duty_cycle, period);
+       if (ret) {
+               dev_err(&rdev->dev, "Failed to configure PWM\n");
+               return ret;
+       }
+
+       ret = pwm_enable(drvdata->pwm);
+       if (ret) {
+               dev_err(&rdev->dev, "Failed to enable PWM\n");
+               return ret;
+       }
+       drvdata->volt_uV = min_uV;
+
+       /* Delay required by PWM regulator to settle to the new voltage */
+       usleep_range(ramp_delay, ramp_delay + 1000);
+
+       return 0;
+}
+
+static struct regulator_ops pwm_regulator_voltage_table_ops = {
        .set_voltage_sel = pwm_regulator_set_voltage_sel,
        .get_voltage_sel = pwm_regulator_get_voltage_sel,
        .list_voltage    = pwm_regulator_list_voltage,
        .map_voltage     = regulator_map_voltage_iterate,
 };
 
+static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
+       .get_voltage = pwm_regulator_get_voltage,
+       .set_voltage = pwm_regulator_set_voltage,
+};
+
 static struct regulator_desc pwm_regulator_desc = {
        .name           = "pwm-regulator",
-       .ops            = &pwm_regulator_voltage_ops,
        .type           = REGULATOR_VOLTAGE,
        .owner          = THIS_MODULE,
        .supply_name    = "pwm",
 };
 
+static int pwm_regulator_init_table(struct platform_device *pdev,
+                                   struct pwm_regulator_data *drvdata)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct pwm_voltages *duty_cycle_table;
+       unsigned int length = 0;
+       int ret;
+
+       of_find_property(np, "voltage-table", &length);
+
+       if ((length < sizeof(*duty_cycle_table)) ||
+           (length % sizeof(*duty_cycle_table))) {
+               dev_err(&pdev->dev,
+                       "voltage-table length(%d) is invalid\n",
+                       length);
+               return -EINVAL;
+       }
+
+       duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
+       if (!duty_cycle_table)
+               return -ENOMEM;
+
+       ret = of_property_read_u32_array(np, "voltage-table",
+                                        (u32 *)duty_cycle_table,
+                                        length / sizeof(u32));
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to read voltage-table\n");
+               return ret;
+       }
+
+       drvdata->duty_cycle_table       = duty_cycle_table;
+       pwm_regulator_desc.ops          = &pwm_regulator_voltage_table_ops;
+       pwm_regulator_desc.n_voltages   = length / sizeof(*duty_cycle_table);
+
+       return 0;
+}
+
+static int pwm_regulator_init_continuous(struct platform_device *pdev,
+                                        struct pwm_regulator_data *drvdata)
+{
+       pwm_regulator_desc.ops = &pwm_regulator_voltage_continuous_ops;
+       pwm_regulator_desc.continuous_voltage_range = true;
+
+       return 0;
+}
+
 static int pwm_regulator_probe(struct platform_device *pdev)
 {
+       const struct regulator_init_data *init_data;
        struct pwm_regulator_data *drvdata;
-       struct property *prop;
        struct regulator_dev *regulator;
        struct regulator_config config = { };
        struct device_node *np = pdev->dev.of_node;
-       int length, ret;
+       int ret;
 
        if (!np) {
                dev_err(&pdev->dev, "Device Tree node missing\n");
@@ -112,44 +222,22 @@ static int pwm_regulator_probe(struct platform_device *pdev)
        if (!drvdata)
                return -ENOMEM;
 
-       /* determine the number of voltage-table */
-       prop = of_find_property(np, "voltage-table", &length);
-       if (!prop) {
-               dev_err(&pdev->dev, "No voltage-table\n");
-               return -EINVAL;
-       }
-
-       if ((length < sizeof(*drvdata->duty_cycle_table)) ||
-           (length % sizeof(*drvdata->duty_cycle_table))) {
-               dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n",
-                       length);
-               return -EINVAL;
-       }
-
-       pwm_regulator_desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table);
-
-       drvdata->duty_cycle_table = devm_kzalloc(&pdev->dev,
-                                                length, GFP_KERNEL);
-       if (!drvdata->duty_cycle_table)
-               return -ENOMEM;
-
-       /* read voltage table from DT property */
-       ret = of_property_read_u32_array(np, "voltage-table",
-                                        (u32 *)drvdata->duty_cycle_table,
-                                        length / sizeof(u32));
-       if (ret < 0) {
-               dev_err(&pdev->dev, "read voltage-table failed\n");
+       if (of_find_property(np, "voltage-table", NULL))
+               ret = pwm_regulator_init_table(pdev, drvdata);
+       else
+               ret = pwm_regulator_init_continuous(pdev, drvdata);
+       if (ret)
                return ret;
-       }
 
-       config.init_data = of_get_regulator_init_data(&pdev->dev, np,
-                                                     &pwm_regulator_desc);
-       if (!config.init_data)
+       init_data = of_get_regulator_init_data(&pdev->dev, np,
+                                              &pwm_regulator_desc);
+       if (!init_data)
                return -ENOMEM;
 
        config.of_node = np;
        config.dev = &pdev->dev;
        config.driver_data = drvdata;
+       config.init_data = init_data;
 
        drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
        if (IS_ERR(drvdata->pwm)) {
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
new file mode 100644 (file)
index 0000000..9c6167d
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2015, Sony Mobile Communications AB.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+struct qcom_rpm_reg {
+       struct device *dev;
+
+       struct qcom_smd_rpm *rpm;
+
+       u32 type;
+       u32 id;
+
+       struct regulator_desc desc;
+
+       int is_enabled;
+       int uV;
+};
+
+struct rpm_regulator_req {
+       u32 key;
+       u32 nbytes;
+       u32 value;
+};
+
+#define RPM_KEY_SWEN   0x6e657773 /* "swen" */
+#define RPM_KEY_UV     0x00007675 /* "uv" */
+#define RPM_KEY_MA     0x0000616d /* "ma" */
+
+static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
+                               struct rpm_regulator_req *req,
+                               size_t size)
+{
+       return qcom_rpm_smd_write(vreg->rpm,
+                                 QCOM_SMD_RPM_ACTIVE_STATE,
+                                 vreg->type,
+                                 vreg->id,
+                                 req, size);
+}
+
+static int rpm_reg_enable(struct regulator_dev *rdev)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+       struct rpm_regulator_req req;
+       int ret;
+
+       req.key = RPM_KEY_SWEN;
+       req.nbytes = sizeof(u32);
+       req.value = 1;
+
+       ret = rpm_reg_write_active(vreg, &req, sizeof(req));
+       if (!ret)
+               vreg->is_enabled = 1;
+
+       return ret;
+}
+
+static int rpm_reg_is_enabled(struct regulator_dev *rdev)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+
+       return vreg->is_enabled;
+}
+
+static int rpm_reg_disable(struct regulator_dev *rdev)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+       struct rpm_regulator_req req;
+       int ret;
+
+       req.key = RPM_KEY_SWEN;
+       req.nbytes = sizeof(u32);
+       req.value = 0;
+
+       ret = rpm_reg_write_active(vreg, &req, sizeof(req));
+       if (!ret)
+               vreg->is_enabled = 0;
+
+       return ret;
+}
+
+static int rpm_reg_get_voltage(struct regulator_dev *rdev)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+
+       return vreg->uV;
+}
+
+static int rpm_reg_set_voltage(struct regulator_dev *rdev,
+                              int min_uV,
+                              int max_uV,
+                              unsigned *selector)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+       struct rpm_regulator_req req;
+       int ret = 0;
+
+       req.key = RPM_KEY_UV;
+       req.nbytes = sizeof(u32);
+       req.value = min_uV;
+
+       ret = rpm_reg_write_active(vreg, &req, sizeof(req));
+       if (!ret)
+               vreg->uV = min_uV;
+
+       return ret;
+}
+
+static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
+{
+       struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
+       struct rpm_regulator_req req;
+
+       req.key = RPM_KEY_MA;
+       req.nbytes = sizeof(u32);
+       req.value = load_uA;
+
+       return rpm_reg_write_active(vreg, &req, sizeof(req));
+}
+
+static const struct regulator_ops rpm_smps_ldo_ops = {
+       .enable = rpm_reg_enable,
+       .disable = rpm_reg_disable,
+       .is_enabled = rpm_reg_is_enabled,
+
+       .get_voltage = rpm_reg_get_voltage,
+       .set_voltage = rpm_reg_set_voltage,
+
+       .set_load = rpm_reg_set_load,
+};
+
+static const struct regulator_ops rpm_switch_ops = {
+       .enable = rpm_reg_enable,
+       .disable = rpm_reg_disable,
+       .is_enabled = rpm_reg_is_enabled,
+};
+
+static const struct regulator_desc pm8x41_hfsmps = {
+       .linear_ranges = (struct regulator_linear_range[]) {
+               REGULATOR_LINEAR_RANGE( 375000,  0,  95, 12500),
+               REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
+       },
+       .n_linear_ranges = 2,
+       .n_voltages = 159,
+       .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8841_ftsmps = {
+       .linear_ranges = (struct regulator_linear_range[]) {
+               REGULATOR_LINEAR_RANGE(350000,  0, 184, 5000),
+               REGULATOR_LINEAR_RANGE(700000, 185, 339, 10000),
+       },
+       .n_linear_ranges = 2,
+       .n_voltages = 340,
+       .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8941_boost = {
+       .linear_ranges = (struct regulator_linear_range[]) {
+               REGULATOR_LINEAR_RANGE(4000000, 0, 15, 100000),
+       },
+       .n_linear_ranges = 1,
+       .n_voltages = 16,
+       .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8941_pldo = {
+       .linear_ranges = (struct regulator_linear_range[]) {
+               REGULATOR_LINEAR_RANGE( 750000,  0,  30, 25000),
+               REGULATOR_LINEAR_RANGE(1500000, 31, 99, 50000),
+       },
+       .n_linear_ranges = 2,
+       .n_voltages = 100,
+       .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8941_nldo = {
+       .linear_ranges = (struct regulator_linear_range[]) {
+               REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
+       },
+       .n_linear_ranges = 1,
+       .n_voltages = 64,
+       .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8941_lnldo = {
+       .fixed_uV = 1740000,
+       .n_voltages = 1,
+       .ops = &rpm_smps_ldo_ops,
+};
+
+static const struct regulator_desc pm8941_switch = {
+       .ops = &rpm_switch_ops,
+};
+
+struct rpm_regulator_data {
+       const char *name;
+       u32 type;
+       u32 id;
+       const struct regulator_desc *desc;
+       const char *supply;
+};
+
+static const struct rpm_regulator_data rpm_pm8841_regulators[] = {
+       { "s1", QCOM_SMD_RPM_SMPB, 1, &pm8x41_hfsmps, "vdd_s1" },
+       { "s2", QCOM_SMD_RPM_SMPB, 2, &pm8841_ftsmps, "vdd_s2" },
+       { "s3", QCOM_SMD_RPM_SMPB, 3, &pm8x41_hfsmps, "vdd_s3" },
+       { "s4", QCOM_SMD_RPM_SMPB, 4, &pm8841_ftsmps, "vdd_s4" },
+       { "s5", QCOM_SMD_RPM_SMPB, 5, &pm8841_ftsmps, "vdd_s5" },
+       { "s6", QCOM_SMD_RPM_SMPB, 6, &pm8841_ftsmps, "vdd_s6" },
+       { "s7", QCOM_SMD_RPM_SMPB, 7, &pm8841_ftsmps, "vdd_s7" },
+       { "s8", QCOM_SMD_RPM_SMPB, 8, &pm8841_ftsmps, "vdd_s8" },
+       {}
+};
+
+static const struct rpm_regulator_data rpm_pm8941_regulators[] = {
+       { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8x41_hfsmps, "vdd_s1" },
+       { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8x41_hfsmps, "vdd_s2" },
+       { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8x41_hfsmps, "vdd_s3" },
+       { "s4", QCOM_SMD_RPM_BOOST, 1, &pm8941_boost },
+
+       { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8941_nldo, "vdd_l1_l3" },
+       { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8941_nldo, "vdd_l2_lvs1_2_3" },
+       { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8941_nldo, "vdd_l1_l3" },
+       { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8941_nldo, "vdd_l4_l11" },
+       { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8941_lnldo, "vdd_l5_l7" },
+       { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
+       { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8941_lnldo, "vdd_l5_l7" },
+       { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
+       { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
+       { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
+       { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8941_nldo, "vdd_l4_l11" },
+       { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
+       { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
+       { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
+       { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
+       { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
+       { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
+       { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
+       { "l19", QCOM_SMD_RPM_LDOA, 19, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
+       { "l20", QCOM_SMD_RPM_LDOA, 20, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
+       { "l21", QCOM_SMD_RPM_LDOA, 21, &pm8941_pldo, "vdd_l21" },
+       { "l22", QCOM_SMD_RPM_LDOA, 22, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
+       { "l23", QCOM_SMD_RPM_LDOA, 23, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
+       { "l24", QCOM_SMD_RPM_LDOA, 24, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
+
+       { "lvs1", QCOM_SMD_RPM_VSA, 1, &pm8941_switch, "vdd_l2_lvs1_2_3" },
+       { "lvs2", QCOM_SMD_RPM_VSA, 2, &pm8941_switch, "vdd_l2_lvs1_2_3" },
+       { "lvs3", QCOM_SMD_RPM_VSA, 3, &pm8941_switch, "vdd_l2_lvs1_2_3" },
+
+       { "5vs1", QCOM_SMD_RPM_VSA, 4, &pm8941_switch, "vin_5vs" },
+       { "5vs2", QCOM_SMD_RPM_VSA, 5, &pm8941_switch, "vin_5vs" },
+
+       {}
+};
+
+static const struct of_device_id rpm_of_match[] = {
+       { .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
+       { .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
+       {}
+};
+MODULE_DEVICE_TABLE(of, rpm_of_match);
+
+static int rpm_reg_probe(struct platform_device *pdev)
+{
+       const struct rpm_regulator_data *reg;
+       const struct of_device_id *match;
+       struct regulator_config config = { };
+       struct regulator_dev *rdev;
+       struct qcom_rpm_reg *vreg;
+       struct qcom_smd_rpm *rpm;
+
+       rpm = dev_get_drvdata(pdev->dev.parent);
+       if (!rpm) {
+               dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
+               return -ENODEV;
+       }
+
+       match = of_match_device(rpm_of_match, &pdev->dev);
+       for (reg = match->data; reg->name; reg++) {
+               vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
+               if (!vreg)
+                       return -ENOMEM;
+
+               vreg->dev = &pdev->dev;
+               vreg->type = reg->type;
+               vreg->id = reg->id;
+               vreg->rpm = rpm;
+
+               memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc));
+
+               vreg->desc.id = -1;
+               vreg->desc.owner = THIS_MODULE;
+               vreg->desc.type = REGULATOR_VOLTAGE;
+               vreg->desc.name = reg->name;
+               vreg->desc.supply_name = reg->supply;
+               vreg->desc.of_match = reg->name;
+
+               config.dev = &pdev->dev;
+               config.driver_data = vreg;
+               rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register %s\n", reg->name);
+                       return PTR_ERR(rdev);
+               }
+       }
+
+       return 0;
+}
+
+static struct platform_driver rpm_reg_driver = {
+       .probe = rpm_reg_probe,
+       .driver = {
+               .name  = "qcom_rpm_smd_regulator",
+               .of_match_table = rpm_of_match,
+       },
+};
+
+static int __init rpm_reg_init(void)
+{
+       return platform_driver_register(&rpm_reg_driver);
+}
+subsys_initcall(rpm_reg_init);
+
+static void __exit rpm_reg_exit(void)
+{
+       platform_driver_unregister(&rpm_reg_driver);
+}
+module_exit(rpm_reg_exit)
+
+MODULE_DESCRIPTION("Qualcomm RPM regulator driver");
+MODULE_LICENSE("GPL v2");
index 850a30a95b5b82149ed183960f9b746c88f764b6..88a5dc88badc7e0c72b1deb770dd1128a8cfa661 100644 (file)
 #include <linux/regmap.h>
 #include <linux/list.h>
 
+/* Pin control enable input pins. */
+#define SPMI_REGULATOR_PIN_CTRL_ENABLE_NONE            0x00
+#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN0             0x01
+#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN1             0x02
+#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN2             0x04
+#define SPMI_REGULATOR_PIN_CTRL_ENABLE_EN3             0x08
+#define SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT      0x10
+
+/* Pin control high power mode input pins. */
+#define SPMI_REGULATOR_PIN_CTRL_HPM_NONE               0x00
+#define SPMI_REGULATOR_PIN_CTRL_HPM_EN0                        0x01
+#define SPMI_REGULATOR_PIN_CTRL_HPM_EN1                        0x02
+#define SPMI_REGULATOR_PIN_CTRL_HPM_EN2                        0x04
+#define SPMI_REGULATOR_PIN_CTRL_HPM_EN3                        0x08
+#define SPMI_REGULATOR_PIN_CTRL_HPM_SLEEP_B            0x10
+#define SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT         0x20
+
+/*
+ * Used with enable parameters to specify that hardware default register values
+ * should be left unaltered.
+ */
+#define SPMI_REGULATOR_USE_HW_DEFAULT                  2
+
+/* Soft start strength of a voltage switch type regulator */
+enum spmi_vs_soft_start_str {
+       SPMI_VS_SOFT_START_STR_0P05_UA = 0,
+       SPMI_VS_SOFT_START_STR_0P25_UA,
+       SPMI_VS_SOFT_START_STR_0P55_UA,
+       SPMI_VS_SOFT_START_STR_0P75_UA,
+       SPMI_VS_SOFT_START_STR_HW_DEFAULT,
+};
+
+/**
+ * struct spmi_regulator_init_data - spmi-regulator initialization data
+ * @pin_ctrl_enable:        Bit mask specifying which hardware pins should be
+ *                             used to enable the regulator, if any
+ *                         Value should be an ORing of
+ *                             SPMI_REGULATOR_PIN_CTRL_ENABLE_* constants.  If
+ *                             the bit specified by
+ *                             SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT is
+ *                             set, then pin control enable hardware registers
+ *                             will not be modified.
+ * @pin_ctrl_hpm:           Bit mask specifying which hardware pins should be
+ *                             used to force the regulator into high power
+ *                             mode, if any
+ *                         Value should be an ORing of
+ *                             SPMI_REGULATOR_PIN_CTRL_HPM_* constants.  If
+ *                             the bit specified by
+ *                             SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT is
+ *                             set, then pin control mode hardware registers
+ *                             will not be modified.
+ * @vs_soft_start_strength: This parameter sets the soft start strength for
+ *                             voltage switch type regulators.  Its value
+ *                             should be one of SPMI_VS_SOFT_START_STR_*.  If
+ *                             its value is SPMI_VS_SOFT_START_STR_HW_DEFAULT,
+ *                             then the soft start strength will be left at its
+ *                             default hardware value.
+ */
+struct spmi_regulator_init_data {
+       unsigned                                pin_ctrl_enable;
+       unsigned                                pin_ctrl_hpm;
+       enum spmi_vs_soft_start_str             vs_soft_start_strength;
+};
+
 /* These types correspond to unique register layouts. */
 enum spmi_regulator_logical_type {
        SPMI_REGULATOR_LOGICAL_TYPE_SMPS,
@@ -458,6 +522,14 @@ static int spmi_regulator_vs_enable(struct regulator_dev *rdev)
        return spmi_regulator_common_enable(rdev);
 }
 
+static int spmi_regulator_vs_ocp(struct regulator_dev *rdev)
+{
+       struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
+       u8 reg = SPMI_VS_OCP_OVERRIDE;
+
+       return spmi_vreg_write(vreg, SPMI_VS_REG_OCP, &reg, 1);
+}
+
 static int spmi_regulator_common_disable(struct regulator_dev *rdev)
 {
        struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
@@ -504,8 +576,7 @@ static int spmi_regulator_select_voltage(struct spmi_regulator *vreg,
         * Force uV to be an allowed set point by applying a ceiling function to
         * the uV value.
         */
-       *voltage_sel = (uV - range->min_uV + range->step_uV - 1)
-                       / range->step_uV;
+       *voltage_sel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV);
        uV = *voltage_sel * range->step_uV + range->min_uV;
 
        if (uV > max_uV) {
@@ -792,6 +863,9 @@ static unsigned int spmi_regulator_common_get_mode(struct regulator_dev *rdev)
        if (reg & SPMI_COMMON_MODE_HPM_MASK)
                return REGULATOR_MODE_NORMAL;
 
+       if (reg & SPMI_COMMON_MODE_AUTO_MASK)
+               return REGULATOR_MODE_FAST;
+
        return REGULATOR_MODE_IDLE;
 }
 
@@ -799,11 +873,13 @@ static int
 spmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct spmi_regulator *vreg = rdev_get_drvdata(rdev);
-       u8 mask = SPMI_COMMON_MODE_HPM_MASK;
+       u8 mask = SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK;
        u8 val = 0;
 
        if (mode == REGULATOR_MODE_NORMAL)
-               val = mask;
+               val = SPMI_COMMON_MODE_HPM_MASK;
+       else if (mode == REGULATOR_MODE_FAST)
+               val = SPMI_COMMON_MODE_AUTO_MASK;
 
        return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask);
 }
@@ -973,6 +1049,7 @@ static struct regulator_ops spmi_vs_ops = {
        .is_enabled             = spmi_regulator_common_is_enabled,
        .set_pull_down          = spmi_regulator_common_set_pull_down,
        .set_soft_start         = spmi_regulator_common_set_soft_start,
+       .set_over_current_protection = spmi_regulator_vs_ocp,
 };
 
 static struct regulator_ops spmi_boost_ops = {
@@ -1203,10 +1280,111 @@ static int spmi_regulator_ftsmps_init_slew_rate(struct spmi_regulator *vreg)
        return ret;
 }
 
+static int spmi_regulator_init_registers(struct spmi_regulator *vreg,
+                               const struct spmi_regulator_init_data *data)
+{
+       int ret;
+       enum spmi_regulator_logical_type type;
+       u8 ctrl_reg[8], reg, mask;
+
+       type = vreg->logical_type;
+
+       ret = spmi_vreg_read(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, 8);
+       if (ret)
+               return ret;
+
+       /* Set up enable pin control. */
+       if ((type == SPMI_REGULATOR_LOGICAL_TYPE_SMPS
+            || type == SPMI_REGULATOR_LOGICAL_TYPE_LDO
+            || type == SPMI_REGULATOR_LOGICAL_TYPE_VS)
+           && !(data->pin_ctrl_enable
+                       & SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) {
+               ctrl_reg[SPMI_COMMON_IDX_ENABLE] &=
+                       ~SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK;
+               ctrl_reg[SPMI_COMMON_IDX_ENABLE] |=
+                   data->pin_ctrl_enable & SPMI_COMMON_ENABLE_FOLLOW_ALL_MASK;
+       }
+
+       /* Set up mode pin control. */
+       if ((type == SPMI_REGULATOR_LOGICAL_TYPE_SMPS
+           || type == SPMI_REGULATOR_LOGICAL_TYPE_LDO)
+               && !(data->pin_ctrl_hpm
+                       & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
+               ctrl_reg[SPMI_COMMON_IDX_MODE] &=
+                       ~SPMI_COMMON_MODE_FOLLOW_ALL_MASK;
+               ctrl_reg[SPMI_COMMON_IDX_MODE] |=
+                       data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_ALL_MASK;
+       }
+
+       if (type == SPMI_REGULATOR_LOGICAL_TYPE_VS
+          && !(data->pin_ctrl_hpm & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
+               ctrl_reg[SPMI_COMMON_IDX_MODE] &=
+                       ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+               ctrl_reg[SPMI_COMMON_IDX_MODE] |=
+                      data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+       }
+
+       if ((type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS
+               || type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS
+               || type == SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO)
+               && !(data->pin_ctrl_hpm
+                       & SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) {
+               ctrl_reg[SPMI_COMMON_IDX_MODE] &=
+                       ~SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+               ctrl_reg[SPMI_COMMON_IDX_MODE] |=
+                      data->pin_ctrl_hpm & SPMI_COMMON_MODE_FOLLOW_AWAKE_MASK;
+       }
+
+       /* Write back any control register values that were modified. */
+       ret = spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, 8);
+       if (ret)
+               return ret;
+
+       /* Set soft start strength and over current protection for VS. */
+       if (type == SPMI_REGULATOR_LOGICAL_TYPE_VS) {
+               if (data->vs_soft_start_strength
+                               != SPMI_VS_SOFT_START_STR_HW_DEFAULT) {
+                       reg = data->vs_soft_start_strength
+                               & SPMI_VS_SOFT_START_SEL_MASK;
+                       mask = SPMI_VS_SOFT_START_SEL_MASK;
+                       return spmi_vreg_update_bits(vreg,
+                                                    SPMI_VS_REG_SOFT_START,
+                                                    reg, mask);
+               }
+       }
+
+       return 0;
+}
+
+static void spmi_regulator_get_dt_config(struct spmi_regulator *vreg,
+               struct device_node *node, struct spmi_regulator_init_data *data)
+{
+       /*
+        * Initialize configuration parameters to use hardware default in case
+        * no value is specified via device tree.
+        */
+       data->pin_ctrl_enable       = SPMI_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT;
+       data->pin_ctrl_hpm          = SPMI_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT;
+       data->vs_soft_start_strength    = SPMI_VS_SOFT_START_STR_HW_DEFAULT;
+
+       /* These bindings are optional, so it is okay if they aren't found. */
+       of_property_read_u32(node, "qcom,ocp-max-retries",
+               &vreg->ocp_max_retries);
+       of_property_read_u32(node, "qcom,ocp-retry-delay",
+               &vreg->ocp_retry_delay_ms);
+       of_property_read_u32(node, "qcom,pin-ctrl-enable",
+               &data->pin_ctrl_enable);
+       of_property_read_u32(node, "qcom,pin-ctrl-hpm", &data->pin_ctrl_hpm);
+       of_property_read_u32(node, "qcom,vs-soft-start-strength",
+               &data->vs_soft_start_strength);
+}
+
 static unsigned int spmi_regulator_of_map_mode(unsigned int mode)
 {
-       if (mode)
+       if (mode == 1)
                return REGULATOR_MODE_NORMAL;
+       if (mode == 2)
+               return REGULATOR_MODE_FAST;
 
        return REGULATOR_MODE_IDLE;
 }
@@ -1215,12 +1393,23 @@ static int spmi_regulator_of_parse(struct device_node *node,
                            const struct regulator_desc *desc,
                            struct regulator_config *config)
 {
+       struct spmi_regulator_init_data data = { };
        struct spmi_regulator *vreg = config->driver_data;
        struct device *dev = config->dev;
        int ret;
 
-       vreg->ocp_max_retries = SPMI_VS_OCP_DEFAULT_MAX_RETRIES;
-       vreg->ocp_retry_delay_ms = SPMI_VS_OCP_DEFAULT_RETRY_DELAY_MS;
+       spmi_regulator_get_dt_config(vreg, node, &data);
+
+       if (!vreg->ocp_max_retries)
+               vreg->ocp_max_retries = SPMI_VS_OCP_DEFAULT_MAX_RETRIES;
+       if (!vreg->ocp_retry_delay_ms)
+               vreg->ocp_retry_delay_ms = SPMI_VS_OCP_DEFAULT_RETRY_DELAY_MS;
+
+       ret = spmi_regulator_init_registers(vreg, &data);
+       if (ret) {
+               dev_err(dev, "common initialization failed, ret=%d\n", ret);
+               return ret;
+       }
 
        if (vreg->logical_type == SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS) {
                ret = spmi_regulator_ftsmps_init_slew_rate(vreg);
index 3fd44353cc80eea153fe1118c81180b5e2d21b67..d86a3dcd61e243a806724e16da6be4db44097a45 100644 (file)
  * more details.
  */
 
-#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/mfd/rk808.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/mfd/rk808.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/gpio/consumer.h>
 
 /* Field Definitions */
 #define RK808_BUCK_VSEL_MASK   0x3f
 #define RK808_RAMP_RATE_6MV_PER_US     (2 << RK808_RAMP_RATE_OFFSET)
 #define RK808_RAMP_RATE_10MV_PER_US    (3 << RK808_RAMP_RATE_OFFSET)
 
+#define RK808_DVS2_POL         BIT(2)
+#define RK808_DVS1_POL         BIT(1)
+
 /* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */
 #define RK808_SLP_REG_OFFSET 1
 
+/* Offset from XXX_ON_VSEL to XXX_DVS_VSEL */
+#define RK808_DVS_REG_OFFSET 2
+
 /* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */
 #define RK808_SLP_SET_OFF_REG_OFFSET 2
 
+/* max steps for increase voltage of Buck1/2, equal 100mv*/
+#define MAX_STEPS_ONE_TIME 8
+
+struct rk808_regulator_data {
+       struct gpio_desc *dvs_gpio[2];
+};
+
 static const int rk808_buck_config_regs[] = {
        RK808_BUCK1_CONFIG_REG,
        RK808_BUCK2_CONFIG_REG,
@@ -70,6 +87,131 @@ static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = {
        REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000),
 };
 
+static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+       struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
+       int id = rdev->desc->id - RK808_ID_DCDC1;
+       struct gpio_desc *gpio = pdata->dvs_gpio[id];
+       unsigned int val;
+       int ret;
+
+       if (!gpio || gpiod_get_value(gpio) == 0)
+               return regulator_get_voltage_sel_regmap(rdev);
+
+       ret = regmap_read(rdev->regmap,
+                         rdev->desc->vsel_reg + RK808_DVS_REG_OFFSET,
+                         &val);
+       if (ret != 0)
+               return ret;
+
+       val &= rdev->desc->vsel_mask;
+       val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+       return val;
+}
+
+static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev,
+                                            unsigned sel)
+{
+       int ret, delta_sel;
+       unsigned int old_sel, tmp, val, mask = rdev->desc->vsel_mask;
+
+       ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+       if (ret != 0)
+               return ret;
+
+       tmp = val & ~mask;
+       old_sel = val & mask;
+       old_sel >>= ffs(mask) - 1;
+       delta_sel = sel - old_sel;
+
+       /*
+        * If directly modify the register to change the voltage, we will face
+        * the risk of overshoot. Put it into a multi-step, can effectively
+        * avoid this problem, a step is 100mv here.
+        */
+       while (delta_sel > MAX_STEPS_ONE_TIME) {
+               old_sel += MAX_STEPS_ONE_TIME;
+               val = old_sel << (ffs(mask) - 1);
+               val |= tmp;
+
+               /*
+                * i2c is 400kHz (2.5us per bit) and we must transmit _at least_
+                * 3 bytes (24 bits) plus start and stop so 26 bits.  So we've
+                * got more than 65 us between each voltage change and thus
+                * won't ramp faster than ~1500 uV / us.
+                */
+               ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, val);
+               delta_sel = sel - old_sel;
+       }
+
+       sel <<= ffs(mask) - 1;
+       val = tmp | sel;
+       ret = regmap_write(rdev->regmap, rdev->desc->vsel_reg, val);
+
+       /*
+        * When we change the voltage register directly, the ramp rate is about
+        * 100000uv/us, wait 1us to make sure the target voltage to be stable,
+        * so we needn't wait extra time after that.
+        */
+       udelay(1);
+
+       return ret;
+}
+
+static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev,
+                                        unsigned sel)
+{
+       struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
+       int id = rdev->desc->id - RK808_ID_DCDC1;
+       struct gpio_desc *gpio = pdata->dvs_gpio[id];
+       unsigned int reg = rdev->desc->vsel_reg;
+       unsigned old_sel;
+       int ret, gpio_level;
+
+       if (!gpio)
+               return rk808_buck1_2_i2c_set_voltage_sel(rdev, sel);
+
+       gpio_level = gpiod_get_value(gpio);
+       if (gpio_level == 0) {
+               reg += RK808_DVS_REG_OFFSET;
+               ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &old_sel);
+       } else {
+               ret = regmap_read(rdev->regmap,
+                                 reg + RK808_DVS_REG_OFFSET,
+                                 &old_sel);
+       }
+
+       if (ret != 0)
+               return ret;
+
+       sel <<= ffs(rdev->desc->vsel_mask) - 1;
+       sel |= old_sel & ~rdev->desc->vsel_mask;
+
+       ret = regmap_write(rdev->regmap, reg, sel);
+       if (ret)
+               return ret;
+
+       gpiod_set_value(gpio, !gpio_level);
+
+       return ret;
+}
+
+static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
+                                      unsigned int old_selector,
+                                      unsigned int new_selector)
+{
+       struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
+       int id = rdev->desc->id - RK808_ID_DCDC1;
+       struct gpio_desc *gpio = pdata->dvs_gpio[id];
+
+       /* if there is no dvs1/2 pin, we don't need wait extra time here. */
+       if (!gpio)
+               return 0;
+
+       return regulator_set_voltage_time_sel(rdev, old_selector, new_selector);
+}
+
 static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
        unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US;
@@ -137,8 +279,9 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
 static struct regulator_ops rk808_buck1_2_ops = {
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel        = rk808_buck1_2_get_voltage_sel_regmap,
+       .set_voltage_sel        = rk808_buck1_2_set_voltage_sel,
+       .set_voltage_time_sel   = rk808_buck1_2_set_voltage_time_sel,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .is_enabled             = regulator_is_enabled_regmap,
@@ -380,25 +523,69 @@ static struct of_regulator_match rk808_reg_matches[] = {
        [RK808_ID_SWITCH2]      = { .name = "SWITCH_REG2" },
 };
 
+static int rk808_regulator_dt_parse_pdata(struct device *dev,
+                                  struct device *client_dev,
+                                  struct regmap *map,
+                                  struct rk808_regulator_data *pdata)
+{
+       struct device_node *np;
+       int tmp, ret, i;
+
+       np = of_get_child_by_name(client_dev->of_node, "regulators");
+       if (!np)
+               return -ENXIO;
+
+       ret = of_regulator_match(dev, np, rk808_reg_matches,
+                                RK808_NUM_REGULATORS);
+       if (ret < 0)
+               goto dt_parse_end;
+
+       for (i = 0; i < ARRAY_SIZE(pdata->dvs_gpio); i++) {
+               pdata->dvs_gpio[i] =
+                       devm_gpiod_get_index_optional(client_dev, "dvs", i,
+                                                     GPIOD_OUT_LOW);
+               if (IS_ERR(pdata->dvs_gpio[i])) {
+                       ret = PTR_ERR(pdata->dvs_gpio[i]);
+                       dev_err(dev, "failed to get dvs%d gpio (%d)\n", i, ret);
+                       goto dt_parse_end;
+               }
+
+               if (!pdata->dvs_gpio[i]) {
+                       dev_warn(dev, "there is no dvs%d gpio\n", i);
+                       continue;
+               }
+
+               tmp = i ? RK808_DVS2_POL : RK808_DVS1_POL;
+               ret = regmap_update_bits(map, RK808_IO_POL_REG, tmp,
+                               gpiod_is_active_low(pdata->dvs_gpio[i]) ?
+                               0 : tmp);
+       }
+
+dt_parse_end:
+       of_node_put(np);
+       return ret;
+}
+
 static int rk808_regulator_probe(struct platform_device *pdev)
 {
        struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
        struct i2c_client *client = rk808->i2c;
-       struct device_node *reg_np;
        struct regulator_config config = {};
        struct regulator_dev *rk808_rdev;
+       struct rk808_regulator_data *pdata;
        int ret, i;
 
-       reg_np = of_get_child_by_name(client->dev.of_node, "regulators");
-       if (!reg_np)
-               return -ENXIO;
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
 
-       ret = of_regulator_match(&pdev->dev, reg_np, rk808_reg_matches,
-                                RK808_NUM_REGULATORS);
-       of_node_put(reg_np);
+       ret = rk808_regulator_dt_parse_pdata(&pdev->dev, &client->dev,
+                                            rk808->regmap, pdata);
        if (ret < 0)
                return ret;
 
+       platform_set_drvdata(pdev, pdata);
+
        /* Instantiate the regulators */
        for (i = 0; i < RK808_NUM_REGULATORS; i++) {
                if (!rk808_reg_matches[i].init_data ||
@@ -406,7 +593,7 @@ static int rk808_regulator_probe(struct platform_device *pdev)
                        continue;
 
                config.dev = &client->dev;
-               config.driver_data = rk808;
+               config.driver_data = pdata;
                config.regmap = rk808->regmap;
                config.of_node = rk808_reg_matches[i].of_node;
                config.init_data = rk808_reg_matches[i].init_data;
@@ -427,6 +614,7 @@ static struct platform_driver rk808_regulator_driver = {
        .probe = rk808_regulator_probe,
        .driver = {
                .name = "rk808-regulator",
+               .owner = THIS_MODULE,
        },
 };
 
index c213e37eb69e06c65a2d592c00afff2e0a92f4ef..572816e30095aebac1025e5a97343c4272cde2d5 100644 (file)
@@ -362,7 +362,6 @@ MODULE_DEVICE_TABLE(i2c, tps51632_id);
 static struct i2c_driver tps51632_i2c_driver = {
        .driver = {
                .name = "tps51632",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(tps51632_of_match),
        },
        .probe = tps51632_probe,
index a1fd626c6c966fb13dce292120278a33e378a3a2..f6a6d36a65334b60257b320870483e219e71746a 100644 (file)
@@ -515,7 +515,6 @@ MODULE_DEVICE_TABLE(i2c, tps62360_id);
 static struct i2c_driver tps62360_i2c_driver = {
        .driver = {
                .name = "tps62360",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_ptr(tps62360_of_match),
        },
        .probe = tps62360_probe,
index b941e564b3f3405a647b0d13794eed5d3dffa3fc..5cc19b44974aa69065c9eff9f8607eb41a7d928e 100644 (file)
@@ -410,7 +410,6 @@ MODULE_DEVICE_TABLE(i2c, tps_65023_id);
 static struct i2c_driver tps_65023_i2c_driver = {
        .driver = {
                .name = "tps65023",
-               .owner = THIS_MODULE,
        },
        .probe = tps_65023_probe,
        .id_table = tps_65023_id,
index 2852de05d64d5cb672d90c9a42a0d9ce20096edf..9e9d22038017a3b54ecdec3c10ad5f705f6ee777 100644 (file)
@@ -422,12 +422,12 @@ static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
                return NULL;
 
        for (i = 0; i < num; i++) {
-               int id;
+               uintptr_t 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;
+               id = (uintptr_t)tps6586x_matches[i].driver_data;
                if (id == TPS6586X_ID_SYS)
                        sys_rail = pdata->reg_init_data[i]->constraints.name;
 
index 167783fa7ac125238e88e4cc1e0ec5b3a114aba9..72c9333752339ce322cc3b47af40865e0a1e1275 100644 (file)
@@ -666,9 +666,8 @@ static int ds1374_remove(struct i2c_client *client)
 #ifdef CONFIG_RTC_DRV_DS1374_WDT
        int res;
 
-       res = misc_deregister(&ds1374_miscdev);
-       if (!res)
-               ds1374_miscdev.parent = NULL;
+       misc_deregister(&ds1374_miscdev);
+       ds1374_miscdev.parent = NULL;
        unregister_reboot_notifier(&ds1374_wdt_notifier);
 #endif
 
index ee3a6faae22a0b07a8eb8c40684e9d36c825bcfe..fe07f3139bf6fce1400ca38dba91d48064cb98bf 100644 (file)
@@ -58,7 +58,7 @@ static struct alias_server *_find_server(struct dasd_uid *uid)
                    && !strncmp(pos->uid.serial, uid->serial,
                                sizeof(uid->serial)))
                        return pos;
-       };
+       }
        return NULL;
 }
 
@@ -69,7 +69,7 @@ static struct alias_lcu *_find_lcu(struct alias_server *server,
        list_for_each_entry(pos, &server->lculist, lcu) {
                if (pos->uid.ssid == uid->ssid)
                        return pos;
-       };
+       }
        return NULL;
 }
 
@@ -97,7 +97,7 @@ static struct alias_pav_group *_find_group(struct alias_lcu *lcu,
                if (pos->uid.base_unit_addr == search_unit_addr &&
                    !strncmp(pos->uid.vduit, uid->vduit, sizeof(uid->vduit)))
                        return pos;
-       };
+       }
        return NULL;
 }
 
index 6215f6455eb84ccc876e70156279681dce0e9bc3..62a323539226dd265c27d80eef1c60a42bdcb155 100644 (file)
@@ -1036,7 +1036,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
 {
        void *conf_data;
        int conf_len, conf_data_saved;
-       int rc, path_err;
+       int rc, path_err, pos;
        __u8 lpm, opm;
        struct dasd_eckd_private *private, path_private;
        struct dasd_path *path_data;
@@ -1068,6 +1068,17 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
                        path_data->opm |= lpm;
                        continue;       /* no error */
                }
+               /* translate path mask to position in mask */
+               pos = 8 - ffs(lpm);
+               kfree(private->path_conf_data[pos]);
+               if ((__u8 *)private->path_conf_data[pos] ==
+                   private->conf_data) {
+                       private->conf_data = NULL;
+                       private->conf_len = 0;
+                       conf_data_saved = 0;
+               }
+               private->path_conf_data[pos] =
+                       (struct dasd_conf_data *) conf_data;
                /* save first valid configuration data */
                if (!conf_data_saved) {
                        kfree(private->conf_data);
@@ -1095,7 +1106,6 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
                                kfree(conf_data);
                                continue;
                        }
-
                        if (dasd_eckd_compare_path_uid(
                                    device, &path_private)) {
                                uid = &path_private.uid;
@@ -1157,9 +1167,6 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
                path_data->cablepm &= ~lpm;
                path_data->hpfpm &= ~lpm;
                path_data->cuirpm &= ~lpm;
-
-               if (conf_data != private->conf_data)
-                       kfree(conf_data);
        }
 
        return path_err;
@@ -1259,7 +1266,11 @@ static void do_path_verification_work(struct work_struct *work)
                schedule_work(work);
                return;
        }
-
+       /* check if path verification already running and delay if so */
+       if (test_and_set_bit(DASD_FLAG_PATH_VERIFY, &device->flags)) {
+               schedule_work(work);
+               return;
+       }
        opm = 0;
        npm = 0;
        ppm = 0;
@@ -1402,7 +1413,7 @@ static void do_path_verification_work(struct work_struct *work)
                device->path_data.hpfpm |= hpfpm;
                spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        }
-
+       clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags);
        dasd_put_device(device);
        if (data->isglobal)
                mutex_unlock(&dasd_path_verification_mutex);
@@ -1810,6 +1821,7 @@ out_err1:
 static void dasd_eckd_uncheck_device(struct dasd_device *device)
 {
        struct dasd_eckd_private *private;
+       int i;
 
        private = (struct dasd_eckd_private *) device->private;
        dasd_alias_disconnect_device_from_lcu(device);
@@ -1818,6 +1830,15 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
        private->vdsneq = NULL;
        private->gneq = NULL;
        private->conf_len = 0;
+       for (i = 0; i < 8; i++) {
+               kfree(private->path_conf_data[i]);
+               if ((__u8 *)private->path_conf_data[i] ==
+                   private->conf_data) {
+                       private->conf_data = NULL;
+                       private->conf_len = 0;
+               }
+               private->path_conf_data[i] = NULL;
+       }
        kfree(private->conf_data);
        private->conf_data = NULL;
 }
@@ -3968,7 +3989,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
        rc = -EFAULT;
        if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
                goto out;
-       if (is_compat_task() || sizeof(long) == 4) {
+       if (is_compat_task()) {
                /* Make sure pointers are sane even on 31 bit. */
                rc = -EINVAL;
                if ((usrparm.psf_data >> 32) != 0)
@@ -4525,12 +4546,13 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device,
        cqr->startdev = device;
        cqr->memdev = device;
        cqr->block = NULL;
-       cqr->retries = 256;
        cqr->expires = 10 * HZ;
-
-       /* we need to check for messages on exactly this path */
        set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
-       cqr->lpm = lpum;
+       /* dasd_sleep_on_immediatly does not do complex error
+        * recovery so clear erp flag and set retry counter to
+        * do basic erp */
+       clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+       cqr->retries = 256;
 
        /* Prepare for Read Subsystem Data */
        prssdp = (struct dasd_psf_prssd_data *) cqr->data;
@@ -4605,10 +4627,10 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
        psf_cuir->message_id = message_id;
        psf_cuir->cssid = sch_id.cssid;
        psf_cuir->ssid = sch_id.ssid;
-
        ccw = cqr->cpaddr;
        ccw->cmd_code = DASD_ECKD_CCW_PSF;
        ccw->cda = (__u32)(addr_t)psf_cuir;
+       ccw->flags = CCW_FLAG_SLI;
        ccw->count = sizeof(struct dasd_psf_cuir_response);
 
        cqr->startdev = device;
@@ -4618,6 +4640,7 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
        cqr->expires = 10*HZ;
        cqr->buildclk = get_tod_clock();
        cqr->status = DASD_CQR_FILLED;
+       set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
 
        rc = dasd_sleep_on(cqr);
 
@@ -4625,118 +4648,252 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
        return rc;
 }
 
-static int dasd_eckd_cuir_change_state(struct dasd_device *device, __u8 lpum)
+/*
+ * return configuration data that is referenced by record selector
+ * if a record selector is specified or per default return the
+ * conf_data pointer for the path specified by lpum
+ */
+static struct dasd_conf_data *dasd_eckd_get_ref_conf(struct dasd_device *device,
+                                                    __u8 lpum,
+                                                    struct dasd_cuir_message *cuir)
 {
-       unsigned long flags;
-       __u8 tbcpm;
+       struct dasd_eckd_private *private;
+       struct dasd_conf_data *conf_data;
+       int path, pos;
 
-       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
-       tbcpm = device->path_data.opm & ~lpum;
-       if (tbcpm) {
-               device->path_data.opm = tbcpm;
-               device->path_data.cuirpm |= lpum;
+       private = (struct dasd_eckd_private *) device->private;
+       if (cuir->record_selector == 0)
+               goto out;
+       for (path = 0x80, pos = 0; path; path >>= 1, pos++) {
+               conf_data = private->path_conf_data[pos];
+               if (conf_data->gneq.record_selector ==
+                   cuir->record_selector)
+                       return conf_data;
+       }
+out:
+       return private->path_conf_data[8 - ffs(lpum)];
+}
+
+/*
+ * This function determines the scope of a reconfiguration request by
+ * analysing the path and device selection data provided in the CUIR request.
+ * Returns a path mask containing CUIR affected paths for the give device.
+ *
+ * If the CUIR request does not contain the required information return the
+ * path mask of the path the attention message for the CUIR request was reveived
+ * on.
+ */
+static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
+                               struct dasd_cuir_message *cuir)
+{
+       struct dasd_conf_data *ref_conf_data;
+       unsigned long bitmask = 0, mask = 0;
+       struct dasd_eckd_private *private;
+       struct dasd_conf_data *conf_data;
+       unsigned int pos, path;
+       char *ref_gneq, *gneq;
+       char *ref_ned, *ned;
+       int tbcpm = 0;
+
+       /* if CUIR request does not specify the scope use the path
+          the attention message was presented on */
+       if (!cuir->ned_map ||
+           !(cuir->neq_map[0] | cuir->neq_map[1] | cuir->neq_map[2]))
+               return lpum;
+
+       private = (struct dasd_eckd_private *) device->private;
+       /* get reference conf data */
+       ref_conf_data = dasd_eckd_get_ref_conf(device, lpum, cuir);
+       /* reference ned is determined by ned_map field */
+       pos = 8 - ffs(cuir->ned_map);
+       ref_ned = (char *)&ref_conf_data->neds[pos];
+       ref_gneq = (char *)&ref_conf_data->gneq;
+       /* transfer 24 bit neq_map to mask */
+       mask = cuir->neq_map[2];
+       mask |= cuir->neq_map[1] << 8;
+       mask |= cuir->neq_map[0] << 16;
+
+       for (path = 0x80; path; path >>= 1) {
+               /* initialise data per path */
+               bitmask = mask;
+               pos = 8 - ffs(path);
+               conf_data = private->path_conf_data[pos];
+               pos = 8 - ffs(cuir->ned_map);
+               ned = (char *) &conf_data->neds[pos];
+               /* compare reference ned and per path ned */
+               if (memcmp(ref_ned, ned, sizeof(*ned)) != 0)
+                       continue;
+               gneq = (char *)&conf_data->gneq;
+               /* compare reference gneq and per_path gneq under
+                  24 bit mask where mask bit 0 equals byte 7 of
+                  the gneq and mask bit 24 equals byte 31 */
+               while (bitmask) {
+                       pos = ffs(bitmask) - 1;
+                       if (memcmp(&ref_gneq[31 - pos], &gneq[31 - pos], 1)
+                           != 0)
+                               break;
+                       clear_bit(pos, &bitmask);
+               }
+               if (bitmask)
+                       continue;
+               /* device and path match the reference values
+                  add path to CUIR scope */
+               tbcpm |= path;
+       }
+       return tbcpm;
+}
+
+static void dasd_eckd_cuir_notify_user(struct dasd_device *device,
+                                      unsigned long paths,
+                                      struct subchannel_id sch_id, int action)
+{
+       struct channel_path_desc *desc;
+       int pos;
+
+       while (paths) {
+               /* get position of bit in mask */
+               pos = ffs(paths) - 1;
+               /* get channel path descriptor from this position */
+               desc = ccw_device_get_chp_desc(device->cdev, 7 - pos);
+               if (action == CUIR_QUIESCE)
+                       pr_warn("Service on the storage server caused path "
+                               "%x.%02x to go offline", sch_id.cssid,
+                               desc ? desc->chpid : 0);
+               else if (action == CUIR_RESUME)
+                       pr_info("Path %x.%02x is back online after service "
+                               "on the storage server", sch_id.cssid,
+                               desc ? desc->chpid : 0);
+               kfree(desc);
+               clear_bit(pos, &paths);
        }
-       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
-       return tbcpm ? 0 : PSF_CUIR_LAST_PATH;
+}
+
+static int dasd_eckd_cuir_remove_path(struct dasd_device *device, __u8 lpum,
+                                     struct dasd_cuir_message *cuir)
+{
+       unsigned long tbcpm;
+
+       tbcpm = dasd_eckd_cuir_scope(device, lpum, cuir);
+       /* nothing to do if path is not in use */
+       if (!(device->path_data.opm & tbcpm))
+               return 0;
+       if (!(device->path_data.opm & ~tbcpm)) {
+               /* no path would be left if the CUIR action is taken
+                  return error */
+               return -EINVAL;
+       }
+       /* remove device from operational path mask */
+       device->path_data.opm &= ~tbcpm;
+       device->path_data.cuirpm |= tbcpm;
+       return tbcpm;
 }
 
 /*
- * walk through all devices and quiesce them
- * if it is the last path return error
+ * walk through all devices and build a path mask to quiesce them
+ * return an error if the last path to a device would be removed
  *
  * if only part of the devices are quiesced and an error
  * occurs no onlining necessary, the storage server will
  * notify the already set offline devices again
  */
 static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum,
-                                struct channel_path_desc *desc,
-                                struct subchannel_id sch_id)
+                                 struct subchannel_id sch_id,
+                                 struct dasd_cuir_message *cuir)
 {
        struct alias_pav_group *pavgroup, *tempgroup;
        struct dasd_eckd_private *private;
        struct dasd_device *dev, *n;
-       int rc;
+       unsigned long paths = 0;
+       unsigned long flags;
+       int tbcpm;
 
        private = (struct dasd_eckd_private *) device->private;
-       rc = 0;
-
        /* active devices */
-       list_for_each_entry_safe(dev, n,
-                                &private->lcu->active_devices,
+       list_for_each_entry_safe(dev, n, &private->lcu->active_devices,
                                 alias_list) {
-               rc = dasd_eckd_cuir_change_state(dev, lpum);
-               if (rc)
-                       goto out;
+               spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+               tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+               spin_unlock_irqrestore(get_ccwdev_lock(dev->cdev), flags);
+               if (tbcpm < 0)
+                       goto out_err;
+               paths |= tbcpm;
        }
-
        /* inactive devices */
-       list_for_each_entry_safe(dev, n,
-                                &private->lcu->inactive_devices,
+       list_for_each_entry_safe(dev, n, &private->lcu->inactive_devices,
                                 alias_list) {
-               rc = dasd_eckd_cuir_change_state(dev, lpum);
-               if (rc)
-                       goto out;
+               spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+               tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+               spin_unlock_irqrestore(get_ccwdev_lock(dev->cdev), flags);
+               if (tbcpm < 0)
+                       goto out_err;
+               paths |= tbcpm;
        }
-
        /* devices in PAV groups */
        list_for_each_entry_safe(pavgroup, tempgroup,
                                 &private->lcu->grouplist, group) {
                list_for_each_entry_safe(dev, n, &pavgroup->baselist,
                                         alias_list) {
-                       rc = dasd_eckd_cuir_change_state(dev, lpum);
-                       if (rc)
-                               goto out;
+                       spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+                       tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+                       spin_unlock_irqrestore(
+                               get_ccwdev_lock(dev->cdev), flags);
+                       if (tbcpm < 0)
+                               goto out_err;
+                       paths |= tbcpm;
                }
                list_for_each_entry_safe(dev, n, &pavgroup->aliaslist,
                                         alias_list) {
-                       rc = dasd_eckd_cuir_change_state(dev, lpum);
-                       if (rc)
-                               goto out;
+                       spin_lock_irqsave(get_ccwdev_lock(dev->cdev), flags);
+                       tbcpm = dasd_eckd_cuir_remove_path(dev, lpum, cuir);
+                       spin_unlock_irqrestore(
+                               get_ccwdev_lock(dev->cdev), flags);
+                       if (tbcpm < 0)
+                               goto out_err;
+                       paths |= tbcpm;
                }
        }
-
-       pr_warn("Service on the storage server caused path %x.%02x to go offline",
-               sch_id.cssid, desc ? desc->chpid : 0);
-       rc = PSF_CUIR_COMPLETED;
-out:
-       return rc;
+       /* notify user about all paths affected by CUIR action */
+       dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_QUIESCE);
+       return 0;
+out_err:
+       return tbcpm;
 }
 
 static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
-                                struct channel_path_desc *desc,
-                                struct subchannel_id sch_id)
+                                struct subchannel_id sch_id,
+                                struct dasd_cuir_message *cuir)
 {
        struct alias_pav_group *pavgroup, *tempgroup;
        struct dasd_eckd_private *private;
        struct dasd_device *dev, *n;
+       unsigned long paths = 0;
+       int tbcpm;
 
-       pr_info("Path %x.%02x is back online after service on the storage server",
-               sch_id.cssid, desc ? desc->chpid : 0);
        private = (struct dasd_eckd_private *) device->private;
-
        /*
         * the path may have been added through a generic path event before
         * only trigger path verification if the path is not already in use
         */
-
        list_for_each_entry_safe(dev, n,
                                 &private->lcu->active_devices,
                                 alias_list) {
-               if (!(dev->path_data.opm & lpum)) {
-                       dev->path_data.tbvpm |= lpum;
+               tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+               paths |= tbcpm;
+               if (!(dev->path_data.opm & tbcpm)) {
+                       dev->path_data.tbvpm |= tbcpm;
                        dasd_schedule_device_bh(dev);
                }
        }
-
        list_for_each_entry_safe(dev, n,
                                 &private->lcu->inactive_devices,
                                 alias_list) {
-               if (!(dev->path_data.opm & lpum)) {
-                       dev->path_data.tbvpm |= lpum;
+               tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+               paths |= tbcpm;
+               if (!(dev->path_data.opm & tbcpm)) {
+                       dev->path_data.tbvpm |= tbcpm;
                        dasd_schedule_device_bh(dev);
                }
        }
-
        /* devices in PAV groups */
        list_for_each_entry_safe(pavgroup, tempgroup,
                                 &private->lcu->grouplist,
@@ -4744,21 +4901,27 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
                list_for_each_entry_safe(dev, n,
                                         &pavgroup->baselist,
                                         alias_list) {
-                       if (!(dev->path_data.opm & lpum)) {
-                               dev->path_data.tbvpm |= lpum;
+                       tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+                       paths |= tbcpm;
+                       if (!(dev->path_data.opm & tbcpm)) {
+                               dev->path_data.tbvpm |= tbcpm;
                                dasd_schedule_device_bh(dev);
                        }
                }
                list_for_each_entry_safe(dev, n,
                                         &pavgroup->aliaslist,
                                         alias_list) {
-                       if (!(dev->path_data.opm & lpum)) {
-                               dev->path_data.tbvpm |= lpum;
+                       tbcpm = dasd_eckd_cuir_scope(dev, lpum, cuir);
+                       paths |= tbcpm;
+                       if (!(dev->path_data.opm & tbcpm)) {
+                               dev->path_data.tbvpm |= tbcpm;
                                dasd_schedule_device_bh(dev);
                        }
                }
        }
-       return PSF_CUIR_COMPLETED;
+       /* notify user about all paths affected by CUIR action */
+       dasd_eckd_cuir_notify_user(device, paths, sch_id, CUIR_RESUME);
+       return 0;
 }
 
 static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
@@ -4768,8 +4931,12 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
        struct channel_path_desc *desc;
        struct subchannel_id sch_id;
        int pos, response;
-       ccw_device_get_schid(device->cdev, &sch_id);
 
+       DBF_DEV_EVENT(DBF_WARNING, device,
+                     "CUIR request: %016llx %016llx %016llx %08x",
+                     ((u64 *)cuir)[0], ((u64 *)cuir)[1], ((u64 *)cuir)[2],
+                     ((u32 *)cuir)[3]);
+       ccw_device_get_schid(device->cdev, &sch_id);
        /* get position of path in mask */
        pos = 8 - ffs(lpum);
        /* get channel path descriptor from this position */
@@ -4777,18 +4944,26 @@ static void dasd_eckd_handle_cuir(struct dasd_device *device, void *messages,
 
        if (cuir->code == CUIR_QUIESCE) {
                /* quiesce */
-               response = dasd_eckd_cuir_quiesce(device, lpum, desc, sch_id);
+               if (dasd_eckd_cuir_quiesce(device, lpum, sch_id, cuir))
+                       response = PSF_CUIR_LAST_PATH;
+               else
+                       response = PSF_CUIR_COMPLETED;
        } else if (cuir->code == CUIR_RESUME) {
                /* resume */
-               response = dasd_eckd_cuir_resume(device, lpum, desc, sch_id);
+               dasd_eckd_cuir_resume(device, lpum, sch_id, cuir);
+               response = PSF_CUIR_COMPLETED;
        } else
                response = PSF_CUIR_NOT_SUPPORTED;
 
-       dasd_eckd_psf_cuir_response(device, response, cuir->message_id,
-                                   desc, sch_id);
-
+       dasd_eckd_psf_cuir_response(device, response,
+                                   cuir->message_id, desc, sch_id);
+       DBF_DEV_EVENT(DBF_WARNING, device,
+                     "CUIR response: %d on message ID %08x", response,
+                     cuir->message_id);
        /* free descriptor copy */
        kfree(desc);
+       /* to make sure there is no attention left schedule work again */
+       device->discipline->check_attention(device, lpum);
 }
 
 static void dasd_eckd_check_attention_work(struct work_struct *work)
@@ -4800,22 +4975,18 @@ static void dasd_eckd_check_attention_work(struct work_struct *work)
 
        data = container_of(work, struct check_attention_work_data, worker);
        device = data->device;
-
        messages = kzalloc(sizeof(*messages), GFP_KERNEL);
        if (!messages) {
                DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                              "Could not allocate attention message buffer");
                goto out;
        }
-
        rc = dasd_eckd_read_message_buffer(device, messages, data->lpum);
        if (rc)
                goto out;
-
        if (messages->length == ATTENTION_LENGTH_CUIR &&
            messages->format == ATTENTION_FORMAT_CUIR)
                dasd_eckd_handle_cuir(device, messages, data->lpum);
-
 out:
        dasd_put_device(device);
        kfree(messages);
index ddab7df36e25dddd0b471f1a71525a7282e975e5..f8f91ee652d36742733163204f0f4380dac45891 100644 (file)
@@ -355,7 +355,8 @@ struct dasd_gneq {
                __u8 identifier:2;
                __u8 reserved:6;
        } __attribute__ ((packed)) flags;
-       __u8 reserved[5];
+       __u8 record_selector;
+       __u8 reserved[4];
        struct {
                __u8 value:2;
                __u8 number:6;
@@ -492,10 +493,18 @@ struct alias_pav_group {
        struct dasd_device *next;
 };
 
+struct dasd_conf_data {
+       struct dasd_ned neds[5];
+       u8 reserved[64];
+       struct dasd_gneq gneq;
+} __packed;
+
 struct dasd_eckd_private {
        struct dasd_eckd_characteristics rdc_data;
        u8 *conf_data;
        int conf_len;
+       /* per path configuration data */
+       struct dasd_conf_data *path_conf_data[8];
        /* pointers to specific parts in the conf_data */
        struct dasd_ned *ned;
        struct dasd_sneq *sneq;
index 227e3dea3155268e7d060b07937bb7ac6d340732..4aed5ed708363b0a30be9c1b20201c478f5a7377 100644 (file)
@@ -534,6 +534,7 @@ struct dasd_attention_data {
 #define DASD_FLAG_SAFE_OFFLINE 10      /* safe offline processing requested*/
 #define DASD_FLAG_SAFE_OFFLINE_RUNNING 11      /* safe offline running */
 #define DASD_FLAG_ABORTALL     12      /* Abort all noretry requests */
+#define DASD_FLAG_PATH_VERIFY  13      /* Path verification worker running */
 
 #define DASD_SLEEPON_START_TAG ((void *) 1)
 #define DASD_SLEEPON_END_TAG   ((void *) 2)
index da212813f2d5dcd301a923df946daa9c481cb06f..dff3fcb69a785102ab2905b3504606688d11b270 100644 (file)
@@ -548,10 +548,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
         */
        num_of_segments = 0;
        for (i = 0; (i < count && (buf[i] != '\0') && (buf[i] != '\n')); i++) {
-               for (j = i; (buf[j] != ':') &&
+               for (j = i; j < count &&
+                       (buf[j] != ':') &&
                        (buf[j] != '\0') &&
-                       (buf[j] != '\n') &&
-                       j < count; j++) {
+                       (buf[j] != '\n'); j++) {
                        local_buf[j-i] = toupper(buf[j]);
                }
                local_buf[j-i] = '\0';
@@ -723,7 +723,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
        /*
         * parse input
         */
-       for (i = 0; ((*(buf+i)!='\0') && (*(buf+i)!='\n') && i < count); i++) {
+       for (i = 0; (i < count && (*(buf+i)!='\0') && (*(buf+i)!='\n')); i++) {
                local_buf[i] = toupper(buf[i]);
        }
        local_buf[i] = '\0';
@@ -904,10 +904,10 @@ dcssblk_check_params(void)
 
        for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
             i++) {
-               for (j = i; (dcssblk_segments[j] != ',')  &&
+               for (j = i; (j < DCSSBLK_PARM_LEN) &&
+                           (dcssblk_segments[j] != ',')  &&
                            (dcssblk_segments[j] != '\0') &&
-                           (dcssblk_segments[j] != '(')  &&
-                           (j < DCSSBLK_PARM_LEN); j++)
+                           (dcssblk_segments[j] != '('); j++)
                {
                        buf[j-i] = dcssblk_segments[j];
                }
index 75ffe9980c3e1cb8e141c6e29d01cef98aaf862f..7c511add5aa7d884d8082398198b1aa92a61dc84 100644 (file)
@@ -413,6 +413,10 @@ con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb)
                else
                        /* Normal end. Copy residual count. */
                        rq->rescnt = irb->scsw.cmd.count;
+       } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+               /* Interrupt without an outstanding request -> update all */
+               cp->update_flags = CON_UPDATE_ALL;
+               con3270_set_timer(cp, 1);
        }
        return RAW3270_IO_DONE;
 }
index 8de2deb176d716daf043e9c80afd1536043eb94b..f7d92584b9931e04cdc80f5aa4e9a218b37f680f 100644 (file)
 #include "ctrlchar.h"
 
 #ifdef CONFIG_MAGIC_SYSRQ
-static int ctrlchar_sysrq_key;
+static struct sysrq_work ctrlchar_sysrq;
 
 static void
 ctrlchar_handle_sysrq(struct work_struct *work)
 {
-       handle_sysrq(ctrlchar_sysrq_key);
+       struct sysrq_work *sysrq = container_of(work, struct sysrq_work, work);
+
+       handle_sysrq(sysrq->key);
 }
 
-static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq);
+void schedule_sysrq_work(struct sysrq_work *sw)
+{
+       INIT_WORK(&sw->work, ctrlchar_handle_sysrq);
+       schedule_work(&sw->work);
+}
 #endif
 
 
@@ -51,8 +57,8 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
 #ifdef CONFIG_MAGIC_SYSRQ
        /* racy */
        if (len == 3 && buf[1] == '-') {
-               ctrlchar_sysrq_key = buf[2];
-               schedule_work(&ctrlchar_work);
+               ctrlchar_sysrq.key = buf[2];
+               schedule_sysrq_work(&ctrlchar_sysrq);
                return CTRLCHAR_SYSRQ;
        }
 #endif
index 1a53552f4981dd466a1b38d3b985d84675602e9c..59c2d6e55e55386c71e86cca3a33f59103adfed8 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <linux/tty.h>
+#include <linux/sysrq.h>
+#include <linux/workqueue.h>
 
 extern unsigned int
 ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty);
@@ -17,3 +19,13 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty);
 #define CTRLCHAR_SYSRQ (3 << 8)
 
 #define CTRLCHAR_MASK (~0xffu)
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+struct sysrq_work {
+       int key;
+       struct work_struct work;
+};
+
+void schedule_sysrq_work(struct sysrq_work *sw);
+#endif
index 93889632fdf9eddc671a7c588a27c40c115fae8d..12db8db04cddf61832b243709e16c7fc0a1ae5ca 100644 (file)
@@ -223,7 +223,7 @@ int diag_ftp_startup(void)
        if (rc)
                return rc;
 
-       ctl_set_bit(0, 63 - 22);
+       irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL);
        return 0;
 }
 
@@ -232,6 +232,6 @@ int diag_ftp_startup(void)
  */
 void diag_ftp_shutdown(void)
 {
-       ctl_clear_bit(0, 63 - 22);
+       irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
        unregister_external_irq(EXT_IRQ_CP_SERVICE, diag_ftp_handler);
 }
index 0da3ae3cd63b3ae549e770f387a90237a594163a..b7d60306b0bcf185c683d5e29312738283c37a98 100644 (file)
@@ -95,7 +95,7 @@ static void dcss_mkname(char *ascii_name, char *ebcdic_name)
                if (ascii_name[i] == '\0')
                        break;
                ebcdic_name[i] = toupper(ascii_name[i]);
-       };
+       }
        for (; i < 8; i++)
                ebcdic_name[i] = ' ';
        ASCEBC(ebcdic_name, 8);
index 5e20513c0587e82ba38eefa7604769e257036665..f58bf4c6c3ee55eabbae7491050f0f3a54a79ba9 100644 (file)
@@ -53,7 +53,7 @@ static DECLARE_COMPLETION(sclp_request_queue_flushed);
 /* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */
 int sclp_console_pages = SCLP_CONSOLE_PAGES;
 /* Flag to indicate if buffer pages are dropped on buffer full condition */
-int sclp_console_drop = 0;
+int sclp_console_drop = 1;
 /* Number of times the console dropped buffer pages */
 unsigned long sclp_console_full;
 
@@ -79,8 +79,8 @@ static int __init sclp_setup_console_drop(char *str)
        int drop, rc;
 
        rc = kstrtoint(str, 0, &drop);
-       if (!rc && drop)
-               sclp_console_drop = 1;
+       if (!rc)
+               sclp_console_drop = drop;
        return 1;
 }
 
index e9485fbbb373e2191601e7ab862dfe8e039afdd9..806239c2cf2f8cf0f50affabdf9dea215aab8e9b 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/sclp.h>
+#include <asm/numa.h>
 
 #include "sclp.h"
 
@@ -388,11 +389,11 @@ static struct notifier_block sclp_mem_nb = {
 };
 
 static void __init align_to_block_size(unsigned long long *start,
-                                      unsigned long long *size)
+                                      unsigned long long *size,
+                                      unsigned long long alignment)
 {
-       unsigned long long start_align, size_align, alignment;
+       unsigned long long start_align, size_align;
 
-       alignment = memory_block_size_bytes();
        start_align = roundup(*start, alignment);
        size_align = rounddown(*start + *size, alignment) - start_align;
 
@@ -404,8 +405,8 @@ static void __init align_to_block_size(unsigned long long *start,
 
 static void __init add_memory_merged(u16 rn)
 {
+       unsigned long long start, size, addr, block_size;
        static u16 first_rn, num;
-       unsigned long long start, size;
 
        if (rn && first_rn && (first_rn + num == rn)) {
                num++;
@@ -423,9 +424,12 @@ static void __init add_memory_merged(u16 rn)
                goto skip_add;
        if (memory_end_set && (start + size > memory_end))
                size = memory_end - start;
-       align_to_block_size(&start, &size);
-       if (size)
-               add_memory(0, start, size);
+       block_size = memory_block_size_bytes();
+       align_to_block_size(&start, &size, block_size);
+       if (!size)
+               goto skip_add;
+       for (addr = start; addr < start + size; addr += block_size)
+               add_memory(numa_pfn_to_nid(PFN_DOWN(addr)), addr, block_size);
 skip_add:
        first_rn = rn;
        num = 1;
index ae67386c03d3b8301a581c58a68a028d70f22fbf..68d6ee7ae504dceab936071319152574304316ff 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/wait.h>
 #include <linux/timer.h>
 #include <linux/kernel.h>
+#include <linux/sysrq.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
@@ -27,6 +28,7 @@
 
 #include <asm/uaccess.h>
 #include "sclp.h"
+#include "ctrlchar.h"
 
 #define SCLP_VT220_MAJOR               TTY_MAJOR
 #define SCLP_VT220_MINOR               65
@@ -477,6 +479,53 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
 #define        SCLP_VT220_SESSION_STARTED      0x80
 #define SCLP_VT220_SESSION_DATA                0x00
 
+#ifdef CONFIG_MAGIC_SYSRQ
+
+static int sysrq_pressed;
+static struct sysrq_work sysrq;
+
+static void sclp_vt220_reset_session(void)
+{
+       sysrq_pressed = 0;
+}
+
+static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++) {
+               /* Handle magic sys request */
+               if (buffer[i] == ('O' ^ 0100)) { /* CTRL-O */
+                       /*
+                        * If pressed again, reset sysrq_pressed
+                        * and flip CTRL-O character
+                        */
+                       sysrq_pressed = !sysrq_pressed;
+                       if (sysrq_pressed)
+                               continue;
+               } else if (sysrq_pressed) {
+                       sysrq.key = buffer[i];
+                       schedule_sysrq_work(&sysrq);
+                       sysrq_pressed = 0;
+                       continue;
+               }
+               tty_insert_flip_char(&sclp_vt220_port, buffer[i], 0);
+       }
+}
+
+#else
+
+static void sclp_vt220_reset_session(void)
+{
+}
+
+static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
+{
+       tty_insert_flip_string(&sclp_vt220_port, buffer, count);
+}
+
+#endif
+
 /*
  * Called by the SCLP to report incoming event buffers.
  */
@@ -492,12 +541,13 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
        switch (*buffer) {
        case SCLP_VT220_SESSION_ENDED:
        case SCLP_VT220_SESSION_STARTED:
+               sclp_vt220_reset_session();
                break;
        case SCLP_VT220_SESSION_DATA:
                /* Send input to line discipline */
                buffer++;
                count--;
-               tty_insert_flip_string(&sclp_vt220_port, buffer, count);
+               sclp_vt220_handle_input(buffer, count);
                tty_flip_buffer_push(&sclp_vt220_port);
                break;
        }
index e91b89dc6d1f61878e9191c8f66b7a90e32acd44..e96fc7fd9498458b5506789f4b900b813885adda 100644 (file)
@@ -659,6 +659,10 @@ tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
                else
                        /* Normal end. Copy residual count. */
                        rq->rescnt = irb->scsw.cmd.count;
+       } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+               /* Interrupt without an outstanding request -> update all */
+               tp->update_flags = TTY_UPDATE_ALL;
+               tty3270_set_timer(tp, 1);
        }
        return RAW3270_IO_DONE;
 }
index e3bf885f4a6c29fd77f29b51c219a47c6a04ca7e..548a18916a31ec11f5abf0fae9c3626755422d46 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/chsc.h>
 #include <asm/crw.h>
 #include <asm/isc.h>
+#include <asm/ebcdic.h>
 
 #include "css.h"
 #include "cio.h"
@@ -272,36 +273,6 @@ static void s390_process_res_acc(struct chp_link *link)
        css_schedule_reprobe();
 }
 
-static int
-__get_chpid_from_lir(void *data)
-{
-       struct lir {
-               u8  iq;
-               u8  ic;
-               u16 sci;
-               /* incident-node descriptor */
-               u32 indesc[28];
-               /* attached-node descriptor */
-               u32 andesc[28];
-               /* incident-specific information */
-               u32 isinfo[28];
-       } __attribute__ ((packed)) *lir;
-
-       lir = data;
-       if (!(lir->iq&0x80))
-               /* NULL link incident record */
-               return -EINVAL;
-       if (!(lir->indesc[0]&0xc0000000))
-               /* node descriptor not valid */
-               return -EINVAL;
-       if (!(lir->indesc[0]&0x10000000))
-               /* don't handle device-type nodes - FIXME */
-               return -EINVAL;
-       /* Byte 3 contains the chpid. Could also be CTCA, but we don't care */
-
-       return (u16) (lir->indesc[0]&0x000000ff);
-}
-
 struct chsc_sei_nt0_area {
        u8  flags;
        u8  vf;                         /* validity flags */
@@ -341,22 +312,132 @@ struct chsc_sei {
        } u;
 } __packed;
 
+/*
+ * Node Descriptor as defined in SA22-7204, "Common I/O-Device Commands"
+ */
+
+#define ND_VALIDITY_VALID      0
+#define ND_VALIDITY_OUTDATED   1
+#define ND_VALIDITY_INVALID    2
+
+struct node_descriptor {
+       /* Flags. */
+       union {
+               struct {
+                       u32 validity:3;
+                       u32 reserved:5;
+               } __packed;
+               u8 byte0;
+       } __packed;
+
+       /* Node parameters. */
+       u32 params:24;
+
+       /* Node ID. */
+       char type[6];
+       char model[3];
+       char manufacturer[3];
+       char plant[2];
+       char seq[12];
+       u16 tag;
+} __packed;
+
+/*
+ * Link Incident Record as defined in SA22-7202, "ESCON I/O Interface"
+ */
+
+#define LIR_IQ_CLASS_INFO              0
+#define LIR_IQ_CLASS_DEGRADED          1
+#define LIR_IQ_CLASS_NOT_OPERATIONAL   2
+
+struct lir {
+       struct {
+               u32 null:1;
+               u32 reserved:3;
+               u32 class:2;
+               u32 reserved2:2;
+       } __packed iq;
+       u32 ic:8;
+       u32 reserved:16;
+       struct node_descriptor incident_node;
+       struct node_descriptor attached_node;
+       u8 reserved2[32];
+} __packed;
+
+#define PARAMS_LEN     10      /* PARAMS=xx,xxxxxx */
+#define NODEID_LEN     35      /* NODEID=tttttt/mdl,mmm.ppssssssssssss,xxxx */
+
+/* Copy EBCIDC text, convert to ASCII and optionally add delimiter. */
+static char *store_ebcdic(char *dest, const char *src, unsigned long len,
+                         char delim)
+{
+       memcpy(dest, src, len);
+       EBCASC(dest, len);
+
+       if (delim)
+               dest[len++] = delim;
+
+       return dest + len;
+}
+
+/* Format node ID and parameters for output in LIR log message. */
+static void format_node_data(char *params, char *id, struct node_descriptor *nd)
+{
+       memset(params, 0, PARAMS_LEN);
+       memset(id, 0, NODEID_LEN);
+
+       if (nd->validity != ND_VALIDITY_VALID) {
+               strncpy(params, "n/a", PARAMS_LEN - 1);
+               strncpy(id, "n/a", NODEID_LEN - 1);
+               return;
+       }
+
+       /* PARAMS=xx,xxxxxx */
+       snprintf(params, PARAMS_LEN, "%02x,%06x", nd->byte0, nd->params);
+       /* NODEID=tttttt/mdl,mmm.ppssssssssssss,xxxx */
+       id = store_ebcdic(id, nd->type, sizeof(nd->type), '/');
+       id = store_ebcdic(id, nd->model, sizeof(nd->model), ',');
+       id = store_ebcdic(id, nd->manufacturer, sizeof(nd->manufacturer), '.');
+       id = store_ebcdic(id, nd->plant, sizeof(nd->plant), 0);
+       id = store_ebcdic(id, nd->seq, sizeof(nd->seq), ',');
+       sprintf(id, "%04X", nd->tag);
+}
+
 static void chsc_process_sei_link_incident(struct chsc_sei_nt0_area *sei_area)
 {
-       struct chp_id chpid;
-       int id;
+       struct lir *lir = (struct lir *) &sei_area->ccdf;
+       char iuparams[PARAMS_LEN], iunodeid[NODEID_LEN], auparams[PARAMS_LEN],
+            aunodeid[NODEID_LEN];
 
-       CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n",
-                     sei_area->rs, sei_area->rsid);
-       if (sei_area->rs != 4)
+       CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x, iq=%02x)\n",
+                     sei_area->rs, sei_area->rsid, sei_area->ccdf[0]);
+
+       /* Ignore NULL Link Incident Records. */
+       if (lir->iq.null)
                return;
-       id = __get_chpid_from_lir(sei_area->ccdf);
-       if (id < 0)
-               CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n");
-       else {
-               chp_id_init(&chpid);
-               chpid.id = id;
-               chsc_chp_offline(chpid);
+
+       /* Inform user that a link requires maintenance actions because it has
+        * become degraded or not operational. Note that this log message is
+        * the primary intention behind a Link Incident Record. */
+
+       format_node_data(iuparams, iunodeid, &lir->incident_node);
+       format_node_data(auparams, aunodeid, &lir->attached_node);
+
+       switch (lir->iq.class) {
+       case LIR_IQ_CLASS_DEGRADED:
+               pr_warn("Link degraded: RS=%02x RSID=%04x IC=%02x "
+                       "IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n",
+                       sei_area->rs, sei_area->rsid, lir->ic, iuparams,
+                       iunodeid, auparams, aunodeid);
+               break;
+       case LIR_IQ_CLASS_NOT_OPERATIONAL:
+               pr_err("Link stopped: RS=%02x RSID=%04x IC=%02x "
+                      "IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n",
+                      sei_area->rs, sei_area->rsid, lir->ic, iuparams,
+                      iunodeid, auparams, aunodeid);
+               break;
+       default:
+               break;
        }
 }
 
index f3c417943dad5510594930f2deef6e2f21f5c59a..6acd0b5776948a128ff986d0f06b7bbfa3581e30 100644 (file)
@@ -540,7 +540,7 @@ int ccw_device_stlck(struct ccw_device *cdev)
        if (rc)
                goto out_unlock;
        /* Perform operation. */
-       cdev->private->state = DEV_STATE_STEAL_LOCK,
+       cdev->private->state = DEV_STATE_STEAL_LOCK;
        ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
        spin_unlock_irq(sch->lock);
        /* Wait for operation to finish. */
index bee8c11cd08661008815e1bfb5e9c548f4d1f795..b3f44bc7f64489e32c40d76304b7c73b88456bc8 100644 (file)
@@ -336,7 +336,6 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
 {
        struct eadm_private *private;
        unsigned long flags;
-       int ret = 0;
 
        spin_lock_irqsave(sch->lock, flags);
        if (!device_is_registered(&sch->dev))
@@ -356,7 +355,7 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
 out_unlock:
        spin_unlock_irqrestore(sch->lock, flags);
 
-       return ret;
+       return 0;
 }
 
 static struct css_device_id eadm_subchannel_ids[] = {
index 559a9dcdb15d274d4bad423bdbef6f01da769639..d78b3d629d78dd9175736b99a2ac2a14adaf26c9 100644 (file)
@@ -1372,7 +1372,7 @@ static int ap_probe_device_type(struct ap_device *ap_dev)
 
        /* Wait for the test message to complete. */
        for (i = 0; i < 6; i++) {
-               mdelay(300);
+               msleep(300);
                status = __ap_recv(ap_dev->qid, &psmid, reply, 4096);
                if (status.response_code == AP_RESPONSE_NORMAL &&
                    psmid == 0x0102030405060708ULL)
index 899ffa19f5ecd1105e2844362d2a9eb2403b880d..f41852768953dfc6aea96316a995a7274a243ebc 100644 (file)
@@ -182,7 +182,7 @@ static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
 
        /* Wait for the test message to complete. */
        for (i = 0; i < 6; i++) {
-               mdelay(300);
+               msleep(300);
                rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
                if (rc == 0 && psmid == 0x0102030405060708ULL)
                        break;
index 2e65b989a9ea529b4e69a555eee2f2fb494c2752..a8556692f632ec3000be0c8d8fd43d3b56396afb 100644 (file)
@@ -390,10 +390,8 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
        return rc;
 }
 
-static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
 {
-       int rc = 0;
-
        QETH_DBF_TEXT(SETUP , 2, "stopcard");
        QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
 
@@ -427,7 +425,6 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
-       return rc;
 }
 
 static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
index 70eb2f61bb9269221f4c389838b67bf90fc071ba..a1aaa36e9ebb425d5c45933baa58e40b598a570a 100644 (file)
@@ -2158,10 +2158,8 @@ static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
        return card ;
 }
 
-static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
+static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
 {
-       int rc = 0;
-
        QETH_DBF_TEXT(SETUP, 2, "stopcard");
        QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
 
@@ -2196,7 +2194,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
-       return rc;
 }
 
 /*
index 21ec5e2f584ce44851560394870cf9b56163a3b1..4ac73e047c114bb3d27aa5fab7ca939297fb4c43 100644 (file)
@@ -204,7 +204,7 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
                break;
        case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
                zfcp_fsf_link_down_info_eval(req, NULL);
-       };
+       }
 }
 
 static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
index 26270c351624f229cf85b6069ffe53ee26d50bef..ce129e595b55b663a11600e46571a1dba0d2ccf7 100644 (file)
@@ -39,7 +39,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.6.0.17"
+#define DRV_VERSION            "1.6.0.17a"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
index 155b286f1a9d3cc8b366a6a5b7610ae562337f62..25436cd2860cc18a63ac599ed58e3c871c264d8e 100644 (file)
@@ -425,6 +425,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
        unsigned long ptr;
        struct fc_rport_priv *rdata;
        spinlock_t *io_lock = NULL;
+       int io_lock_acquired = 0;
 
        if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
                return SCSI_MLQUEUE_HOST_BUSY;
@@ -518,6 +519,7 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
        spin_lock_irqsave(io_lock, flags);
 
        /* initialize rest of io_req */
+       io_lock_acquired = 1;
        io_req->port_id = rport->port_id;
        io_req->start_time = jiffies;
        CMD_STATE(sc) = FNIC_IOREQ_CMD_PENDING;
@@ -571,7 +573,7 @@ out:
                  (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
 
        /* if only we issued IO, will we have the io lock */
-       if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
+       if (io_lock_acquired)
                spin_unlock_irqrestore(io_lock, flags);
 
        atomic_dec(&fnic->in_flight);
index 1b3a094734522803c7f3fecd39da5c297a1feb43..30f9ef0c0d4f8cea52b182f370a04ed1ba4a9908 100644 (file)
@@ -733,8 +733,6 @@ static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp,
        if (resp) {
                resp(sp, fp, arg);
                res = true;
-       } else if (!IS_ERR(fp)) {
-               fc_frame_free(fp);
        }
 
        spin_lock_bh(&ep->ex_lock);
@@ -1596,7 +1594,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
         * If new exch resp handler is valid then call that
         * first.
         */
-       fc_invoke_resp(ep, sp, fp);
+       if (!fc_invoke_resp(ep, sp, fp))
+               fc_frame_free(fp);
 
        fc_exch_release(ep);
        return;
@@ -1695,7 +1694,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
        fc_exch_hold(ep);
        if (!rc)
                fc_exch_delete(ep);
-       fc_invoke_resp(ep, sp, fp);
+       if (!fc_invoke_resp(ep, sp, fp))
+               fc_frame_free(fp);
        if (has_rec)
                fc_exch_timer_set(ep, ep->r_a_tov);
        fc_exch_release(ep);
index c6795941b45d98579cd6117cc5b72f8c5c4d0bf9..2d5909c4685ca63375f5041d960effada171f5fc 100644 (file)
@@ -1039,11 +1039,26 @@ restart:
                fc_fcp_pkt_hold(fsp);
                spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 
-               if (!fc_fcp_lock_pkt(fsp)) {
+               spin_lock_bh(&fsp->scsi_pkt_lock);
+               if (!(fsp->state & FC_SRB_COMPL)) {
+                       fsp->state |= FC_SRB_COMPL;
+                       /*
+                        * TODO: dropping scsi_pkt_lock and then reacquiring
+                        * again around fc_fcp_cleanup_cmd() is required,
+                        * since fc_fcp_cleanup_cmd() calls into
+                        * fc_seq_set_resp() and that func preempts cpu using
+                        * schedule. May be schedule and related code should be
+                        * removed instead of unlocking here to avoid scheduling
+                        * while atomic bug.
+                        */
+                       spin_unlock_bh(&fsp->scsi_pkt_lock);
+
                        fc_fcp_cleanup_cmd(fsp, error);
+
+                       spin_lock_bh(&fsp->scsi_pkt_lock);
                        fc_io_compl(fsp);
-                       fc_fcp_unlock_pkt(fsp);
                }
+               spin_unlock_bh(&fsp->scsi_pkt_lock);
 
                fc_fcp_pkt_release(fsp);
                spin_lock_irqsave(&si->scsi_queue_lock, flags);
index 8053f24f03499335112721cd50c2816da40393a6..98d9bb6ff725ff46621a408bdf1f208175e21daf 100644 (file)
@@ -2941,10 +2941,10 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
 {
        struct iscsi_conn *conn = cls_conn->dd_data;
        struct iscsi_session *session = conn->session;
-       unsigned long flags;
 
        del_timer_sync(&conn->transport_timer);
 
+       mutex_lock(&session->eh_mutex);
        spin_lock_bh(&session->frwd_lock);
        conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
        if (session->leadconn == conn) {
@@ -2956,28 +2956,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
        }
        spin_unlock_bh(&session->frwd_lock);
 
-       /*
-        * Block until all in-progress commands for this connection
-        * time out or fail.
-        */
-       for (;;) {
-               spin_lock_irqsave(session->host->host_lock, flags);
-               if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */
-                       spin_unlock_irqrestore(session->host->host_lock, flags);
-                       break;
-               }
-               spin_unlock_irqrestore(session->host->host_lock, flags);
-               msleep_interruptible(500);
-               iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
-                                 "host_busy %d host_failed %d\n",
-                                 atomic_read(&session->host->host_busy),
-                                 session->host->host_failed);
-               /*
-                * force eh_abort() to unblock
-                */
-               wake_up(&conn->ehwait);
-       }
-
        /* flush queued up work because we free the connection below */
        iscsi_suspend_tx(conn);
 
@@ -2994,6 +2972,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
        if (session->leadconn == conn)
                session->leadconn = NULL;
        spin_unlock_bh(&session->frwd_lock);
+       mutex_unlock(&session->eh_mutex);
 
        iscsi_destroy_conn(cls_conn);
 }
index cfadccef045c5f91d9efb5f575c98d1d9c68b090..6457a8a0db9c37ed8892c28effe768a533f2e7f3 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
-#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -2523,33 +2522,3 @@ void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
        }
 }
 EXPORT_SYMBOL(scsi_build_sense_buffer);
-
-/**
- * scsi_set_sense_information - set the information field in a
- *             formatted sense data buffer
- * @buf:       Where to build sense data
- * @info:      64-bit information value to be set
- *
- **/
-void scsi_set_sense_information(u8 *buf, u64 info)
-{
-       if ((buf[0] & 0x7f) == 0x72) {
-               u8 *ucp, len;
-
-               len = buf[7];
-               ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0);
-               if (!ucp) {
-                       buf[7] = len + 0xa;
-                       ucp = buf + 8 + len;
-               }
-               ucp[0] = 0;
-               ucp[1] = 0xa;
-               ucp[2] = 0x80; /* Valid bit */
-               ucp[3] = 0;
-               put_unaligned_be64(info, &ucp[4]);
-       } else if ((buf[0] & 0x7f) == 0x70) {
-               buf[0] |= 0x80;
-               put_unaligned_be64(info, &buf[3]);
-       }
-}
-EXPORT_SYMBOL(scsi_set_sense_information);
index 9e43ae1d2163dacaae769a816dc6973cfabbdca0..e4b7998379485454d26e39f6a5a91917a155ffbb 100644 (file)
@@ -217,15 +217,15 @@ static int sdev_runtime_suspend(struct device *dev)
 {
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        struct scsi_device *sdev = to_scsi_device(dev);
-       int err;
+       int err = 0;
 
-       err = blk_pre_runtime_suspend(sdev->request_queue);
-       if (err)
-               return err;
-       if (pm && pm->runtime_suspend)
+       if (pm && pm->runtime_suspend) {
+               err = blk_pre_runtime_suspend(sdev->request_queue);
+               if (err)
+                       return err;
                err = pm->runtime_suspend(dev);
-       blk_post_runtime_suspend(sdev->request_queue, err);
-
+               blk_post_runtime_suspend(sdev->request_queue, err);
+       }
        return err;
 }
 
@@ -248,11 +248,11 @@ static int sdev_runtime_resume(struct device *dev)
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int err = 0;
 
-       blk_pre_runtime_resume(sdev->request_queue);
-       if (pm && pm->runtime_resume)
+       if (pm && pm->runtime_resume) {
+               blk_pre_runtime_resume(sdev->request_queue);
                err = pm->runtime_resume(dev);
-       blk_post_runtime_resume(sdev->request_queue, err);
-
+               blk_post_runtime_resume(sdev->request_queue, err);
+       }
        return err;
 }
 
index 3b2fcb4fada0491c4500b42555fdef542b4399d2..a20da8c25b4f960224fb4d772aafea38c57e1656 100644 (file)
@@ -2770,9 +2770,9 @@ static int sd_revalidate_disk(struct gendisk *disk)
        max_xfer = sdkp->max_xfer_blocks;
        max_xfer <<= ilog2(sdp->sector_size) - 9;
 
-       max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
-                               max_xfer);
-       blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
+       sdkp->disk->queue->limits.max_sectors =
+               min_not_zero(queue_max_hw_sectors(sdkp->disk->queue), max_xfer);
+
        set_capacity(disk, sdkp->capacity);
        sd_config_write_same(sdkp);
        kfree(buffer);
index b0f30fb68914220ea75b401dd52b7d537c00687e..4887f317ea58f7c5566fcb1481559831b7f81180 100644 (file)
@@ -326,6 +326,15 @@ config SPI_MESON_SPIFC
          This enables master mode support for the SPIFC (SPI flash
          controller) available in Amlogic Meson SoCs.
 
+config SPI_MT65XX
+       tristate "MediaTek SPI controller"
+       depends on ARCH_MEDIATEK || COMPILE_TEST
+       help
+         This selects the MediaTek(R) SPI bus driver.
+         If you want to use MediaTek(R) SPI interface,
+         say Y or M here.If you are not sure, say N.
+         SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
+
 config SPI_OC_TINY
        tristate "OpenCores tiny SPI"
        depends on GPIOLIB || COMPILE_TEST
@@ -598,6 +607,17 @@ config SPI_XILINX
 
          Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
 
+config SPI_XLP
+       tristate "Netlogic XLP SPI controller driver"
+       depends on CPU_XLP || COMPILE_TEST
+       help
+         Enable support for the SPI controller on the Netlogic XLP SoCs.
+         Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX, XLP9XX
+         and XLP5XX.
+
+         If you have a Netlogic XLP platform say Y here.
+         If unsure, say N.
+
 config SPI_XTENSA_XTFPGA
        tristate "Xtensa SPI controller for xtfpga"
        depends on (XTENSA && XTENSA_PLATFORM_XTFPGA) || COMPILE_TEST
index 1154dbac8f2c184b165f7f4f9c2392a2820f6c97..6a7f6f9d0d1c8cd7dbb89cbd1a902d2997264baa 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC)         += spi-meson-spifc.o
 obj-$(CONFIG_SPI_MPC512x_PSC)          += spi-mpc512x-psc.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)          += spi-mpc52xx-psc.o
 obj-$(CONFIG_SPI_MPC52xx)              += spi-mpc52xx.o
+obj-$(CONFIG_SPI_MT65XX)                += spi-mt65xx.o
 obj-$(CONFIG_SPI_MXS)                  += spi-mxs.o
 obj-$(CONFIG_SPI_NUC900)               += spi-nuc900.o
 obj-$(CONFIG_SPI_OC_TINY)              += spi-oc-tiny.o
@@ -88,5 +89,6 @@ 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
+obj-$(CONFIG_SPI_XLP)                  += spi-xlp.o
 obj-$(CONFIG_SPI_XTENSA_XTFPGA)                += spi-xtensa-xtfpga.o
 obj-$(CONFIG_SPI_ZYNQMP_GQSPI)         += spi-zynqmp-gqspi.o
index c9eca347787db7ba5f85f6b1c4e10ad66e856abb..bf9ed380bb1c0754addbd27aedf7d874cee89ff2 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/interrupt.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
-#include <linux/platform_data/atmel.h>
 #include <linux/platform_data/dma-atmel.h>
 #include <linux/of.h>
 
index 59705ab23577494b68a136ca0f3c377b3371ca2b..e7874a6171ecdb4b5b5e7c99bb706aaca2135e2d 100644 (file)
@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
                                         struct spi_device *spi,
                                         struct spi_transfer *tfr,
                                         u32 cs,
-                                        unsigned long xfer_time_us)
+                                        unsigned long long xfer_time_us)
 {
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
        unsigned long timeout;
@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
 {
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
        unsigned long spi_hz, clk_hz, cdiv;
-       unsigned long spi_used_hz, xfer_time_us;
+       unsigned long spi_used_hz;
+       unsigned long long xfer_time_us;
        u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
 
        /* set clock */
@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
        spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
        bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
 
-       /* handle all the modes */
+       /* handle all the 3-wire mode */
        if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
                cs |= BCM2835_SPI_CS_REN;
-       if (spi->mode & SPI_CPOL)
-               cs |= BCM2835_SPI_CS_CPOL;
-       if (spi->mode & SPI_CPHA)
-               cs |= BCM2835_SPI_CS_CPHA;
+       else
+               cs &= ~BCM2835_SPI_CS_REN;
 
        /* for gpio_cs set dummy CS so that no HW-CS get changed
         * we can not run this in bcm2835_spi_set_cs, as it does
@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
        bs->rx_len = tfr->len;
 
        /* calculate the estimated time in us the transfer runs */
-       xfer_time_us = tfr->len
+       xfer_time_us = (unsigned long long)tfr->len
                * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
-               * 1000000 / spi_used_hz;
+               * 1000000;
+       do_div(xfer_time_us, spi_used_hz);
 
        /* for short requests run polling*/
        if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
        return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
 }
 
+static int bcm2835_spi_prepare_message(struct spi_master *master,
+                                      struct spi_message *msg)
+{
+       struct spi_device *spi = msg->spi;
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
+       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+       cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
+
+       if (spi->mode & SPI_CPOL)
+               cs |= BCM2835_SPI_CS_CPOL;
+       if (spi->mode & SPI_CPHA)
+               cs |= BCM2835_SPI_CS_CPHA;
+
+       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+
+       return 0;
+}
+
 static void bcm2835_spi_handle_err(struct spi_master *master,
                                   struct spi_message *msg)
 {
@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        master->set_cs = bcm2835_spi_set_cs;
        master->transfer_one = bcm2835_spi_transfer_one;
        master->handle_err = bcm2835_spi_handle_err;
+       master->prepare_message = bcm2835_spi_prepare_message;
        master->dev.of_node = pdev->dev.of_node;
 
        bs = spi_master_get_devdata(master);
index f5ca6dc3a157879895aa0953c4c6681594b3d5ff..55789f7cda9280b2f0d21b65b6a7f3c019780047 100644 (file)
@@ -76,6 +76,7 @@
 #define HSSPI_FIFO_REG(x)                      (0x200 + (x) * 0x200)
 
 
+#define HSSPI_OP_MULTIBIT                      BIT(11)
 #define HSSPI_OP_CODE_SHIFT                    13
 #define HSSPI_OP_SLEEP                         (0 << HSSPI_OP_CODE_SHIFT)
 #define HSSPI_OP_READ_WRITE                    (1 << HSSPI_OP_CODE_SHIFT)
@@ -171,9 +172,12 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
        if (opcode != HSSPI_OP_READ)
                step_size -= HSSPI_OPCODE_LEN;
 
-       __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
-                    2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
-                    2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
+       if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) ||
+           (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL))
+               opcode |= HSSPI_OP_MULTIBIT;
+
+       __raw_writel(1 << MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT |
+                    1 << MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT | 0xff,
                     bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
 
        while (pending > 0) {
@@ -374,7 +378,8 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
        master->num_chipselect = 8;
        master->setup = bcm63xx_hsspi_setup;
        master->transfer_one_message = bcm63xx_hsspi_transfer_one;
-       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
+                           SPI_RX_DUAL | SPI_TX_DUAL;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->auto_runtime_pm = true;
 
index 06b34e5bcfa37eaf9eba3e9ff8d1d017454dc81d..47bb9b898dfdc6ab18ae5fd10349f23882200e4f 100644 (file)
@@ -49,7 +49,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
 {
        /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
 
-       bool oldbit = !(word & 1);
+       u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
        /* clock starts at inactive polarity */
        for (word <<= (32 - bits); likely(bits); bits--) {
 
@@ -81,7 +81,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
 {
        /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
 
-       bool oldbit = !(word & (1 << 31));
+       u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
        /* clock starts at inactive polarity */
        for (word <<= (32 - bits); likely(bits); bits--) {
 
index 987afebea09379507f2c8505e7f4c14acbde079c..3cf9faa6cc3fe871174ec1b2777472b0ac4c6883 100644 (file)
@@ -139,6 +139,8 @@ struct davinci_spi {
        u32                     (*get_tx)(struct davinci_spi *);
 
        u8                      *bytes_per_word;
+
+       u8                      prescaler_limit;
 };
 
 static struct davinci_spi_config davinci_spi_default_cfg;
@@ -255,7 +257,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
  * This function calculates the prescale value that generates a clock rate
  * less than or equal to the specified maximum.
  *
- * Returns: calculated prescale - 1 for easy programming into SPI registers
+ * Returns: calculated prescale value for easy programming into SPI registers
  * or negative error number if valid prescalar cannot be updated.
  */
 static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
@@ -263,12 +265,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi,
 {
        int ret;
 
-       ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz);
+       /* Subtract 1 to match what will be programmed into SPI register. */
+       ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1;
 
-       if (ret < 1 || ret > 256)
+       if (ret < dspi->prescaler_limit || ret > 255)
                return -EINVAL;
 
-       return ret - 1;
+       return ret;
 }
 
 /**
@@ -832,13 +835,40 @@ rx_dma_failed:
 }
 
 #if defined(CONFIG_OF)
+
+/* OF SPI data structure */
+struct davinci_spi_of_data {
+       u8      version;
+       u8      prescaler_limit;
+};
+
+static const struct davinci_spi_of_data dm6441_spi_data = {
+       .version = SPI_VERSION_1,
+       .prescaler_limit = 2,
+};
+
+static const struct davinci_spi_of_data da830_spi_data = {
+       .version = SPI_VERSION_2,
+       .prescaler_limit = 2,
+};
+
+static const struct davinci_spi_of_data keystone_spi_data = {
+       .version = SPI_VERSION_1,
+       .prescaler_limit = 0,
+};
+
 static const struct of_device_id davinci_spi_of_match[] = {
        {
                .compatible = "ti,dm6441-spi",
+               .data = &dm6441_spi_data,
        },
        {
                .compatible = "ti,da830-spi",
-               .data = (void *)SPI_VERSION_2,
+               .data = &da830_spi_data,
+       },
+       {
+               .compatible = "ti,keystone-spi",
+               .data = &keystone_spi_data,
        },
        { },
 };
@@ -857,21 +887,21 @@ static int spi_davinci_get_pdata(struct platform_device *pdev,
                        struct davinci_spi *dspi)
 {
        struct device_node *node = pdev->dev.of_node;
+       struct davinci_spi_of_data *spi_data;
        struct davinci_spi_platform_data *pdata;
        unsigned int num_cs, intr_line = 0;
        const struct of_device_id *match;
 
        pdata = &dspi->pdata;
 
-       pdata->version = SPI_VERSION_1;
        match = of_match_device(davinci_spi_of_match, &pdev->dev);
        if (!match)
                return -ENODEV;
 
-       /* match data has the SPI version number for SPI_VERSION_2 */
-       if (match->data == (void *)SPI_VERSION_2)
-               pdata->version = SPI_VERSION_2;
+       spi_data = (struct davinci_spi_of_data *)match->data;
 
+       pdata->version = spi_data->version;
+       pdata->prescaler_limit = spi_data->prescaler_limit;
        /*
         * default num_cs is 1 and all chipsel are internal to the chip
         * indicated by chip_sel being NULL or cs_gpios being NULL or
@@ -991,7 +1021,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
 
        dspi->bitbang.chipselect = davinci_spi_chipselect;
        dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
-
+       dspi->prescaler_limit = pdata->prescaler_limit;
        dspi->version = pdata->version;
 
        dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
index eb03e1215195bd5f9e9ea882cb1895db6ea79cdd..7edede6e024ba493ce0dfc7038d83e03eb88ef85 100644 (file)
@@ -74,6 +74,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 
        dws->max_freq = clk_get_rate(dwsmmio->clk);
 
+       of_property_read_u32(pdev->dev.of_node, "reg-io-width",
+                            &dws->reg_io_width);
+
        num_cs = 4;
 
        if (pdev->dev.of_node)
index 8d67d03c71ebcdec375023f8db910d3d0d8469ec..4fbfcdc5cb244d6e9f2a7edaba603b7ccd269fb0 100644 (file)
@@ -194,7 +194,7 @@ static void dw_writer(struct dw_spi *dws)
                        else
                                txw = *(u16 *)(dws->tx);
                }
-               dw_writel(dws, DW_SPI_DR, txw);
+               dw_write_io_reg(dws, DW_SPI_DR, txw);
                dws->tx += dws->n_bytes;
        }
 }
@@ -205,7 +205,7 @@ static void dw_reader(struct dw_spi *dws)
        u16 rxw;
 
        while (max--) {
-               rxw = dw_readl(dws, DW_SPI_DR);
+               rxw = dw_read_io_reg(dws, DW_SPI_DR);
                /* Care rx only if the transfer's original "rx" is not null */
                if (dws->rx_end - dws->len) {
                        if (dws->n_bytes == 1)
index 6c91391c1a4f8f07b40cb546de3eb169c44670f3..b75ed327d5a29832ad3461cb28da1089ade94cba 100644 (file)
@@ -109,6 +109,7 @@ struct dw_spi {
        u32                     fifo_len;       /* depth of the FIFO buffer */
        u32                     max_freq;       /* max bus freq supported */
 
+       u32                     reg_io_width;   /* DR I/O width in bytes */
        u16                     bus_num;
        u16                     num_cs;         /* supported slave numbers */
 
@@ -145,11 +146,45 @@ static inline u32 dw_readl(struct dw_spi *dws, u32 offset)
        return __raw_readl(dws->regs + offset);
 }
 
+static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
+{
+       return __raw_readw(dws->regs + offset);
+}
+
 static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
 {
        __raw_writel(val, dws->regs + offset);
 }
 
+static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
+{
+       __raw_writew(val, dws->regs + offset);
+}
+
+static inline u32 dw_read_io_reg(struct dw_spi *dws, u32 offset)
+{
+       switch (dws->reg_io_width) {
+       case 2:
+               return dw_readw(dws, offset);
+       case 4:
+       default:
+               return dw_readl(dws, offset);
+       }
+}
+
+static inline void dw_write_io_reg(struct dw_spi *dws, u32 offset, u32 val)
+{
+       switch (dws->reg_io_width) {
+       case 2:
+               dw_writew(dws, offset, val);
+               break;
+       case 4:
+       default:
+               dw_writel(dws, offset, val);
+               break;
+       }
+}
+
 static inline void spi_enable_chip(struct dw_spi *dws, int enable)
 {
        dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
index d3f05a0525a428194e0cb792604eed8ac481bd00..c27124a5ec8ee02264df2feaf283fdbb92991cf3 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/pm_runtime.h>
 #include <sysdev/fsl_soc.h>
 
 #include "spi-fsl-lib.h"
@@ -85,6 +86,8 @@ struct fsl_espi_transfer {
 #define SPCOM_TRANLEN(x)       ((x) << 0)
 #define        SPCOM_TRANLEN_MAX       0xFFFF  /* Max transaction length */
 
+#define AUTOSUSPEND_TIMEOUT 2000
+
 static void fsl_espi_change_mode(struct spi_device *spi)
 {
        struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
        mpc8xxx_spi = spi_master_get_devdata(spi->master);
        reg_base = mpc8xxx_spi->reg_base;
 
+       pm_runtime_get_sync(mpc8xxx_spi->dev);
+
        hw_mode = cs->hw_mode; /* Save original settings */
        cs->hw_mode = mpc8xxx_spi_read_reg(
                        &reg_base->csmode[spi->chip_select]);
@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
        mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
 
        retval = fsl_espi_setup_transfer(spi, NULL);
+
+       pm_runtime_mark_last_busy(mpc8xxx_spi->dev);
+       pm_runtime_put_autosuspend(mpc8xxx_spi->dev);
+
        if (retval < 0) {
                cs->hw_mode = hw_mode; /* Restore settings */
                return retval;
@@ -604,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
        return ret;
 }
 
-static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+#ifdef CONFIG_PM
+static int fsl_espi_runtime_suspend(struct device *dev)
 {
-       iounmap(mspi->reg_base);
-}
-
-static int fsl_espi_suspend(struct spi_master *master)
-{
-       struct mpc8xxx_spi *mpc8xxx_spi;
-       struct fsl_espi_reg *reg_base;
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+       struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
        u32 regval;
 
-       mpc8xxx_spi = spi_master_get_devdata(master);
-       reg_base = mpc8xxx_spi->reg_base;
-
        regval = mpc8xxx_spi_read_reg(&reg_base->mode);
        regval &= ~SPMODE_ENABLE;
        mpc8xxx_spi_write_reg(&reg_base->mode, regval);
@@ -625,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master)
        return 0;
 }
 
-static int fsl_espi_resume(struct spi_master *master)
+static int fsl_espi_runtime_resume(struct device *dev)
 {
-       struct mpc8xxx_spi *mpc8xxx_spi;
-       struct fsl_espi_reg *reg_base;
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+       struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
        u32 regval;
 
-       mpc8xxx_spi = spi_master_get_devdata(master);
-       reg_base = mpc8xxx_spi->reg_base;
-
        regval = mpc8xxx_spi_read_reg(&reg_base->mode);
        regval |= SPMODE_ENABLE;
        mpc8xxx_spi_write_reg(&reg_base->mode, regval);
 
        return 0;
 }
+#endif
 
 static struct spi_master * fsl_espi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
@@ -667,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
        master->setup = fsl_espi_setup;
        master->cleanup = fsl_espi_cleanup;
        master->transfer_one_message = fsl_espi_do_one_msg;
-       master->prepare_transfer_hardware = fsl_espi_resume;
-       master->unprepare_transfer_hardware = fsl_espi_suspend;
+       master->auto_runtime_pm = true;
 
        mpc8xxx_spi = spi_master_get_devdata(master);
-       mpc8xxx_spi->spi_remove = fsl_espi_remove;
 
-       mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
-       if (!mpc8xxx_spi->reg_base) {
-               ret = -ENOMEM;
+       mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(mpc8xxx_spi->reg_base)) {
+               ret = PTR_ERR(mpc8xxx_spi->reg_base);
                goto err_probe;
        }
 
        reg_base = mpc8xxx_spi->reg_base;
 
        /* Register for SPI Interrupt */
-       ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+       ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq,
                          0, "fsl_espi", mpc8xxx_spi);
        if (ret)
-               goto free_irq;
+               goto err_probe;
 
        if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
                mpc8xxx_spi->rx_shift = 16;
@@ -731,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
 
        mpc8xxx_spi_write_reg(&reg_base->mode, regval);
 
-       ret = spi_register_master(master);
+       pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+
+       ret = devm_spi_register_master(dev, master);
        if (ret < 0)
-               goto unreg_master;
+               goto err_pm;
 
        dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
 
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
        return master;
 
-unreg_master:
-       free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
-       iounmap(mpc8xxx_spi->reg_base);
+err_pm:
+       pm_runtime_put_noidle(dev);
+       pm_runtime_disable(dev);
+       pm_runtime_set_suspended(dev);
 err_probe:
        spi_master_put(master);
 err:
@@ -809,7 +818,9 @@ err:
 
 static int of_fsl_espi_remove(struct platform_device *dev)
 {
-       return mpc8xxx_spi_remove(&dev->dev);
+       pm_runtime_disable(&dev->dev);
+
+       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -824,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
                return ret;
        }
 
-       return fsl_espi_suspend(master);
+       ret = pm_runtime_force_suspend(dev);
+       if (ret < 0)
+               return ret;
+
+       return 0;
 }
 
 static int of_fsl_espi_resume(struct device *dev)
@@ -834,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
        struct mpc8xxx_spi *mpc8xxx_spi;
        struct fsl_espi_reg *reg_base;
        u32 regval;
-       int i;
+       int i, ret;
 
        mpc8xxx_spi = spi_master_get_devdata(master);
        reg_base = mpc8xxx_spi->reg_base;
@@ -854,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)
 
        mpc8xxx_spi_write_reg(&reg_base->mode, regval);
 
+       ret = pm_runtime_force_resume(dev);
+       if (ret < 0)
+               return ret;
+
        return spi_master_resume(master);
 }
 #endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops espi_pm = {
+       SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend,
+                          fsl_espi_runtime_resume, NULL)
        SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
 };
 
index cb35d2f0d0e63cf0d5dcf2d7aaddb22c54590c4a..1e43412cd9f88921519f4d981c7a3229afc4a248 100644 (file)
@@ -114,25 +114,6 @@ void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
 }
 EXPORT_SYMBOL_GPL(mpc8xxx_spi_probe);
 
-int mpc8xxx_spi_remove(struct device *dev)
-{
-       struct mpc8xxx_spi *mpc8xxx_spi;
-       struct spi_master *master;
-
-       master = dev_get_drvdata(dev);
-       mpc8xxx_spi = spi_master_get_devdata(master);
-
-       spi_unregister_master(master);
-
-       free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-
-       if (mpc8xxx_spi->spi_remove)
-               mpc8xxx_spi->spi_remove(mpc8xxx_spi);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(mpc8xxx_spi_remove);
-
 int of_mpc8xxx_spi_probe(struct platform_device *ofdev)
 {
        struct device *dev = &ofdev->dev;
index 1326a392adcad162dd303617a03bf675d40a7a68..84f5dcb7a897d1388b0c08223c69ba661ca21017 100644 (file)
@@ -54,9 +54,6 @@ struct mpc8xxx_spi {
        void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
        u32(*get_tx) (struct mpc8xxx_spi *);
 
-       /* hooks for different controller driver */
-       void (*spi_remove) (struct mpc8xxx_spi *mspi);
-
        unsigned int count;
        unsigned int irq;
 
index 60c590790854242dde41e86135192ca2c1cbb4a9..8b290d9d7935044640da36688e82fd01e90bf114 100644 (file)
@@ -559,12 +559,6 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
        return ret;
 }
 
-static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
-{
-       iounmap(mspi->reg_base);
-       fsl_spi_cpm_free(mspi);
-}
-
 static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
 {
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
@@ -631,7 +625,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
        master->transfer_one_message = fsl_spi_do_one_msg;
 
        mpc8xxx_spi = spi_master_get_devdata(master);
-       mpc8xxx_spi->spi_remove = fsl_spi_remove;
        mpc8xxx_spi->max_bits_per_word = 32;
        mpc8xxx_spi->type = fsl_spi_get_type(dev);
 
@@ -639,10 +632,10 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
        if (ret)
                goto err_cpm_init;
 
-       mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
-       if (mpc8xxx_spi->reg_base == NULL) {
-               ret = -ENOMEM;
-               goto err_ioremap;
+       mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(mpc8xxx_spi->reg_base)) {
+               ret = PTR_ERR(mpc8xxx_spi->reg_base);
+               goto err_probe;
        }
 
        if (mpc8xxx_spi->type == TYPE_GRLIB)
@@ -661,11 +654,11 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
                                        &mpc8xxx_spi->tx_shift, 8, 1);
 
        /* Register for SPI Interrupt */
-       ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
-                         0, "fsl_spi", mpc8xxx_spi);
+       ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_spi_irq,
+                              0, "fsl_spi", mpc8xxx_spi);
 
        if (ret != 0)
-               goto free_irq;
+               goto err_probe;
 
        reg_base = mpc8xxx_spi->reg_base;
 
@@ -686,20 +679,16 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
 
        mpc8xxx_spi_write_reg(&reg_base->mode, regval);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(dev, master);
        if (ret < 0)
-               goto unreg_master;
+               goto err_probe;
 
        dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
                 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
 
        return master;
 
-unreg_master:
-       free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
-       iounmap(mpc8xxx_spi->reg_base);
-err_ioremap:
+err_probe:
        fsl_spi_cpm_free(mpc8xxx_spi);
 err_cpm_init:
        spi_master_put(master);
@@ -866,11 +855,8 @@ static int of_fsl_spi_remove(struct platform_device *ofdev)
 {
        struct spi_master *master = platform_get_drvdata(ofdev);
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
-       int ret;
 
-       ret = mpc8xxx_spi_remove(&ofdev->dev);
-       if (ret)
-               return ret;
+       fsl_spi_cpm_free(mpc8xxx_spi);
        if (mpc8xxx_spi->type == TYPE_FSL)
                of_fsl_spi_free_chipselects(&ofdev->dev);
        return 0;
@@ -916,7 +902,12 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
 
 static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
 {
-       return mpc8xxx_spi_remove(&pdev->dev);
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+
+       fsl_spi_cpm_free(mpc8xxx_spi);
+
+       return 0;
 }
 
 MODULE_ALIAS("platform:mpc8xxx_spi");
index acce90ac7371d58d94b47dc3cb1da029969fb95f..823cbc92d1e75447b1487158ac097e1de3d50470 100644 (file)
@@ -105,6 +105,10 @@ struct img_spfi {
        bool rx_dma_busy;
 };
 
+struct img_spfi_device_data {
+       bool gpio_requested;
+};
+
 static inline u32 spfi_readl(struct img_spfi *spfi, u32 reg)
 {
        return readl(spfi->regs + reg);
@@ -267,15 +271,15 @@ static int img_spfi_start_pio(struct spi_master *master,
                cpu_relax();
        }
 
-       ret = spfi_wait_all_done(spfi);
-       if (ret < 0)
-               return ret;
-
        if (rx_bytes > 0 || tx_bytes > 0) {
                dev_err(spfi->dev, "PIO transfer timed out\n");
                return -ETIMEDOUT;
        }
 
+       ret = spfi_wait_all_done(spfi);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
@@ -440,21 +444,50 @@ static int img_spfi_unprepare(struct spi_master *master,
 
 static int img_spfi_setup(struct spi_device *spi)
 {
-       int ret;
-
-       ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ?
-                              GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
-                              dev_name(&spi->dev));
-       if (ret)
-               dev_err(&spi->dev, "can't request chipselect gpio %d\n",
+       int ret = -EINVAL;
+       struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
+
+       if (!spfi_data) {
+               spfi_data = kzalloc(sizeof(*spfi_data), GFP_KERNEL);
+               if (!spfi_data)
+                       return -ENOMEM;
+               spfi_data->gpio_requested = false;
+               spi_set_ctldata(spi, spfi_data);
+       }
+       if (!spfi_data->gpio_requested) {
+               ret = gpio_request_one(spi->cs_gpio,
+                                      (spi->mode & SPI_CS_HIGH) ?
+                                      GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+                                      dev_name(&spi->dev));
+               if (ret)
+                       dev_err(&spi->dev, "can't request chipselect gpio %d\n",
                                spi->cs_gpio);
-
+               else
+                       spfi_data->gpio_requested = true;
+       } else {
+               if (gpio_is_valid(spi->cs_gpio)) {
+                       int mode = ((spi->mode & SPI_CS_HIGH) ?
+                                   GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH);
+
+                       ret = gpio_direction_output(spi->cs_gpio, mode);
+                       if (ret)
+                               dev_err(&spi->dev, "chipselect gpio %d setup failed (%d)\n",
+                                       spi->cs_gpio, ret);
+               }
+       }
        return ret;
 }
 
 static void img_spfi_cleanup(struct spi_device *spi)
 {
-       gpio_free(spi->cs_gpio);
+       struct img_spfi_device_data *spfi_data = spi_get_ctldata(spi);
+
+       if (spfi_data) {
+               if (spfi_data->gpio_requested)
+                       gpio_free(spi->cs_gpio);
+               kfree(spfi_data);
+               spi_set_ctldata(spi, NULL);
+       }
 }
 
 static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
@@ -548,6 +581,7 @@ static int img_spfi_probe(struct platform_device *pdev)
        struct img_spfi *spfi;
        struct resource *res;
        int ret;
+       u32 max_speed_hz;
 
        master = spi_alloc_master(&pdev->dev, sizeof(*spfi));
        if (!master)
@@ -612,6 +646,19 @@ static int img_spfi_probe(struct platform_device *pdev)
        master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
        master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
 
+       /*
+        * Maximum speed supported by spfi is limited to the lower value
+        * between 1/4 of the SPFI clock or to "spfi-max-frequency"
+        * defined in the device tree.
+        * If no value is defined in the device tree assume the maximum
+        * speed supported to be 1/4 of the SPFI clock.
+        */
+       if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency",
+                                 &max_speed_hz)) {
+               if (master->max_speed_hz > max_speed_hz)
+                       master->max_speed_hz = max_speed_hz;
+       }
+
        master->setup = img_spfi_setup;
        master->cleanup = img_spfi_cleanup;
        master->transfer_one = img_spfi_transfer_one;
index 965d2bdcfdcc710e4c8f0374fffe4e9570b117b7..1e75341689a622916bad62e4429d4ed4c5315fc2 100644 (file)
 #include <linux/gpio.h>
 #include <asm/mpc52xx_psc.h>
 
+enum {
+       TYPE_MPC5121,
+       TYPE_MPC5125,
+};
+
+/*
+ * This macro abstracts the differences in the PSC register layout between
+ * MPC5121 (which uses a struct mpc52xx_psc) and MPC5125 (using mpc5125_psc).
+ */
+#define psc_addr(mps, regname) ({                                      \
+       void *__ret = NULL;                                             \
+       switch (mps->type) {                                            \
+       case TYPE_MPC5121: {                                            \
+                       struct mpc52xx_psc __iomem *psc = mps->psc;     \
+                       __ret = &psc->regname;                          \
+               };                                                      \
+               break;                                                  \
+       case TYPE_MPC5125: {                                            \
+                       struct mpc5125_psc __iomem *psc = mps->psc;     \
+                       __ret = &psc->regname;                          \
+               };                                                      \
+               break;                                                  \
+       }                                                               \
+       __ret; })
+
 struct mpc512x_psc_spi {
        void (*cs_control)(struct spi_device *spi, bool on);
 
        /* driver internal data */
-       struct mpc52xx_psc __iomem *psc;
+       int type;
+       void __iomem *psc;
        struct mpc512x_psc_fifo __iomem *fifo;
        unsigned int irq;
        u8 bits_per_word;
@@ -71,13 +97,12 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
 {
        struct mpc512x_psc_spi_cs *cs = spi->controller_state;
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
-       struct mpc52xx_psc __iomem *psc = mps->psc;
        u32 sicr;
        u32 ccr;
        int speed;
        u16 bclkdiv;
 
-       sicr = in_be32(&psc->sicr);
+       sicr = in_be32(psc_addr(mps, sicr));
 
        /* Set clock phase and polarity */
        if (spi->mode & SPI_CPHA)
@@ -94,9 +119,9 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
                sicr |= 0x10000000;
        else
                sicr &= ~0x10000000;
-       out_be32(&psc->sicr, sicr);
+       out_be32(psc_addr(mps, sicr), sicr);
 
-       ccr = in_be32(&psc->ccr);
+       ccr = in_be32(psc_addr(mps, ccr));
        ccr &= 0xFF000000;
        speed = cs->speed_hz;
        if (!speed)
@@ -104,7 +129,7 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
        bclkdiv = (mps->mclk_rate / speed) - 1;
 
        ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
-       out_be32(&psc->ccr, ccr);
+       out_be32(psc_addr(mps, ccr), ccr);
        mps->bits_per_word = cs->bits_per_word;
 
        if (mps->cs_control && gpio_is_valid(spi->cs_gpio))
@@ -315,16 +340,15 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
 static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
 {
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
-       struct mpc52xx_psc __iomem *psc = mps->psc;
 
        dev_dbg(&master->dev, "%s()\n", __func__);
 
        /* Zero MR2 */
-       in_8(&psc->mode);
-       out_8(&psc->mode, 0x0);
+       in_8(psc_addr(mps, mr2));
+       out_8(psc_addr(mps, mr2), 0x0);
 
        /* enable transmitter/receiver */
-       out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+       out_8(psc_addr(mps, command), MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
 
        return 0;
 }
@@ -332,13 +356,12 @@ static int mpc512x_psc_spi_prep_xfer_hw(struct spi_master *master)
 static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)
 {
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
-       struct mpc52xx_psc __iomem *psc = mps->psc;
        struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
 
        dev_dbg(&master->dev, "%s()\n", __func__);
 
        /* disable transmitter/receiver and fifo interrupt */
-       out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+       out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
        out_be32(&fifo->tximr, 0);
 
        return 0;
@@ -388,7 +411,6 @@ static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
 static int mpc512x_psc_spi_port_config(struct spi_master *master,
                                       struct mpc512x_psc_spi *mps)
 {
-       struct mpc52xx_psc __iomem *psc = mps->psc;
        struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
        u32 sicr;
        u32 ccr;
@@ -396,12 +418,12 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
        u16 bclkdiv;
 
        /* Reset the PSC into a known state */
-       out_8(&psc->command, MPC52xx_PSC_RST_RX);
-       out_8(&psc->command, MPC52xx_PSC_RST_TX);
-       out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+       out_8(psc_addr(mps, command), MPC52xx_PSC_RST_RX);
+       out_8(psc_addr(mps, command), MPC52xx_PSC_RST_TX);
+       out_8(psc_addr(mps, command), MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
 
        /* Disable psc interrupts all useful interrupts are in fifo */
-       out_be16(&psc->isr_imr.imr, 0);
+       out_be16(psc_addr(mps, isr_imr.imr), 0);
 
        /* Disable fifo interrupts, will be enabled later */
        out_be32(&fifo->tximr, 0);
@@ -417,18 +439,18 @@ static int mpc512x_psc_spi_port_config(struct spi_master *master,
                0x00004000 |    /* MSTR = 1   -- SPI master */
                0x00000800;     /* UseEOF = 1 -- SS low until EOF */
 
-       out_be32(&psc->sicr, sicr);
+       out_be32(psc_addr(mps, sicr), sicr);
 
-       ccr = in_be32(&psc->ccr);
+       ccr = in_be32(psc_addr(mps, ccr));
        ccr &= 0xFF000000;
        speed = 1000000;        /* default 1MHz */
        bclkdiv = (mps->mclk_rate / speed) - 1;
        ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
-       out_be32(&psc->ccr, ccr);
+       out_be32(psc_addr(mps, ccr), ccr);
 
        /* Set 2ms DTL delay */
-       out_8(&psc->ctur, 0x00);
-       out_8(&psc->ctlr, 0x82);
+       out_8(psc_addr(mps, ctur), 0x00);
+       out_8(psc_addr(mps, ctlr), 0x82);
 
        /* we don't use the alarms */
        out_be32(&fifo->rxalarm, 0xfff);
@@ -482,6 +504,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
 
        dev_set_drvdata(dev, master);
        mps = spi_master_get_devdata(master);
+       mps->type = (int)of_device_get_match_data(dev);
        mps->irq = irq;
 
        if (pdata == NULL) {
@@ -589,7 +612,8 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
 }
 
 static const struct of_device_id mpc512x_psc_spi_of_match[] = {
-       { .compatible = "fsl,mpc5121-psc-spi", },
+       { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
+       { .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
        {},
 };
 
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
new file mode 100644 (file)
index 0000000..5f6315c
--- /dev/null
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Leilk Liu <leilk.liu@mediatek.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/spi-mt65xx.h>
+#include <linux/pm_runtime.h>
+#include <linux/spi/spi.h>
+
+#define SPI_CFG0_REG                      0x0000
+#define SPI_CFG1_REG                      0x0004
+#define SPI_TX_SRC_REG                    0x0008
+#define SPI_RX_DST_REG                    0x000c
+#define SPI_TX_DATA_REG                   0x0010
+#define SPI_RX_DATA_REG                   0x0014
+#define SPI_CMD_REG                       0x0018
+#define SPI_STATUS0_REG                   0x001c
+#define SPI_PAD_SEL_REG                   0x0024
+
+#define SPI_CFG0_SCK_HIGH_OFFSET          0
+#define SPI_CFG0_SCK_LOW_OFFSET           8
+#define SPI_CFG0_CS_HOLD_OFFSET           16
+#define SPI_CFG0_CS_SETUP_OFFSET          24
+
+#define SPI_CFG1_CS_IDLE_OFFSET           0
+#define SPI_CFG1_PACKET_LOOP_OFFSET       8
+#define SPI_CFG1_PACKET_LENGTH_OFFSET     16
+#define SPI_CFG1_GET_TICK_DLY_OFFSET      30
+
+#define SPI_CFG1_CS_IDLE_MASK             0xff
+#define SPI_CFG1_PACKET_LOOP_MASK         0xff00
+#define SPI_CFG1_PACKET_LENGTH_MASK       0x3ff0000
+
+#define SPI_CMD_ACT                  BIT(0)
+#define SPI_CMD_RESUME               BIT(1)
+#define SPI_CMD_RST                  BIT(2)
+#define SPI_CMD_PAUSE_EN             BIT(4)
+#define SPI_CMD_DEASSERT             BIT(5)
+#define SPI_CMD_CPHA                 BIT(8)
+#define SPI_CMD_CPOL                 BIT(9)
+#define SPI_CMD_RX_DMA               BIT(10)
+#define SPI_CMD_TX_DMA               BIT(11)
+#define SPI_CMD_TXMSBF               BIT(12)
+#define SPI_CMD_RXMSBF               BIT(13)
+#define SPI_CMD_RX_ENDIAN            BIT(14)
+#define SPI_CMD_TX_ENDIAN            BIT(15)
+#define SPI_CMD_FINISH_IE            BIT(16)
+#define SPI_CMD_PAUSE_IE             BIT(17)
+
+#define MT8173_SPI_MAX_PAD_SEL 3
+
+#define MTK_SPI_PAUSE_INT_STATUS 0x2
+
+#define MTK_SPI_IDLE 0
+#define MTK_SPI_PAUSED 1
+
+#define MTK_SPI_MAX_FIFO_SIZE 32
+#define MTK_SPI_PACKET_SIZE 1024
+
+struct mtk_spi_compatible {
+       bool need_pad_sel;
+       /* Must explicitly send dummy Tx bytes to do Rx only transfer */
+       bool must_tx;
+};
+
+struct mtk_spi {
+       void __iomem *base;
+       u32 state;
+       u32 pad_sel;
+       struct clk *spi_clk, *parent_clk;
+       struct spi_transfer *cur_transfer;
+       u32 xfer_len;
+       struct scatterlist *tx_sgl, *rx_sgl;
+       u32 tx_sgl_len, rx_sgl_len;
+       const struct mtk_spi_compatible *dev_comp;
+};
+
+static const struct mtk_spi_compatible mt6589_compat;
+static const struct mtk_spi_compatible mt8135_compat;
+static const struct mtk_spi_compatible mt8173_compat = {
+       .need_pad_sel = true,
+       .must_tx = true,
+};
+
+/*
+ * A piece of default chip info unless the platform
+ * supplies it.
+ */
+static const struct mtk_chip_config mtk_default_chip_info = {
+       .rx_mlsb = 1,
+       .tx_mlsb = 1,
+};
+
+static const struct of_device_id mtk_spi_of_match[] = {
+       { .compatible = "mediatek,mt6589-spi", .data = (void *)&mt6589_compat },
+       { .compatible = "mediatek,mt8135-spi", .data = (void *)&mt8135_compat },
+       { .compatible = "mediatek,mt8173-spi", .data = (void *)&mt8173_compat },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mtk_spi_of_match);
+
+static void mtk_spi_reset(struct mtk_spi *mdata)
+{
+       u32 reg_val;
+
+       /* set the software reset bit in SPI_CMD_REG. */
+       reg_val = readl(mdata->base + SPI_CMD_REG);
+       reg_val |= SPI_CMD_RST;
+       writel(reg_val, mdata->base + SPI_CMD_REG);
+
+       reg_val = readl(mdata->base + SPI_CMD_REG);
+       reg_val &= ~SPI_CMD_RST;
+       writel(reg_val, mdata->base + SPI_CMD_REG);
+}
+
+static void mtk_spi_config(struct mtk_spi *mdata,
+                          struct mtk_chip_config *chip_config)
+{
+       u32 reg_val;
+
+       reg_val = readl(mdata->base + SPI_CMD_REG);
+
+       /* set the mlsbx and mlsbtx */
+       if (chip_config->tx_mlsb)
+               reg_val |= SPI_CMD_TXMSBF;
+       else
+               reg_val &= ~SPI_CMD_TXMSBF;
+       if (chip_config->rx_mlsb)
+               reg_val |= SPI_CMD_RXMSBF;
+       else
+               reg_val &= ~SPI_CMD_RXMSBF;
+
+       /* set the tx/rx endian */
+#ifdef __LITTLE_ENDIAN
+       reg_val &= ~SPI_CMD_TX_ENDIAN;
+       reg_val &= ~SPI_CMD_RX_ENDIAN;
+#else
+       reg_val |= SPI_CMD_TX_ENDIAN;
+       reg_val |= SPI_CMD_RX_ENDIAN;
+#endif
+
+       /* set finish and pause interrupt always enable */
+       reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_IE;
+
+       /* disable dma mode */
+       reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA);
+
+       /* disable deassert mode */
+       reg_val &= ~SPI_CMD_DEASSERT;
+
+       writel(reg_val, mdata->base + SPI_CMD_REG);
+
+       /* pad select */
+       if (mdata->dev_comp->need_pad_sel)
+               writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG);
+}
+
+static int mtk_spi_prepare_hardware(struct spi_master *master)
+{
+       struct spi_transfer *trans;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+       struct spi_message *msg = master->cur_msg;
+
+       trans = list_first_entry(&msg->transfers, struct spi_transfer,
+                                transfer_list);
+       if (!trans->cs_change) {
+               mdata->state = MTK_SPI_IDLE;
+               mtk_spi_reset(mdata);
+       }
+
+       return 0;
+}
+
+static int mtk_spi_prepare_message(struct spi_master *master,
+                                  struct spi_message *msg)
+{
+       u32 reg_val;
+       u8 cpha, cpol;
+       struct mtk_chip_config *chip_config;
+       struct spi_device *spi = msg->spi;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       cpha = spi->mode & SPI_CPHA ? 1 : 0;
+       cpol = spi->mode & SPI_CPOL ? 1 : 0;
+
+       reg_val = readl(mdata->base + SPI_CMD_REG);
+       if (cpha)
+               reg_val |= SPI_CMD_CPHA;
+       else
+               reg_val &= ~SPI_CMD_CPHA;
+       if (cpol)
+               reg_val |= SPI_CMD_CPOL;
+       else
+               reg_val &= ~SPI_CMD_CPOL;
+       writel(reg_val, mdata->base + SPI_CMD_REG);
+
+       chip_config = spi->controller_data;
+       if (!chip_config) {
+               chip_config = (void *)&mtk_default_chip_info;
+               spi->controller_data = chip_config;
+       }
+       mtk_spi_config(mdata, chip_config);
+
+       return 0;
+}
+
+static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
+{
+       u32 reg_val;
+       struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
+
+       reg_val = readl(mdata->base + SPI_CMD_REG);
+       if (!enable)
+               reg_val |= SPI_CMD_PAUSE_EN;
+       else
+               reg_val &= ~SPI_CMD_PAUSE_EN;
+       writel(reg_val, mdata->base + SPI_CMD_REG);
+}
+
+static void mtk_spi_prepare_transfer(struct spi_master *master,
+                                    struct spi_transfer *xfer)
+{
+       u32 spi_clk_hz, div, sck_time, cs_time, reg_val = 0;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       spi_clk_hz = clk_get_rate(mdata->spi_clk);
+       if (xfer->speed_hz < spi_clk_hz / 2)
+               div = DIV_ROUND_UP(spi_clk_hz, xfer->speed_hz);
+       else
+               div = 1;
+
+       sck_time = (div + 1) / 2;
+       cs_time = sck_time * 2;
+
+       reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_HIGH_OFFSET);
+       reg_val |= (((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET);
+       reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET);
+       reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET);
+       writel(reg_val, mdata->base + SPI_CFG0_REG);
+
+       reg_val = readl(mdata->base + SPI_CFG1_REG);
+       reg_val &= ~SPI_CFG1_CS_IDLE_MASK;
+       reg_val |= (((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET);
+       writel(reg_val, mdata->base + SPI_CFG1_REG);
+}
+
+static void mtk_spi_setup_packet(struct spi_master *master)
+{
+       u32 packet_size, packet_loop, reg_val;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE);
+       packet_loop = mdata->xfer_len / packet_size;
+
+       reg_val = readl(mdata->base + SPI_CFG1_REG);
+       reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK);
+       reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
+       reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
+       writel(reg_val, mdata->base + SPI_CFG1_REG);
+}
+
+static void mtk_spi_enable_transfer(struct spi_master *master)
+{
+       u32 cmd;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       cmd = readl(mdata->base + SPI_CMD_REG);
+       if (mdata->state == MTK_SPI_IDLE)
+               cmd |= SPI_CMD_ACT;
+       else
+               cmd |= SPI_CMD_RESUME;
+       writel(cmd, mdata->base + SPI_CMD_REG);
+}
+
+static int mtk_spi_get_mult_delta(u32 xfer_len)
+{
+       u32 mult_delta;
+
+       if (xfer_len > MTK_SPI_PACKET_SIZE)
+               mult_delta = xfer_len % MTK_SPI_PACKET_SIZE;
+       else
+               mult_delta = 0;
+
+       return mult_delta;
+}
+
+static void mtk_spi_update_mdata_len(struct spi_master *master)
+{
+       int mult_delta;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       if (mdata->tx_sgl_len && mdata->rx_sgl_len) {
+               if (mdata->tx_sgl_len > mdata->rx_sgl_len) {
+                       mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len);
+                       mdata->xfer_len = mdata->rx_sgl_len - mult_delta;
+                       mdata->rx_sgl_len = mult_delta;
+                       mdata->tx_sgl_len -= mdata->xfer_len;
+               } else {
+                       mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len);
+                       mdata->xfer_len = mdata->tx_sgl_len - mult_delta;
+                       mdata->tx_sgl_len = mult_delta;
+                       mdata->rx_sgl_len -= mdata->xfer_len;
+               }
+       } else if (mdata->tx_sgl_len) {
+               mult_delta = mtk_spi_get_mult_delta(mdata->tx_sgl_len);
+               mdata->xfer_len = mdata->tx_sgl_len - mult_delta;
+               mdata->tx_sgl_len = mult_delta;
+       } else if (mdata->rx_sgl_len) {
+               mult_delta = mtk_spi_get_mult_delta(mdata->rx_sgl_len);
+               mdata->xfer_len = mdata->rx_sgl_len - mult_delta;
+               mdata->rx_sgl_len = mult_delta;
+       }
+}
+
+static void mtk_spi_setup_dma_addr(struct spi_master *master,
+                                  struct spi_transfer *xfer)
+{
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       if (mdata->tx_sgl)
+               writel(xfer->tx_dma, mdata->base + SPI_TX_SRC_REG);
+       if (mdata->rx_sgl)
+               writel(xfer->rx_dma, mdata->base + SPI_RX_DST_REG);
+}
+
+static int mtk_spi_fifo_transfer(struct spi_master *master,
+                                struct spi_device *spi,
+                                struct spi_transfer *xfer)
+{
+       int cnt;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       mdata->cur_transfer = xfer;
+       mdata->xfer_len = xfer->len;
+       mtk_spi_prepare_transfer(master, xfer);
+       mtk_spi_setup_packet(master);
+
+       if (xfer->len % 4)
+               cnt = xfer->len / 4 + 1;
+       else
+               cnt = xfer->len / 4;
+       iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt);
+
+       mtk_spi_enable_transfer(master);
+
+       return 1;
+}
+
+static int mtk_spi_dma_transfer(struct spi_master *master,
+                               struct spi_device *spi,
+                               struct spi_transfer *xfer)
+{
+       int cmd;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       mdata->tx_sgl = NULL;
+       mdata->rx_sgl = NULL;
+       mdata->tx_sgl_len = 0;
+       mdata->rx_sgl_len = 0;
+       mdata->cur_transfer = xfer;
+
+       mtk_spi_prepare_transfer(master, xfer);
+
+       cmd = readl(mdata->base + SPI_CMD_REG);
+       if (xfer->tx_buf)
+               cmd |= SPI_CMD_TX_DMA;
+       if (xfer->rx_buf)
+               cmd |= SPI_CMD_RX_DMA;
+       writel(cmd, mdata->base + SPI_CMD_REG);
+
+       if (xfer->tx_buf)
+               mdata->tx_sgl = xfer->tx_sg.sgl;
+       if (xfer->rx_buf)
+               mdata->rx_sgl = xfer->rx_sg.sgl;
+
+       if (mdata->tx_sgl) {
+               xfer->tx_dma = sg_dma_address(mdata->tx_sgl);
+               mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl);
+       }
+       if (mdata->rx_sgl) {
+               xfer->rx_dma = sg_dma_address(mdata->rx_sgl);
+               mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl);
+       }
+
+       mtk_spi_update_mdata_len(master);
+       mtk_spi_setup_packet(master);
+       mtk_spi_setup_dma_addr(master, xfer);
+       mtk_spi_enable_transfer(master);
+
+       return 1;
+}
+
+static int mtk_spi_transfer_one(struct spi_master *master,
+                               struct spi_device *spi,
+                               struct spi_transfer *xfer)
+{
+       if (master->can_dma(master, spi, xfer))
+               return mtk_spi_dma_transfer(master, spi, xfer);
+       else
+               return mtk_spi_fifo_transfer(master, spi, xfer);
+}
+
+static bool mtk_spi_can_dma(struct spi_master *master,
+                           struct spi_device *spi,
+                           struct spi_transfer *xfer)
+{
+       return xfer->len > MTK_SPI_MAX_FIFO_SIZE;
+}
+
+static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+{
+       u32 cmd, reg_val, cnt;
+       struct spi_master *master = dev_id;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+       struct spi_transfer *trans = mdata->cur_transfer;
+
+       reg_val = readl(mdata->base + SPI_STATUS0_REG);
+       if (reg_val & MTK_SPI_PAUSE_INT_STATUS)
+               mdata->state = MTK_SPI_PAUSED;
+       else
+               mdata->state = MTK_SPI_IDLE;
+
+       if (!master->can_dma(master, master->cur_msg->spi, trans)) {
+               if (trans->rx_buf) {
+                       if (mdata->xfer_len % 4)
+                               cnt = mdata->xfer_len / 4 + 1;
+                       else
+                               cnt = mdata->xfer_len / 4;
+                       ioread32_rep(mdata->base + SPI_RX_DATA_REG,
+                                    trans->rx_buf, cnt);
+               }
+               spi_finalize_current_transfer(master);
+               return IRQ_HANDLED;
+       }
+
+       if (mdata->tx_sgl)
+               trans->tx_dma += mdata->xfer_len;
+       if (mdata->rx_sgl)
+               trans->rx_dma += mdata->xfer_len;
+
+       if (mdata->tx_sgl && (mdata->tx_sgl_len == 0)) {
+               mdata->tx_sgl = sg_next(mdata->tx_sgl);
+               if (mdata->tx_sgl) {
+                       trans->tx_dma = sg_dma_address(mdata->tx_sgl);
+                       mdata->tx_sgl_len = sg_dma_len(mdata->tx_sgl);
+               }
+       }
+       if (mdata->rx_sgl && (mdata->rx_sgl_len == 0)) {
+               mdata->rx_sgl = sg_next(mdata->rx_sgl);
+               if (mdata->rx_sgl) {
+                       trans->rx_dma = sg_dma_address(mdata->rx_sgl);
+                       mdata->rx_sgl_len = sg_dma_len(mdata->rx_sgl);
+               }
+       }
+
+       if (!mdata->tx_sgl && !mdata->rx_sgl) {
+               /* spi disable dma */
+               cmd = readl(mdata->base + SPI_CMD_REG);
+               cmd &= ~SPI_CMD_TX_DMA;
+               cmd &= ~SPI_CMD_RX_DMA;
+               writel(cmd, mdata->base + SPI_CMD_REG);
+
+               spi_finalize_current_transfer(master);
+               return IRQ_HANDLED;
+       }
+
+       mtk_spi_update_mdata_len(master);
+       mtk_spi_setup_packet(master);
+       mtk_spi_setup_dma_addr(master, trans);
+       mtk_spi_enable_transfer(master);
+
+       return IRQ_HANDLED;
+}
+
+static int mtk_spi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct mtk_spi *mdata;
+       const struct of_device_id *of_id;
+       struct resource *res;
+       int irq, ret;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*mdata));
+       if (!master) {
+               dev_err(&pdev->dev, "failed to alloc spi master\n");
+               return -ENOMEM;
+       }
+
+       master->auto_runtime_pm = true;
+       master->dev.of_node = pdev->dev.of_node;
+       master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+       master->set_cs = mtk_spi_set_cs;
+       master->prepare_transfer_hardware = mtk_spi_prepare_hardware;
+       master->prepare_message = mtk_spi_prepare_message;
+       master->transfer_one = mtk_spi_transfer_one;
+       master->can_dma = mtk_spi_can_dma;
+
+       of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
+       if (!of_id) {
+               dev_err(&pdev->dev, "failed to probe of_node\n");
+               ret = -EINVAL;
+               goto err_put_master;
+       }
+
+       mdata = spi_master_get_devdata(master);
+       mdata->dev_comp = of_id->data;
+       if (mdata->dev_comp->must_tx)
+               master->flags = SPI_MASTER_MUST_TX;
+
+       if (mdata->dev_comp->need_pad_sel) {
+               ret = of_property_read_u32(pdev->dev.of_node,
+                                          "mediatek,pad-select",
+                                          &mdata->pad_sel);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to read pad select: %d\n",
+                               ret);
+                       goto err_put_master;
+               }
+
+               if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) {
+                       dev_err(&pdev->dev, "wrong pad-select: %u\n",
+                               mdata->pad_sel);
+                       ret = -EINVAL;
+                       goto err_put_master;
+               }
+       }
+
+       platform_set_drvdata(pdev, master);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               dev_err(&pdev->dev, "failed to determine base address\n");
+               goto err_put_master;
+       }
+
+       mdata->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mdata->base)) {
+               ret = PTR_ERR(mdata->base);
+               goto err_put_master;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get irq (%d)\n", irq);
+               ret = irq;
+               goto err_put_master;
+       }
+
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+       ret = devm_request_irq(&pdev->dev, irq, mtk_spi_interrupt,
+                              IRQF_TRIGGER_NONE, dev_name(&pdev->dev), master);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register irq (%d)\n", ret);
+               goto err_put_master;
+       }
+
+       mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk");
+       if (IS_ERR(mdata->spi_clk)) {
+               ret = PTR_ERR(mdata->spi_clk);
+               dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret);
+               goto err_put_master;
+       }
+
+       mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk");
+       if (IS_ERR(mdata->parent_clk)) {
+               ret = PTR_ERR(mdata->parent_clk);
+               dev_err(&pdev->dev, "failed to get parent-clk: %d\n", ret);
+               goto err_put_master;
+       }
+
+       ret = clk_prepare_enable(mdata->spi_clk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret);
+               goto err_put_master;
+       }
+
+       ret = clk_set_parent(mdata->spi_clk, mdata->parent_clk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret);
+               goto err_disable_clk;
+       }
+
+       clk_disable_unprepare(mdata->spi_clk);
+
+       pm_runtime_enable(&pdev->dev);
+
+       ret = devm_spi_register_master(&pdev->dev, master);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register master (%d)\n", ret);
+               goto err_put_master;
+       }
+
+       return 0;
+
+err_disable_clk:
+       clk_disable_unprepare(mdata->spi_clk);
+err_put_master:
+       spi_master_put(master);
+
+       return ret;
+}
+
+static int mtk_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       pm_runtime_disable(&pdev->dev);
+
+       mtk_spi_reset(mdata);
+       clk_disable_unprepare(mdata->spi_clk);
+       spi_master_put(master);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mtk_spi_suspend(struct device *dev)
+{
+       int ret;
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       ret = spi_master_suspend(master);
+       if (ret)
+               return ret;
+
+       if (!pm_runtime_suspended(dev))
+               clk_disable_unprepare(mdata->spi_clk);
+
+       return ret;
+}
+
+static int mtk_spi_resume(struct device *dev)
+{
+       int ret;
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       if (!pm_runtime_suspended(dev)) {
+               ret = clk_prepare_enable(mdata->spi_clk);
+               if (ret < 0) {
+                       dev_err(dev, "failed to enable spi_clk (%d)\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = spi_master_resume(master);
+       if (ret < 0)
+               clk_disable_unprepare(mdata->spi_clk);
+
+       return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int mtk_spi_runtime_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       clk_disable_unprepare(mdata->spi_clk);
+
+       return 0;
+}
+
+static int mtk_spi_runtime_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+       int ret;
+
+       ret = clk_prepare_enable(mdata->spi_clk);
+       if (ret < 0) {
+               dev_err(dev, "failed to enable spi_clk (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops mtk_spi_pm = {
+       SET_SYSTEM_SLEEP_PM_OPS(mtk_spi_suspend, mtk_spi_resume)
+       SET_RUNTIME_PM_OPS(mtk_spi_runtime_suspend,
+                          mtk_spi_runtime_resume, NULL)
+};
+
+static struct platform_driver mtk_spi_driver = {
+       .driver = {
+               .name = "mtk-spi",
+               .pm     = &mtk_spi_pm,
+               .of_match_table = mtk_spi_of_match,
+       },
+       .probe = mtk_spi_probe,
+       .remove = mtk_spi_remove,
+};
+
+module_platform_driver(mtk_spi_driver);
+
+MODULE_DESCRIPTION("MTK SPI Controller driver");
+MODULE_AUTHOR("Leilk Liu <leilk.liu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mtk-spi");
index 58673841286c335adc123d5200c1a0f128ecab04..3d09e0b69b73241c58d50e788dbdaf5cd16bf7ea 100644 (file)
@@ -245,6 +245,7 @@ static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
 
 static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
 {
+       struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
        u32 l;
 
        /* The controller handles the inverted chip selects
@@ -255,6 +256,12 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
                enable = !enable;
 
        if (spi->controller_state) {
+               int err = pm_runtime_get_sync(mcspi->dev);
+               if (err < 0) {
+                       dev_err(mcspi->dev, "failed to get sync: %d\n", err);
+                       return;
+               }
+
                l = mcspi_cached_chconf0(spi);
 
                if (enable)
@@ -263,6 +270,9 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
                        l |= OMAP2_MCSPI_CHCONF_FORCE;
 
                mcspi_write_chconf0(spi, l);
+
+               pm_runtime_mark_last_busy(mcspi->dev);
+               pm_runtime_put_autosuspend(mcspi->dev);
        }
 }
 
index 8cad107a5b3f7e6d3b77f79fbf56f4b49f944267..a87cfd4ba17b38f47a8e6c823c335c308c482dc8 100644 (file)
 #define ORION_SPI_DATA_OUT_REG         0x08
 #define ORION_SPI_DATA_IN_REG          0x0c
 #define ORION_SPI_INT_CAUSE_REG                0x10
+#define ORION_SPI_TIMING_PARAMS_REG    0x18
+
+#define ORION_SPI_TMISO_SAMPLE_MASK    (0x3 << 6)
+#define ORION_SPI_TMISO_SAMPLE_1       (1 << 6)
+#define ORION_SPI_TMISO_SAMPLE_2       (2 << 6)
 
 #define ORION_SPI_MODE_CPOL            (1 << 11)
 #define ORION_SPI_MODE_CPHA            (1 << 12)
@@ -70,6 +75,7 @@ struct orion_spi_dev {
        unsigned int            min_divisor;
        unsigned int            max_divisor;
        u32                     prescale_mask;
+       bool                    is_errata_50mhz_ac;
 };
 
 struct orion_spi {
@@ -195,6 +201,41 @@ orion_spi_mode_set(struct spi_device *spi)
        writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
 }
 
+static void
+orion_spi_50mhz_ac_timing_erratum(struct spi_device *spi, unsigned int speed)
+{
+       u32 reg;
+       struct orion_spi *orion_spi;
+
+       orion_spi = spi_master_get_devdata(spi->master);
+
+       /*
+        * Erratum description: (Erratum NO. FE-9144572) The device
+        * SPI interface supports frequencies of up to 50 MHz.
+        * However, due to this erratum, when the device core clock is
+        * 250 MHz and the SPI interfaces is configured for 50MHz SPI
+        * clock and CPOL=CPHA=1 there might occur data corruption on
+        * reads from the SPI device.
+        * Erratum Workaround:
+        * Work in one of the following configurations:
+        * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
+        * Register".
+        * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
+        * Register" before setting the interface.
+        */
+       reg = readl(spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
+       reg &= ~ORION_SPI_TMISO_SAMPLE_MASK;
+
+       if (clk_get_rate(orion_spi->clk) == 250000000 &&
+                       speed == 50000000 && spi->mode & SPI_CPOL &&
+                       spi->mode & SPI_CPHA)
+               reg |= ORION_SPI_TMISO_SAMPLE_2;
+       else
+               reg |= ORION_SPI_TMISO_SAMPLE_1; /* This is the default value */
+
+       writel(reg, spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
+}
+
 /*
  * called only when no transfer is active on the bus
  */
@@ -216,6 +257,9 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
        orion_spi_mode_set(spi);
 
+       if (orion_spi->devdata->is_errata_50mhz_ac)
+               orion_spi_50mhz_ac_timing_erratum(spi, speed);
+
        rc = orion_spi_baudrate_set(spi, speed);
        if (rc)
                return rc;
@@ -413,6 +457,14 @@ static const struct orion_spi_dev armada_375_spi_dev_data = {
        .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
 };
 
+static const struct orion_spi_dev armada_380_spi_dev_data = {
+       .typ = ARMADA_SPI,
+       .max_hz = 50000000,
+       .max_divisor = 1920,
+       .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK,
+       .is_errata_50mhz_ac = true,
+};
+
 static const struct of_device_id orion_spi_of_match_table[] = {
        {
                .compatible = "marvell,orion-spi",
@@ -428,7 +480,7 @@ static const struct of_device_id orion_spi_of_match_table[] = {
        },
        {
                .compatible = "marvell,armada-380-spi",
-               .data = &armada_xp_spi_dev_data,
+               .data = &armada_380_spi_dev_data,
        },
        {
                .compatible = "marvell,armada-390-spi",
index 3cfd4357489aba1a5904da3f39d0d12346d2a908..d19d7f28aecb3c5ac9ca6409fc9c8e2e5f7fc180 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/of_device.h>
 #include <linux/module.h>
 #include <linux/spi/pxa2xx_spi.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 
 #include <linux/dmaengine.h>
index 7293d6d875c5c692184d1c45aea151f063bb6cd0..fdd7919770419bcbf63afaf326e719e43ae6513b 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/spi/spi.h>
@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = {
                .tx_threshold_lo = 160,
                .tx_threshold_hi = 224,
        },
+       {       /* LPSS_SPT_SSP */
+               .offset = 0x200,
+               .reg_general = -1,
+               .reg_ssp = 0x20,
+               .reg_cs_ctrl = 0x24,
+               .rx_threshold = 1,
+               .tx_threshold_lo = 32,
+               .tx_threshold_hi = 56,
+       },
 };
 
 static inline const struct lpss_config
@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
        switch (drv_data->ssp_type) {
        case LPSS_LPT_SSP:
        case LPSS_BYT_SSP:
+       case LPSS_SPT_SSP:
                return true;
        default:
                return false;
@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi)
                break;
        case LPSS_LPT_SSP:
        case LPSS_BYT_SSP:
+       case LPSS_SPT_SSP:
                config = lpss_get_config(drv_data);
                tx_thres = config->tx_threshold_lo;
                tx_hi_thres = config->tx_threshold_hi;
@@ -1276,6 +1288,31 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
 };
 MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
 
+/*
+ * PCI IDs of compound devices that integrate both host controller and private
+ * integrated DMA engine. Please note these are not used in module
+ * autoloading and probing in this module but matching the LPSS SSP type.
+ */
+static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
+       /* SPT-LP */
+       { PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP },
+       { PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP },
+       /* SPT-H */
+       { PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
+       { PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
+       { },
+};
+
+static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
+{
+       struct device *dev = param;
+
+       if (dev != chan->device->dev->parent)
+               return false;
+
+       return true;
+}
+
 static struct pxa2xx_spi_master *
 pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 {
@@ -1283,16 +1320,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
        struct acpi_device *adev;
        struct ssp_device *ssp;
        struct resource *res;
-       const struct acpi_device_id *id;
+       const struct acpi_device_id *adev_id = NULL;
+       const struct pci_device_id *pcidev_id = NULL;
        int devid, type;
 
        if (!ACPI_HANDLE(&pdev->dev) ||
            acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
                return NULL;
 
-       id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
-       if (id)
-               type = (int)id->driver_data;
+       if (dev_is_pci(pdev->dev.parent))
+               pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match,
+                                        to_pci_dev(pdev->dev.parent));
+       else
+               adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
+                                           &pdev->dev);
+
+       if (adev_id)
+               type = (int)adev_id->driver_data;
+       else if (pcidev_id)
+               type = (int)pcidev_id->driver_data;
        else
                return NULL;
 
@@ -1311,6 +1357,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
        if (IS_ERR(ssp->mmio_base))
                return NULL;
 
+       if (pcidev_id) {
+               pdata->tx_param = pdev->dev.parent;
+               pdata->rx_param = pdev->dev.parent;
+               pdata->dma_filter = pxa2xx_spi_idma_filter;
+       }
+
        ssp->clk = devm_clk_get(&pdev->dev, NULL);
        ssp->irq = platform_get_irq(pdev, 0);
        ssp->type = type;
@@ -1362,8 +1414,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       /* Allocate master with space for drv_data and null dma buffer */
-       master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
+       master = spi_alloc_master(dev, sizeof(struct driver_data));
        if (!master) {
                dev_err(&pdev->dev, "cannot alloc spi_master\n");
                pxa_ssp_free(ssp);
@@ -1390,7 +1441,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        master->auto_runtime_pm = true;
 
        drv_data->ssp_type = ssp->type;
-       drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
 
        drv_data->ioaddr = ssp->mmio_base;
        drv_data->ssdr_physical = ssp->phys_base + SSDR;
@@ -1424,8 +1474,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        }
 
        /* Setup DMA if requested */
-       drv_data->tx_channel = -1;
-       drv_data->rx_channel = -1;
        if (platform_info->enable_dma) {
                status = pxa2xx_spi_dma_setup(drv_data);
                if (status) {
index 9f01e9c9aa753c913d791f9930c4d2649ed7ccdc..0a9b6390a817f60467b03f9e3fa589cc5bddf79f 100644 (file)
@@ -36,11 +36,6 @@ struct driver_data {
        /* PXA hookup */
        struct pxa2xx_spi_master *master_info;
 
-       /* PXA private DMA setup stuff */
-       int rx_channel;
-       int tx_channel;
-       u32 *null_dma_buf;
-
        /* SSP register addresses */
        void __iomem *ioaddr;
        u32 ssdr_physical;
index 68e7efeb9a27a6751d49ad3a6583b2fe5d97a811..79a8bc4f6cec9e32ec9c78627a2e68fc85ab5e12 100644 (file)
@@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, master);
 
        rs = spi_master_get_devdata(master);
-       memset(rs, 0, sizeof(struct rockchip_spi));
 
        /* Get basic io resource and map it */
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index f9189a0c8cec81f243c7e2ad4587356d13cf27a6..818843336932c9af8ea4a7bfe223888a179d31c6 100644 (file)
@@ -383,7 +383,8 @@ static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
        rspi_write8(rspi, data, reg);
 }
 
-static int qspi_set_send_trigger(struct rspi_data *rspi, unsigned int len)
+static unsigned int qspi_set_send_trigger(struct rspi_data *rspi,
+                                         unsigned int len)
 {
        unsigned int n;
 
@@ -724,25 +725,25 @@ static int rspi_rz_transfer_one(struct spi_master *master,
 static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx,
                                        u8 *rx, unsigned int len)
 {
-       int i, n, ret;
-       int error;
+       unsigned int i, n;
+       int ret;
 
        while (len > 0) {
                n = qspi_set_send_trigger(rspi, len);
                qspi_set_receive_trigger(rspi, len);
                if (n == QSPI_BUFFER_SIZE) {
-                       error = rspi_wait_for_tx_empty(rspi);
-                       if (error < 0) {
+                       ret = rspi_wait_for_tx_empty(rspi);
+                       if (ret < 0) {
                                dev_err(&rspi->master->dev, "transmit timeout\n");
-                               return error;
+                               return ret;
                        }
                        for (i = 0; i < n; i++)
                                rspi_write_data(rspi, *tx++);
 
-                       error = rspi_wait_for_rx_full(rspi);
-                       if (error < 0) {
+                       ret = rspi_wait_for_rx_full(rspi);
+                       if (ret < 0) {
                                dev_err(&rspi->master->dev, "receive timeout\n");
-                               return error;
+                               return ret;
                        }
                        for (i = 0; i < n; i++)
                                *rx++ = rspi_read_data(rspi);
index f747ca26998624752cf1fbb6f9c051c477c49198..f36bc320a80799067e6402feeb2ebb64c4f58169 100644 (file)
@@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        }
 
        hw = spi_master_get_devdata(master);
-       memset(hw, 0, sizeof(struct s3c24xx_spi));
 
        hw->master = master;
        hw->pdata = pdata = dev_get_platdata(&pdev->dev);
index 2a8c513c4d07808d7ceaa46827e57a2d6267f0e4..cd1cfac0447f98343917c31c83564ab1d6cf21b0 100644 (file)
@@ -1191,8 +1191,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n",
                                        sdd->port_id, master->num_chipselect);
-       dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tDMA=[Rx-%d, Tx-%d]\n",
-                                       mem_res,
+       dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\tDMA=[Rx-%d, Tx-%d]\n",
+                                       mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1,
                                        sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
        return 0;
index d3370a612d8432cf48b6f4d5d885e696833b4349..a7934ab00b96505f3753fa38266238f3abcc6f64 100644 (file)
@@ -48,8 +48,8 @@ struct sh_msiof_spi_priv {
        const struct sh_msiof_chipdata *chipdata;
        struct sh_msiof_spi_info *info;
        struct completion done;
-       int tx_fifo_size;
-       int rx_fifo_size;
+       unsigned int tx_fifo_size;
+       unsigned int rx_fifo_size;
        void *tx_dma_page;
        void *rx_dma_page;
        dma_addr_t tx_dma_addr;
@@ -95,8 +95,6 @@ struct sh_msiof_spi_priv {
 #define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */
 #define MDR2_GRPMASK1  0x00000001 /* Group Output Mask 1 (SH, A1) */
 
-#define MAX_WDLEN      256U
-
 /* TSCR and RSCR */
 #define SCR_BRPS_MASK      0x1f00 /* Prescaler Setting (1-32) */
 #define SCR_BRPS(i)    (((i) - 1) << 8)
@@ -850,7 +848,12 @@ static int sh_msiof_transfer_one(struct spi_master *master,
                 *  DMA supports 32-bit words only, hence pack 8-bit and 16-bit
                 *  words, with byte resp. word swapping.
                 */
-               unsigned int l = min(len, MAX_WDLEN * 4);
+               unsigned int l = 0;
+
+               if (tx_buf)
+                       l = min(len, p->tx_fifo_size * 4);
+               if (rx_buf)
+                       l = min(len, p->rx_fifo_size * 4);
 
                if (bits <= 8) {
                        if (l & 3)
@@ -963,7 +966,7 @@ static const struct sh_msiof_chipdata sh_data = {
 
 static const struct sh_msiof_chipdata r8a779x_data = {
        .tx_fifo_size = 64,
-       .rx_fifo_size = 256,
+       .rx_fifo_size = 64,
        .master_flags = SPI_MASTER_MUST_TX,
 };
 
@@ -1265,11 +1268,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
 
 static const struct platform_device_id spi_driver_ids[] = {
        { "spi_sh_msiof",       (kernel_ulong_t)&sh_data },
-       { "spi_r8a7790_msiof",  (kernel_ulong_t)&r8a779x_data },
-       { "spi_r8a7791_msiof",  (kernel_ulong_t)&r8a779x_data },
-       { "spi_r8a7792_msiof",  (kernel_ulong_t)&r8a779x_data },
-       { "spi_r8a7793_msiof",  (kernel_ulong_t)&r8a779x_data },
-       { "spi_r8a7794_msiof",  (kernel_ulong_t)&r8a779x_data },
        {},
 };
 MODULE_DEVICE_TABLE(platform, spi_driver_ids);
index 5c061687035886e5768bf6031616068906540b04..aa6d284131e0fd99fd19ef92dc0adff73ee18a02 100644 (file)
@@ -99,6 +99,8 @@ struct ti_qspi {
 #define QSPI_INVAL                     (4 << 16)
 #define QSPI_WC_CMD_INT_EN                     (1 << 14)
 #define QSPI_FLEN(n)                   ((n - 1) << 0)
+#define QSPI_WLEN_MAX_BITS             128
+#define QSPI_WLEN_MAX_BYTES            16
 
 /* STATUS REGISTER */
 #define BUSY                           0x01
@@ -217,14 +219,16 @@ static inline u32 qspi_is_busy(struct ti_qspi *qspi)
 
 static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
 {
-       int wlen, count;
+       int wlen, count, xfer_len;
        unsigned int cmd;
        const u8 *txbuf;
+       u32 data;
 
        txbuf = t->tx_buf;
        cmd = qspi->cmd | QSPI_WR_SNGL;
        count = t->len;
        wlen = t->bits_per_word >> 3;   /* in bytes */
+       xfer_len = wlen;
 
        while (count) {
                if (qspi_is_busy(qspi))
@@ -234,7 +238,29 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
                case 1:
                        dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %02x\n",
                                        cmd, qspi->dc, *txbuf);
-                       writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG);
+                       if (count >= QSPI_WLEN_MAX_BYTES) {
+                               u32 *txp = (u32 *)txbuf;
+
+                               data = cpu_to_be32(*txp++);
+                               writel(data, qspi->base +
+                                      QSPI_SPI_DATA_REG_3);
+                               data = cpu_to_be32(*txp++);
+                               writel(data, qspi->base +
+                                      QSPI_SPI_DATA_REG_2);
+                               data = cpu_to_be32(*txp++);
+                               writel(data, qspi->base +
+                                      QSPI_SPI_DATA_REG_1);
+                               data = cpu_to_be32(*txp++);
+                               writel(data, qspi->base +
+                                      QSPI_SPI_DATA_REG);
+                               xfer_len = QSPI_WLEN_MAX_BYTES;
+                               cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS);
+                       } else {
+                               writeb(*txbuf, qspi->base + QSPI_SPI_DATA_REG);
+                               cmd = qspi->cmd | QSPI_WR_SNGL;
+                               xfer_len = wlen;
+                               cmd |= QSPI_WLEN(wlen);
+                       }
                        break;
                case 2:
                        dev_dbg(qspi->dev, "tx cmd %08x dc %08x data %04x\n",
@@ -254,8 +280,8 @@ static int qspi_write_msg(struct ti_qspi *qspi, struct spi_transfer *t)
                        dev_err(qspi->dev, "write timed out\n");
                        return -ETIMEDOUT;
                }
-               txbuf += wlen;
-               count -= wlen;
+               txbuf += xfer_len;
+               count -= xfer_len;
        }
 
        return 0;
index bb478dccf1d82dd5d9fb1316bd04cf1755f08f0a..3c28e24b10f59604ae95e53cd2d5df495ce4ef5e 100644 (file)
@@ -237,11 +237,11 @@ static const struct i2c_device_id spi_xcomm_ids[] = {
        { "spi-xcomm" },
        { },
 };
+MODULE_DEVICE_TABLE(i2c, spi_xcomm_ids);
 
 static struct i2c_driver spi_xcomm_driver = {
        .driver = {
                .name   = "spi-xcomm",
-               .owner  = THIS_MODULE,
        },
        .id_table       = spi_xcomm_ids,
        .probe          = spi_xcomm_probe,
index 133f53a9c1d4eb9b5235b88de03dac9c5d2ea27e..a339c1e9997a93a431cf5ce9be5947b6333ac3e9 100644 (file)
@@ -249,19 +249,23 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
        xspi->tx_ptr = t->tx_buf;
        xspi->rx_ptr = t->rx_buf;
        remaining_words = t->len / xspi->bytes_per_word;
-       reinit_completion(&xspi->done);
 
        if (xspi->irq >= 0 &&  remaining_words > xspi->buffer_size) {
+               u32 isr;
                use_irq = true;
-               xspi->write_fn(XSPI_INTR_TX_EMPTY,
-                               xspi->regs + XIPIF_V123B_IISR_OFFSET);
-               /* Enable the global IPIF interrupt */
-               xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
-                               xspi->regs + XIPIF_V123B_DGIER_OFFSET);
                /* Inhibit irq to avoid spurious irqs on tx_empty*/
                cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
                xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
                               xspi->regs + XSPI_CR_OFFSET);
+               /* ACK old irqs (if any) */
+               isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+               if (isr)
+                       xspi->write_fn(isr,
+                                      xspi->regs + XIPIF_V123B_IISR_OFFSET);
+               /* Enable the global IPIF interrupt */
+               xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+                               xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+               reinit_completion(&xspi->done);
        }
 
        while (remaining_words) {
@@ -302,8 +306,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
                remaining_words -= n_words;
        }
 
-       if (use_irq)
+       if (use_irq) {
                xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+               xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+       }
 
        return t->len;
 }
diff --git a/drivers/spi/spi-xlp.c b/drivers/spi/spi-xlp.c
new file mode 100644 (file)
index 0000000..8f04fec
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2003-2015 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 (GPL v2)
+ * 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.
+ */
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+
+/* SPI Configuration Register */
+#define XLP_SPI_CONFIG                 0x00
+#define XLP_SPI_CPHA                   BIT(0)
+#define XLP_SPI_CPOL                   BIT(1)
+#define XLP_SPI_CS_POL                 BIT(2)
+#define XLP_SPI_TXMISO_EN              BIT(3)
+#define XLP_SPI_TXMOSI_EN              BIT(4)
+#define XLP_SPI_RXMISO_EN              BIT(5)
+#define XLP_SPI_CS_LSBFE               BIT(10)
+#define XLP_SPI_RXCAP_EN               BIT(11)
+
+/* SPI Frequency Divider Register */
+#define XLP_SPI_FDIV                   0x04
+
+/* SPI Command Register */
+#define XLP_SPI_CMD                    0x08
+#define XLP_SPI_CMD_IDLE_MASK          0x0
+#define XLP_SPI_CMD_TX_MASK            0x1
+#define XLP_SPI_CMD_RX_MASK            0x2
+#define XLP_SPI_CMD_TXRX_MASK          0x3
+#define XLP_SPI_CMD_CONT               BIT(4)
+#define XLP_SPI_XFR_BITCNT_SHIFT       16
+
+/* SPI Status Register */
+#define XLP_SPI_STATUS                 0x0c
+#define XLP_SPI_XFR_PENDING            BIT(0)
+#define XLP_SPI_XFR_DONE               BIT(1)
+#define XLP_SPI_TX_INT                 BIT(2)
+#define XLP_SPI_RX_INT                 BIT(3)
+#define XLP_SPI_TX_UF                  BIT(4)
+#define XLP_SPI_RX_OF                  BIT(5)
+#define XLP_SPI_STAT_MASK              0x3f
+
+/* SPI Interrupt Enable Register */
+#define XLP_SPI_INTR_EN                        0x10
+#define XLP_SPI_INTR_DONE              BIT(0)
+#define XLP_SPI_INTR_TXTH              BIT(1)
+#define XLP_SPI_INTR_RXTH              BIT(2)
+#define XLP_SPI_INTR_TXUF              BIT(3)
+#define XLP_SPI_INTR_RXOF              BIT(4)
+
+/* SPI FIFO Threshold Register */
+#define XLP_SPI_FIFO_THRESH            0x14
+
+/* SPI FIFO Word Count Register */
+#define XLP_SPI_FIFO_WCNT              0x18
+#define XLP_SPI_RXFIFO_WCNT_MASK       0xf
+#define XLP_SPI_TXFIFO_WCNT_MASK       0xf0
+#define XLP_SPI_TXFIFO_WCNT_SHIFT      4
+
+/* SPI Transmit Data FIFO Register */
+#define XLP_SPI_TXDATA_FIFO            0x1c
+
+/* SPI Receive Data FIFO Register */
+#define XLP_SPI_RXDATA_FIFO            0x20
+
+/* SPI System Control Register */
+#define XLP_SPI_SYSCTRL                        0x100
+#define XLP_SPI_SYS_RESET              BIT(0)
+#define XLP_SPI_SYS_CLKDIS             BIT(1)
+#define XLP_SPI_SYS_PMEN               BIT(8)
+
+#define SPI_CS_OFFSET                  0x40
+#define XLP_SPI_TXRXTH                 0x80
+#define XLP_SPI_FIFO_SIZE              8
+#define XLP_SPI_MAX_CS                 4
+#define XLP_SPI_DEFAULT_FREQ           133333333
+#define XLP_SPI_FDIV_MIN               4
+#define XLP_SPI_FDIV_MAX               65535
+/*
+ * SPI can transfer only 28 bytes properly at a time. So split the
+ * transfer into 28 bytes size.
+ */
+#define XLP_SPI_XFER_SIZE              28
+
+struct xlp_spi_priv {
+       struct device           dev;            /* device structure */
+       void __iomem            *base;          /* spi registers base address */
+       const u8                *tx_buf;        /* tx data buffer */
+       u8                      *rx_buf;        /* rx data buffer */
+       int                     tx_len;         /* tx xfer length */
+       int                     rx_len;         /* rx xfer length */
+       int                     txerrors;       /* TXFIFO underflow count */
+       int                     rxerrors;       /* RXFIFO overflow count */
+       int                     cs;             /* slave device chip select */
+       u32                     spi_clk;        /* spi clock frequency */
+       bool                    cmd_cont;       /* cs active */
+       struct completion       done;           /* completion notification */
+};
+
+static inline u32 xlp_spi_reg_read(struct xlp_spi_priv *priv,
+                               int cs, int regoff)
+{
+       return readl(priv->base + regoff + cs * SPI_CS_OFFSET);
+}
+
+static inline void xlp_spi_reg_write(struct xlp_spi_priv *priv, int cs,
+                               int regoff, u32 val)
+{
+       writel(val, priv->base + regoff + cs * SPI_CS_OFFSET);
+}
+
+static inline void xlp_spi_sysctl_write(struct xlp_spi_priv *priv,
+                               int regoff, u32 val)
+{
+       writel(val, priv->base + regoff);
+}
+
+/*
+ * Setup global SPI_SYSCTRL register for all SPI channels.
+ */
+static void xlp_spi_sysctl_setup(struct xlp_spi_priv *xspi)
+{
+       int cs;
+
+       for (cs = 0; cs < XLP_SPI_MAX_CS; cs++)
+               xlp_spi_sysctl_write(xspi, XLP_SPI_SYSCTRL,
+                               XLP_SPI_SYS_RESET << cs);
+       xlp_spi_sysctl_write(xspi, XLP_SPI_SYSCTRL, XLP_SPI_SYS_PMEN);
+}
+
+static int xlp_spi_setup(struct spi_device *spi)
+{
+       struct xlp_spi_priv *xspi;
+       u32 fdiv, cfg;
+       int cs;
+
+       xspi = spi_master_get_devdata(spi->master);
+       cs = spi->chip_select;
+       /*
+        * The value of fdiv must be between 4 and 65535.
+        */
+       fdiv = DIV_ROUND_UP(xspi->spi_clk, spi->max_speed_hz);
+       if (fdiv > XLP_SPI_FDIV_MAX)
+               fdiv = XLP_SPI_FDIV_MAX;
+       else if (fdiv < XLP_SPI_FDIV_MIN)
+               fdiv = XLP_SPI_FDIV_MIN;
+
+       xlp_spi_reg_write(xspi, cs, XLP_SPI_FDIV, fdiv);
+       xlp_spi_reg_write(xspi, cs, XLP_SPI_FIFO_THRESH, XLP_SPI_TXRXTH);
+       cfg = xlp_spi_reg_read(xspi, cs, XLP_SPI_CONFIG);
+       if (spi->mode & SPI_CPHA)
+               cfg |= XLP_SPI_CPHA;
+       else
+               cfg &= ~XLP_SPI_CPHA;
+       if (spi->mode & SPI_CPOL)
+               cfg |= XLP_SPI_CPOL;
+       else
+               cfg &= ~XLP_SPI_CPOL;
+       if (!(spi->mode & SPI_CS_HIGH))
+               cfg |= XLP_SPI_CS_POL;
+       else
+               cfg &= ~XLP_SPI_CS_POL;
+       if (spi->mode & SPI_LSB_FIRST)
+               cfg |= XLP_SPI_CS_LSBFE;
+       else
+               cfg &= ~XLP_SPI_CS_LSBFE;
+
+       cfg |= XLP_SPI_TXMOSI_EN | XLP_SPI_RXMISO_EN;
+       if (fdiv == 4)
+               cfg |= XLP_SPI_RXCAP_EN;
+       xlp_spi_reg_write(xspi, cs, XLP_SPI_CONFIG, cfg);
+
+       return 0;
+}
+
+static void xlp_spi_read_rxfifo(struct xlp_spi_priv *xspi)
+{
+       u32 rx_data, rxfifo_cnt;
+       int i, j, nbytes;
+
+       rxfifo_cnt = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_FIFO_WCNT);
+       rxfifo_cnt &= XLP_SPI_RXFIFO_WCNT_MASK;
+       while (rxfifo_cnt) {
+               rx_data = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_RXDATA_FIFO);
+               j = 0;
+               nbytes = min(xspi->rx_len, 4);
+               for (i = nbytes - 1; i >= 0; i--, j++)
+                       xspi->rx_buf[i] = (rx_data >> (j * 8)) & 0xff;
+
+               xspi->rx_len -= nbytes;
+               xspi->rx_buf += nbytes;
+               rxfifo_cnt--;
+       }
+}
+
+static void xlp_spi_fill_txfifo(struct xlp_spi_priv *xspi)
+{
+       u32 tx_data, txfifo_cnt;
+       int i, j, nbytes;
+
+       txfifo_cnt = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_FIFO_WCNT);
+       txfifo_cnt &= XLP_SPI_TXFIFO_WCNT_MASK;
+       txfifo_cnt >>= XLP_SPI_TXFIFO_WCNT_SHIFT;
+       while (xspi->tx_len && (txfifo_cnt < XLP_SPI_FIFO_SIZE)) {
+               j = 0;
+               tx_data = 0;
+               nbytes = min(xspi->tx_len, 4);
+               for (i = nbytes - 1; i >= 0; i--, j++)
+                       tx_data |= xspi->tx_buf[i] << (j * 8);
+
+               xlp_spi_reg_write(xspi, xspi->cs, XLP_SPI_TXDATA_FIFO, tx_data);
+               xspi->tx_len -= nbytes;
+               xspi->tx_buf += nbytes;
+               txfifo_cnt++;
+       }
+}
+
+static irqreturn_t xlp_spi_interrupt(int irq, void *dev_id)
+{
+       struct xlp_spi_priv *xspi = dev_id;
+       u32 stat;
+
+       stat = xlp_spi_reg_read(xspi, xspi->cs, XLP_SPI_STATUS) &
+               XLP_SPI_STAT_MASK;
+       if (!stat)
+               return IRQ_NONE;
+
+       if (stat & XLP_SPI_TX_INT) {
+               if (xspi->tx_len)
+                       xlp_spi_fill_txfifo(xspi);
+               if (stat & XLP_SPI_TX_UF)
+                       xspi->txerrors++;
+       }
+
+       if (stat & XLP_SPI_RX_INT) {
+               if (xspi->rx_len)
+                       xlp_spi_read_rxfifo(xspi);
+               if (stat & XLP_SPI_RX_OF)
+                       xspi->rxerrors++;
+       }
+
+       /* write status back to clear interrupts */
+       xlp_spi_reg_write(xspi, xspi->cs, XLP_SPI_STATUS, stat);
+       if (stat & XLP_SPI_XFR_DONE)
+               complete(&xspi->done);
+
+       return IRQ_HANDLED;
+}
+
+static void xlp_spi_send_cmd(struct xlp_spi_priv *xspi, int xfer_len,
+                       int cmd_cont)
+{
+       u32 cmd = 0;
+
+       if (xspi->tx_buf)
+               cmd |= XLP_SPI_CMD_TX_MASK;
+       if (xspi->rx_buf)
+               cmd |= XLP_SPI_CMD_RX_MASK;
+       if (cmd_cont)
+               cmd |= XLP_SPI_CMD_CONT;
+       cmd |= ((xfer_len * 8 - 1) << XLP_SPI_XFR_BITCNT_SHIFT);
+       xlp_spi_reg_write(xspi, xspi->cs, XLP_SPI_CMD, cmd);
+}
+
+static int xlp_spi_xfer_block(struct  xlp_spi_priv *xs,
+               const unsigned char *tx_buf,
+               unsigned char *rx_buf, int xfer_len, int cmd_cont)
+{
+       int timeout;
+       u32 intr_mask = 0;
+
+       xs->tx_buf = tx_buf;
+       xs->rx_buf = rx_buf;
+       xs->tx_len = (xs->tx_buf == NULL) ? 0 : xfer_len;
+       xs->rx_len = (xs->rx_buf == NULL) ? 0 : xfer_len;
+       xs->txerrors = xs->rxerrors = 0;
+
+       /* fill TXDATA_FIFO, then send the CMD */
+       if (xs->tx_len)
+               xlp_spi_fill_txfifo(xs);
+
+       xlp_spi_send_cmd(xs, xfer_len, cmd_cont);
+
+       /*
+        * We are getting some spurious tx interrupts, so avoid enabling
+        * tx interrupts when only rx is in process.
+        * Enable all the interrupts in tx case.
+        */
+       if (xs->tx_len)
+               intr_mask |= XLP_SPI_INTR_TXTH | XLP_SPI_INTR_TXUF |
+                               XLP_SPI_INTR_RXTH | XLP_SPI_INTR_RXOF;
+       else
+               intr_mask |= XLP_SPI_INTR_RXTH | XLP_SPI_INTR_RXOF;
+
+       intr_mask |= XLP_SPI_INTR_DONE;
+       xlp_spi_reg_write(xs, xs->cs, XLP_SPI_INTR_EN, intr_mask);
+
+       timeout = wait_for_completion_timeout(&xs->done,
+                               msecs_to_jiffies(1000));
+       /* Disable interrupts */
+       xlp_spi_reg_write(xs, xs->cs, XLP_SPI_INTR_EN, 0x0);
+       if (!timeout) {
+               dev_err(&xs->dev, "xfer timedout!\n");
+               goto out;
+       }
+       if (xs->txerrors || xs->rxerrors)
+               dev_err(&xs->dev, "Over/Underflow rx %d tx %d xfer %d!\n",
+                               xs->rxerrors, xs->txerrors, xfer_len);
+
+       return xfer_len;
+out:
+       return -ETIMEDOUT;
+}
+
+static int xlp_spi_txrx_bufs(struct xlp_spi_priv *xs, struct spi_transfer *t)
+{
+       int bytesleft, sz;
+       unsigned char *rx_buf;
+       const unsigned char *tx_buf;
+
+       tx_buf = t->tx_buf;
+       rx_buf = t->rx_buf;
+       bytesleft = t->len;
+       while (bytesleft) {
+               if (bytesleft > XLP_SPI_XFER_SIZE)
+                       sz = xlp_spi_xfer_block(xs, tx_buf, rx_buf,
+                                       XLP_SPI_XFER_SIZE, 1);
+               else
+                       sz = xlp_spi_xfer_block(xs, tx_buf, rx_buf,
+                                       bytesleft, xs->cmd_cont);
+               if (sz < 0)
+                       return sz;
+               bytesleft -= sz;
+               if (tx_buf)
+                       tx_buf += sz;
+               if (rx_buf)
+                       rx_buf += sz;
+       }
+       return bytesleft;
+}
+
+static int xlp_spi_transfer_one(struct spi_master *master,
+                                       struct spi_device *spi,
+                                       struct spi_transfer *t)
+{
+       struct xlp_spi_priv *xspi = spi_master_get_devdata(master);
+       int ret = 0;
+
+       xspi->cs = spi->chip_select;
+       xspi->dev = spi->dev;
+
+       if (spi_transfer_is_last(master, t))
+               xspi->cmd_cont = 0;
+       else
+               xspi->cmd_cont = 1;
+
+       if (xlp_spi_txrx_bufs(xspi, t))
+               ret = -EIO;
+
+       spi_finalize_current_transfer(master);
+       return ret;
+}
+
+static int xlp_spi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct xlp_spi_priv *xspi;
+       struct resource *res;
+       struct clk *clk;
+       int irq, err;
+
+       xspi = devm_kzalloc(&pdev->dev, sizeof(*xspi), GFP_KERNEL);
+       if (!xspi)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       xspi->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(xspi->base))
+               return PTR_ERR(xspi->base);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no IRQ resource found\n");
+               return -EINVAL;
+       }
+       err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0,
+                       pdev->name, xspi);
+       if (err) {
+               dev_err(&pdev->dev, "unable to request irq %d\n", irq);
+               return err;
+       }
+
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk)) {
+               dev_err(&pdev->dev, "could not get spi clock\n");
+               return -ENODEV;
+       }
+       xspi->spi_clk = clk_get_rate(clk);
+
+       master = spi_alloc_master(&pdev->dev, 0);
+       if (!master) {
+               dev_err(&pdev->dev, "could not alloc master\n");
+               return -ENOMEM;
+       }
+
+       master->bus_num = 0;
+       master->num_chipselect = XLP_SPI_MAX_CS;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->setup = xlp_spi_setup;
+       master->transfer_one = xlp_spi_transfer_one;
+       master->dev.of_node = pdev->dev.of_node;
+
+       init_completion(&xspi->done);
+       spi_master_set_devdata(master, xspi);
+       xlp_spi_sysctl_setup(xspi);
+
+       /* register spi controller */
+       err = devm_spi_register_master(&pdev->dev, master);
+       if (err) {
+               dev_err(&pdev->dev, "spi register master failed!\n");
+               spi_master_put(master);
+               return err;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id xlp_spi_dt_id[] = {
+       { .compatible = "netlogic,xlp832-spi" },
+       { },
+};
+
+static struct platform_driver xlp_spi_driver = {
+       .probe  = xlp_spi_probe,
+       .driver = {
+               .name   = "xlp-spi",
+               .of_match_table = xlp_spi_dt_id,
+       },
+};
+module_platform_driver(xlp_spi_driver);
+
+MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>");
+MODULE_DESCRIPTION("Netlogic XLP SPI controller driver");
+MODULE_LICENSE("GPL v2");
index cf8b91b23a763d60f8253e3ef1e8ccd420e52a0c..3abb3903f2ad454ef964299204bd3c2454890062 100644 (file)
@@ -67,11 +67,141 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf)
 }
 static DEVICE_ATTR_RO(modalias);
 
+#define SPI_STATISTICS_ATTRS(field, file)                              \
+static ssize_t spi_master_##field##_show(struct device *dev,           \
+                                        struct device_attribute *attr, \
+                                        char *buf)                     \
+{                                                                      \
+       struct spi_master *master = container_of(dev,                   \
+                                                struct spi_master, dev); \
+       return spi_statistics_##field##_show(&master->statistics, buf); \
+}                                                                      \
+static struct device_attribute dev_attr_spi_master_##field = {         \
+       .attr = { .name = file, .mode = S_IRUGO },                      \
+       .show = spi_master_##field##_show,                              \
+};                                                                     \
+static ssize_t spi_device_##field##_show(struct device *dev,           \
+                                        struct device_attribute *attr, \
+                                       char *buf)                      \
+{                                                                      \
+       struct spi_device *spi = container_of(dev,                      \
+                                             struct spi_device, dev);  \
+       return spi_statistics_##field##_show(&spi->statistics, buf);    \
+}                                                                      \
+static struct device_attribute dev_attr_spi_device_##field = {         \
+       .attr = { .name = file, .mode = S_IRUGO },                      \
+       .show = spi_device_##field##_show,                              \
+}
+
+#define SPI_STATISTICS_SHOW_NAME(name, file, field, format_string)     \
+static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \
+                                           char *buf)                  \
+{                                                                      \
+       unsigned long flags;                                            \
+       ssize_t len;                                                    \
+       spin_lock_irqsave(&stat->lock, flags);                          \
+       len = sprintf(buf, format_string, stat->field);                 \
+       spin_unlock_irqrestore(&stat->lock, flags);                     \
+       return len;                                                     \
+}                                                                      \
+SPI_STATISTICS_ATTRS(name, file)
+
+#define SPI_STATISTICS_SHOW(field, format_string)                      \
+       SPI_STATISTICS_SHOW_NAME(field, __stringify(field),             \
+                                field, format_string)
+
+SPI_STATISTICS_SHOW(messages, "%lu");
+SPI_STATISTICS_SHOW(transfers, "%lu");
+SPI_STATISTICS_SHOW(errors, "%lu");
+SPI_STATISTICS_SHOW(timedout, "%lu");
+
+SPI_STATISTICS_SHOW(spi_sync, "%lu");
+SPI_STATISTICS_SHOW(spi_sync_immediate, "%lu");
+SPI_STATISTICS_SHOW(spi_async, "%lu");
+
+SPI_STATISTICS_SHOW(bytes, "%llu");
+SPI_STATISTICS_SHOW(bytes_rx, "%llu");
+SPI_STATISTICS_SHOW(bytes_tx, "%llu");
+
 static struct attribute *spi_dev_attrs[] = {
        &dev_attr_modalias.attr,
        NULL,
 };
-ATTRIBUTE_GROUPS(spi_dev);
+
+static const struct attribute_group spi_dev_group = {
+       .attrs  = spi_dev_attrs,
+};
+
+static struct attribute *spi_device_statistics_attrs[] = {
+       &dev_attr_spi_device_messages.attr,
+       &dev_attr_spi_device_transfers.attr,
+       &dev_attr_spi_device_errors.attr,
+       &dev_attr_spi_device_timedout.attr,
+       &dev_attr_spi_device_spi_sync.attr,
+       &dev_attr_spi_device_spi_sync_immediate.attr,
+       &dev_attr_spi_device_spi_async.attr,
+       &dev_attr_spi_device_bytes.attr,
+       &dev_attr_spi_device_bytes_rx.attr,
+       &dev_attr_spi_device_bytes_tx.attr,
+       NULL,
+};
+
+static const struct attribute_group spi_device_statistics_group = {
+       .name  = "statistics",
+       .attrs  = spi_device_statistics_attrs,
+};
+
+static const struct attribute_group *spi_dev_groups[] = {
+       &spi_dev_group,
+       &spi_device_statistics_group,
+       NULL,
+};
+
+static struct attribute *spi_master_statistics_attrs[] = {
+       &dev_attr_spi_master_messages.attr,
+       &dev_attr_spi_master_transfers.attr,
+       &dev_attr_spi_master_errors.attr,
+       &dev_attr_spi_master_timedout.attr,
+       &dev_attr_spi_master_spi_sync.attr,
+       &dev_attr_spi_master_spi_sync_immediate.attr,
+       &dev_attr_spi_master_spi_async.attr,
+       &dev_attr_spi_master_bytes.attr,
+       &dev_attr_spi_master_bytes_rx.attr,
+       &dev_attr_spi_master_bytes_tx.attr,
+       NULL,
+};
+
+static const struct attribute_group spi_master_statistics_group = {
+       .name  = "statistics",
+       .attrs  = spi_master_statistics_attrs,
+};
+
+static const struct attribute_group *spi_master_groups[] = {
+       &spi_master_statistics_group,
+       NULL,
+};
+
+void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
+                                      struct spi_transfer *xfer,
+                                      struct spi_master *master)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&stats->lock, flags);
+
+       stats->transfers++;
+
+       stats->bytes += xfer->len;
+       if ((xfer->tx_buf) &&
+           (xfer->tx_buf != master->dummy_tx))
+               stats->bytes_tx += xfer->len;
+       if ((xfer->rx_buf) &&
+           (xfer->rx_buf != master->dummy_rx))
+               stats->bytes_rx += xfer->len;
+
+       spin_unlock_irqrestore(&stats->lock, flags);
+}
+EXPORT_SYMBOL_GPL(spi_statistics_add_transfer_stats);
 
 /* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
  * and the sysfs version makes coldplug work too.
@@ -249,6 +379,9 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
        spi->dev.bus = &spi_bus_type;
        spi->dev.release = spidev_release;
        spi->cs_gpio = -ENOENT;
+
+       spin_lock_init(&spi->statistics.lock);
+
        device_initialize(&spi->dev);
        return spi;
 }
@@ -476,21 +609,30 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                       enum dma_data_direction dir)
 {
        const bool vmalloced_buf = is_vmalloc_addr(buf);
-       const int desc_len = vmalloced_buf ? PAGE_SIZE : master->max_dma_len;
-       const int sgs = DIV_ROUND_UP(len, desc_len);
+       int desc_len;
+       int sgs;
        struct page *vm_page;
        void *sg_buf;
        size_t min;
        int i, ret;
 
+       if (vmalloced_buf) {
+               desc_len = PAGE_SIZE;
+               sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
+       } else {
+               desc_len = master->max_dma_len;
+               sgs = DIV_ROUND_UP(len, desc_len);
+       }
+
        ret = sg_alloc_table(sgt, sgs, GFP_KERNEL);
        if (ret != 0)
                return ret;
 
        for (i = 0; i < sgs; i++) {
-               min = min_t(size_t, len, desc_len);
 
                if (vmalloced_buf) {
+                       min = min_t(size_t,
+                                   len, desc_len - offset_in_page(buf));
                        vm_page = vmalloc_to_page(buf);
                        if (!vm_page) {
                                sg_free_table(sgt);
@@ -499,6 +641,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                        sg_set_page(&sgt->sgl[i], vm_page,
                                    min, offset_in_page(buf));
                } else {
+                       min = min_t(size_t, len, desc_len);
                        sg_buf = buf;
                        sg_set_buf(&sgt->sgl[i], sg_buf, min);
                }
@@ -539,8 +682,15 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
        if (!master->can_dma)
                return 0;
 
-       tx_dev = master->dma_tx->device->dev;
-       rx_dev = master->dma_rx->device->dev;
+       if (master->dma_tx)
+               tx_dev = master->dma_tx->device->dev;
+       else
+               tx_dev = &master->dev;
+
+       if (master->dma_rx)
+               rx_dev = master->dma_rx->device->dev;
+       else
+               rx_dev = &master->dev;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                if (!master->can_dma(master, msg->spi, xfer))
@@ -579,8 +729,15 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
        if (!master->cur_msg_mapped || !master->can_dma)
                return 0;
 
-       tx_dev = master->dma_tx->device->dev;
-       rx_dev = master->dma_rx->device->dev;
+       if (master->dma_tx)
+               tx_dev = master->dma_tx->device->dev;
+       else
+               tx_dev = &master->dev;
+
+       if (master->dma_rx)
+               rx_dev = master->dma_rx->device->dev;
+       else
+               rx_dev = &master->dev;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                if (!master->can_dma(master, msg->spi, xfer))
@@ -689,17 +846,29 @@ static int spi_transfer_one_message(struct spi_master *master,
        bool keep_cs = false;
        int ret = 0;
        unsigned long ms = 1;
+       struct spi_statistics *statm = &master->statistics;
+       struct spi_statistics *stats = &msg->spi->statistics;
 
        spi_set_cs(msg->spi, true);
 
+       SPI_STATISTICS_INCREMENT_FIELD(statm, messages);
+       SPI_STATISTICS_INCREMENT_FIELD(stats, messages);
+
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                trace_spi_transfer_start(msg, xfer);
 
+               spi_statistics_add_transfer_stats(statm, xfer, master);
+               spi_statistics_add_transfer_stats(stats, xfer, master);
+
                if (xfer->tx_buf || xfer->rx_buf) {
                        reinit_completion(&master->xfer_completion);
 
                        ret = master->transfer_one(master, msg->spi, xfer);
                        if (ret < 0) {
+                               SPI_STATISTICS_INCREMENT_FIELD(statm,
+                                                              errors);
+                               SPI_STATISTICS_INCREMENT_FIELD(stats,
+                                                              errors);
                                dev_err(&msg->spi->dev,
                                        "SPI transfer failed: %d\n", ret);
                                goto out;
@@ -715,6 +884,10 @@ static int spi_transfer_one_message(struct spi_master *master,
                        }
 
                        if (ms == 0) {
+                               SPI_STATISTICS_INCREMENT_FIELD(statm,
+                                                              timedout);
+                               SPI_STATISTICS_INCREMENT_FIELD(stats,
+                                                              timedout);
                                dev_err(&msg->spi->dev,
                                        "SPI transfer timed out\n");
                                msg->status = -ETIMEDOUT;
@@ -1416,10 +1589,10 @@ static struct class spi_master_class = {
        .name           = "spi_master",
        .owner          = THIS_MODULE,
        .dev_release    = spi_master_release,
+       .dev_groups     = spi_master_groups,
 };
 
 
-
 /**
  * spi_alloc_master - allocate SPI master controller
  * @dev: the controller, possibly using the platform_bus
@@ -1585,6 +1758,8 @@ int spi_register_master(struct spi_master *master)
                        goto done;
                }
        }
+       /* add statistics */
+       spin_lock_init(&master->statistics.lock);
 
        mutex_lock(&board_lock);
        list_add_tail(&master->list, &spi_master_list);
@@ -1740,6 +1915,20 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
  * other core methods are currently defined as inline functions.
  */
 
+static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_word)
+{
+       if (master->bits_per_word_mask) {
+               /* Only 32 bits fit in the mask */
+               if (bits_per_word > 32)
+                       return -EINVAL;
+               if (!(master->bits_per_word_mask &
+                               SPI_BPW_MASK(bits_per_word)))
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * spi_setup - setup SPI mode and clock rate
  * @spi: the device whose settings are being modified
@@ -1798,6 +1987,9 @@ int spi_setup(struct spi_device *spi)
        if (!spi->bits_per_word)
                spi->bits_per_word = 8;
 
+       if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word))
+               return -EINVAL;
+
        if (!spi->max_speed_hz)
                spi->max_speed_hz = spi->master->max_speed_hz;
 
@@ -1860,19 +2052,15 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 
                if (!xfer->speed_hz)
                        xfer->speed_hz = spi->max_speed_hz;
+               if (!xfer->speed_hz)
+                       xfer->speed_hz = master->max_speed_hz;
 
                if (master->max_speed_hz &&
                    xfer->speed_hz > master->max_speed_hz)
                        xfer->speed_hz = master->max_speed_hz;
 
-               if (master->bits_per_word_mask) {
-                       /* Only 32 bits fit in the mask */
-                       if (xfer->bits_per_word > 32)
-                               return -EINVAL;
-                       if (!(master->bits_per_word_mask &
-                                       BIT(xfer->bits_per_word - 1)))
-                               return -EINVAL;
-               }
+               if (__spi_validate_bits_per_word(master, xfer->bits_per_word))
+                       return -EINVAL;
 
                /*
                 * SPI transfer length should be multiple of SPI word size
@@ -1939,6 +2127,9 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
 
        message->spi = spi;
 
+       SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_async);
+       SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_async);
+
        trace_spi_message_submit(message);
 
        return master->transfer(spi, message);
@@ -2075,6 +2266,9 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
        message->context = &done;
        message->spi = spi;
 
+       SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_sync);
+       SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync);
+
        if (!bus_locked)
                mutex_lock(&master->bus_lock_mutex);
 
@@ -2102,8 +2296,13 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
                /* Push out the messages in the calling context if we
                 * can.
                 */
-               if (master->transfer == spi_queued_transfer)
+               if (master->transfer == spi_queued_transfer) {
+                       SPI_STATISTICS_INCREMENT_FIELD(&master->statistics,
+                                                      spi_sync_immediate);
+                       SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
+                                                      spi_sync_immediate);
                        __spi_pump_messages(master, false);
+               }
 
                wait_for_completion(&done);
                status = message->status;
index c7de64171c452325ab43884b501977a33f724b93..fba92a5265310c78acd9fb7e9c621f6d88942d24 100644 (file)
@@ -602,11 +602,11 @@ static int spidev_open(struct inode *inode, struct file *filp)
        if (!spidev->tx_buffer) {
                spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);
                if (!spidev->tx_buffer) {
-                               dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
-                               status = -ENOMEM;
+                       dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
+                       status = -ENOMEM;
                        goto err_find_dev;
-                       }
                }
+       }
 
        if (!spidev->rx_buffer) {
                spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);
@@ -709,7 +709,7 @@ static int spidev_probe(struct spi_device *spi)
 
        /*
         * spidev should never be referenced in DT without a specific
-        * compatbile string, it is a Linux implementation thing
+        * compatible string, it is a Linux implementation thing
         * rather than a description of the hardware.
         */
        if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) {
index 982580af1d16bb8384d7f0f8a344bd04f81ce372..0d3b70b3bda8e40ee57ddefd6d752668036a674d 100644 (file)
@@ -12,7 +12,7 @@ if SPMI
 
 config SPMI_MSM_PMIC_ARB
        tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
-       depends on IRQ_DOMAIN
+       select IRQ_DOMAIN
        depends on ARCH_QCOM || COMPILE_TEST
        depends on HAS_IOMEM
        default ARCH_QCOM
index d7119db49cfe561b5cd534ccf5c0c1bf45ac0ce0..a4d8c043a7106907259c3deb78c36fbb9b631b47 100644 (file)
@@ -575,6 +575,22 @@ static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
        return 0;
 }
 
+static int qpnpint_get_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which,
+                                    bool *state)
+{
+       u8 irq = d->hwirq >> 8;
+       u8 status = 0;
+
+       if (which != IRQCHIP_STATE_LINE_LEVEL)
+               return -EINVAL;
+
+       qpnpint_spmi_read(d, QPNPINT_REG_RT_STS, &status, 1);
+       *state = !!(status & BIT(irq));
+
+       return 0;
+}
+
 static struct irq_chip pmic_arb_irqchip = {
        .name           = "pmic_arb",
        .irq_enable     = qpnpint_irq_enable,
@@ -582,6 +598,7 @@ static struct irq_chip pmic_arb_irqchip = {
        .irq_mask       = qpnpint_irq_mask,
        .irq_unmask     = qpnpint_irq_unmask,
        .irq_set_type   = qpnpint_irq_set_type,
+       .irq_get_irqchip_state  = qpnpint_get_irqchip_state,
        .flags          = IRQCHIP_MASK_ON_SUSPEND
                        | IRQCHIP_SKIP_SET_WAKE,
 };
index 94938436aef9c7313403882141a8fc1858413190..11467e17bdd8fcf464140ab8706f1bb3ed7095b2 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/pm_runtime.h>
 
 #include <dt-bindings/spmi/spmi.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/spmi.h>
 
 static DEFINE_IDA(ctrl_ida);
 
@@ -96,28 +98,42 @@ EXPORT_SYMBOL_GPL(spmi_device_remove);
 static inline int
 spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
 {
+       int ret;
+
        if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type)
                return -EINVAL;
 
-       return ctrl->cmd(ctrl, opcode, sid);
+       ret = ctrl->cmd(ctrl, opcode, sid);
+       trace_spmi_cmd(opcode, sid, ret);
+       return ret;
 }
 
 static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode,
                                u8 sid, u16 addr, u8 *buf, size_t len)
 {
+       int ret;
+
        if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type)
                return -EINVAL;
 
-       return ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
+       trace_spmi_read_begin(opcode, sid, addr);
+       ret = ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
+       trace_spmi_read_end(opcode, sid, addr, ret, len, buf);
+       return ret;
 }
 
 static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode,
                                 u8 sid, u16 addr, const u8 *buf, size_t len)
 {
+       int ret;
+
        if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type)
                return -EINVAL;
 
-       return ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
+       trace_spmi_write_begin(opcode, sid, addr, len, buf);
+       ret = ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
+       trace_spmi_write_end(opcode, sid, addr, ret);
+       return ret;
 }
 
 /**
index 7f6cae5beb90fc30388be0281a5c5b9f9023bad4..e29293c0c71e315e9bee9610dad6ee440960087f 100644 (file)
@@ -56,8 +56,6 @@ source "drivers/staging/vt6656/Kconfig"
 
 source "drivers/staging/iio/Kconfig"
 
-source "drivers/staging/sm7xxfb/Kconfig"
-
 source "drivers/staging/sm750fb/Kconfig"
 
 source "drivers/staging/xgifb/Kconfig"
@@ -78,8 +76,6 @@ source "drivers/staging/android/Kconfig"
 
 source "drivers/staging/board/Kconfig"
 
-source "drivers/staging/ozwpan/Kconfig"
-
 source "drivers/staging/gdm72xx/Kconfig"
 
 source "drivers/staging/gdm724x/Kconfig"
@@ -112,4 +108,6 @@ source "drivers/staging/fsl-mc/Kconfig"
 
 source "drivers/staging/wilc1000/Kconfig"
 
+source "drivers/staging/most/Kconfig"
+
 endif # STAGING
index 347f6477aa3eb4a11429c977f73596e520fb403c..50824dde2c09af863f2921ecd2512d7361d9ef48 100644 (file)
@@ -22,7 +22,6 @@ obj-$(CONFIG_VT6655)          += vt6655/
 obj-$(CONFIG_VT6656)           += vt6656/
 obj-$(CONFIG_VME_BUS)          += vme/
 obj-$(CONFIG_IIO)              += iio/
-obj-$(CONFIG_FB_SM7XX)         += sm7xxfb/
 obj-$(CONFIG_FB_SM750)         += sm750fb/
 obj-$(CONFIG_FB_XGI)           += xgifb/
 obj-$(CONFIG_USB_EMXX)         += emxx_udc/
@@ -32,7 +31,6 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)  += ste_rmi4/
 obj-$(CONFIG_MFD_NVEC)         += nvec/
 obj-$(CONFIG_ANDROID)          += android/
 obj-$(CONFIG_STAGING_BOARD)    += board/
-obj-$(CONFIG_USB_WPAN_HCD)     += ozwpan/
 obj-$(CONFIG_WIMAX_GDM72XX)    += gdm72xx/
 obj-$(CONFIG_LTE_GDM724X)      += gdm724x/
 obj-$(CONFIG_FIREWIRE_SERIAL)  += fwserial/
@@ -48,3 +46,4 @@ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
 obj-$(CONFIG_FB_TFT)           += fbtft/
 obj-$(CONFIG_FSL_MC_BUS)       += fsl-mc/
 obj-$(CONFIG_WILC1000)         += wilc1000/
+obj-$(CONFIG_MOST)             += most/
index 24d657b3ab9946d0166198c213c025843f204aad..68307121c9c18830ed88477ad152e5188cec0537 100644 (file)
@@ -20,7 +20,8 @@ config ANDROID_TIMED_OUTPUT
 
 config ANDROID_TIMED_GPIO
        tristate "Android timed gpio driver"
-       depends on GPIOLIB && ANDROID_TIMED_OUTPUT
+       depends on GPIOLIB || COMPILE_TEST
+       depends on ANDROID_TIMED_OUTPUT
        default n
         ---help---
          Unlike generic gpio is to allow programs to access and manipulate gpio
index 06954cdf3dbad55254366d776e0b5d5782fdbff1..20288fc53946ce9648b36d8af821f74e1c833abd 100644 (file)
@@ -2,16 +2,8 @@ TODO:
        - checkpatch.pl cleanups
        - sparse fixes
        - rename files to be not so "generic"
-       - make sure things build as modules properly
        - add proper arch dependencies as needed
        - audit userspace interfaces to make sure they are sane
-       - kuid_t should never be exposed to user space as it is
-          kernel internal type. Data structure for this kuid_t is:
-          typedef struct {
-               uid_t val;
-          } kuid_t;
-       - This bug is introduced by Xiong Zhou in the patch bd471258f2e09
-       - ("staging: android: logger: use kuid_t instead of uid_t")
 
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
-Brian Swetland <swetland@google.com>
+Arve HjønnevÃ¥g <arve@android.com> and Riley Andrews <riandrews@android.com>
index c5c037ccf32cc0097f25fe16ddc7848cbd41e547..60200a3da82103c1501673e2c3b51ebe2fb283d0 100644 (file)
@@ -388,7 +388,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
 
                /* ... and allocate the backing shmem file */
                vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
-               if (unlikely(IS_ERR(vmfile))) {
+               if (IS_ERR(vmfile)) {
                        ret = PTR_ERR(vmfile);
                        goto out;
                }
@@ -660,7 +660,7 @@ restart:
                if (page_range_subsumed_by_range(range, pgstart, pgend))
                        return 0;
                if (page_range_in_range(range, pgstart, pgend)) {
-                       pgstart = min_t(size_t, range->pgstart, pgstart),
+                       pgstart = min_t(size_t, range->pgstart, pgstart);
                        pgend = max_t(size_t, range->pgend, pgend);
                        purged |= range->purged;
                        range_del(range);
@@ -863,14 +863,9 @@ static int __init ashmem_init(void)
 
 static void __exit ashmem_exit(void)
 {
-       int ret;
-
        unregister_shrinker(&ashmem_shrinker);
 
-       ret = misc_deregister(&ashmem_misc);
-       if (unlikely(ret))
-               pr_err("failed to unregister misc device!\n");
-
+       misc_deregister(&ashmem_misc);
        kmem_cache_destroy(ashmem_range_cachep);
        kmem_cache_destroy(ashmem_area_cachep);
 
index 6f48112635571f78e0d10e50c2d3fb6f0b9277d3..eec878e183f5d81e51649efad85a470805fb0080 100644 (file)
@@ -1103,10 +1103,10 @@ static struct dma_buf_ops dma_buf_ops = {
 struct dma_buf *ion_share_dma_buf(struct ion_client *client,
                                                struct ion_handle *handle)
 {
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
        struct ion_buffer *buffer;
        struct dma_buf *dmabuf;
        bool valid_handle;
-       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
        mutex_lock(&client->lock);
        valid_handle = ion_handle_validate(client, handle);
@@ -1466,7 +1466,6 @@ static const struct file_operations debug_heap_fops = {
        .release = single_release,
 };
 
-#ifdef DEBUG_HEAP_SHRINKER
 static int debug_shrink_set(void *data, u64 val)
 {
        struct ion_heap *heap = data;
@@ -1474,15 +1473,14 @@ static int debug_shrink_set(void *data, u64 val)
        int objs;
 
        sc.gfp_mask = -1;
-       sc.nr_to_scan = 0;
+       sc.nr_to_scan = val;
 
-       if (!val)
-               return 0;
-
-       objs = heap->shrinker.shrink(&heap->shrinker, &sc);
-       sc.nr_to_scan = objs;
+       if (!val) {
+               objs = heap->shrinker.count_objects(&heap->shrinker, &sc);
+               sc.nr_to_scan = objs;
+       }
 
-       heap->shrinker.shrink(&heap->shrinker, &sc);
+       heap->shrinker.scan_objects(&heap->shrinker, &sc);
        return 0;
 }
 
@@ -1495,14 +1493,13 @@ static int debug_shrink_get(void *data, u64 *val)
        sc.gfp_mask = -1;
        sc.nr_to_scan = 0;
 
-       objs = heap->shrinker.shrink(&heap->shrinker, &sc);
+       objs = heap->shrinker.count_objects(&heap->shrinker, &sc);
        *val = objs;
        return 0;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get,
                        debug_shrink_set, "%llu\n");
-#endif
 
 void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
 {
@@ -1540,8 +1537,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
                        path, heap->name);
        }
 
-#ifdef DEBUG_HEAP_SHRINKER
-       if (heap->shrinker.shrink) {
+       if (heap->shrinker.count_objects && heap->shrinker.scan_objects) {
                char debug_name[64];
 
                snprintf(debug_name, 64, "%s_shrink", heap->name);
@@ -1556,7 +1552,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
                                path, debug_name);
                }
        }
-#endif
+
        up_write(&dev->lock);
 }
 
index 54746157d799a6e0f000f76cfc419948c240d28d..0813163f962f09e328d6fc448238201f84cc55cd 100644 (file)
@@ -173,8 +173,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
        chunk_heap->heap.ops = &chunk_heap_ops;
        chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;
        chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
-       pr_debug("%s: base %lu size %zu align %ld\n", __func__, chunk_heap->base,
-               heap_data->size, heap_data->align);
+       pr_debug("%s: base %lu size %zu align %ld\n", __func__,
+               chunk_heap->base, heap_data->size, heap_data->align);
 
        return &chunk_heap->heap;
 
index f4211f1be48818e25a879935f9893d2145a355a8..0b2448c32495094739283edc4bae031f999bdb8e 100644 (file)
@@ -73,8 +73,8 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer,
        if (!info->table)
                goto free_mem;
 
-       if (dma_common_get_sgtable
-           (dev, info->table, info->cpu_addr, info->handle, len))
+       if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle,
+                           len))
                goto free_table;
        /* keep this for memory release */
        buffer->priv_virt = info;
index 4b88f11e52d372ff3b33c5d448852fcddfeaac5c..19ad3aba499ae579889892e6c6168833f4c0851f 100644 (file)
@@ -116,7 +116,7 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high)
 int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
                                int nr_to_scan)
 {
-       int freed;
+       int freed = 0;
        bool high;
 
        if (current_is_kswapd())
@@ -127,7 +127,7 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
        if (nr_to_scan == 0)
                return ion_page_pool_total(pool, high);
 
-       for (freed = 0; freed < nr_to_scan; freed++) {
+       while (freed < nr_to_scan) {
                struct page *page;
 
                mutex_lock(&pool->mutex);
@@ -141,6 +141,7 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
                }
                mutex_unlock(&pool->mutex);
                ion_page_pool_free_pages(pool, page);
+               freed += (1 << pool->order);
        }
 
        return freed;
index da2a63c0a9ba5896e96652356c97d718aa761c1f..7a7a9a047230889a8d0883e68364609968c875a0 100644 (file)
@@ -212,14 +212,26 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask,
 {
        struct ion_system_heap *sys_heap;
        int nr_total = 0;
-       int i;
+       int i, nr_freed;
+       int only_scan = 0;
 
        sys_heap = container_of(heap, struct ion_system_heap, heap);
 
+       if (!nr_to_scan)
+               only_scan = 1;
+
        for (i = 0; i < num_orders; i++) {
                struct ion_page_pool *pool = sys_heap->pools[i];
 
-               nr_total += ion_page_pool_shrink(pool, gfp_mask, nr_to_scan);
+               nr_freed = ion_page_pool_shrink(pool, gfp_mask, nr_to_scan);
+               nr_total += nr_freed;
+
+               if (!only_scan) {
+                       nr_to_scan -= nr_freed;
+                       /* shrink completed */
+                       if (nr_to_scan <= 0)
+                               break;
+               }
        }
 
        return nr_total;
index 7d6e6b6bc894c9336674bbd16455592f1cf396ab..b8dcf5a26cc4ac1250bda0ded24d1ceff3c8cf24 100644 (file)
@@ -269,7 +269,8 @@ static int ion_test_remove(struct platform_device *pdev)
        if (!testdev)
                return -ENODATA;
 
-       return misc_deregister(&testdev->misc);
+       misc_deregister(&testdev->misc);
+       return 0;
 }
 
 static struct platform_device *ion_test_pdev;
index a21b79fb4c8e4a61599e08ad87d1455babee077a..61f8a3aede96ead8641b00c74aa8bbd38a1f00a7 100644 (file)
@@ -337,11 +337,11 @@ int sync_fence_wait(struct sync_fence *fence, long timeout);
 
 #ifdef CONFIG_DEBUG_FS
 
-extern void sync_timeline_debug_add(struct sync_timeline *obj);
-extern void sync_timeline_debug_remove(struct sync_timeline *obj);
-extern void sync_fence_debug_add(struct sync_fence *fence);
-extern void sync_fence_debug_remove(struct sync_fence *fence);
-extern void sync_dump(void);
+void sync_timeline_debug_add(struct sync_timeline *obj);
+void sync_timeline_debug_remove(struct sync_timeline *obj);
+void sync_fence_debug_add(struct sync_fence *fence);
+void sync_fence_debug_remove(struct sync_fence *fence);
+void sync_dump(void);
 
 #else
 # define sync_timeline_debug_add(obj)
index 938a35cd99bb4f019586a6a47e563c1798cf85af..ce11726f1a6c316c082fcf86876369562cf9b562 100644 (file)
@@ -61,9 +61,9 @@ static int gpio_get_time(struct timed_output_dev *dev)
 
 static void gpio_enable(struct timed_output_dev *dev, int value)
 {
-       struct timed_gpio_data  *data =
+       struct timed_gpio_data *data =
                container_of(dev, struct timed_gpio_data, dev);
-       unsigned long   flags;
+       unsigned long flags;
 
        spin_lock_irqsave(&data->lock, flags);
 
index 5455bf3d5a9191323bca2b9e71c4835a314f2e6f..b8e2f611fd47b027fb0486a02306515e9ec7798a 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
index 7dee73dfbf88ff09f4f3fef468eaa2ab75c2a584..57e71f9f14a2385bf8537b6d94dce5de164d4f4a 100644 (file)
@@ -2,7 +2,7 @@ config COMEDI
        tristate "Data acquisition support (comedi)"
        depends on m
        ---help---
-         Enable support a wide range of data acquisition devices
+         Enable support for a wide range of data acquisition devices
          for Linux.
 
 if COMEDI
index 25848244c4b129ca521370523fe064e8430bf8d3..f356386d833a1fe80c83b9a492634d295991688a 100644 (file)
@@ -202,7 +202,8 @@ static int get_compat_cmd(struct comedi_cmd __user *cmd,
        err |= __get_user(temp.uint, &cmd32->stop_arg);
        err |= __put_user(temp.uint, &cmd->stop_arg);
        err |= __get_user(temp.uptr, &cmd32->chanlist);
-       err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist);
+       err |= __put_user((unsigned int __force *)compat_ptr(temp.uptr),
+                       &cmd->chanlist);
        err |= __get_user(temp.uint, &cmd32->chanlist_len);
        err |= __put_user(temp.uint, &cmd->chanlist_len);
        err |= __get_user(temp.uptr, &cmd32->data);
index 985d94b6cbfd6eeb21afe792ca14e6be2d2ee866..fd54d098ab02248eabff1b250afc123b27433260 100644 (file)
@@ -215,7 +215,6 @@ static struct comedi_subdevice
        struct comedi_subdevice *s;
        unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
 
-       BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
        mutex_lock(&comedi_subdevice_minor_table_lock);
        s = comedi_subdevice_minor_table[i];
        if (s && s->device != dev)
@@ -228,7 +227,6 @@ static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor)
 {
        struct comedi_device *dev;
 
-       BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
        mutex_lock(&comedi_board_minor_table_lock);
        dev = comedi_dev_get(comedi_board_minor_table[minor]);
        mutex_unlock(&comedi_board_minor_table_lock);
@@ -241,7 +239,6 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor)
        struct comedi_subdevice *s;
        unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
 
-       BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
        mutex_lock(&comedi_subdevice_minor_table_lock);
        s = comedi_subdevice_minor_table[i];
        dev = comedi_dev_get(s ? s->device : NULL);
@@ -2599,14 +2596,14 @@ static int comedi_open(struct inode *inode, struct file *file)
        cfp->dev = dev;
 
        mutex_lock(&dev->mutex);
-       if (!dev->attached && !capable(CAP_NET_ADMIN)) {
-               dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n");
+       if (!dev->attached && !capable(CAP_SYS_ADMIN)) {
+               dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n");
                rc = -ENODEV;
                goto out;
        }
        if (dev->attached && dev->use_count == 0) {
                if (!try_module_get(dev->driver->module)) {
-                       rc = -ENOSYS;
+                       rc = -ENXIO;
                        goto out;
                }
                if (dev->open) {
@@ -2777,12 +2774,6 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
        return dev;
 }
 
-static void comedi_free_board_minor(unsigned minor)
-{
-       BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
-       comedi_free_board_dev(comedi_clear_board_minor(minor));
-}
-
 void comedi_release_hardware_device(struct device *hardware_device)
 {
        int minor;
@@ -2838,12 +2829,10 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
 
        if (!s)
                return;
-       if (s->minor < 0)
+       if (s->minor < COMEDI_NUM_BOARD_MINORS ||
+           s->minor >= COMEDI_NUM_MINORS)
                return;
 
-       BUG_ON(s->minor >= COMEDI_NUM_MINORS);
-       BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS);
-
        i = s->minor - COMEDI_NUM_BOARD_MINORS;
        mutex_lock(&comedi_subdevice_minor_table_lock);
        if (s == comedi_subdevice_minor_table[i])
@@ -2857,10 +2846,13 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
 
 static void comedi_cleanup_board_minors(void)
 {
+       struct comedi_device *dev;
        unsigned i;
 
-       for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++)
-               comedi_free_board_minor(i);
+       for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+               dev = comedi_clear_board_minor(i);
+               comedi_free_board_dev(dev);
+       }
 }
 
 static int __init comedi_init(void)
@@ -2932,14 +2924,7 @@ module_init(comedi_init);
 
 static void __exit comedi_cleanup(void)
 {
-       int i;
-
        comedi_cleanup_board_minors();
-       for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i)
-               BUG_ON(comedi_board_minor_table[i]);
-       for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i)
-               BUG_ON(comedi_subdevice_minor_table[i]);
-
        class_destroy(comedi_class);
        cdev_del(&comedi_cdev);
        unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
index ed0b60c925def80fa326491eba9b1467e4497073..b03bc6639f79478fe3034c4e98fd42178a3467bc 100644 (file)
@@ -820,7 +820,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                         "driver '%s' does not support attach using comedi_config\n",
                         driv->driver_name);
                module_put(driv->module);
-               ret = -ENOSYS;
+               ret = -EIO;
                goto out;
        }
        dev->driver = driv;
index fa99c8ca4f95093c98f8fb8f37ab8ba6fac63660..f0c0d58383ca7fb06a8cb88c2da4383689d531cb 100644 (file)
@@ -1,22 +1,3 @@
-/* Digital Input IRQ Function Selection */
-#define APCI1564_DI_INT_OR                             (0 << 1)
-#define APCI1564_DI_INT_AND                            (1 << 1)
-
-/* Digital Input Interrupt Enable Disable. */
-#define APCI1564_DI_INT_ENABLE                         0x4
-#define APCI1564_DI_INT_DISABLE                                0xfffffffb
-
-/* Digital Output Interrupt Enable Disable. */
-#define APCI1564_DO_VCC_INT_ENABLE                     0x1
-#define APCI1564_DO_VCC_INT_DISABLE                    0xfffffffe
-#define APCI1564_DO_CC_INT_ENABLE                      0x2
-#define APCI1564_DO_CC_INT_DISABLE                     0xfffffffd
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-#define ADDIDATA_TIMER                                 0
-#define ADDIDATA_COUNTER                               1
-#define ADDIDATA_WATCHDOG                              2
-
 static int apci1564_timer_insn_config(struct comedi_device *dev,
                                      struct comedi_subdevice *s,
                                      struct comedi_insn *insn,
@@ -27,15 +8,16 @@ static int apci1564_timer_insn_config(struct comedi_device *dev,
 
        devpriv->tsk_current = current;
 
-       /* First Stop The Timer */
+       /* Stop the timer */
        ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
-       ctrl &= 0xfffff9fe;
-       /* Stop The Timer */
+       ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                 ADDI_TCW_CTRL_ENA);
        outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
 
        if (data[1] == 1) {
                /* Enable timer int & disable all the other int sources */
-               outl(0x02, devpriv->timer + ADDI_TCW_CTRL_REG);
+               outl(ADDI_TCW_CTRL_IRQ_ENA,
+                    devpriv->timer + ADDI_TCW_CTRL_REG);
                outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
                outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
                outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
@@ -59,9 +41,11 @@ static int apci1564_timer_insn_config(struct comedi_device *dev,
        outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
 
        ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
-       ctrl &= 0xfff719e2;
-       ctrl |= (2 << 13) | 0x10;
-       /* mode 2 */
+       ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
+                 ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
+                 ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
+       ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
        outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
 
        return insn->n;
@@ -76,13 +60,13 @@ static int apci1564_timer_insn_write(struct comedi_device *dev,
        unsigned int ctrl;
 
        ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+       ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
        switch (data[1]) {
        case 0: /* Stop The Timer */
-               ctrl &= 0xfffff9fe;
+               ctrl &= ~ADDI_TCW_CTRL_ENA;
                break;
        case 1: /* Enable the Timer */
-               ctrl &= 0xfffff9ff;
-               ctrl |= 0x1;
+               ctrl |= ADDI_TCW_CTRL_ENA;
                break;
        }
        outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
@@ -98,7 +82,8 @@ static int apci1564_timer_insn_read(struct comedi_device *dev,
        struct apci1564_private *devpriv = dev->private;
 
        /* Stores the status of the Timer */
-       data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & 0x1;
+       data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) &
+                 ADDI_TCW_STATUS_OVERFLOW;
 
        /* Stores the Actual value of the Timer */
        data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
@@ -118,35 +103,34 @@ static int apci1564_counter_insn_config(struct comedi_device *dev,
 
        devpriv->tsk_current = current;
 
-       /* First Stop The Counter */
-       ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
-       ctrl &= 0xfffff9fe;
        /* Stop The Timer */
+       ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+       ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                 ADDI_TCW_CTRL_ENA);
        outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
 
        /* Set the reload value */
        outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
 
-       /* Set the mode :             */
-       /* - Disable the hardware     */
-       /* - Disable the counter mode */
-       /* - Disable the warning      */
-       /* - Disable the reset        */
-       /* - Disable the timer mode   */
-       /* - Enable the counter mode  */
-
-       ctrl &= 0xfffc19e2;
-       ctrl |= 0x80000 | (data[4] << 16);
+       /* Set the mode */
+       ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
+                 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
+                 ADDI_TCW_CTRL_WARN_ENA);
+       ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]);
        outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
 
        /* Enable or Disable Interrupt */
-       ctrl &= 0xfffff9fd;
-       ctrl |= (data[1] << 1);
+       if (data[1])
+               ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
+       else
+               ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA;
        outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
 
        /* Set the Up/Down selection */
-       ctrl &= 0xfffbf9ff;
-       ctrl |= (data[6] << 18);
+       if (data[6])
+               ctrl |= ADDI_TCW_CTRL_CNT_UP;
+       else
+               ctrl &= ~ADDI_TCW_CTRL_CNT_UP;
        outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
 
        return insn->n;
@@ -163,17 +147,16 @@ static int apci1564_counter_insn_write(struct comedi_device *dev,
        unsigned int ctrl;
 
        ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+       ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
        switch (data[1]) {
        case 0: /* Stops the Counter subdevice */
                ctrl = 0;
                break;
        case 1: /* Start the Counter subdevice */
-               ctrl &= 0xfffff9ff;
-               ctrl |= 0x1;
+               ctrl |= ADDI_TCW_CTRL_ENA;
                break;
        case 2: /* Clears the Counter subdevice */
-               ctrl &= 0xfffff9ff;
-               ctrl |= 0x400;
+               ctrl |= ADDI_TCW_CTRL_GATE;
                break;
        }
        outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
@@ -195,10 +178,10 @@ static int apci1564_counter_insn_read(struct comedi_device *dev,
        data[0] = inl(iobase + ADDI_TCW_VAL_REG);
 
        status = inl(iobase + ADDI_TCW_STATUS_REG);
-       data[1] = (status >> 1) & 1;    /* software trigger status */
-       data[2] = (status >> 2) & 1;    /* hardware trigger status */
-       data[3] = (status >> 3) & 1;    /* software clear status */
-       data[4] = (status >> 0) & 1;    /* overflow status */
+       data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0;
+       data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0;
+       data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0;
+       data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0;
 
        return insn->n;
 }
index 1f2f78186d58c1545946e80b3cf0fd371974b9e9..375707497896f65fc562fdc1c35e4e5f67732f5d 100644 (file)
@@ -22,54 +22,50 @@ static int apci3501_config_insn_timer(struct comedi_device *dev,
                                      unsigned int *data)
 {
        struct apci3501_private *devpriv = dev->private;
-       unsigned int ul_Command1 = 0;
+       unsigned int ctrl;
+
+       if (data[0] != ADDIDATA_WATCHDOG &&
+           data[0] != ADDIDATA_TIMER)
+               return -EINVAL;
 
        devpriv->tsk_Current = current;
-       if (data[0] == ADDIDATA_WATCHDOG) {
-
-               devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
-               /* Disable the watchdog */
-               outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
-
-               if (data[1] == 1) {
-                       /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
-                       outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               } else {
-                       /* disable Timer interrupt */
-                       outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               }
 
-               outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
-               outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
+       devpriv->timer_mode = data[0];
 
-               /* Set the mode (e2->e0) */
-               ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG) | 0xFFF819E0UL;
-               outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+       /* first, disable the watchdog or stop the timer */
+       if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
+               ctrl = 0;
+       } else {
+               ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+               ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                         ADDI_TCW_CTRL_ENA);
        }
-
-       else if (data[0] == ADDIDATA_TIMER) {
-               /* First Stop The Timer */
-               ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-               ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
-               outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
-               if (data[1] == 1) {
-                       /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
-                       outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               } else {
-                       /* disable Timer interrupt */
-                       outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               }
-
-               outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
-               outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
-
+       outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
+
+       /* enable/disable the timer interrupt */
+       ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0;
+       outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
+
+       outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG);
+       outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG);
+
+       ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+       if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
+               /* Set the mode (e2->e0) NOTE: this doesn't look correct */
+               ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK |
+                         ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE |
+                         ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA |
+                         ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA |
+                         ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_ENA);
+       } else {
                /* mode 2 */
-               ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-               ul_Command1 =
-                       (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
-               outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+               ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
+                         ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                         ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
+                         ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
+               ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
        }
+       outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
 
        return insn->n;
 }
@@ -92,49 +88,27 @@ static int apci3501_write_insn_timer(struct comedi_device *dev,
                                     unsigned int *data)
 {
        struct apci3501_private *devpriv = dev->private;
-       unsigned int ul_Command1 = 0;
-
-       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
-
-               if (data[1] == 1) {
-                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
-                       /* Enable the Watchdog */
-                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               } else if (data[1] == 0) { /* Stop The Watchdog */
-                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
-                       outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               } else if (data[1] == 2) {
-                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
-                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               }
-       }
-
-       if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
-               if (data[1] == 1) {
-
-                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
-                       /* Enable the Timer */
-                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               } else if (data[1] == 0) {
-                       /* Stop The Timer */
-                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-                       ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
-                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
-               }
-
-               else if (data[1] == 2) {
-                       /* Trigger the Timer */
-                       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-                       ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
-                       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+       unsigned int ctrl;
+
+       if (devpriv->timer_mode == ADDIDATA_WATCHDOG ||
+           devpriv->timer_mode == ADDIDATA_TIMER) {
+               ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+               ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
+
+               if (data[1] == 1) {             /* enable */
+                       ctrl |= ADDI_TCW_CTRL_ENA;
+               } else if (data[1] == 0) {      /* stop */
+                       if (devpriv->timer_mode == ADDIDATA_WATCHDOG)
+                               ctrl = 0;
+                       else
+                               ctrl &= ~ADDI_TCW_CTRL_ENA;
+               } else if (data[1] == 2) {      /* trigger */
+                       ctrl |= ADDI_TCW_CTRL_TRIG;
                }
+               outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
        }
 
-       inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
+       inl(devpriv->tcw + ADDI_TCW_STATUS_REG);
        return insn->n;
 }
 
@@ -155,19 +129,13 @@ static int apci3501_read_insn_timer(struct comedi_device *dev,
 {
        struct apci3501_private *devpriv = dev->private;
 
-       if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
-               data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
-               data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
-       }
+       if (devpriv->timer_mode != ADDIDATA_TIMER &&
+           devpriv->timer_mode != ADDIDATA_WATCHDOG)
+               return -EINVAL;
 
-       else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
-               data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
-               data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
-       }
+       data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) &
+                 ADDI_TCW_STATUS_OVERFLOW;
+       data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG);
 
-       else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
-               && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
-               dev_err(dev->class_dev, "Invalid subdevice.\n");
-       }
        return insn->n;
 }
index 33e58b9a21b296895332fc7df5e0834dffc4f78e..f1ccfbd4c578ef89fec698df5365f2ad10ffd83e 100644 (file)
  *   0x48 - 0x64  Timer 12-Bit
  */
 #define APCI1564_EEPROM_REG                    0x00
-#define APCI1564_EEPROM_VCC_STATUS             (1 << 8)
+#define APCI1564_EEPROM_VCC_STATUS             BIT(8)
 #define APCI1564_EEPROM_TO_REV(x)              (((x) >> 4) & 0xf)
-#define APCI1564_EEPROM_DI                     (1 << 3)
-#define APCI1564_EEPROM_DO                     (1 << 2)
-#define APCI1564_EEPROM_CS                     (1 << 1)
-#define APCI1564_EEPROM_CLK                    (1 << 0)
+#define APCI1564_EEPROM_DI                     BIT(3)
+#define APCI1564_EEPROM_DO                     BIT(2)
+#define APCI1564_EEPROM_CS                     BIT(1)
+#define APCI1564_EEPROM_CLK                    BIT(0)
 #define APCI1564_REV1_TIMER_IOBASE             0x04
 #define APCI1564_REV2_MAIN_IOBASE              0x04
 #define APCI1564_REV2_TIMER_IOBASE             0x48
 #define APCI1564_DI_INT_MODE2_REG              0x08
 #define APCI1564_DI_INT_STATUS_REG             0x0c
 #define APCI1564_DI_IRQ_REG                    0x10
+#define APCI1564_DI_IRQ_ENA                    BIT(2)
+#define APCI1564_DI_IRQ_MODE                   BIT(1)  /* 1=AND, 0=OR */
 #define APCI1564_DO_REG                                0x14
 #define APCI1564_DO_INT_CTRL_REG               0x18
+#define APCI1564_DO_INT_CTRL_CC_INT_ENA                BIT(1)
+#define APCI1564_DO_INT_CTRL_VCC_INT_ENA       BIT(0)
 #define APCI1564_DO_INT_STATUS_REG             0x1c
+#define APCI1564_DO_INT_STATUS_CC              BIT(1)
+#define APCI1564_DO_INT_STATUS_VCC             BIT(0)
 #define APCI1564_DO_IRQ_REG                    0x20
+#define APCI1564_DO_IRQ_INTR                   BIT(0)
 #define APCI1564_WDOG_REG                      0x24
 #define APCI1564_WDOG_RELOAD_REG               0x28
 #define APCI1564_WDOG_TIMEBASE_REG             0x2c
@@ -159,9 +166,9 @@ static irqreturn_t apci1564_interrupt(int irq, void *d)
        unsigned int chan;
 
        status = inl(dev->iobase + APCI1564_DI_IRQ_REG);
-       if (status & APCI1564_DI_INT_ENABLE) {
+       if (status & APCI1564_DI_IRQ_ENA) {
                /* disable the interrupt */
-               outl(status & APCI1564_DI_INT_DISABLE,
+               outl(status & ~APCI1564_DI_IRQ_ENA,
                     dev->iobase + APCI1564_DI_IRQ_REG);
 
                s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) &
@@ -300,11 +307,9 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
                        outl(0x0, dev->iobase + APCI1564_DI_INT_MODE2_REG);
                        break;
                case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
-                       if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
-                                             APCI1564_DI_INT_OR)) {
+                       if (devpriv->ctrl != APCI1564_DI_IRQ_ENA) {
                                /* switching to 'OR' mode */
-                               devpriv->ctrl = APCI1564_DI_INT_ENABLE |
-                                               APCI1564_DI_INT_OR;
+                               devpriv->ctrl = APCI1564_DI_IRQ_ENA;
                                /* wipe old channels */
                                devpriv->mode1 = 0;
                                devpriv->mode2 = 0;
@@ -318,11 +323,11 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
                        devpriv->mode2 |= data[5] << shift;
                        break;
                case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
-                       if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
-                                             APCI1564_DI_INT_AND)) {
+                       if (devpriv->ctrl != (APCI1564_DI_IRQ_ENA |
+                                             APCI1564_DI_IRQ_MODE)) {
                                /* switching to 'AND' mode */
-                               devpriv->ctrl = APCI1564_DI_INT_ENABLE |
-                                               APCI1564_DI_INT_AND;
+                               devpriv->ctrl = APCI1564_DI_IRQ_ENA |
+                                               APCI1564_DI_IRQ_MODE;
                                /* wipe old channels */
                                devpriv->mode1 = 0;
                                devpriv->mode2 = 0;
index 73786a3f3df98e60fee1b4843ad145a931f22406..40ff91411139d9c9a28b0e73f2986aa4a163bd1c 100644 (file)
 #include <linux/sched.h>
 
 #include "../comedi_pci.h"
+#include "addi_tcw.h"
 #include "amcc_s5933.h"
 
 /*
  * PCI bar 1 register I/O map
  */
 #define APCI3501_AO_CTRL_STATUS_REG            0x00
-#define APCI3501_AO_CTRL_BIPOLAR               (1 << 0)
-#define APCI3501_AO_STATUS_READY               (1 << 8)
+#define APCI3501_AO_CTRL_BIPOLAR               BIT(0)
+#define APCI3501_AO_STATUS_READY               BIT(8)
 #define APCI3501_AO_DATA_REG                   0x04
 #define APCI3501_AO_DATA_CHAN(x)               ((x) << 0)
 #define APCI3501_AO_DATA_VAL(x)                        ((x) << 8)
-#define APCI3501_AO_DATA_BIPOLAR               (1 << 31)
+#define APCI3501_AO_DATA_BIPOLAR               BIT(31)
 #define APCI3501_AO_TRIG_SCS_REG               0x08
-#define APCI3501_TIMER_SYNC_REG                        0x20
-#define APCI3501_TIMER_RELOAD_REG              0x24
-#define APCI3501_TIMER_TIMEBASE_REG            0x28
-#define APCI3501_TIMER_CTRL_REG                        0x2c
-#define APCI3501_TIMER_STATUS_REG              0x30
-#define APCI3501_TIMER_IRQ_REG                 0x34
-#define APCI3501_TIMER_WARN_RELOAD_REG         0x38
-#define APCI3501_TIMER_WARN_TIMEBASE_REG       0x3c
+#define APCI3501_TIMER_BASE                    0x20
 #define APCI3501_DO_REG                                0x40
 #define APCI3501_DI_REG                                0x50
 
 #define EEPROM_TIMER_WATCHDOG_COUNTER  10
 
 struct apci3501_private {
-       int i_IobaseAmcc;
+       unsigned long amcc;
+       unsigned long tcw;
        struct task_struct *tsk_Current;
-       unsigned char b_TimerSelectMode;
+       unsigned char timer_mode;
 };
 
 static struct comedi_lrange apci3501_ao_range = {
@@ -222,11 +217,10 @@ static unsigned short apci3501_eeprom_readw(unsigned long iobase,
 static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
 {
        struct apci3501_private *devpriv = dev->private;
-       unsigned long iobase = devpriv->i_IobaseAmcc;
        unsigned char nfuncs;
        int i;
 
-       nfuncs = apci3501_eeprom_readw(iobase, 10) & 0xff;
+       nfuncs = apci3501_eeprom_readw(devpriv->amcc, 10) & 0xff;
 
        /* Read functionality details */
        for (i = 0; i < nfuncs; i++) {
@@ -235,11 +229,11 @@ static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
                unsigned char func;
                unsigned short val;
 
-               func = apci3501_eeprom_readw(iobase, 12 + offset) & 0x3f;
-               addr = apci3501_eeprom_readw(iobase, 14 + offset);
+               func = apci3501_eeprom_readw(devpriv->amcc, 12 + offset) & 0x3f;
+               addr = apci3501_eeprom_readw(devpriv->amcc, 14 + offset);
 
                if (func == EEPROM_ANALOGOUTPUT) {
-                       val = apci3501_eeprom_readw(iobase, addr + 10);
+                       val = apci3501_eeprom_readw(devpriv->amcc, addr + 10);
                        return (val >> 4) & 0x3ff;
                }
        }
@@ -254,7 +248,7 @@ static int apci3501_eeprom_insn_read(struct comedi_device *dev,
        struct apci3501_private *devpriv = dev->private;
        unsigned short addr = CR_CHAN(insn->chanspec);
 
-       data[0] = apci3501_eeprom_readw(devpriv->i_IobaseAmcc, 2 * addr);
+       data[0] = apci3501_eeprom_readw(devpriv->amcc, 2 * addr);
 
        return insn->n;
 }
@@ -263,26 +257,29 @@ static irqreturn_t apci3501_interrupt(int irq, void *d)
 {
        struct comedi_device *dev = d;
        struct apci3501_private *devpriv = dev->private;
-       unsigned int ui_Timer_AOWatchdog;
-       unsigned long ul_Command1;
+       unsigned int status;
+       unsigned int ctrl;
 
        /*  Disable Interrupt */
-       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-       ul_Command1 = ul_Command1 & 0xFFFFF9FDul;
-       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+       ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+       ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                 ADDI_TCW_CTRL_IRQ_ENA);
+       outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
 
-       ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1;
-       if ((!ui_Timer_AOWatchdog)) {
+       status = inl(devpriv->tcw + ADDI_TCW_IRQ_REG);
+       if (!(status & ADDI_TCW_IRQ)) {
                dev_err(dev->class_dev, "IRQ from unknown source\n");
                return IRQ_NONE;
        }
 
        /* Enable Interrupt Send a signal to from kernel to user space */
        send_sig(SIGIO, devpriv->tsk_Current, 0);
-       ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
-       ul_Command1 = (ul_Command1 & 0xFFFFF9FDul) | 1 << 1;
-       outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
-       inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
+       ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+       ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+                 ADDI_TCW_CTRL_IRQ_ENA);
+       ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
+       outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
+       inl(devpriv->tcw + ADDI_TCW_STATUS_REG);
 
        return IRQ_HANDLED;
 }
@@ -334,8 +331,9 @@ static int apci3501_auto_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
+       devpriv->amcc = pci_resource_start(pcidev, 0);
        dev->iobase = pci_resource_start(pcidev, 1);
-       devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+       devpriv->tcw = dev->iobase + APCI3501_TIMER_BASE;
 
        ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev);
 
index 8794d4cbbfb01a13ab1b1451be39e9448f117f67..db6d5a4e88890bbae007cd943d9b87ee52ffc2b8 100644 (file)
 #define ADDI_TCW_VAL_REG               0x00
 
 #define ADDI_TCW_SYNC_REG              0x00
-#define ADDI_TCW_SYNC_CTR_TRIG         (1 << 8)
-#define ADDI_TCW_SYNC_CTR_DIS          (1 << 7)
-#define ADDI_TCW_SYNC_CTR_ENA          (1 << 6)
-#define ADDI_TCW_SYNC_TIMER_TRIG       (1 << 5)
-#define ADDI_TCW_SYNC_TIMER_DIS                (1 << 4)
-#define ADDI_TCW_SYNC_TIMER_ENA                (1 << 3)
-#define ADDI_TCW_SYNC_WDOG_TRIG                (1 << 2)
-#define ADDI_TCW_SYNC_WDOG_DIS         (1 << 1)
-#define ADDI_TCW_SYNC_WDOG_ENA         (1 << 0)
+#define ADDI_TCW_SYNC_CTR_TRIG         BIT(8)
+#define ADDI_TCW_SYNC_CTR_DIS          BIT(7)
+#define ADDI_TCW_SYNC_CTR_ENA          BIT(6)
+#define ADDI_TCW_SYNC_TIMER_TRIG       BIT(5)
+#define ADDI_TCW_SYNC_TIMER_DIS                BIT(4)
+#define ADDI_TCW_SYNC_TIMER_ENA                BIT(3)
+#define ADDI_TCW_SYNC_WDOG_TRIG                BIT(2)
+#define ADDI_TCW_SYNC_WDOG_DIS         BIT(1)
+#define ADDI_TCW_SYNC_WDOG_ENA         BIT(0)
 
 #define ADDI_TCW_RELOAD_REG            0x04
 
 #define ADDI_TCW_TIMEBASE_REG          0x08
 
 #define ADDI_TCW_CTRL_REG              0x0c
-#define ADDI_TCW_CTRL_EXT_CLK_STATUS   (1 << 21)
-#define ADDI_TCW_CTRL_CASCADE          (1 << 20)
-#define ADDI_TCW_CTRL_CNTR_ENA         (1 << 19)
-#define ADDI_TCW_CTRL_CNT_UP           (1 << 18)
-#define ADDI_TCW_CTRL_EXT_CLK(x)       ((x) << 16)
-#define ADDI_TCW_CTRL_OUT(x)           ((x) << 11)
-#define ADDI_TCW_CTRL_GATE             (1 << 10)
-#define ADDI_TCW_CTRL_TRIG             (1 << 9)
-#define ADDI_TCW_CTRL_EXT_GATE(x)      ((x) << 7)
-#define ADDI_TCW_CTRL_EXT_TRIG(x)      ((x) << 5)
-#define ADDI_TCW_CTRL_TIMER_ENA                (1 << 4)
-#define ADDI_TCW_CTRL_RESET_ENA                (1 << 3)
-#define ADDI_TCW_CTRL_WARN_ENA         (1 << 2)
-#define ADDI_TCW_CTRL_IRQ_ENA          (1 << 1)
-#define ADDI_TCW_CTRL_ENA              (1 << 0)
+#define ADDI_TCW_CTRL_EXT_CLK_STATUS   BIT(21)
+#define ADDI_TCW_CTRL_CASCADE          BIT(20)
+#define ADDI_TCW_CTRL_CNTR_ENA         BIT(19)
+#define ADDI_TCW_CTRL_CNT_UP           BIT(18)
+#define ADDI_TCW_CTRL_EXT_CLK(x)       (((x) & 3) << 16)
+#define ADDI_TCW_CTRL_EXT_CLK_MASK     ADDI_TCW_CTRL_EXT_CLK(3)
+#define ADDI_TCW_CTRL_MODE(x)          (((x) & 7) << 13)
+#define ADDI_TCW_CTRL_MODE_MASK                ADDI_TCW_CTRL_MODE(7)
+#define ADDI_TCW_CTRL_OUT(x)           (((x) & 3) << 11)
+#define ADDI_TCW_CTRL_OUT_MASK         ADDI_TCW_CTRL_OUT(3)
+#define ADDI_TCW_CTRL_GATE             BIT(10)
+#define ADDI_TCW_CTRL_TRIG             BIT(9)
+#define ADDI_TCW_CTRL_EXT_GATE(x)      (((x) & 3) << 7)
+#define ADDI_TCW_CTRL_EXT_GATE_MASK    ADDI_TCW_CTRL_EXT_GATE(3)
+#define ADDI_TCW_CTRL_EXT_TRIG(x)      (((x) & 3) << 5)
+#define ADDI_TCW_CTRL_EXT_TRIG_MASK    ADDI_TCW_CTRL_EXT_TRIG(3)
+#define ADDI_TCW_CTRL_TIMER_ENA                BIT(4)
+#define ADDI_TCW_CTRL_RESET_ENA                BIT(3)
+#define ADDI_TCW_CTRL_WARN_ENA         BIT(2)
+#define ADDI_TCW_CTRL_IRQ_ENA          BIT(1)
+#define ADDI_TCW_CTRL_ENA              BIT(0)
 
 #define ADDI_TCW_STATUS_REG            0x10
-#define ADDI_TCW_STATUS_SOFT_CLR       (1 << 3)
-#define ADDI_TCW_STATUS_SOFT_TRIG      (1 << 1)
-#define ADDI_TCW_STATUS_OVERFLOW       (1 << 0)
+#define ADDI_TCW_STATUS_SOFT_CLR       BIT(3)
+#define ADDI_TCW_STATUS_HARDWARE_TRIG  BIT(2)
+#define ADDI_TCW_STATUS_SOFT_TRIG      BIT(1)
+#define ADDI_TCW_STATUS_OVERFLOW       BIT(0)
 
 #define ADDI_TCW_IRQ_REG               0x14
-#define ADDI_TCW_IRQ                   (1 << 0)
+#define ADDI_TCW_IRQ                   BIT(0)
 
 #define ADDI_TCW_WARN_TIMEVAL_REG      0x18
 
index 934af3ff789732f4aeb4928997e72318ad609f7b..b0fc027cf485d11cebdb6d495bbce59e239c9996 100644 (file)
@@ -120,8 +120,20 @@ static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev,
 {
        unsigned long reg = (unsigned long)s->private;
 
-       if (comedi_dio_update_state(s, data))
-               outl(s->state, dev->iobase + reg);
+       if (comedi_dio_update_state(s, data)) {
+               unsigned int val = s->state;
+
+               if (s->n_chan == 16) {
+                       /*
+                        * It seems the PCI-7230 needs the 16-bit DO state
+                        * to be shifted left by 16 bits before being written
+                        * to the 32-bit register.  Set the value in both
+                        * halves of the register to be sure.
+                        */
+                       val |= val << 16;
+               }
+               outl(val, dev->iobase + reg);
+       }
 
        data[1] = s->state;
 
index 4ebf5aae50199083a0104fe59b9867892e00a26a..47e38398921ed26588f1409217f1aafe5bf5c277 100644 (file)
@@ -141,11 +141,13 @@ static const struct comedi_lrange cb_pcimdas_ai_uni_range = {
  * jumper-settable on the board. The settings are not software-readable.
  */
 static const struct comedi_lrange cb_pcimdas_ao_range = {
-       4, {
+       6, {
                BIP_RANGE(10),
                BIP_RANGE(5),
                UNI_RANGE(10),
-               UNI_RANGE(5)
+               UNI_RANGE(5),
+               RANGE_ext(-1, 1),
+               RANGE_ext(0, 1)
        }
 };
 
index a6798ad8fa7fa76703135e8818258350b117265c..a562df498b017e278f266f7ff8a07160991a2f61 100644 (file)
@@ -130,11 +130,7 @@ static int dac02_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        s->range_table  = &das02_ao_ranges;
        s->insn_write   = dac02_ao_insn_write;
 
-       ret = comedi_alloc_subdev_readback(s);
-       if (ret)
-               return ret;
-
-       return 0;
+       return comedi_alloc_subdev_readback(s);
 }
 
 static struct comedi_driver dac02_driver = {
index 93fab68901617903ef478cc05e1fcc2bbc79199c..9c02b17a28347aff19e4cfe1e6016e615c87ae2e 100644 (file)
@@ -108,7 +108,7 @@ static struct pcmcia_driver das08_cs_driver = {
 };
 module_comedi_pcmcia_driver(driver_das08_cs, das08_cs_driver);
 
-MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, "
-             "Frank Mori Hess <fmhess@users.sourceforge.net>");
+MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
+MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
 MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards");
 MODULE_LICENSE("GPL");
index d7cf4b153f7c37889efd8032712ee64a33f27426..056bca9c67d5d637885073a3b635e625c1f392dd 100644 (file)
@@ -1032,8 +1032,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
        /*  check that clock setting is valid */
        if (it->options[3]) {
-               if (it->options[3] != 0 &&
-                   it->options[3] != 1 && it->options[3] != 10) {
+               if (it->options[3] != 1 && it->options[3] != 10) {
                        dev_err(dev->class_dev,
                                "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
                        return -EINVAL;
index a18a8878bdb8abea0a24130d55d1cf5111fa02c9..3a37373fbb6f15b482bc25c34c1acc787b497b1e 100644 (file)
@@ -69,18 +69,18 @@ irq can be omitted, although the cmd interface will not work without it.
 
     "cio-das16/m1"
 
-  0    a/d bits 0-3, mux               start 12 bit
-  1    a/d bits 4-11           unused
-  2    status          control
-  3    di 4 bit                do 4 bit
-  4    unused                  clear interrupt
-  5    interrupt, pacer
-  6    channel/gain queue address
-  7    channel/gain queue data
-  89ab 8254
-  cdef 8254
-  400  8255
-  404-407      8254
+  0            a/d bits 0-3, mux               start 12 bit
+  1            a/d bits 4-11           unused
+  2            status          control
+  3            di 4 bit                do 4 bit
+  4            unused                  clear interrupt
+  5            interrupt, pacer
+  6            channel/gain queue address
+  7            channel/gain queue data
+  89ab         8254
+  cdef         8254
+  400          8255
+  404-407      8254
 
 */
 
@@ -411,15 +411,18 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status)
        hw_counter = comedi_8254_read(devpriv->counter, 1);
        /* make sure hardware counter reading is not bogus due to initial value
         * not having been loaded yet */
-       if (devpriv->adc_count == 0 && hw_counter == devpriv->initial_hw_count) {
+       if (devpriv->adc_count == 0 &&
+           hw_counter == devpriv->initial_hw_count) {
                num_samples = 0;
        } else {
-               /* The calculation of num_samples looks odd, but it uses the following facts.
-                * 16 bit hardware counter is initialized with value of zero (which really
-                * means 0x1000).  The counter decrements by one on each conversion
-                * (when the counter decrements from zero it goes to 0xffff).  num_samples
-                * is a 16 bit variable, so it will roll over in a similar fashion to the
-                * hardware counter.  Work it out, and this is what you get. */
+               /* The calculation of num_samples looks odd, but it uses the
+                * following facts. 16 bit hardware counter is initialized with
+                * value of zero (which really means 0x1000).  The counter
+                * decrements by one on each conversion (when the counter
+                * decrements from zero it goes to 0xffff).  num_samples is a
+                * 16 bit variable, so it will roll over in a similar fashion
+                * to the hardware counter.  Work it out, and this is what you
+                * get. */
                num_samples = -hw_counter - devpriv->adc_count;
        }
        /*  check if we only need some of the points */
index bb2883c83afaa010b713e51fc96ff346208b824b..958c0d4aae5c0acabbbea3f6623dd9e173a45e0b 100644 (file)
@@ -607,11 +607,7 @@ static int dmm32at_attach(struct comedi_device *dev,
 
        /* Digital I/O subdevice */
        s = &dev->subdevices[2];
-       ret = subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
-       if (ret)
-               return ret;
-
-       return 0;
+       return subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
 }
 
 static struct comedi_driver dmm32at_driver = {
index e1f493241cd6434e631f40f9c5f8a42adeedff19..55cae61458cb975a2d3b3f5abf98e04611e021cb 100644 (file)
@@ -136,11 +136,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        s->range_table  = &range_fl512;
        s->insn_write   = fl512_ao_insn_write;
 
-       ret = comedi_alloc_subdev_readback(s);
-       if (ret)
-               return ret;
-
-       return 0;
+       return comedi_alloc_subdev_readback(s);
 }
 
 static struct comedi_driver fl512_driver = {
index a8f3ca48784bcba8160c7a23be8ffc06686c6e79..15a53204a36a5a579745e2ea78c5339289911f05 100644 (file)
@@ -1,43 +1,41 @@
 /*
  comedi/drivers/me4000.c
  Source code for the Meilhaus ME-4000 board family.
-
  COMEDI - Linux Control and Measurement Device Interface
  Copyright (C) 2000 David A. Schleef <ds@schleef.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.
me4000.c
* Source code for the Meilhaus ME-4000 board family.
+ *
* COMEDI - Linux Control and Measurement Device Interface
* Copyright (C) 2000 David A. Schleef <ds@schleef.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.
  */
-/*
-Driver: me4000
-Description: Meilhaus ME-4000 series boards
-Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
-Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
-Updated: Mon, 18 Mar 2002 15:34:01 -0800
-Status: broken (no support for loading firmware)
-
-Supports:
-
-    - Analog Input
-    - Analog Output
-    - Digital I/O
-    - Counter
-
-Configuration Options: not applicable, uses PCI auto config
-
-The firmware required by these boards is available in the
-comedi_nonfree_firmware tarball available from
-http://www.comedi.org.  However, the driver's support for
-loading the firmware through comedi_config is currently
-broken.
 
+/*
+ * Driver: me4000
+ * Description: Meilhaus ME-4000 series boards
+ * Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i,
+ *         ME-4680is
+ * Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
+ * Updated: Mon, 18 Mar 2002 15:34:01 -0800
+ * Status: untested
+ *
+ * Supports:
+ *     - Analog Input
+ *     - Analog Output
+ *     - Digital I/O
+ *     - Counter
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ *
+ * The firmware required by these boards is available in the
+ * comedi_nonfree_firmware tarball available from
+ * http://www.comedi.org.
  */
 
 #include <linux/module.h>
@@ -57,66 +55,61 @@ broken.
 #define ME4000_AO_CHAN(x)                      ((x) * 0x18)
 
 #define ME4000_AO_CTRL_REG(x)                  (0x00 + ME4000_AO_CHAN(x))
-#define ME4000_AO_CTRL_BIT_MODE_0              (1 << 0)
-#define ME4000_AO_CTRL_BIT_MODE_1              (1 << 1)
-#define ME4000_AO_CTRL_MASK_MODE               (3 << 0)
-#define ME4000_AO_CTRL_BIT_STOP                        (1 << 2)
-#define ME4000_AO_CTRL_BIT_ENABLE_FIFO         (1 << 3)
-#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG      (1 << 4)
-#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE                (1 << 5)
-#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP      (1 << 7)
-#define ME4000_AO_CTRL_BIT_ENABLE_DO           (1 << 8)
-#define ME4000_AO_CTRL_BIT_ENABLE_IRQ          (1 << 9)
-#define ME4000_AO_CTRL_BIT_RESET_IRQ           (1 << 10)
+#define ME4000_AO_CTRL_MODE_0                  BIT(0)
+#define ME4000_AO_CTRL_MODE_1                  BIT(1)
+#define ME4000_AO_CTRL_STOP                    BIT(2)
+#define ME4000_AO_CTRL_ENABLE_FIFO             BIT(3)
+#define ME4000_AO_CTRL_ENABLE_EX_TRIG          BIT(4)
+#define ME4000_AO_CTRL_EX_TRIG_EDGE            BIT(5)
+#define ME4000_AO_CTRL_IMMEDIATE_STOP          BIT(7)
+#define ME4000_AO_CTRL_ENABLE_DO               BIT(8)
+#define ME4000_AO_CTRL_ENABLE_IRQ              BIT(9)
+#define ME4000_AO_CTRL_RESET_IRQ               BIT(10)
 #define ME4000_AO_STATUS_REG(x)                        (0x04 + ME4000_AO_CHAN(x))
-#define ME4000_AO_STATUS_BIT_FSM               (1 << 0)
-#define ME4000_AO_STATUS_BIT_FF                        (1 << 1)
-#define ME4000_AO_STATUS_BIT_HF                        (1 << 2)
-#define ME4000_AO_STATUS_BIT_EF                        (1 << 3)
+#define ME4000_AO_STATUS_FSM                   BIT(0)
+#define ME4000_AO_STATUS_FF                    BIT(1)
+#define ME4000_AO_STATUS_HF                    BIT(2)
+#define ME4000_AO_STATUS_EF                    BIT(3)
 #define ME4000_AO_FIFO_REG(x)                  (0x08 + ME4000_AO_CHAN(x))
 #define ME4000_AO_SINGLE_REG(x)                        (0x0c + ME4000_AO_CHAN(x))
 #define ME4000_AO_TIMER_REG(x)                 (0x10 + ME4000_AO_CHAN(x))
 #define ME4000_AI_CTRL_REG                     0x74
 #define ME4000_AI_STATUS_REG                   0x74
-#define ME4000_AI_CTRL_BIT_MODE_0              (1 << 0)
-#define ME4000_AI_CTRL_BIT_MODE_1              (1 << 1)
-#define ME4000_AI_CTRL_BIT_MODE_2              (1 << 2)
-#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD         (1 << 3)
-#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP      (1 << 4)
-#define ME4000_AI_CTRL_BIT_STOP                        (1 << 5)
-#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO                (1 << 6)
-#define ME4000_AI_CTRL_BIT_DATA_FIFO           (1 << 7)
-#define ME4000_AI_CTRL_BIT_FULLSCALE           (1 << 8)
-#define ME4000_AI_CTRL_BIT_OFFSET              (1 << 9)
-#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG      (1 << 10)
-#define ME4000_AI_CTRL_BIT_EX_TRIG             (1 << 11)
-#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING     (1 << 12)
-#define ME4000_AI_CTRL_BIT_EX_IRQ              (1 << 13)
-#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET                (1 << 14)
-#define ME4000_AI_CTRL_BIT_LE_IRQ              (1 << 15)
-#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET                (1 << 16)
-#define ME4000_AI_CTRL_BIT_HF_IRQ              (1 << 17)
-#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET                (1 << 18)
-#define ME4000_AI_CTRL_BIT_SC_IRQ              (1 << 19)
-#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET                (1 << 20)
-#define ME4000_AI_CTRL_BIT_SC_RELOAD           (1 << 21)
-#define ME4000_AI_STATUS_BIT_EF_CHANNEL                (1 << 22)
-#define ME4000_AI_STATUS_BIT_HF_CHANNEL                (1 << 23)
-#define ME4000_AI_STATUS_BIT_FF_CHANNEL                (1 << 24)
-#define ME4000_AI_STATUS_BIT_EF_DATA           (1 << 25)
-#define ME4000_AI_STATUS_BIT_HF_DATA           (1 << 26)
-#define ME4000_AI_STATUS_BIT_FF_DATA           (1 << 27)
-#define ME4000_AI_STATUS_BIT_LE                        (1 << 28)
-#define ME4000_AI_STATUS_BIT_FSM               (1 << 29)
-#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH                (1 << 31)
+#define ME4000_AI_CTRL_MODE_0                  BIT(0)
+#define ME4000_AI_CTRL_MODE_1                  BIT(1)
+#define ME4000_AI_CTRL_MODE_2                  BIT(2)
+#define ME4000_AI_CTRL_SAMPLE_HOLD             BIT(3)
+#define ME4000_AI_CTRL_IMMEDIATE_STOP          BIT(4)
+#define ME4000_AI_CTRL_STOP                    BIT(5)
+#define ME4000_AI_CTRL_CHANNEL_FIFO            BIT(6)
+#define ME4000_AI_CTRL_DATA_FIFO               BIT(7)
+#define ME4000_AI_CTRL_FULLSCALE               BIT(8)
+#define ME4000_AI_CTRL_OFFSET                  BIT(9)
+#define ME4000_AI_CTRL_EX_TRIG_ANALOG          BIT(10)
+#define ME4000_AI_CTRL_EX_TRIG                 BIT(11)
+#define ME4000_AI_CTRL_EX_TRIG_FALLING         BIT(12)
+#define ME4000_AI_CTRL_EX_IRQ                  BIT(13)
+#define ME4000_AI_CTRL_EX_IRQ_RESET            BIT(14)
+#define ME4000_AI_CTRL_LE_IRQ                  BIT(15)
+#define ME4000_AI_CTRL_LE_IRQ_RESET            BIT(16)
+#define ME4000_AI_CTRL_HF_IRQ                  BIT(17)
+#define ME4000_AI_CTRL_HF_IRQ_RESET            BIT(18)
+#define ME4000_AI_CTRL_SC_IRQ                  BIT(19)
+#define ME4000_AI_CTRL_SC_IRQ_RESET            BIT(20)
+#define ME4000_AI_CTRL_SC_RELOAD               BIT(21)
+#define ME4000_AI_STATUS_EF_CHANNEL            BIT(22)
+#define ME4000_AI_STATUS_HF_CHANNEL            BIT(23)
+#define ME4000_AI_STATUS_FF_CHANNEL            BIT(24)
+#define ME4000_AI_STATUS_EF_DATA               BIT(25)
+#define ME4000_AI_STATUS_HF_DATA               BIT(26)
+#define ME4000_AI_STATUS_FF_DATA               BIT(27)
+#define ME4000_AI_STATUS_LE                    BIT(28)
+#define ME4000_AI_STATUS_FSM                   BIT(29)
+#define ME4000_AI_CTRL_EX_TRIG_BOTH            BIT(31)
 #define ME4000_AI_CHANNEL_LIST_REG             0x78
-#define ME4000_AI_LIST_INPUT_SINGLE_ENDED      (0 << 5)
-#define ME4000_AI_LIST_INPUT_DIFFERENTIAL      (1 << 5)
-#define ME4000_AI_LIST_RANGE_BIPOLAR_10                (0 << 6)
-#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5       (1 << 6)
-#define ME4000_AI_LIST_RANGE_UNIPOLAR_10       (2 << 6)
-#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5      (3 << 6)
-#define ME4000_AI_LIST_LAST_ENTRY              (1 << 8)
+#define ME4000_AI_LIST_INPUT_DIFFERENTIAL      BIT(5)
+#define ME4000_AI_LIST_RANGE(x)                        ((3 - ((x) & 3)) << 6)
+#define ME4000_AI_LIST_LAST_ENTRY              BIT(8)
 #define ME4000_AI_DATA_REG                     0x7c
 #define ME4000_AI_CHAN_TIMER_REG               0x80
 #define ME4000_AI_CHAN_PRE_TIMER_REG           0x84
@@ -126,14 +119,14 @@ broken.
 #define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG      0x94
 #define ME4000_AI_START_REG                    0x98
 #define ME4000_IRQ_STATUS_REG                  0x9c
-#define ME4000_IRQ_STATUS_BIT_EX               (1 << 0)
-#define ME4000_IRQ_STATUS_BIT_LE               (1 << 1)
-#define ME4000_IRQ_STATUS_BIT_AI_HF            (1 << 2)
-#define ME4000_IRQ_STATUS_BIT_AO_0_HF          (1 << 3)
-#define ME4000_IRQ_STATUS_BIT_AO_1_HF          (1 << 4)
-#define ME4000_IRQ_STATUS_BIT_AO_2_HF          (1 << 5)
-#define ME4000_IRQ_STATUS_BIT_AO_3_HF          (1 << 6)
-#define ME4000_IRQ_STATUS_BIT_SC               (1 << 7)
+#define ME4000_IRQ_STATUS_EX                   BIT(0)
+#define ME4000_IRQ_STATUS_LE                   BIT(1)
+#define ME4000_IRQ_STATUS_AI_HF                        BIT(2)
+#define ME4000_IRQ_STATUS_AO_0_HF              BIT(3)
+#define ME4000_IRQ_STATUS_AO_1_HF              BIT(4)
+#define ME4000_IRQ_STATUS_AO_2_HF              BIT(5)
+#define ME4000_IRQ_STATUS_AO_3_HF              BIT(6)
+#define ME4000_IRQ_STATUS_SC                   BIT(7)
 #define ME4000_DIO_PORT_0_REG                  0xa0
 #define ME4000_DIO_PORT_1_REG                  0xa4
 #define ME4000_DIO_PORT_2_REG                  0xa8
@@ -141,20 +134,20 @@ broken.
 #define ME4000_DIO_DIR_REG                     0xb0
 #define ME4000_AO_LOADSETREG_XX                        0xb4
 #define ME4000_DIO_CTRL_REG                    0xb8
-#define ME4000_DIO_CTRL_BIT_MODE_0             (1 << 0)
-#define ME4000_DIO_CTRL_BIT_MODE_1             (1 << 1)
-#define ME4000_DIO_CTRL_BIT_MODE_2             (1 << 2)
-#define ME4000_DIO_CTRL_BIT_MODE_3             (1 << 3)
-#define ME4000_DIO_CTRL_BIT_MODE_4             (1 << 4)
-#define ME4000_DIO_CTRL_BIT_MODE_5             (1 << 5)
-#define ME4000_DIO_CTRL_BIT_MODE_6             (1 << 6)
-#define ME4000_DIO_CTRL_BIT_MODE_7             (1 << 7)
-#define ME4000_DIO_CTRL_BIT_FUNCTION_0         (1 << 8)
-#define ME4000_DIO_CTRL_BIT_FUNCTION_1         (1 << 9)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0                (1 << 10)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1                (1 << 11)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2                (1 << 12)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3                (1 << 13)
+#define ME4000_DIO_CTRL_MODE_0                 BIT(0)
+#define ME4000_DIO_CTRL_MODE_1                 BIT(1)
+#define ME4000_DIO_CTRL_MODE_2                 BIT(2)
+#define ME4000_DIO_CTRL_MODE_3                 BIT(3)
+#define ME4000_DIO_CTRL_MODE_4                 BIT(4)
+#define ME4000_DIO_CTRL_MODE_5                 BIT(5)
+#define ME4000_DIO_CTRL_MODE_6                 BIT(6)
+#define ME4000_DIO_CTRL_MODE_7                 BIT(7)
+#define ME4000_DIO_CTRL_FUNCTION_0             BIT(8)
+#define ME4000_DIO_CTRL_FUNCTION_1             BIT(9)
+#define ME4000_DIO_CTRL_FIFO_HIGH_0            BIT(10)
+#define ME4000_DIO_CTRL_FIFO_HIGH_1            BIT(11)
+#define ME4000_DIO_CTRL_FIFO_HIGH_2            BIT(12)
+#define ME4000_DIO_CTRL_FIFO_HIGH_3            BIT(13)
 #define ME4000_AO_DEMUX_ADJUST_REG             0xbc
 #define ME4000_AO_DEMUX_ADJUST_VALUE           0x4c
 #define ME4000_AI_SAMPLE_COUNTER_REG           0xc0
@@ -166,8 +159,12 @@ broken.
 
 #define ME4000_AI_CHANNEL_LIST_COUNT           1024
 
-struct me4000_info {
+struct me4000_private {
        unsigned long plx_regbase;
+       unsigned int ai_ctrl_mode;
+       unsigned int ai_init_ticks;
+       unsigned int ai_scan_ticks;
+       unsigned int ai_chan_ticks;
 };
 
 enum me4000_boardid {
@@ -188,134 +185,126 @@ enum me4000_boardid {
 
 struct me4000_board {
        const char *name;
-       int ao_nchan;
-       int ao_fifo;
        int ai_nchan;
-       int ai_diff_nchan;
-       int ai_sh_nchan;
-       int ex_trig_analog;
-       int dio_nchan;
-       int has_counter;
+       unsigned int can_do_diff_ai:1;
+       unsigned int can_do_sh_ai:1;    /* sample & hold (8 channels) */
+       unsigned int ex_trig_analog:1;
+       unsigned int has_ao:1;
+       unsigned int has_ao_fifo:1;
+       unsigned int has_counter:1;
 };
 
 static const struct me4000_board me4000_boards[] = {
        [BOARD_ME4650] = {
                .name           = "ME-4650",
                .ai_nchan       = 16,
-               .dio_nchan      = 32,
        },
        [BOARD_ME4660] = {
                .name           = "ME-4660",
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .dio_nchan      = 32,
+               .can_do_diff_ai = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4660I] = {
                .name           = "ME-4660i",
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .dio_nchan      = 32,
+               .can_do_diff_ai = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4660S] = {
                .name           = "ME-4660s",
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .ai_sh_nchan    = 8,
-               .dio_nchan      = 32,
+               .can_do_diff_ai = 1,
+               .can_do_sh_ai   = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4660IS] = {
                .name           = "ME-4660is",
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .ai_sh_nchan    = 8,
-               .dio_nchan      = 32,
+               .can_do_diff_ai = 1,
+               .can_do_sh_ai   = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4670] = {
                .name           = "ME-4670",
-               .ao_nchan       = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
+               .can_do_diff_ai = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4670I] = {
                .name           = "ME-4670i",
-               .ao_nchan       = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
+               .can_do_diff_ai = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4670S] = {
                .name           = "ME-4670s",
-               .ao_nchan       = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .ai_sh_nchan    = 8,
+               .can_do_diff_ai = 1,
+               .can_do_sh_ai   = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4670IS] = {
                .name           = "ME-4670is",
-               .ao_nchan       = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .ai_sh_nchan    = 8,
+               .can_do_diff_ai = 1,
+               .can_do_sh_ai   = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4680] = {
                .name           = "ME-4680",
-               .ao_nchan       = 4,
-               .ao_fifo        = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
+               .can_do_diff_ai = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
+               .has_ao_fifo    = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4680I] = {
                .name           = "ME-4680i",
-               .ao_nchan       = 4,
-               .ao_fifo        = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
+               .can_do_diff_ai = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
+               .has_ao_fifo    = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4680S] = {
                .name           = "ME-4680s",
-               .ao_nchan       = 4,
-               .ao_fifo        = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .ai_sh_nchan    = 8,
+               .can_do_diff_ai = 1,
+               .can_do_sh_ai   = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
+               .has_ao_fifo    = 1,
                .has_counter    = 1,
        },
        [BOARD_ME4680IS] = {
                .name           = "ME-4680is",
-               .ao_nchan       = 4,
-               .ao_fifo        = 4,
                .ai_nchan       = 32,
-               .ai_diff_nchan  = 16,
-               .ai_sh_nchan    = 8,
+               .can_do_diff_ai = 1,
+               .can_do_sh_ai   = 1,
                .ex_trig_analog = 1,
-               .dio_nchan      = 32,
+               .has_ao         = 1,
+               .has_ao_fifo    = 1,
                .has_counter    = 1,
        },
 };
 
+/*
+ * NOTE: the ranges here are inverted compared to the values
+ * written to the ME4000_AI_CHANNEL_LIST_REG,
+ *
+ * The ME4000_AI_LIST_RANGE() macro handles the inversion.
+ */
 static const struct comedi_lrange me4000_ai_range = {
        4, {
                UNI_RANGE(2.5),
@@ -330,7 +319,7 @@ static int me4000_xilinx_download(struct comedi_device *dev,
                                  unsigned long context)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-       struct me4000_info *info = dev->private;
+       struct me4000_private *devpriv = dev->private;
        unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
        unsigned int file_length;
        unsigned int val;
@@ -343,42 +332,42 @@ static int me4000_xilinx_download(struct comedi_device *dev,
         * Set PLX local interrupt 2 polarity to high.
         * Interrupt is thrown by init pin of xilinx.
         */
-       outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR);
+       outl(PLX9052_INTCSR_LI2POL, devpriv->plx_regbase + PLX9052_INTCSR);
 
        /* Set /CS and /WRITE of the Xilinx */
-       val = inl(info->plx_regbase + PLX9052_CNTRL);
+       val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
        val |= PLX9052_CNTRL_UIO2_DATA;
-       outl(val, info->plx_regbase + PLX9052_CNTRL);
+       outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
 
        /* Init Xilinx with CS1 */
        inb(xilinx_iobase + 0xC8);
 
        /* Wait until /INIT pin is set */
-       udelay(20);
-       val = inl(info->plx_regbase + PLX9052_INTCSR);
+       usleep_range(20, 1000);
+       val = inl(devpriv->plx_regbase + PLX9052_INTCSR);
        if (!(val & PLX9052_INTCSR_LI2STAT)) {
                dev_err(dev->class_dev, "Can't init Xilinx\n");
                return -EIO;
        }
 
        /* Reset /CS and /WRITE of the Xilinx */
-       val = inl(info->plx_regbase + PLX9052_CNTRL);
+       val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
        val &= ~PLX9052_CNTRL_UIO2_DATA;
-       outl(val, info->plx_regbase + PLX9052_CNTRL);
+       outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
 
        /* Download Xilinx firmware */
        file_length = (((unsigned int)data[0] & 0xff) << 24) +
                      (((unsigned int)data[1] & 0xff) << 16) +
                      (((unsigned int)data[2] & 0xff) << 8) +
                      ((unsigned int)data[3] & 0xff);
-       udelay(10);
+       usleep_range(10, 1000);
 
        for (i = 0; i < file_length; i++) {
                outb(data[16 + i], xilinx_iobase);
-               udelay(10);
+               usleep_range(10, 1000);
 
                /* Check if BUSY flag is low */
-               val = inl(info->plx_regbase + PLX9052_CNTRL);
+               val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
                if (val & PLX9052_CNTRL_UIO1_DATA) {
                        dev_err(dev->class_dev,
                                "Xilinx is still busy (i = %d)\n", i);
@@ -387,7 +376,7 @@ static int me4000_xilinx_download(struct comedi_device *dev,
        }
 
        /* If done flag is high download was successful */
-       val = inl(info->plx_regbase + PLX9052_CNTRL);
+       val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
        if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
                dev_err(dev->class_dev, "DONE flag is not set\n");
                dev_err(dev->class_dev, "Download not successful\n");
@@ -395,44 +384,53 @@ static int me4000_xilinx_download(struct comedi_device *dev,
        }
 
        /* Set /CS and /WRITE */
-       val = inl(info->plx_regbase + PLX9052_CNTRL);
+       val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
        val |= PLX9052_CNTRL_UIO2_DATA;
-       outl(val, info->plx_regbase + PLX9052_CNTRL);
+       outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
 
        return 0;
 }
 
+static void me4000_ai_reset(struct comedi_device *dev)
+{
+       unsigned int ctrl;
+
+       /* Stop any running conversion */
+       ctrl = inl(dev->iobase + ME4000_AI_CTRL_REG);
+       ctrl |= ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP;
+       outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
+
+       /* Clear the control register */
+       outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
+}
+
 static void me4000_reset(struct comedi_device *dev)
 {
-       struct me4000_info *info = dev->private;
+       struct me4000_private *devpriv = dev->private;
        unsigned int val;
        int chan;
 
-       /* Make a hardware reset */
-       val = inl(info->plx_regbase + PLX9052_CNTRL);
+       /* Disable interrupts on the PLX */
+       outl(0, devpriv->plx_regbase + PLX9052_INTCSR);
+
+       /* Software reset the PLX */
+       val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
        val |= PLX9052_CNTRL_PCI_RESET;
-       outl(val, info->plx_regbase + PLX9052_CNTRL);
+       outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
        val &= ~PLX9052_CNTRL_PCI_RESET;
-       outl(val, info->plx_regbase + PLX9052_CNTRL);
+       outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
 
        /* 0x8000 to the DACs means an output voltage of 0V */
        for (chan = 0; chan < 4; chan++)
                outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
 
-       /* Set both stop bits in the analog input control register */
-       outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
-            dev->iobase + ME4000_AI_CTRL_REG);
+       me4000_ai_reset(dev);
 
        /* Set both stop bits in the analog output control register */
-       val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
+       val = ME4000_AO_CTRL_IMMEDIATE_STOP | ME4000_AO_CTRL_STOP;
        for (chan = 0; chan < 4; chan++)
                outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
 
-       /* Enable interrupts on the PLX */
-       outl(PLX9052_INTCSR_LI1ENAB |
-            PLX9052_INTCSR_LI1POL |
-            PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR);
-
        /* Set the adustment register for AO demux */
        outl(ME4000_AO_DEMUX_ADJUST_VALUE,
             dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
@@ -445,96 +443,68 @@ static void me4000_reset(struct comedi_device *dev)
                outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
 }
 
-/*=============================================================================
-  Analog input section
-  ===========================================================================*/
-
-static int me4000_ai_insn_read(struct comedi_device *dev,
-                              struct comedi_subdevice *subdevice,
-                              struct comedi_insn *insn, unsigned int *data)
+static unsigned int me4000_ai_get_sample(struct comedi_device *dev,
+                                        struct comedi_subdevice *s)
 {
-       const struct me4000_board *board = dev->board_ptr;
-       int chan = CR_CHAN(insn->chanspec);
-       int rang = CR_RANGE(insn->chanspec);
-       int aref = CR_AREF(insn->chanspec);
+       unsigned int val;
 
-       unsigned int entry = 0;
-       unsigned int tmp;
-       unsigned int lval;
+       /* read two's complement value and munge to offset binary */
+       val = inl(dev->iobase + ME4000_AI_DATA_REG);
+       return comedi_offset_munge(s, val);
+}
 
-       if (insn->n == 0) {
+static int me4000_ai_eoc(struct comedi_device *dev,
+                        struct comedi_subdevice *s,
+                        struct comedi_insn *insn,
+                        unsigned long context)
+{
+       unsigned int status;
+
+       status = inl(dev->iobase + ME4000_AI_STATUS_REG);
+       if (status & ME4000_AI_STATUS_EF_DATA)
                return 0;
-       } else if (insn->n > 1) {
-               dev_err(dev->class_dev, "Invalid instruction length %d\n",
-                       insn->n);
-               return -EINVAL;
-       }
+       return -EBUSY;
+}
 
-       switch (rang) {
-       case 0:
-               entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
-               break;
-       case 1:
-               entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
-               break;
-       case 2:
-               entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
-               break;
-       case 3:
-               entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
-               break;
-       default:
-               dev_err(dev->class_dev, "Invalid range specified\n");
-               return -EINVAL;
-       }
+static int me4000_ai_insn_read(struct comedi_device *dev,
+                              struct comedi_subdevice *s,
+                              struct comedi_insn *insn,
+                              unsigned int *data)
+{
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int range = CR_RANGE(insn->chanspec);
+       unsigned int aref = CR_AREF(insn->chanspec);
+       unsigned int entry;
+       int ret = 0;
+       int i;
 
-       switch (aref) {
-       case AREF_GROUND:
-       case AREF_COMMON:
-               if (chan >= board->ai_nchan) {
+       entry = chan | ME4000_AI_LIST_RANGE(range);
+       if (aref == AREF_DIFF) {
+               if (!(s->subdev_flags & SDF_DIFF)) {
                        dev_err(dev->class_dev,
-                               "Analog input is not available\n");
+                               "Differential inputs are not available\n");
                        return -EINVAL;
                }
-               entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
-               break;
 
-       case AREF_DIFF:
-               if (rang == 0 || rang == 1) {
+               if (!comedi_range_is_bipolar(s, range)) {
                        dev_err(dev->class_dev,
                                "Range must be bipolar when aref = diff\n");
                        return -EINVAL;
                }
 
-               if (chan >= board->ai_diff_nchan) {
+               if (chan >= (s->n_chan / 2)) {
                        dev_err(dev->class_dev,
                                "Analog input is not available\n");
                        return -EINVAL;
                }
-               entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
-               break;
-       default:
-               dev_err(dev->class_dev, "Invalid aref specified\n");
-               return -EINVAL;
+               entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
        }
 
        entry |= ME4000_AI_LIST_LAST_ENTRY;
 
-       /* Clear channel list, data fifo and both stop bits */
-       tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
-       tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
-                ME4000_AI_CTRL_BIT_DATA_FIFO |
-                ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
-       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
-       /* Set the acquisition mode to single */
-       tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
-                ME4000_AI_CTRL_BIT_MODE_2);
-       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
-       /* Enable channel list and data fifo */
-       tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
-       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+       /* Enable channel list and data fifo for single acquisition mode */
+       outl(ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO,
+            dev->iobase + ME4000_AI_CTRL_REG);
 
        /* Generate channel list entry */
        outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
@@ -543,36 +513,29 @@ static int me4000_ai_insn_read(struct comedi_device *dev,
        outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
        outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
 
-       /* Start conversion by dummy read */
-       inl(dev->iobase + ME4000_AI_START_REG);
+       for (i = 0; i < insn->n; i++) {
+               unsigned int val;
 
-       /* Wait until ready */
-       udelay(10);
-       if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
-            ME4000_AI_STATUS_BIT_EF_DATA)) {
-               dev_err(dev->class_dev, "Value not available after wait\n");
-               return -EIO;
+               /* start conversion by dummy read */
+               inl(dev->iobase + ME4000_AI_START_REG);
+
+               ret = comedi_timeout(dev, s, insn, me4000_ai_eoc, 0);
+               if (ret)
+                       break;
+
+               val = me4000_ai_get_sample(dev, s);
+               data[i] = comedi_offset_munge(s, val);
        }
 
-       /* Read value from data fifo */
-       lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
-       data[0] = lval ^ 0x8000;
+       me4000_ai_reset(dev);
 
-       return 1;
+       return ret ? ret : insn->n;
 }
 
 static int me4000_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
-       unsigned int tmp;
-
-       /* Stop any running conversion */
-       tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
-       tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
-       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
-       /* Clear the control register */
-       outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
+       me4000_ai_reset(dev);
 
        return 0;
 }
@@ -581,8 +544,6 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev,
                                    struct comedi_subdevice *s,
                                    struct comedi_cmd *cmd)
 {
-       const struct me4000_board *board = dev->board_ptr;
-       unsigned int max_diff_chan = board->ai_diff_nchan;
        unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
        int i;
 
@@ -598,7 +559,13 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev,
                }
 
                if (aref == AREF_DIFF) {
-                       if (chan >= max_diff_chan) {
+                       if (!(s->subdev_flags & SDF_DIFF)) {
+                               dev_err(dev->class_dev,
+                                       "Differential inputs are not available\n");
+                               return -EINVAL;
+                       }
+
+                       if (chan >= (s->n_chan / 2)) {
                                dev_dbg(dev->class_dev,
                                        "Channel number to high\n");
                                return -EINVAL;
@@ -615,202 +582,127 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev,
        return 0;
 }
 
-static int ai_round_cmd_args(struct comedi_device *dev,
-                            struct comedi_subdevice *s,
-                            struct comedi_cmd *cmd,
-                            unsigned int *init_ticks,
-                            unsigned int *scan_ticks, unsigned int *chan_ticks)
+static void me4000_ai_round_cmd_args(struct comedi_device *dev,
+                                    struct comedi_subdevice *s,
+                                    struct comedi_cmd *cmd)
 {
+       struct me4000_private *devpriv = dev->private;
        int rest;
 
-       *init_ticks = 0;
-       *scan_ticks = 0;
-       *chan_ticks = 0;
+       devpriv->ai_init_ticks = 0;
+       devpriv->ai_scan_ticks = 0;
+       devpriv->ai_chan_ticks = 0;
 
        if (cmd->start_arg) {
-               *init_ticks = (cmd->start_arg * 33) / 1000;
+               devpriv->ai_init_ticks = (cmd->start_arg * 33) / 1000;
                rest = (cmd->start_arg * 33) % 1000;
 
                if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
                        if (rest > 33)
-                               (*init_ticks)++;
+                               devpriv->ai_init_ticks++;
                } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
                        if (rest)
-                               (*init_ticks)++;
+                               devpriv->ai_init_ticks++;
                }
        }
 
        if (cmd->scan_begin_arg) {
-               *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
+               devpriv->ai_scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
                rest = (cmd->scan_begin_arg * 33) % 1000;
 
                if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
                        if (rest > 33)
-                               (*scan_ticks)++;
+                               devpriv->ai_scan_ticks++;
                } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
                        if (rest)
-                               (*scan_ticks)++;
+                               devpriv->ai_scan_ticks++;
                }
        }
 
        if (cmd->convert_arg) {
-               *chan_ticks = (cmd->convert_arg * 33) / 1000;
+               devpriv->ai_chan_ticks = (cmd->convert_arg * 33) / 1000;
                rest = (cmd->convert_arg * 33) % 1000;
 
                if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
                        if (rest > 33)
-                               (*chan_ticks)++;
+                               devpriv->ai_chan_ticks++;
                } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
                        if (rest)
-                               (*chan_ticks)++;
+                               devpriv->ai_chan_ticks++;
                }
        }
-
-       return 0;
-}
-
-static void ai_write_timer(struct comedi_device *dev,
-                          unsigned int init_ticks,
-                          unsigned int scan_ticks, unsigned int chan_ticks)
-{
-       outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
-       outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
-
-       if (scan_ticks) {
-               outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
-               outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
-       }
-
-       outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
-       outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
 }
 
-static int ai_write_chanlist(struct comedi_device *dev,
-                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
+static void me4000_ai_write_chanlist(struct comedi_device *dev,
+                                    struct comedi_subdevice *s,
+                                    struct comedi_cmd *cmd)
 {
-       unsigned int entry;
-       unsigned int chan;
-       unsigned int rang;
-       unsigned int aref;
        int i;
 
        for (i = 0; i < cmd->chanlist_len; i++) {
-               chan = CR_CHAN(cmd->chanlist[i]);
-               rang = CR_RANGE(cmd->chanlist[i]);
-               aref = CR_AREF(cmd->chanlist[i]);
-
-               entry = chan;
+               unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+               unsigned int range = CR_RANGE(cmd->chanlist[i]);
+               unsigned int aref = CR_AREF(cmd->chanlist[i]);
+               unsigned int entry;
 
-               if (rang == 0)
-                       entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
-               else if (rang == 1)
-                       entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
-               else if (rang == 2)
-                       entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
-               else
-                       entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
+               entry = chan | ME4000_AI_LIST_RANGE(range);
 
                if (aref == AREF_DIFF)
                        entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
-               else
-                       entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
+
+               if (i == (cmd->chanlist_len - 1))
+                       entry |= ME4000_AI_LIST_LAST_ENTRY;
 
                outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
        }
-
-       return 0;
 }
 
-static int ai_prepare(struct comedi_device *dev,
-                     struct comedi_subdevice *s,
-                     struct comedi_cmd *cmd,
-                     unsigned int init_ticks,
-                     unsigned int scan_ticks, unsigned int chan_ticks)
+static int me4000_ai_do_cmd(struct comedi_device *dev,
+                           struct comedi_subdevice *s)
 {
-       unsigned int tmp = 0;
+       struct me4000_private *devpriv = dev->private;
+       struct comedi_cmd *cmd = &s->async->cmd;
+       unsigned int ctrl;
 
        /* Write timer arguments */
-       ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
+       outl(devpriv->ai_init_ticks - 1,
+            dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
+       outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
+
+       if (devpriv->ai_scan_ticks) {
+               outl(devpriv->ai_scan_ticks - 1,
+                    dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
+               outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
+       }
 
-       /* Reset control register */
-       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+       outl(devpriv->ai_chan_ticks - 1,
+            dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
+       outl(devpriv->ai_chan_ticks - 1,
+            dev->iobase + ME4000_AI_CHAN_TIMER_REG);
 
        /* Start sources */
-       if ((cmd->start_src == TRIG_EXT &&
-            cmd->scan_begin_src == TRIG_TIMER &&
-            cmd->convert_src == TRIG_TIMER) ||
-           (cmd->start_src == TRIG_EXT &&
-            cmd->scan_begin_src == TRIG_FOLLOW &&
-            cmd->convert_src == TRIG_TIMER)) {
-               tmp = ME4000_AI_CTRL_BIT_MODE_1 |
-                   ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
-                   ME4000_AI_CTRL_BIT_DATA_FIFO;
-       } else if (cmd->start_src == TRIG_EXT &&
-                  cmd->scan_begin_src == TRIG_EXT &&
-                  cmd->convert_src == TRIG_TIMER) {
-               tmp = ME4000_AI_CTRL_BIT_MODE_2 |
-                   ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
-                   ME4000_AI_CTRL_BIT_DATA_FIFO;
-       } else if (cmd->start_src == TRIG_EXT &&
-                  cmd->scan_begin_src == TRIG_EXT &&
-                  cmd->convert_src == TRIG_EXT) {
-               tmp = ME4000_AI_CTRL_BIT_MODE_0 |
-                   ME4000_AI_CTRL_BIT_MODE_1 |
-                   ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
-                   ME4000_AI_CTRL_BIT_DATA_FIFO;
-       } else {
-               tmp = ME4000_AI_CTRL_BIT_MODE_0 |
-                   ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
-                   ME4000_AI_CTRL_BIT_DATA_FIFO;
-       }
+       ctrl = devpriv->ai_ctrl_mode |
+              ME4000_AI_CTRL_CHANNEL_FIFO |
+              ME4000_AI_CTRL_DATA_FIFO;
 
        /* Stop triggers */
        if (cmd->stop_src == TRIG_COUNT) {
                outl(cmd->chanlist_len * cmd->stop_arg,
                     dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
-               tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
+               ctrl |= ME4000_AI_CTRL_SC_IRQ;
        } else if (cmd->stop_src == TRIG_NONE &&
                   cmd->scan_end_src == TRIG_COUNT) {
                outl(cmd->scan_end_arg,
                     dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
-               tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
-       } else {
-               tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
+               ctrl |= ME4000_AI_CTRL_SC_IRQ;
        }
+       ctrl |= ME4000_AI_CTRL_HF_IRQ;
 
        /* Write the setup to the control register */
-       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+       outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
 
        /* Write the channel list */
-       ai_write_chanlist(dev, s, cmd);
-
-       return 0;
-}
-
-static int me4000_ai_do_cmd(struct comedi_device *dev,
-                           struct comedi_subdevice *s)
-{
-       int err;
-       unsigned int init_ticks = 0;
-       unsigned int scan_ticks = 0;
-       unsigned int chan_ticks = 0;
-       struct comedi_cmd *cmd = &s->async->cmd;
-
-       /* Reset the analog input */
-       err = me4000_ai_cancel(dev, s);
-       if (err)
-               return err;
-
-       /* Round the timer arguments */
-       err = ai_round_cmd_args(dev,
-                               s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
-       if (err)
-               return err;
-
-       /* Prepare the AI for acquisition */
-       err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
-       if (err)
-               return err;
+       me4000_ai_write_chanlist(dev, s, cmd);
 
        /* Start acquistion by dummy read */
        inl(dev->iobase + ME4000_AI_START_REG);
@@ -822,14 +714,9 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                                 struct comedi_subdevice *s,
                                 struct comedi_cmd *cmd)
 {
-       unsigned int init_ticks;
-       unsigned int chan_ticks;
-       unsigned int scan_ticks;
+       struct me4000_private *devpriv = dev->private;
        int err = 0;
 
-       /* Round the timer arguments */
-       ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
-
        /* Step 1 : check if triggers are trivially valid */
 
        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
@@ -857,21 +744,28 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
        if (cmd->start_src == TRIG_NOW &&
            cmd->scan_begin_src == TRIG_TIMER &&
            cmd->convert_src == TRIG_TIMER) {
+               devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
        } else if (cmd->start_src == TRIG_NOW &&
                   cmd->scan_begin_src == TRIG_FOLLOW &&
                   cmd->convert_src == TRIG_TIMER) {
+               devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_TIMER &&
                   cmd->convert_src == TRIG_TIMER) {
+               devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_FOLLOW &&
                   cmd->convert_src == TRIG_TIMER) {
+               devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_EXT &&
                   cmd->convert_src == TRIG_TIMER) {
+               devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_2;
        } else if (cmd->start_src == TRIG_EXT &&
                   cmd->scan_begin_src == TRIG_EXT &&
                   cmd->convert_src == TRIG_EXT) {
+               devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0 |
+                                       ME4000_AI_CTRL_MODE_1;
        } else {
                err |= -EINVAL;
        }
@@ -887,15 +781,19 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                cmd->chanlist_len = 1;
                err |= -EINVAL;
        }
-       if (init_ticks < 66) {
+
+       /* Round the timer arguments */
+       me4000_ai_round_cmd_args(dev, s, cmd);
+
+       if (devpriv->ai_init_ticks < 66) {
                cmd->start_arg = 2000;
                err |= -EINVAL;
        }
-       if (scan_ticks && scan_ticks < 67) {
+       if (devpriv->ai_scan_ticks && devpriv->ai_scan_ticks < 67) {
                cmd->scan_begin_arg = 2031;
                err |= -EINVAL;
        }
-       if (chan_ticks < 66) {
+       if (devpriv->ai_chan_ticks < 66) {
                cmd->convert_arg = 2000;
                err |= -EINVAL;
        }
@@ -915,17 +813,18 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
            cmd->scan_begin_src == TRIG_TIMER &&
            cmd->convert_src == TRIG_TIMER) {
                /* Check timer arguments */
-               if (init_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
                        cmd->start_arg = 2000;  /*  66 ticks at least */
                        err++;
                }
-               if (chan_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid convert arg\n");
                        cmd->convert_arg = 2000;        /*  66 ticks at least */
                        err++;
                }
-               if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+               if (devpriv->ai_scan_ticks <=
+                   cmd->chanlist_len * devpriv->ai_chan_ticks) {
                        dev_err(dev->class_dev, "Invalid scan end arg\n");
 
                        /*  At least one tick more */
@@ -936,12 +835,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                   cmd->scan_begin_src == TRIG_FOLLOW &&
                   cmd->convert_src == TRIG_TIMER) {
                /* Check timer arguments */
-               if (init_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
                        cmd->start_arg = 2000;  /*  66 ticks at least */
                        err++;
                }
-               if (chan_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid convert arg\n");
                        cmd->convert_arg = 2000;        /*  66 ticks at least */
                        err++;
@@ -950,17 +849,18 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                   cmd->scan_begin_src == TRIG_TIMER &&
                   cmd->convert_src == TRIG_TIMER) {
                /* Check timer arguments */
-               if (init_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
                        cmd->start_arg = 2000;  /*  66 ticks at least */
                        err++;
                }
-               if (chan_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid convert arg\n");
                        cmd->convert_arg = 2000;        /*  66 ticks at least */
                        err++;
                }
-               if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+               if (devpriv->ai_scan_ticks <=
+                   cmd->chanlist_len * devpriv->ai_chan_ticks) {
                        dev_err(dev->class_dev, "Invalid scan end arg\n");
 
                        /*  At least one tick more */
@@ -971,12 +871,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                   cmd->scan_begin_src == TRIG_FOLLOW &&
                   cmd->convert_src == TRIG_TIMER) {
                /* Check timer arguments */
-               if (init_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
                        cmd->start_arg = 2000;  /*  66 ticks at least */
                        err++;
                }
-               if (chan_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid convert arg\n");
                        cmd->convert_arg = 2000;        /*  66 ticks at least */
                        err++;
@@ -985,12 +885,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                   cmd->scan_begin_src == TRIG_EXT &&
                   cmd->convert_src == TRIG_TIMER) {
                /* Check timer arguments */
-               if (init_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
                        cmd->start_arg = 2000;  /*  66 ticks at least */
                        err++;
                }
-               if (chan_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid convert arg\n");
                        cmd->convert_arg = 2000;        /*  66 ticks at least */
                        err++;
@@ -999,7 +899,7 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev,
                   cmd->scan_begin_src == TRIG_EXT &&
                   cmd->convert_src == TRIG_EXT) {
                /* Check timer arguments */
-               if (init_ticks < ME4000_AI_MIN_TICKS) {
+               if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
                        dev_err(dev->class_dev, "Invalid start arg\n");
                        cmd->start_arg = 2000;  /*  66 ticks at least */
                        err++;
@@ -1039,103 +939,57 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
                return IRQ_NONE;
 
        if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
-           ME4000_IRQ_STATUS_BIT_AI_HF) {
+           ME4000_IRQ_STATUS_AI_HF) {
                /* Read status register to find out what happened */
-               tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
-
-               if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
-                   !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
-                   (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
-                       c = ME4000_AI_FIFO_COUNT;
-
-                       /*
-                        * FIFO overflow, so stop conversion
-                        * and disable all interrupts
-                        */
-                       tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
-                       tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
-                                ME4000_AI_CTRL_BIT_SC_IRQ);
-                       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
-                       s->async->events |= COMEDI_CB_ERROR;
+               tmp = inl(dev->iobase + ME4000_AI_STATUS_REG);
 
+               if (!(tmp & ME4000_AI_STATUS_FF_DATA) &&
+                   !(tmp & ME4000_AI_STATUS_HF_DATA) &&
+                   (tmp & ME4000_AI_STATUS_EF_DATA)) {
                        dev_err(dev->class_dev, "FIFO overflow\n");
-               } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
-                          && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
-                          && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+                       s->async->events |= COMEDI_CB_ERROR;
+                       c = ME4000_AI_FIFO_COUNT;
+               } else if ((tmp & ME4000_AI_STATUS_FF_DATA) &&
+                          !(tmp & ME4000_AI_STATUS_HF_DATA) &&
+                          (tmp & ME4000_AI_STATUS_EF_DATA)) {
                        c = ME4000_AI_FIFO_COUNT / 2;
                } else {
-                       dev_err(dev->class_dev,
-                               "Can't determine state of fifo\n");
-                       c = 0;
-
-                       /*
-                        * Undefined state, so stop conversion
-                        * and disable all interrupts
-                        */
-                       tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
-                       tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
-                                ME4000_AI_CTRL_BIT_SC_IRQ);
-                       outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
-                       s->async->events |= COMEDI_CB_ERROR;
-
                        dev_err(dev->class_dev, "Undefined FIFO state\n");
+                       s->async->events |= COMEDI_CB_ERROR;
+                       c = 0;
                }
 
                for (i = 0; i < c; i++) {
-                       /* Read value from data fifo */
-                       lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
-                       lval ^= 0x8000;
-
-                       if (!comedi_buf_write_samples(s, &lval, 1)) {
-                               /*
-                                * Buffer overflow, so stop conversion
-                                * and disable all interrupts
-                                */
-                               tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
-                               tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
-                                        ME4000_AI_CTRL_BIT_SC_IRQ);
-                               outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+                       lval = me4000_ai_get_sample(dev, s);
+                       if (!comedi_buf_write_samples(s, &lval, 1))
                                break;
-                       }
                }
 
                /* Work is done, so reset the interrupt */
-               tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
+               tmp |= ME4000_AI_CTRL_HF_IRQ_RESET;
                outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-               tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
+               tmp &= ~ME4000_AI_CTRL_HF_IRQ_RESET;
                outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
        }
 
        if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
-           ME4000_IRQ_STATUS_BIT_SC) {
+           ME4000_IRQ_STATUS_SC) {
+               /* Acquisition is complete */
                s->async->events |= COMEDI_CB_EOA;
 
-               /*
-                * Acquisition is complete, so stop
-                * conversion and disable all interrupts
-                */
-               tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
-               tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
-               tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
-               outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
                /* Poll data until fifo empty */
-               while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
-                      ME4000_AI_STATUS_BIT_EF_DATA) {
-                       /* Read value from data fifo */
-                       lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
-                       lval ^= 0x8000;
-
+               while (inl(dev->iobase + ME4000_AI_STATUS_REG) &
+                      ME4000_AI_STATUS_EF_DATA) {
+                       lval = me4000_ai_get_sample(dev, s);
                        if (!comedi_buf_write_samples(s, &lval, 1))
                                break;
                }
 
                /* Work is done, so reset the interrupt */
-               tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+               tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
+               tmp |= ME4000_AI_CTRL_SC_IRQ_RESET;
                outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-               tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+               tmp &= ~ME4000_AI_CTRL_SC_IRQ_RESET;
                outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
        }
 
@@ -1149,12 +1003,12 @@ static int me4000_ao_insn_write(struct comedi_device *dev,
                                struct comedi_insn *insn,
                                unsigned int *data)
 {
-       int chan = CR_CHAN(insn->chanspec);
+       unsigned int chan = CR_CHAN(insn->chanspec);
        unsigned int tmp;
 
        /* Stop any running conversion */
        tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
-       tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
+       tmp |= ME4000_AO_CTRL_IMMEDIATE_STOP;
        outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
 
        /* Clear control register and set to single mode */
@@ -1217,18 +1071,18 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
                return ret;
 
        tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
-       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 |
-                ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 |
-                ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 |
-                ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7);
+       tmp &= ~(ME4000_DIO_CTRL_MODE_0 | ME4000_DIO_CTRL_MODE_1 |
+                ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3 |
+                ME4000_DIO_CTRL_MODE_4 | ME4000_DIO_CTRL_MODE_5 |
+                ME4000_DIO_CTRL_MODE_6 | ME4000_DIO_CTRL_MODE_7);
        if (s->io_bits & 0x000000ff)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
+               tmp |= ME4000_DIO_CTRL_MODE_0;
        if (s->io_bits & 0x0000ff00)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
+               tmp |= ME4000_DIO_CTRL_MODE_2;
        if (s->io_bits & 0x00ff0000)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
+               tmp |= ME4000_DIO_CTRL_MODE_4;
        if (s->io_bits & 0xff000000)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
+               tmp |= ME4000_DIO_CTRL_MODE_6;
 
        /*
         * Check for optoisolated ME-4000 version.
@@ -1238,9 +1092,8 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
        if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
                s->io_bits |= 0x000000ff;
                s->io_bits &= ~0x0000ff00;
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
-               tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
-                        ME4000_DIO_CTRL_BIT_MODE_3);
+               tmp |= ME4000_DIO_CTRL_MODE_0;
+               tmp &= ~(ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3);
        }
 
        outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
@@ -1253,7 +1106,7 @@ static int me4000_auto_attach(struct comedi_device *dev,
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        const struct me4000_board *board = NULL;
-       struct me4000_info *info;
+       struct me4000_private *devpriv;
        struct comedi_subdevice *s;
        int result;
 
@@ -1264,17 +1117,17 @@ static int me4000_auto_attach(struct comedi_device *dev,
        dev->board_ptr = board;
        dev->board_name = board->name;
 
-       info = comedi_alloc_devpriv(dev, sizeof(*info));
-       if (!info)
+       devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+       if (!devpriv)
                return -ENOMEM;
 
        result = comedi_pci_enable(dev);
        if (result)
                return result;
 
-       info->plx_regbase = pci_resource_start(pcidev, 1);
+       devpriv->plx_regbase = pci_resource_start(pcidev, 1);
        dev->iobase = pci_resource_start(pcidev, 2);
-       if (!info->plx_regbase || !dev->iobase)
+       if (!devpriv->plx_regbase || !dev->iobase)
                return -ENODEV;
 
        result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
@@ -1287,79 +1140,66 @@ static int me4000_auto_attach(struct comedi_device *dev,
        if (pcidev->irq > 0) {
                result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED,
                                     dev->board_name, dev);
-               if (result == 0)
+               if (result == 0) {
                        dev->irq = pcidev->irq;
+
+                       /* Enable interrupts on the PLX */
+                       outl(PLX9052_INTCSR_LI1ENAB | PLX9052_INTCSR_LI1POL |
+                            PLX9052_INTCSR_PCIENAB,
+                            devpriv->plx_regbase + PLX9052_INTCSR);
+               }
        }
 
        result = comedi_alloc_subdevices(dev, 4);
        if (result)
                return result;
 
-    /*=========================================================================
-      Analog input subdevice
-      ========================================================================*/
-
+       /* Analog Input subdevice */
        s = &dev->subdevices[0];
-
-       if (board->ai_nchan) {
-               s->type = COMEDI_SUBD_AI;
-               s->subdev_flags =
-                   SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
-               s->n_chan = board->ai_nchan;
-               s->maxdata = 0xFFFF;    /*  16 bit ADC */
-               s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
-               s->range_table = &me4000_ai_range;
-               s->insn_read = me4000_ai_insn_read;
-
-               if (dev->irq) {
-                       dev->read_subdev = s;
-                       s->subdev_flags |= SDF_CMD_READ;
-                       s->cancel = me4000_ai_cancel;
-                       s->do_cmdtest = me4000_ai_do_cmd_test;
-                       s->do_cmd = me4000_ai_do_cmd;
-               }
-       } else {
-               s->type = COMEDI_SUBD_UNUSED;
+       s->type         = COMEDI_SUBD_AI;
+       s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
+       if (board->can_do_diff_ai)
+               s->subdev_flags |= SDF_DIFF;
+       s->n_chan       = board->ai_nchan;
+       s->maxdata      = 0xffff;
+       s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
+       s->range_table  = &me4000_ai_range;
+       s->insn_read    = me4000_ai_insn_read;
+
+       if (dev->irq) {
+               dev->read_subdev = s;
+               s->subdev_flags |= SDF_CMD_READ;
+               s->cancel       = me4000_ai_cancel;
+               s->do_cmdtest   = me4000_ai_do_cmd_test;
+               s->do_cmd       = me4000_ai_do_cmd;
        }
 
-    /*=========================================================================
-      Analog output subdevice
-      ========================================================================*/
-
+       /* Analog Output subdevice */
        s = &dev->subdevices[1];
-
-       if (board->ao_nchan) {
-               s->type = COMEDI_SUBD_AO;
-               s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
-               s->n_chan = board->ao_nchan;
-               s->maxdata = 0xFFFF;    /*  16 bit DAC */
-               s->range_table = &range_bipolar10;
-               s->insn_write = me4000_ao_insn_write;
+       if (board->has_ao) {
+               s->type         = COMEDI_SUBD_AO;
+               s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
+               s->n_chan       = 4;
+               s->maxdata      = 0xffff;
+               s->range_table  = &range_bipolar10;
+               s->insn_write   = me4000_ao_insn_write;
 
                result = comedi_alloc_subdev_readback(s);
                if (result)
                        return result;
        } else {
-               s->type = COMEDI_SUBD_UNUSED;
+               s->type         = COMEDI_SUBD_UNUSED;
        }
 
-    /*=========================================================================
-      Digital I/O subdevice
-      ========================================================================*/
-
+       /* Digital I/O subdevice */
        s = &dev->subdevices[2];
-
-       if (board->dio_nchan) {
-               s->type = COMEDI_SUBD_DIO;
-               s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan = board->dio_nchan;
-               s->maxdata = 1;
-               s->range_table = &range_digital;
-               s->insn_bits = me4000_dio_insn_bits;
-               s->insn_config = me4000_dio_insn_config;
-       } else {
-               s->type = COMEDI_SUBD_UNUSED;
-       }
+       s->type         = COMEDI_SUBD_DIO;
+       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+       s->n_chan       = 32;
+       s->maxdata      = 1;
+       s->range_table  = &range_digital;
+       s->insn_bits    = me4000_dio_insn_bits;
+       s->insn_config  = me4000_dio_insn_config;
 
        /*
         * Check for optoisolated ME-4000 version. If one the first
@@ -1367,7 +1207,7 @@ static int me4000_auto_attach(struct comedi_device *dev,
         */
        if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
                s->io_bits |= 0xFF;
-               outl(ME4000_DIO_CTRL_BIT_MODE_0,
+               outl(ME4000_DIO_CTRL_MODE_0,
                     dev->iobase + ME4000_DIO_DIR_REG);
        }
 
@@ -1393,8 +1233,12 @@ static int me4000_auto_attach(struct comedi_device *dev,
 
 static void me4000_detach(struct comedi_device *dev)
 {
-       if (dev->iobase)
-               me4000_reset(dev);
+       if (dev->irq) {
+               struct me4000_private *devpriv = dev->private;
+
+               /* Disable interrupts on the PLX */
+               outl(0, devpriv->plx_regbase + PLX9052_INTCSR);
+       }
        comedi_pci_detach(dev);
 }
 
@@ -1438,6 +1282,6 @@ static struct pci_driver me4000_pci_driver = {
 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(ME4000_FIRMWARE);
index a208cb3484375d8868d6ab4f3701876cb5b5a566..d9de83ab026712792a61a6cb806326316573cddb 100644 (file)
@@ -55,11 +55,7 @@ static int dio24_auto_attach(struct comedi_device *dev,
 
        /* 8255 dio */
        s = &dev->subdevices[0];
-       ret = subdev_8255_init(dev, s, NULL, 0x00);
-       if (ret)
-               return ret;
-
-       return 0;
+       return subdev_8255_init(dev, s, NULL, 0x00);
 }
 
 static struct comedi_driver driver_dio24 = {
index 5f649f88d55cbd9035dcf955dd3e9c75231028d9..88de8da3eff3f272669f23a0b1d11929bb31daf7 100644 (file)
@@ -172,7 +172,7 @@ struct ni6501_private {
 };
 
 static int ni6501_port_command(struct comedi_device *dev, int command,
-                              const u8 *port, u8 *bitmap)
+                              unsigned int val, u8 *bitmap)
 {
        struct usb_device *usb = comedi_to_usb_dev(dev);
        struct ni6501_private *devpriv = dev->private;
@@ -190,22 +190,22 @@ static int ni6501_port_command(struct comedi_device *dev, int command,
                request_size = sizeof(READ_PORT_REQUEST);
                response_size = sizeof(READ_PORT_RESPONSE);
                memcpy(tx, READ_PORT_REQUEST, request_size);
-               tx[14] = port[0];
+               tx[14] = val & 0xff;
                break;
        case WRITE_PORT:
                request_size = sizeof(WRITE_PORT_REQUEST);
                response_size = sizeof(GENERIC_RESPONSE);
                memcpy(tx, WRITE_PORT_REQUEST, request_size);
-               tx[14] = port[0];
-               tx[17] = bitmap[0];
+               tx[14] = val & 0xff;
+               tx[17] = *bitmap;
                break;
        case SET_PORT_DIR:
                request_size = sizeof(SET_PORT_DIR_REQUEST);
                response_size = sizeof(GENERIC_RESPONSE);
                memcpy(tx, SET_PORT_DIR_REQUEST, request_size);
-               tx[14] = port[0];
-               tx[15] = port[1];
-               tx[16] = port[2];
+               tx[14] = val & 0xff;
+               tx[15] = (val >> 8) & 0xff;
+               tx[16] = (val >> 16) & 0xff;
                break;
        default:
                ret = -EINVAL;
@@ -235,7 +235,7 @@ static int ni6501_port_command(struct comedi_device *dev, int command,
        /* Check if results are valid */
 
        if (command == READ_PORT) {
-               bitmap[0] = devpriv->usb_rx_buf[14];
+               *bitmap = devpriv->usb_rx_buf[14];
                /* mask bitmap for comparing */
                devpriv->usb_rx_buf[14] = 0x00;
 
@@ -349,17 +349,12 @@ static int ni6501_dio_insn_config(struct comedi_device *dev,
                                  unsigned int *data)
 {
        int ret;
-       u8 port[3];
 
        ret = comedi_dio_insn_config(dev, s, insn, data, 0);
        if (ret)
                return ret;
 
-       port[0] = (s->io_bits) & 0xff;
-       port[1] = (s->io_bits >> 8) & 0xff;
-       port[2] = (s->io_bits >> 16) & 0xff;
-
-       ret = ni6501_port_command(dev, SET_PORT_DIR, port, NULL);
+       ret = ni6501_port_command(dev, SET_PORT_DIR, s->io_bits, NULL);
        if (ret)
                return ret;
 
@@ -382,7 +377,7 @@ static int ni6501_dio_insn_bits(struct comedi_device *dev,
                if (mask & (0xFF << port * 8)) {
                        bitmap = (s->state >> port * 8) & 0xFF;
                        ret = ni6501_port_command(dev, WRITE_PORT,
-                                                 &port, &bitmap);
+                                                 port, &bitmap);
                        if (ret)
                                return ret;
                }
@@ -391,7 +386,7 @@ static int ni6501_dio_insn_bits(struct comedi_device *dev,
        data[1] = 0;
 
        for (port = 0; port < 3; port++) {
-               ret = ni6501_port_command(dev, READ_PORT, &port, &bitmap);
+               ret = ni6501_port_command(dev, READ_PORT, port, &bitmap);
                if (ret)
                        return ret;
                data[1] |= bitmap << port * 8;
index 781b321587dc601a954af44459a7044ada205613..a353d1b155bbd270dec44f6d1dba60384a6c3afd 100644 (file)
@@ -305,7 +305,7 @@ static int check_channel_list(struct comedi_device *dev,
                chansegment[0] = chanlist[0];
                for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
                        /*  we detect loop, this must by finish */
-                           if (chanlist[0] == chanlist[i])
+                       if (chanlist[0] == chanlist[i])
                                break;
                        nowmustbechan =
                            (CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
index 781918d8d85f5452ad9d61fb28b2c95a9b4da13d..35f0f676eb28378979c0eacd745a4178db1901a6 100644 (file)
@@ -2852,11 +2852,7 @@ static int s626_auto_attach(struct comedi_device *dev,
        s->insn_read    = s626_enc_insn_read;
        s->insn_write   = s626_enc_insn_write;
 
-       ret = s626_initialize(dev);
-       if (ret)
-               return ret;
-
-       return 0;
+       return s626_initialize(dev);
 }
 
 static void s626_detach(struct comedi_device *dev)
index 83da162deb526c0a790efba41b23ff4784e563b8..5f19374c460de63f4431ca3bd73d241a0ba37c76 100644 (file)
@@ -32,6 +32,7 @@ Status: in development
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/ktime.h>
 
 #include <linux/termios.h>
 #include <asm/ioctls.h>
@@ -121,9 +122,9 @@ static int serial2002_tty_write(struct file *f, unsigned char *buf, int count)
 static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
 {
        struct poll_wqueues table;
-       struct timeval start, now;
+       ktime_t start, now;
 
-       do_gettimeofday(&start);
+       start = ktime_get();
        poll_initwait(&table);
        while (1) {
                long elapsed;
@@ -134,9 +135,8 @@ static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
                            POLLHUP | POLLERR)) {
                        break;
                }
-               do_gettimeofday(&now);
-               elapsed = 1000000 * (now.tv_sec - start.tv_sec) +
-                         now.tv_usec - start.tv_usec;
+               now = ktime_get();
+               elapsed = ktime_us_delta(now, start);
                if (elapsed > timeout)
                        break;
                set_current_state(TASK_INTERRUPTIBLE);
index eaa9add491df7cbade63ee3786f36540aac71606..649cf47184a403241badec00b70164657a7054bd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * usbduxsigma.c
- * Copyright (C) 2011-2014 Bernd Porr, mail@berndporr.me.uk
+ * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk
  *
  * 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
@@ -18,7 +18,7 @@
  * Description: University of Stirling USB DAQ & INCITE Technology Limited
  * Devices: [ITL] USB-DUX-SIGMA (usbduxsigma)
  * Author: Bernd Porr <mail@berndporr.me.uk>
- * Updated: 10 Oct 2014
+ * Updated: 20 July 2015
  * Status: stable
  */
 
@@ -39,6 +39,7 @@
  *   0.4: fixed D/A voltage range
  *   0.5: various bug fixes, health check at startup
  *   0.6: corrected wrong input range
+ *   0.7: rewrite code that urb->interval is always 1
  */
 
 #include <linux/kernel.h>
 #define RETRIES 10
 
 /* bulk transfer commands to usbduxsigma */
-#define USBBUXSIGMA_AD_CMD             0
+#define USBBUXSIGMA_AD_CMD             9
 #define USBDUXSIGMA_DA_CMD             1
 #define USBDUXSIGMA_DIO_CFG_CMD                2
 #define USBDUXSIGMA_DIO_BITS_CMD       3
@@ -217,24 +218,28 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev,
        int ret;
        int i;
 
-       devpriv->ai_counter--;
-       if (devpriv->ai_counter == 0) {
-               devpriv->ai_counter = devpriv->ai_timer;
-
-               /* get the data from the USB bus and hand it over to comedi */
-               for (i = 0; i < cmd->chanlist_len; i++) {
-                       /* transfer data, note first byte is the DIO state */
-                       val = be32_to_cpu(devpriv->in_buf[i+1]);
-                       val &= 0x00ffffff;      /* strip status byte */
-                       val ^= 0x00800000;      /* convert to unsigned */
+       if ((urb->actual_length > 0) && (urb->status != -EXDEV)) {
+               devpriv->ai_counter--;
+               if (devpriv->ai_counter == 0) {
+                       devpriv->ai_counter = devpriv->ai_timer;
+
+                       /* get the data from the USB bus
+                          and hand it over to comedi */
+                       for (i = 0; i < cmd->chanlist_len; i++) {
+                               /* transfer data,
+                                  note first byte is the DIO state */
+                               val = be32_to_cpu(devpriv->in_buf[i+1]);
+                               val &= 0x00ffffff; /* strip status byte */
+                               val ^= 0x00800000; /* convert to unsigned */
+
+                               if (!comedi_buf_write_samples(s, &val, 1))
+                                       return;
+                       }
 
-                       if (!comedi_buf_write_samples(s, &val, 1))
-                               return;
+                       if (cmd->stop_src == TRIG_COUNT &&
+                           async->scans_done >= cmd->stop_arg)
+                               async->events |= COMEDI_CB_EOA;
                }
-
-               if (cmd->stop_src == TRIG_COUNT &&
-                   async->scans_done >= cmd->stop_arg)
-                       async->events |= COMEDI_CB_EOA;
        }
 
        /* if command is still running, resubmit urb */
@@ -374,10 +379,7 @@ static void usbduxsigma_ao_handle_urb(struct comedi_device *dev,
                urb->transfer_buffer_length = SIZEOUTBUF;
                urb->dev = comedi_to_usb_dev(dev);
                urb->status = 0;
-               if (devpriv->high_speed)
-                       urb->interval = 8;      /* uframes */
-               else
-                       urb->interval = 1;      /* frames */
+               urb->interval = 1;      /* (u)frames */
                urb->number_of_packets = 1;
                urb->iso_frame_desc[0].offset = 0;
                urb->iso_frame_desc[0].length = SIZEOUTBUF;
@@ -441,7 +443,6 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev,
                                   int input_urb)
 {
        struct usb_device *usb = comedi_to_usb_dev(dev);
-       struct usbduxsigma_private *devpriv = dev->private;
        struct urb *urb;
        int ret;
        int i;
@@ -452,7 +453,7 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev,
 
                /* in case of a resubmission after an unlink... */
                if (input_urb)
-                       urb->interval = devpriv->ai_interval;
+                       urb->interval = 1;
                urb->context = dev;
                urb->dev = usb;
                urb->status = 0;
@@ -481,6 +482,7 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
        struct usbduxsigma_private *devpriv = dev->private;
        int high_speed = devpriv->high_speed;
        int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len);
+       unsigned int tmp;
        int err = 0;
 
        /* Step 1 : check if triggers are trivially valid */
@@ -508,35 +510,20 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
 
        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-
-       if (cmd->scan_begin_src == TRIG_TIMER) {
-               unsigned int tmp;
-
-               if (high_speed) {
-                       /*
-                        * In high speed mode microframes are possible.
-                        * However, during one microframe we can roughly
-                        * sample two channels. Thus, the more channels
-                        * are in the channel list the more time we need.
-                        */
-                       err |= comedi_check_trigger_arg_min(&cmd->
-                                                           scan_begin_arg,
-                                                           (1000000 / 8 *
-                                                            interval));
-
-                       tmp = (cmd->scan_begin_arg / 125000) * 125000;
-               } else {
-                       /* full speed */
-                       /* 1kHz scans every USB frame */
-                       err |= comedi_check_trigger_arg_min(&cmd->
-                                                           scan_begin_arg,
-                                                           1000000);
-
-                       tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
-               }
-               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
+       if (high_speed) {
+               /*
+                * In high speed mode microframes are possible.
+                * However, during one microframe we can roughly
+                * sample two channels. Thus, the more channels
+                * are in the channel list the more time we need.
+                */
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   (125000 * interval));
+       } else {
+               /* full speed */
+               /* 1kHz scans every USB frame */
+               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+                                                   1000000);
        }
 
        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
@@ -552,21 +539,8 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
 
        /* Step 4: fix up any arguments */
 
-       if (high_speed) {
-               /*
-                * every 2 channels get a time window of 125us. Thus, if we
-                * sample all 16 channels we need 1ms. If we sample only one
-                * channel we need only 125us
-                */
-               devpriv->ai_interval = interval;
-               devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
-       } else {
-               /* interval always 1ms */
-               devpriv->ai_interval = 1;
-               devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
-       }
-       if (devpriv->ai_timer < 1)
-               err |= -EINVAL;
+       tmp = rounddown(cmd->scan_begin_arg, high_speed ? 125000 : 1000000);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
 
        if (err)
                return 4;
@@ -668,19 +642,36 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev,
 
        down(&devpriv->sem);
 
+       if (devpriv->high_speed) {
+               /*
+                * every 2 channels get a time window of 125us. Thus, if we
+                * sample all 16 channels we need 1ms. If we sample only one
+                * channel we need only 125us
+                */
+               unsigned int interval = usbduxsigma_chans_to_interval(len);
+
+               devpriv->ai_interval = interval;
+               devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
+       } else {
+               /* interval always 1ms */
+               devpriv->ai_interval = 1;
+               devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
+       }
+
        for (i = 0; i < len; i++) {
                unsigned int chan  = CR_CHAN(cmd->chanlist[i]);
 
                create_adc_command(chan, &muxsg0, &muxsg1);
        }
 
-       devpriv->dux_commands[1] = len;  /* num channels per time step */
-       devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
-       devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
-       devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
-       devpriv->dux_commands[5] = muxsg0;
-       devpriv->dux_commands[6] = muxsg1;
-       devpriv->dux_commands[7] = sysred;
+       devpriv->dux_commands[1] = devpriv->ai_interval;
+       devpriv->dux_commands[2] = len;  /* num channels per time step */
+       devpriv->dux_commands[3] = 0x12; /* CONFIG0 */
+       devpriv->dux_commands[4] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
+       devpriv->dux_commands[5] = 0x00; /* CONFIG3: diff. channels off */
+       devpriv->dux_commands[6] = muxsg0;
+       devpriv->dux_commands[7] = muxsg1;
+       devpriv->dux_commands[8] = sysred;
 
        ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
        if (ret < 0) {
@@ -848,29 +839,22 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
                                  struct comedi_cmd *cmd)
 {
        struct usbduxsigma_private *devpriv = dev->private;
+       unsigned int tmp;
        int err = 0;
-       int high_speed;
-       unsigned int flags;
-
-       /* high speed conversions are not used yet */
-       high_speed = 0;         /* (devpriv->high_speed) */
 
        /* Step 1 : check if triggers are trivially valid */
 
        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 
-       if (high_speed) {
-               /*
-                * start immediately a new scan
-                * the sampling rate is set by the coversion rate
-                */
-               flags = TRIG_FOLLOW;
-       } else {
-               /* start a new scan (output at once) with a timer */
-               flags = TRIG_TIMER;
-       }
-       err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
-
+       /*
+        * For now, always use "scan" timing with all channels updated at once
+        * (cmd->scan_begin_src == TRIG_TIMER, cmd->convert_src == TRIG_NOW).
+        *
+        * In a future version, "convert" timing with channels updated
+        * indivually may be supported in high speed mode
+        * (cmd->scan_begin_src == TRIG_FOLLOW, cmd->convert_src == TRIG_TIMER).
+        */
+       err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
        err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
@@ -894,17 +878,7 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
 
        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 
-       if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
-               err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-
-       if (cmd->scan_begin_src == TRIG_TIMER) {
-               err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                   1000000);
-       }
-
-       /* not used now, is for later use */
-       if (cmd->convert_src == TRIG_TIMER)
-               err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000);
+       err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000);
 
        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
                                           cmd->chanlist_len);
@@ -919,19 +893,8 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
 
        /* Step 4: fix up any arguments */
 
-       /* we count in timer steps */
-       if (high_speed) {
-               /* timing of the conversion itself: every 125 us */
-               devpriv->ao_timer = cmd->convert_arg / 125000;
-       } else {
-               /*
-                * timing of the scan: every 1ms
-                * we get all channels at once
-                */
-               devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
-       }
-       if (devpriv->ao_timer < 1)
-               err |= -EINVAL;
+       tmp = rounddown(cmd->scan_begin_arg, 1000000);
+       err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
 
        if (err)
                return 4;
@@ -948,6 +911,14 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev,
 
        down(&devpriv->sem);
 
+       /*
+        * For now, only "scan" timing is supported.  A future version may
+        * support "convert" timing in high speed mode.
+        *
+        * Timing of the scan: every 1ms all channels updated at once.
+        */
+       devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
+
        devpriv->ao_counter = devpriv->ao_timer;
 
        if (cmd->start_src == TRIG_NOW) {
@@ -1427,10 +1398,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
                urb->transfer_buffer_length = SIZEOUTBUF;
                urb->iso_frame_desc[0].offset = 0;
                urb->iso_frame_desc[0].length = SIZEOUTBUF;
-               if (devpriv->high_speed)
-                       urb->interval = 8;      /* uframes */
-               else
-                       urb->interval = 1;      /* frames */
+               urb->interval = 1;      /* (u)frames */
        }
 
        if (devpriv->pwm_buf_sz) {
@@ -1653,7 +1621,7 @@ static struct usb_driver usbduxsigma_usb_driver = {
 };
 module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
 
-MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
-MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
+MODULE_AUTHOR("Bernd Porr, mail@berndporr.me.uk");
+MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- mail@berndporr.me.uk");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(FIRMWARE);
index 6a393b24bdd936160fd3f6573078a26b7c10328e..ce3a58a7a1713b7d32c43fc50ce7c0045980ccbf 100644 (file)
@@ -102,7 +102,18 @@ int do_rangeinfo_ioctl(struct comedi_device *dev,
  * @s: comedi_subdevice struct
  * @n: number of elements in the chanlist
  * @chanlist: the chanlist to validate
-*/
+ *
+ * Each element consists of a channel number, a range index, an analog
+ * reference type and some flags, all packed into an unsigned int.
+ *
+ * This checks that the channel number and range index are supported by
+ * the comedi subdevice.  It does not check whether the analog reference
+ * type and the flags are supported.  Drivers that care should check those
+ * themselves.
+ *
+ * Return: %0 if all @chanlist elements are valid (success),
+ *         %-EINVAL if one or more elements are invalid.
+ */
 int comedi_check_chanlist(struct comedi_subdevice *s, int n,
                          unsigned int *chanlist)
 {
index 26b0446d943af6c7134821732d47fe3ea9ede20a..9112dd2bf4d7757503ea1b53191d213dcbc93785 100644 (file)
@@ -4953,9 +4953,8 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
                spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
                spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
 
-               rc = put_user(C_CLOCAL(tty) ? 1 : 0,
+               return put_user(C_CLOCAL(tty) ? 1 : 0,
                                (unsigned long __user *) arg);
-               return rc;
 
        case TIOCSSOFTCAR:
                spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
@@ -7004,25 +7003,29 @@ static void dgap_cleanup_board(struct board_t *brd)
        kfree(brd);
 }
 
-static void dgap_remove_one(struct pci_dev *dev)
+static void dgap_stop(bool removesys, struct pci_driver *drv)
 {
-       unsigned int i;
-       ulong lock_flags;
-       struct pci_driver *drv = to_pci_driver(dev->dev.driver);
+       unsigned long lock_flags;
 
        spin_lock_irqsave(&dgap_poll_lock, lock_flags);
        dgap_poll_stop = 1;
        spin_unlock_irqrestore(&dgap_poll_lock, lock_flags);
 
-       /* Turn off poller right away. */
        del_timer_sync(&dgap_poll_timer);
-
-       dgap_remove_driver_sysfiles(drv);
+       if (removesys)
+               dgap_remove_driver_sysfiles(drv);
 
        device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
        class_destroy(dgap_class);
        unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
+}
 
+static void dgap_remove_one(struct pci_dev *dev)
+{
+       unsigned int i;
+       struct pci_driver *drv = to_pci_driver(dev->dev.driver);
+
+       dgap_stop(true, drv);
        for (i = 0; i < dgap_numboards; ++i) {
                dgap_remove_ports_sysfiles(dgap_board[i]);
                dgap_cleanup_tty(dgap_board[i]);
@@ -7096,21 +7099,6 @@ failed_class:
        return rc;
 }
 
-static void dgap_stop(void)
-{
-       unsigned long lock_flags;
-
-       spin_lock_irqsave(&dgap_poll_lock, lock_flags);
-       dgap_poll_stop = 1;
-       spin_unlock_irqrestore(&dgap_poll_lock, lock_flags);
-
-       del_timer_sync(&dgap_poll_timer);
-
-       device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
-       class_destroy(dgap_class);
-       unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
-}
-
 /************************************************************************
  *
  * Driver load/unload functions
@@ -7133,8 +7121,10 @@ static int dgap_init_module(void)
                return rc;
 
        rc = pci_register_driver(&dgap_driver);
-       if (rc)
-               goto err_stop;
+       if (rc) {
+               dgap_stop(false, NULL);
+               return rc;
+       }
 
        rc = dgap_create_driver_sysfiles(&dgap_driver);
        if (rc)
@@ -7146,9 +7136,6 @@ static int dgap_init_module(void)
 
 err_unregister:
        pci_unregister_driver(&dgap_driver);
-err_stop:
-       dgap_stop();
-
        return rc;
 }
 
index d04671fa4b75369de203046d0d028e803f15f28b..06ece5151fe4a170ad04972d5bf3789e7c33ee21 100644 (file)
@@ -21,9 +21,9 @@
 #ifndef __DGNC_DRIVER_H
 #define __DGNC_DRIVER_H
 
-#include <linux/types.h>       /* To pick up the varions Linux types */
-#include <linux/tty.h>   /* To pick up the various tty structs/defines */
-#include <linux/interrupt.h>   /* For irqreturn_t type */
+#include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
 
 #include "digi.h"              /* Digi specific ioctl header */
 #include "dgnc_sysfs.h"                /* Support for SYSFS */
index be0f90a6768b0b822f94a8cb548c42e0041d5bd9..7be7d55bc49ea9e92c674ef256f075b6fafb50bb 100644 (file)
@@ -25,16 +25,16 @@ struct un_t;
 struct pci_driver;
 struct class_device;
 
-extern void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
-extern void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
+void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
+void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
 
-extern void dgnc_create_driver_sysfiles(struct pci_driver *);
-extern void dgnc_remove_driver_sysfiles(struct pci_driver *);
+void dgnc_create_driver_sysfiles(struct pci_driver *);
+void dgnc_remove_driver_sysfiles(struct pci_driver *);
 
-extern int dgnc_tty_class_init(void);
-extern int dgnc_tty_class_destroy(void);
+int dgnc_tty_class_init(void);
+int dgnc_tty_class_destroy(void);
 
-extern void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
-extern void dgnc_remove_tty_sysfs(struct device *c);
+void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
+void dgnc_remove_tty_sysfs(struct device *c);
 
 #endif
index 4178d96f94cf152076bf6a62fdec5cd08c6bc389..b6b76ff09657134ee55f07bcce621cb97c1450c4 100644 (file)
@@ -3153,36 +3153,46 @@ static const struct usb_gadget_ops nbu2ss_gadget_ops = {
        .ioctl                  = nbu2ss_gad_ioctl,
 };
 
-static const char g_ep0_name[] = "ep0";
-static const char g_ep1_name[] = "ep1-bulk";
-static const char g_ep2_name[] = "ep2-bulk";
-static const char g_ep3_name[] = "ep3in-int";
-static const char g_ep4_name[] = "ep4-iso";
-static const char g_ep5_name[] = "ep5-iso";
-static const char g_ep6_name[] = "ep6-bulk";
-static const char g_ep7_name[] = "ep7-bulk";
-static const char g_ep8_name[] = "ep8in-int";
-static const char g_ep9_name[] = "ep9-iso";
-static const char g_epa_name[] = "epa-iso";
-static const char g_epb_name[] = "epb-bulk";
-static const char g_epc_name[] = "epc-nulk";
-static const char g_epd_name[] = "epdin-int";
-
-static const char *gp_ep_name[NUM_ENDPOINTS] = {
-       g_ep0_name,
-       g_ep1_name,
-       g_ep2_name,
-       g_ep3_name,
-       g_ep4_name,
-       g_ep5_name,
-       g_ep6_name,
-       g_ep7_name,
-       g_ep8_name,
-       g_ep9_name,
-       g_epa_name,
-       g_epb_name,
-       g_epc_name,
-       g_epd_name,
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} ep_info[NUM_ENDPOINTS] = {
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
+
+       EP_INFO("ep0",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep1-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep2-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep3in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep4-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep5-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep6-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep7-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep8in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep9-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("epa-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("epb-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("epc-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("epdin-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+
+#undef EP_INFO
 };
 
 /*-------------------------------------------------------------------------*/
@@ -3200,10 +3210,12 @@ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
                ep->desc = NULL;
 
                ep->ep.driver_data = NULL;
-               ep->ep.name = gp_ep_name[i];
+               ep->ep.name = ep_info[i].name;
+               ep->ep.caps = ep_info[i].caps;
                ep->ep.ops = &nbu2ss_ep_ops;
 
-               ep->ep.maxpacket = (i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE);
+               usb_ep_set_maxpacket_limit(&ep->ep,
+                               i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE);
 
                list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
                INIT_LIST_HEAD(&ep->queue);
index d4018780ce588d8d6b8b67888a85934360231bb2..d473010fa4748409d32e3d088679f81310cec0ec 100644 (file)
@@ -1,6 +1,7 @@
 menuconfig FB_TFT
        tristate "Support for small TFT LCD display modules"
-       depends on FB && SPI && GPIOLIB
+       depends on FB && SPI
+       depends on GPIOLIB || COMPILE_TEST
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
@@ -152,6 +153,12 @@ config FB_TFT_TLS8204
        help
          Generic Framebuffer support for TLS8204
 
+config FB_TFT_UC1611
+       tristate "FB driver for the UC1611 LCD controller"
+       depends on FB_TFT
+       help
+         Generic Framebuffer support for UC1611
+
 config FB_TFT_UC1701
        tristate "FB driver for the UC1701 LCD Controller"
        depends on FB_TFT
index 554b5260b0ee8450666b2fe181e334b1d7c71656..b26efdc877756636c329340df8426f90508b8835 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_FB_TFT_SSD1351)     += fb_ssd1351.o
 obj-$(CONFIG_FB_TFT_ST7735R)     += fb_st7735r.o
 obj-$(CONFIG_FB_TFT_TINYLCD)     += fb_tinylcd.o
 obj-$(CONFIG_FB_TFT_TLS8204)     += fb_tls8204.o
+obj-$(CONFIG_FB_TFT_UC1611)      += fb_uc1611.o
 obj-$(CONFIG_FB_TFT_UC1701)      += fb_uc1701.o
 obj-$(CONFIG_FB_TFT_UPD161704)   += fb_upd161704.o
 obj-$(CONFIG_FB_TFT_WATTEROTT)   += fb_watterott.o
diff --git a/drivers/staging/fbtft/fb_uc1611.c b/drivers/staging/fbtft/fb_uc1611.c
new file mode 100644 (file)
index 0000000..32f3a9d
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * FB driver for the UltraChip UC1611 LCD controller
+ *
+ * The display is 4-bit grayscale (16 shades) 240x160.
+ *
+ * Copyright (C) 2015 Henri Chain
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+
+#include "fbtft.h"
+
+#define DRVNAME                "fb_uc1611"
+#define WIDTH          240
+#define HEIGHT         160
+#define BPP            8
+#define FPS            40
+
+/*
+ * LCD voltage is a combination of ratio, gain, pot and temp
+ *
+ * V_LCD = V_BIAS * ratio
+ * V_LCD = (C_V0 + C_PM Ã— pot) * (1 + (T - 25) * temp)
+ * C_V0 and C_PM depend on ratio and gain
+ * T is ambient temperature
+ */
+
+/* BR -> actual ratio: 0-3 -> 5, 10, 11, 13 */
+static unsigned ratio = 2;
+module_param(ratio, uint, 0);
+MODULE_PARM_DESC(ratio, "BR[1:0] Bias voltage ratio: 0-3 (default: 2)");
+
+static unsigned gain = 3;
+module_param(gain, uint, 0);
+MODULE_PARM_DESC(gain, "GN[1:0] Bias voltage gain: 0-3 (default: 3)");
+
+static unsigned pot = 16;
+module_param(pot, uint, 0);
+MODULE_PARM_DESC(pot, "PM[6:0] Bias voltage pot.: 0-63 (default: 16)");
+
+/* TC -> % compensation per deg C: 0-3 -> -.05, -.10, -.015, -.20 */
+static unsigned temp;
+module_param(temp, uint, 0);
+MODULE_PARM_DESC(temp, "TC[1:0] Temperature compensation: 0-3 (default: 0)");
+
+/* PC[1:0] -> LCD capacitance: 0-3 -> <20nF, 20-28 nF, 29-40 nF, 40-56 nF */
+static unsigned load = 1;
+module_param(load, uint, 0);
+MODULE_PARM_DESC(load, "PC[1:0] Panel Loading: 0-3 (default: 1)");
+
+/* PC[3:2] -> V_LCD: 0, 1, 3 -> ext., int. with ratio = 5, int. standard */
+static unsigned pump = 3;
+module_param(pump, uint, 0);
+MODULE_PARM_DESC(pump, "PC[3:2] Pump control: 0,1,3 (default: 3)");
+
+static int init_display(struct fbtft_par *par)
+{
+       int ret;
+
+       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+       /* Set CS active high */
+       par->spi->mode |= SPI_CS_HIGH;
+       ret = par->spi->master->setup(par->spi);
+       if (ret) {
+               dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
+               return ret;
+       }
+
+       /* Reset controller */
+       write_reg(par, 0xE2);
+
+       /* Set bias ratio */
+       write_reg(par, 0xE8 | (ratio & 0x03));
+
+       /* Set bias gain and potentiometer */
+       write_reg(par, 0x81);
+       write_reg(par, (gain & 0x03) << 6 | (pot & 0x3F));
+
+       /* Set temperature compensation */
+       write_reg(par, 0x24 | (temp & 0x03));
+
+       /* Set panel loading */
+       write_reg(par, 0x28 | (load & 0x03));
+
+       /* Set pump control */
+       write_reg(par, 0x2C | (pump & 0x03));
+
+       /* Set inverse display */
+       write_reg(par, 0xA6 | (0x01 & 0x01));
+
+       /* Set 4-bit grayscale mode */
+       write_reg(par, 0xD0 | (0x02 & 0x03));
+
+       /* Set Display enable */
+       write_reg(par, 0xA8 | 0x07);
+
+       return 0;
+}
+
+static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
+{
+       fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
+                     "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
+                     __func__, xs, ys, xe, ye);
+
+       switch (par->info->var.rotate) {
+       case 90:
+       case 270:
+               /* Set column address */
+               write_reg(par, ys & 0x0F);
+               write_reg(par, 0x10 | (ys >> 4));
+
+               /* Set page address (divide xs by 2) (not used by driver) */
+               write_reg(par, 0x60 | ((xs >> 1) & 0x0F));
+               write_reg(par, 0x70 | (xs >> 5));
+               break;
+       default:
+               /* Set column address (not used by driver) */
+               write_reg(par, xs & 0x0F);
+               write_reg(par, 0x10 | (xs >> 4));
+
+               /* Set page address (divide ys by 2) */
+               write_reg(par, 0x60 | ((ys >> 1) & 0x0F));
+               write_reg(par, 0x70 | (ys >> 5));
+               break;
+       }
+}
+
+static int blank(struct fbtft_par *par, bool on)
+{
+       fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n",
+                     __func__, on ? "true" : "false");
+
+       if (on)
+               write_reg(par, 0xA8 | 0x00);
+       else
+               write_reg(par, 0xA8 | 0x07);
+       return 0;
+}
+
+static int set_var(struct fbtft_par *par)
+{
+       fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+       /* par->info->fix.visual = FB_VISUAL_PSEUDOCOLOR; */
+       par->info->var.grayscale = 1;
+       par->info->var.red.offset    = 0;
+       par->info->var.red.length    = 8;
+       par->info->var.green.offset  = 0;
+       par->info->var.green.length  = 8;
+       par->info->var.blue.offset   = 0;
+       par->info->var.blue.length   = 8;
+       par->info->var.transp.offset = 0;
+       par->info->var.transp.length = 0;
+
+       switch (par->info->var.rotate) {
+       case 90:
+               /* Set RAM address control */
+               write_reg(par, 0x88
+                       | (0x0 & 0x1) << 2 /* Increment positively */
+                       | (0x1 & 0x1) << 1 /* Increment page first */
+                       | (0x1 & 0x1));    /* Wrap around (default) */
+
+               /* Set LCD mapping */
+               write_reg(par, 0xC0
+                       | (0x0 & 0x1) << 2 /* Mirror Y OFF */
+                       | (0x0 & 0x1) << 1 /* Mirror X OFF */
+                       | (0x0 & 0x1));    /* MS nibble last (default) */
+               break;
+       case 180:
+               /* Set RAM address control */
+               write_reg(par, 0x88
+                       | (0x0 & 0x1) << 2 /* Increment positively */
+                       | (0x0 & 0x1) << 1 /* Increment column first */
+                       | (0x1 & 0x1));    /* Wrap around (default) */
+
+               /* Set LCD mapping */
+               write_reg(par, 0xC0
+                       | (0x1 & 0x1) << 2 /* Mirror Y ON */
+                       | (0x0 & 0x1) << 1 /* Mirror X OFF */
+                       | (0x0 & 0x1));    /* MS nibble last (default) */
+               break;
+       case 270:
+               /* Set RAM address control */
+               write_reg(par, 0x88
+                       | (0x0 & 0x1) << 2 /* Increment positively */
+                       | (0x1 & 0x1) << 1 /* Increment page first */
+                       | (0x1 & 0x1));    /* Wrap around (default) */
+
+               /* Set LCD mapping */
+               write_reg(par, 0xC0
+                       | (0x1 & 0x1) << 2 /* Mirror Y ON */
+                       | (0x1 & 0x1) << 1 /* Mirror X ON */
+                       | (0x0 & 0x1));    /* MS nibble last (default) */
+               break;
+       default:
+               /* Set RAM address control */
+               write_reg(par, 0x88
+                       | (0x0 & 0x1) << 2 /* Increment positively */
+                       | (0x0 & 0x1) << 1 /* Increment column first */
+                       | (0x1 & 0x1));    /* Wrap around (default) */
+
+               /* Set LCD mapping */
+               write_reg(par, 0xC0
+                       | (0x0 & 0x1) << 2 /* Mirror Y OFF */
+                       | (0x1 & 0x1) << 1 /* Mirror X ON */
+                       | (0x0 & 0x1));    /* MS nibble last (default) */
+               break;
+       }
+
+       return 0;
+}
+
+static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
+{
+       u8 *vmem8 = (u8 *)(par->info->screen_base);
+       u8 *buf8 = (u8 *)(par->txbuf.buf);
+       u16 *buf16 = (u16 *)(par->txbuf.buf);
+       int line_length = par->info->fix.line_length;
+       int y_start = (offset / line_length);
+       int y_end = (offset + len - 1) / line_length;
+       int x, y, i;
+       int ret = 0;
+
+       fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__);
+
+       switch (par->pdata->display.buswidth) {
+       case 8:
+               switch (par->info->var.rotate) {
+               case 90:
+               case 270:
+                       i = y_start * line_length;
+                       for (y = y_start; y <= y_end; y++) {
+                               for (x = 0; x < line_length; x += 2) {
+                                       *buf8 = vmem8[i] >> 4;
+                                       *buf8 |= vmem8[i + 1] & 0xF0;
+                                       buf8++;
+                                       i += 2;
+                               }
+                       }
+                       break;
+               default:
+                       /* Must be even because pages are two lines */
+                       y_start &= 0xFE;
+                       i = y_start * line_length;
+                       for (y = y_start; y <= y_end; y += 2) {
+                               for (x = 0; x < line_length; x++) {
+                                       *buf8 = vmem8[i] >> 4;
+                                       *buf8 |= vmem8[i + line_length] & 0xF0;
+                                       buf8++;
+                                       i++;
+                               }
+                               i += line_length;
+                       }
+                       break;
+               }
+               gpio_set_value(par->gpio.dc, 1);
+
+               /* Write data */
+               ret = par->fbtftops.write(par, par->txbuf.buf, len / 2);
+               break;
+       case 9:
+               switch (par->info->var.rotate) {
+               case 90:
+               case 270:
+                       i = y_start * line_length;
+                       for (y = y_start; y <= y_end; y++) {
+                               for (x = 0; x < line_length; x += 2) {
+                                       *buf16 = 0x100;
+                                       *buf16 |= vmem8[i] >> 4;
+                                       *buf16 |= vmem8[i + 1] & 0xF0;
+                                       buf16++;
+                                       i += 2;
+                               }
+                       }
+                       break;
+               default:
+                       /* Must be even because pages are two lines */
+                       y_start &= 0xFE;
+                       i = y_start * line_length;
+                       for (y = y_start; y <= y_end; y += 2) {
+                               for (x = 0; x < line_length; x++) {
+                                       *buf16 = 0x100;
+                                       *buf16 |= vmem8[i] >> 4;
+                                       *buf16 |= vmem8[i + line_length] & 0xF0;
+                                       buf16++;
+                                       i++;
+                               }
+                               i += line_length;
+                       }
+                       break;
+               }
+
+               /* Write data */
+               ret = par->fbtftops.write(par, par->txbuf.buf, len);
+               break;
+       default:
+               dev_err(par->info->device, "unsupported buswidth %d\n",
+                       par->pdata->display.buswidth);
+       }
+
+       if (ret < 0)
+               dev_err(par->info->device, "write failed and returned: %d\n",
+                       ret);
+
+       return ret;
+}
+
+static struct fbtft_display display = {
+       .txbuflen = -1,
+       .regwidth = 8,
+       .width = WIDTH,
+       .height = HEIGHT,
+       .bpp = BPP,
+       .fps = FPS,
+       .fbtftops = {
+               .write_vmem = write_vmem,
+               .init_display = init_display,
+               .set_addr_win = set_addr_win,
+               .set_var = set_var,
+               .blank = blank,
+       },
+};
+
+FBTFT_REGISTER_DRIVER(DRVNAME, "ultrachip,uc1611", &display);
+
+MODULE_ALIAS("spi:" DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+MODULE_ALIAS("spi:uc1611");
+MODULE_ALIAS("platform:uc1611");
+
+MODULE_DESCRIPTION("FB driver for the UC1611 LCD controller");
+MODULE_AUTHOR("Henri Chain");
+MODULE_LICENSE("GPL");
index 9cc81412be69b724100c749a25f292cb0a08a9c2..23392eb6799ec0e946f238b42b9d02c0673e92d8 100644 (file)
@@ -677,13 +677,13 @@ static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src)
  *
  */
 struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
-                                       struct device *dev)
+                                       struct device *dev,
+                                       struct fbtft_platform_data *pdata)
 {
        struct fb_info *info;
        struct fbtft_par *par;
        struct fb_ops *fbops = NULL;
        struct fb_deferred_io *fbdefio = NULL;
-       struct fbtft_platform_data *pdata = dev->platform_data;
        u8 *vmem = NULL;
        void *txbuf = NULL;
        void *buf = NULL;
@@ -828,7 +828,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
 
        par = info->par;
        par->info = info;
-       par->pdata = dev->platform_data;
+       par->pdata = pdata;
        par->debug = display->debug;
        par->buf = buf;
        spin_lock_init(&par->dirty_lock);
@@ -1076,6 +1076,11 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
        p = of_prop_next_u32(prop, NULL, &val);
        if (!p)
                return -EINVAL;
+
+       par->fbtftops.reset(par);
+       if (par->gpio.cs != -1)
+               gpio_set_value(par->gpio.cs, 0);  /* Activate chip */
+
        while (p) {
                if (val & FBTFT_OF_INIT_CMD) {
                        val &= 0xFFFF;
@@ -1260,12 +1265,11 @@ EXPORT_SYMBOL(fbtft_init_display);
  */
 static int fbtft_verify_gpios(struct fbtft_par *par)
 {
-       struct fbtft_platform_data *pdata;
+       struct fbtft_platform_data *pdata = par->pdata;
        int i;
 
        fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
 
-       pdata = par->info->device->platform_data;
        if (pdata->display.buswidth != 9 && par->startbyte == 0 &&
                                                        par->gpio.dc < 0) {
                dev_err(par->info->device,
@@ -1383,10 +1387,9 @@ int fbtft_probe_common(struct fbtft_display *display,
                pdata = fbtft_probe_dt(dev);
                if (IS_ERR(pdata))
                        return PTR_ERR(pdata);
-               dev->platform_data = pdata;
        }
 
-       info = fbtft_framebuffer_alloc(display, dev);
+       info = fbtft_framebuffer_alloc(display, dev, pdata);
        if (!info)
                return -ENOMEM;
 
index 7d817eb26eabeecf6ec5fc49fc76f39b69022d20..7e9a506d65f91dcdd93b2ab271811b0df01be9d9 100644 (file)
@@ -262,39 +262,38 @@ struct fbtft_par {
        par->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__)
 
 /* fbtft-core.c */
-extern void fbtft_dbg_hex(const struct device *dev,
-       int groupsize, void *buf, size_t len, const char *fmt, ...);
-extern struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
-       struct device *dev);
-extern void fbtft_framebuffer_release(struct fb_info *info);
-extern int fbtft_register_framebuffer(struct fb_info *fb_info);
-extern int fbtft_unregister_framebuffer(struct fb_info *fb_info);
-extern void fbtft_register_backlight(struct fbtft_par *par);
-extern void fbtft_unregister_backlight(struct fbtft_par *par);
-extern int fbtft_init_display(struct fbtft_par *par);
-extern int fbtft_probe_common(struct fbtft_display *display,
-       struct spi_device *sdev, struct platform_device *pdev);
-extern int fbtft_remove_common(struct device *dev, struct fb_info *info);
+void fbtft_dbg_hex(const struct device *dev, int groupsize,
+                  void *buf, size_t len, const char *fmt, ...);
+struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
+                                       struct device *dev,
+                                       struct fbtft_platform_data *pdata);
+void fbtft_framebuffer_release(struct fb_info *info);
+int fbtft_register_framebuffer(struct fb_info *fb_info);
+int fbtft_unregister_framebuffer(struct fb_info *fb_info);
+void fbtft_register_backlight(struct fbtft_par *par);
+void fbtft_unregister_backlight(struct fbtft_par *par);
+int fbtft_init_display(struct fbtft_par *par);
+int fbtft_probe_common(struct fbtft_display *display, struct spi_device *sdev,
+                      struct platform_device *pdev);
+int fbtft_remove_common(struct device *dev, struct fb_info *info);
 
 /* fbtft-io.c */
-extern int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_spi_emulate_9(struct fbtft_par *par,
-       void *buf, size_t len);
-extern int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_gpio16_wr_latched(struct fbtft_par *par,
-       void *buf, size_t len);
+int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len);
 
 /* fbtft-bus.c */
-extern int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len);
-extern int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len);
-extern int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len);
-extern int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len);
-extern void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...);
-extern void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
-extern void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
-extern void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
+int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len);
+int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len);
+int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len);
+int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len);
+void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...);
+void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
+void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
+void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
 
 
 #define FBTFT_REGISTER_DRIVER(_name, _compatible, _display)                \
index 211d504901f25f54a2faf62d4ef9380f07c38c00..fa916e88d54937e9e5272a6a0b40f875d1d2c4f9 100644 (file)
@@ -396,6 +396,37 @@ static struct fbtft_device_display displays[] = {
                                },
                        }
                }
+       }, {
+               .name = "ew24ha0",
+               .spi = &(struct spi_board_info) {
+                       .modalias = "fb_uc1611",
+                       .max_speed_hz = 32000000,
+                       .mode = SPI_MODE_3,
+                       .platform_data = &(struct fbtft_platform_data) {
+                               .display = {
+                                       .buswidth = 8,
+                               },
+                               .gpios = (const struct fbtft_gpio []) {
+                                       { "dc", 24 },
+                                       {},
+                               },
+                       }
+               }
+       }, {
+               .name = "ew24ha0_9bit",
+               .spi = &(struct spi_board_info) {
+                       .modalias = "fb_uc1611",
+                       .max_speed_hz = 32000000,
+                       .mode = SPI_MODE_3,
+                       .platform_data = &(struct fbtft_platform_data) {
+                               .display = {
+                                       .buswidth = 9,
+                               },
+                               .gpios = (const struct fbtft_gpio []) {
+                                       {},
+                               },
+                       }
+               }
        }, {
                .name = "flexfb",
                .spi = &(struct spi_board_info) {
index 2c4ce07f51064fdf10f6441b86307fd44c562424..c763efc5de7dc468708945845b22154860b00869 100644 (file)
  * 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/module.h>
@@ -30,7 +26,6 @@
 
 #define DRVNAME            "flexfb"
 
-
 static char *chip;
 module_param(chip, charp, 0);
 MODULE_PARM_DESC(chip, "LCD controller");
@@ -68,7 +63,6 @@ static bool latched;
 module_param(latched, bool, 0);
 MODULE_PARM_DESC(latched, "Use with latched 16-bit databus");
 
-
 static int *initp;
 static int initp_num;
 
@@ -132,14 +126,115 @@ static int ssd1351_init[] = { -1, 0xfd, 0x12, -1, 0xfd, 0xb1, -1, 0xae, -1, 0xb3
                              -1, 0xab, 0x01, -1, 0xb1, 0x32, -1, 0xb4, 0xa0, 0xb5, 0x55, -1, 0xbb, 0x17, -1, 0xbe, 0x05,
                              -1, 0xc1, 0xc8, 0x80, 0xc8, -1, 0xc7, 0x0f, -1, 0xb6, 0x01, -1, 0xa6, -1, 0xaf, -3 };
 
+/**
+ * struct flexfb_lcd_controller - Describes the LCD controller properties
+ * @name: Model name of the chip
+ * @width: Width of display in pixels
+ * @height: Height of display in pixels
+ * @setaddrwin: Which set_addr_win() implementation to use
+ * @regwidth: LCD Controller Register width in bits
+ * @init_seq: LCD initialization sequence
+ * @init_seq_sz: Size of LCD initialization sequence
+ */
+struct flexfb_lcd_controller {
+       const char *name;
+       unsigned int width;
+       unsigned int height;
+       unsigned int setaddrwin;
+       unsigned int regwidth;
+       int *init_seq;
+       int init_seq_sz;
+};
+
+static const struct flexfb_lcd_controller flexfb_chip_table[] = {
+       {
+               .name = "st7735r",
+               .width = 120,
+               .height = 160,
+               .init_seq = st7735r_init,
+               .init_seq_sz = ARRAY_SIZE(st7735r_init),
+       },
+       {
+               .name = "hx8340bn",
+               .width = 176,
+               .height = 220,
+               .init_seq = hx8340bn_init,
+               .init_seq_sz = ARRAY_SIZE(hx8340bn_init),
+       },
+       {
+               .name = "ili9225",
+               .width = 176,
+               .height = 220,
+               .regwidth = 16,
+               .init_seq = ili9225_init,
+               .init_seq_sz = ARRAY_SIZE(ili9225_init),
+       },
+       {
+               .name = "ili9225",
+               .width = 176,
+               .height = 220,
+               .regwidth = 16,
+               .init_seq = ili9225_init,
+               .init_seq_sz = ARRAY_SIZE(ili9225_init),
+       },
+       {
+               .name = "ili9225",
+               .width = 176,
+               .height = 220,
+               .regwidth = 16,
+               .init_seq = ili9225_init,
+               .init_seq_sz = ARRAY_SIZE(ili9225_init),
+       },
+       {
+               .name = "ili9320",
+               .width = 240,
+               .height = 320,
+               .setaddrwin = 1,
+               .regwidth = 16,
+               .init_seq = ili9320_init,
+               .init_seq_sz = ARRAY_SIZE(ili9320_init),
+       },
+       {
+               .name = "ili9325",
+               .width = 240,
+               .height = 320,
+               .setaddrwin = 1,
+               .regwidth = 16,
+               .init_seq = ili9325_init,
+               .init_seq_sz = ARRAY_SIZE(ili9325_init),
+       },
+       {
+               .name = "ili9341",
+               .width = 240,
+               .height = 320,
+               .init_seq = ili9341_init,
+               .init_seq_sz = ARRAY_SIZE(ili9341_init),
+       },
+       {
+               .name = "ssd1289",
+               .width = 240,
+               .height = 320,
+               .setaddrwin = 2,
+               .regwidth = 16,
+               .init_seq = ssd1289_init,
+               .init_seq_sz = ARRAY_SIZE(ssd1289_init),
+       },
+       {
+               .name = "ssd1351",
+               .width = 128,
+               .height = 128,
+               .setaddrwin = 3,
+               .init_seq = ssd1351_init,
+               .init_seq_sz = ARRAY_SIZE(ssd1351_init),
+       },
+};
 
 /* ili9320, ili9325 */
 static void flexfb_set_addr_win_1(struct fbtft_par *par,
                                  int xs, int ys, int xe, int ye)
 {
-       fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
-                    "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
-                    __func__, xs, ys, xe, ye);
+       fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
+                     __func__, xs, ys, xe, ye);
        switch (par->info->var.rotate) {
        /* R20h = Horizontal GRAM Start Address */
        /* R21h = Vertical GRAM Start Address */
@@ -242,7 +337,7 @@ static int flexfb_verify_gpios_db(struct fbtft_par *par)
                return -EINVAL;
        }
        if (latched)
-               num_db = buswidth/2;
+               num_db = buswidth / 2;
        for (i = 0; i < num_db; i++) {
                if (par->gpio.db[i] < 0) {
                        dev_err(par->info->device,
@@ -255,8 +350,38 @@ static int flexfb_verify_gpios_db(struct fbtft_par *par)
        return 0;
 }
 
+static void flexfb_chip_load_param(const struct flexfb_lcd_controller *chip)
+{
+       if (!width)
+               width = chip->width;
+       if (!height)
+               height = chip->height;
+       setaddrwin = chip->setaddrwin;
+       if (chip->regwidth)
+               regwidth = chip->regwidth;
+       if (!init_num) {
+               initp = chip->init_seq;
+               initp_num = chip->init_seq_sz;
+       }
+}
+
 static struct fbtft_display flex_display = { };
 
+static int flexfb_chip_init(const struct device *dev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(flexfb_chip_table); i++)
+               if (!strcmp(chip, flexfb_chip_table[i].name)) {
+                       flexfb_chip_load_param(&flexfb_chip_table[i]);
+                       return 0;
+               }
+
+       dev_err(dev, "chip=%s is not supported\n", chip);
+
+       return -EINVAL;
+}
+
 static int flexfb_probe_common(struct spi_device *sdev,
                               struct platform_device *pdev)
 {
@@ -277,110 +402,9 @@ static int flexfb_probe_common(struct spi_device *sdev,
                       sdev ? "'SPI device'" : "'Platform device'");
 
        if (chip) {
-
-               if (!strcmp(chip, "st7735r")) {
-                       if (!width)
-                               width = 128;
-                       if (!height)
-                               height = 160;
-                       if (init_num == 0) {
-                               initp = st7735r_init;
-                               initp_num = ARRAY_SIZE(st7735r_init);
-                       }
-
-
-               } else if (!strcmp(chip, "hx8340bn")) {
-                       if (!width)
-                               width = 176;
-                       if (!height)
-                               height = 220;
-                       setaddrwin = 0;
-                       if (init_num == 0) {
-                               initp = hx8340bn_init;
-                               initp_num = ARRAY_SIZE(hx8340bn_init);
-                       }
-
-
-               } else if (!strcmp(chip, "ili9225")) {
-                       if (!width)
-                               width = 176;
-                       if (!height)
-                               height = 220;
-                       setaddrwin = 0;
-                       regwidth = 16;
-                       if (init_num == 0) {
-                               initp = ili9225_init;
-                               initp_num = ARRAY_SIZE(ili9225_init);
-                       }
-
-
-
-               } else if (!strcmp(chip, "ili9320")) {
-                       if (!width)
-                               width = 240;
-                       if (!height)
-                               height = 320;
-                       setaddrwin = 1;
-                       regwidth = 16;
-                       if (init_num == 0) {
-                               initp = ili9320_init;
-                               initp_num = ARRAY_SIZE(ili9320_init);
-                       }
-
-
-               } else if (!strcmp(chip, "ili9325")) {
-                       if (!width)
-                               width = 240;
-                       if (!height)
-                               height = 320;
-                       setaddrwin = 1;
-                       regwidth = 16;
-                       if (init_num == 0) {
-                               initp = ili9325_init;
-                               initp_num = ARRAY_SIZE(ili9325_init);
-                       }
-
-               } else if (!strcmp(chip, "ili9341")) {
-                       if (!width)
-                               width = 240;
-                       if (!height)
-                               height = 320;
-                       setaddrwin = 0;
-                       regwidth = 8;
-                       if (init_num == 0) {
-                               initp = ili9341_init;
-                               initp_num = ARRAY_SIZE(ili9341_init);
-                       }
-
-
-               } else if (!strcmp(chip, "ssd1289")) {
-                       if (!width)
-                               width = 240;
-                       if (!height)
-                               height = 320;
-                       setaddrwin = 2;
-                       regwidth = 16;
-                       if (init_num == 0) {
-                               initp = ssd1289_init;
-                               initp_num = ARRAY_SIZE(ssd1289_init);
-                       }
-
-
-
-               } else if (!strcmp(chip, "ssd1351")) {
-                       if (!width)
-                               width = 128;
-                       if (!height)
-                               height = 128;
-                       setaddrwin = 3;
-                       if (init_num == 0) {
-                               initp = ssd1351_init;
-                               initp_num = ARRAY_SIZE(ssd1351_init);
-                       }
-               } else {
-                       dev_err(dev, "chip=%s is not supported\n", chip);
-                       return -EINVAL;
-               }
+               ret = flexfb_chip_init(dev);
+               if (ret)
+                       return ret;
        }
 
        if (width == 0 || height == 0) {
@@ -395,7 +419,7 @@ static int flexfb_probe_common(struct spi_device *sdev,
        fbtft_init_dbg(dev, "regwidth = %d\n", regwidth);
        fbtft_init_dbg(dev, "buswidth = %d\n", buswidth);
 
-       info = fbtft_framebuffer_alloc(&flex_display, dev);
+       info = fbtft_framebuffer_alloc(&flex_display, dev, dev->platform_data);
        if (!info)
                return -ENOMEM;
 
@@ -527,8 +551,8 @@ static int flexfb_remove_common(struct device *dev, struct fb_info *info)
                return -EINVAL;
        par = info->par;
        if (par)
-               fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par,
-                       "%s()\n", __func__);
+               fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, "%s()\n",
+                             __func__);
        fbtft_unregister_framebuffer(info);
        fbtft_framebuffer_release(info);
 
diff --git a/drivers/staging/fsl-mc/README.txt b/drivers/staging/fsl-mc/README.txt
new file mode 100644 (file)
index 0000000..8214102
--- /dev/null
@@ -0,0 +1,364 @@
+Copyright (C) 2015 Freescale Semiconductor Inc.
+
+DPAA2 (Data Path Acceleration Architecture Gen2)
+------------------------------------------------
+
+This document provides an overview of the Freescale DPAA2 architecture
+and how it is integrated into the Linux kernel.
+
+Contents summary
+   -DPAA2 overview
+   -Overview of DPAA2 objects
+   -DPAA2 Linux driver architecture overview
+        -bus driver
+        -dprc driver
+        -allocator
+        -dpio driver
+        -Ethernet
+        -mac
+
+DPAA2 Overview
+--------------
+
+DPAA2 is a hardware architecture designed for high-speeed network
+packet processing.  DPAA2 consists of sophisticated mechanisms for
+processing Ethernet packets, queue management, buffer management,
+autonomous L2 switching, virtual Ethernet bridging, and accelerator
+(e.g. crypto) sharing.
+
+A DPAA2 hardware component called the Management Complex (or MC) manages the
+DPAA2 hardware resources.  The MC provides an object-based abstraction for
+software drivers to use the DPAA2 hardware.
+
+The MC uses DPAA2 hardware resources such as queues, buffer pools, and
+network ports to create functional objects/devices such as network
+interfaces, an L2 switch, or accelerator instances.
+
+The MC provides memory-mapped I/O command interfaces (MC portals)
+which DPAA2 software drivers use to operate on DPAA2 objects:
+
+         +--------------------------------------+
+         |                  OS                  |
+         |                        DPAA2 drivers |
+         |                             |        |
+         +-----------------------------|--------+
+                                       |
+                                       | (create,discover,connect
+                                       |  config,use,destroy)
+                                       |
+                         DPAA2         |
+         +------------------------| mc portal |-+
+         |                             |        |
+         |   +- - - - - - - - - - - - -V- - -+  |
+         |   |                               |  |
+         |   |   Management Complex (MC)     |  |
+         |   |                               |  |
+         |   +- - - - - - - - - - - - - - - -+  |
+         |                                      |
+         | Hardware                  Hardware   |
+         | Resources                 Objects    |
+         | ---------                 -------    |
+         | -queues                   -DPRC      |
+         | -buffer pools             -DPMCP     |
+         | -Eth MACs/ports           -DPIO      |
+         | -network interface        -DPNI      |
+         |  profiles                 -DPMAC     |
+         | -queue portals            -DPBP      |
+         | -MC portals                ...       |
+         |  ...                                 |
+         |                                      |
+         +--------------------------------------+
+
+The MC mediates operations such as create, discover,
+connect, configuration, and destroy.  Fast-path operations
+on data, such as packet transmit/receive, are not mediated by
+the MC and are done directly using memory mapped regions in
+DPIO objects.
+
+Overview of DPAA2 Objects
+-------------------------
+The section provides a brief overview of some key objects
+in the DPAA2 hardware.  A simple scenario is described illustrating
+the objects involved in creating a network interfaces.
+
+-DPRC (Datapath Resource Container)
+
+    A DPRC is an container object that holds all the other
+    types of DPAA2 objects.  In the example diagram below there
+    are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC)
+    in the container.
+
+    +---------------------------------------------------------+
+    | DPRC                                                    |
+    |                                                         |
+    |  +-------+  +-------+  +-------+  +-------+  +-------+  |
+    |  | DPMCP |  | DPIO  |  | DPBP  |  | DPNI  |  | DPMAC |  |
+    |  +-------+  +-------+  +-------+  +---+---+  +---+---+  |
+    |  | DPMCP |  | DPIO  |                                   |
+    |  +-------+  +-------+                                   |
+    |  | DPMCP |                                              |
+    |  +-------+                                              |
+    |                                                         |
+    +---------------------------------------------------------+
+
+    From the point of view of an OS, a DPRC is bus-like.  Like
+    a plug-and-play bus, such as PCI, DPRC commands can be used to
+    enumerate the contents of the DPRC, discover the hardware
+    objects present (including mappable regions and interrupts).
+
+     dprc.1 (bus)
+       |
+       +--+--------+-------+-------+-------+
+          |        |       |       |       |
+        dpmcp.1  dpio.1  dpbp.1  dpni.1  dpmac.1
+        dpmcp.2  dpio.2
+        dpmcp.3
+
+    Hardware objects can be created and destroyed dynamically, providing
+    the ability to hot plug/unplug objects in and out of the DPRC.
+
+    A DPRC has a mappable mmio region (an MC portal) that can be used
+    to send MC commands.  It has an interrupt for status events (like
+    hotplug).
+
+    All objects in a container share the same hardware "isolation context".
+    This means that with respect to an IOMMU the isolation granularity
+    is at the DPRC (container) level, not at the individual object
+    level.
+
+    DPRCs can be defined statically and populated with objects
+    via a config file passed to the MC when firmware starts
+    it.  There is also a Linux user space tool called "restool"
+    that can be used to create/destroy containers and objects
+    dynamically.
+
+-DPAA2 Objects for an Ethernet Network Interface
+
+    A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX
+    queuing mechanisms, configuration mechanisms, buffer management,
+    physical ports, and interrupts.  DPAA2 uses a more granular approach
+    utilizing multiple hardware objects.  Each object has specialized
+    functions, and are used together by software to provide Ethernet network
+    interface functionality.  This approach provides efficient use of finite
+    hardware resources, flexibility, and performance advantages.
+
+    The diagram below shows the objects needed for a simple
+    network interface configuration on a system with 2 CPUs.
+
+              +---+---+ +---+---+
+                 CPU0     CPU1
+              +---+---+ +---+---+
+                  |         |
+              +---+---+ +---+---+
+                 DPIO     DPIO
+              +---+---+ +---+---+
+                    \     /
+                     \   /
+                      \ /
+                   +---+---+
+                      DPNI  --- DPBP,DPMCP
+                   +---+---+
+                       |
+                       |
+                   +---+---+
+                     DPMAC
+                   +---+---+
+                       |
+                    port/PHY
+
+    Below the objects are described.  For each object a brief description
+    is provided along with a summary of the kinds of operations the object
+    supports and a summary of key resources of the object (mmio regions
+    and irqs).
+
+       -DPMAC (Datapath Ethernet MAC): represents an Ethernet MAC, a
+        hardware device that connects to an Ethernet PHY and allows
+        physical transmission and reception of Ethernet frames.
+           -mmio regions: none
+           -irqs: dpni link change
+           -commands: set link up/down, link config, get stats,
+             irq config, enable, reset
+
+       -DPNI (Datapath Network Interface): contains TX/RX queues,
+        network interface configuration, and rx buffer pool configuration
+        mechanisms.
+           -mmio regions: none
+           -irqs: link state
+           -commands: port config, offload config, queue config,
+            parse/classify config, irq config, enable, reset
+
+       -DPIO (Datapath I/O): provides interfaces to enqueue and dequeue
+        packets and do hardware buffer pool management operations.  For
+        optimum performance there is typically DPIO per CPU.  This allows
+        each CPU to perform simultaneous enqueue/dequeue operations.
+           -mmio regions: queue operations, buffer mgmt
+           -irqs: data availability, congestion notification, buffer
+                  pool depletion
+           -commands: irq config, enable, reset
+
+       -DPBP (Datapath Buffer Pool): represents a hardware buffer
+        pool.
+           -mmio regions: none
+           -irqs: none
+           -commands: enable, reset
+
+       -DPMCP (Datapath MC Portal): provides an MC command portal.
+        Used by drivers to send commands to the MC to manage
+        objects.
+           -mmio regions: MC command portal
+           -irqs: command completion
+           -commands: irq config, enable, reset
+
+    Object Connections
+    ------------------
+    Some objects have explicit relationships that must
+    be configured:
+
+       -DPNI <--> DPMAC
+       -DPNI <--> DPNI
+       -DPNI <--> L2-switch-port
+          A DPNI must be connected to something such as a DPMAC,
+          another DPNI, or L2 switch port.  The DPNI connection
+          is made via a DPRC command.
+
+              +-------+  +-------+
+              | DPNI  |  | DPMAC |
+              +---+---+  +---+---+
+                  |          |
+                  +==========+
+
+       -DPNI <--> DPBP
+          A network interface requires a 'buffer pool' (DPBP
+          object) which provides a list of pointers to memory
+          where received Ethernet data is to be copied.  The
+          Ethernet driver configures the DPBPs associated with
+          the network interface.
+
+    Interrupts
+    ----------
+    All interrupts generated by DPAA2 objects are message
+    interrupts.  At the hardware level message interrupts
+    generated by devices will normally have 3 components--
+    1) a non-spoofable 'device-id' expressed on the hardware
+    bus, 2) an address, 3) a data value.
+
+    In the case of DPAA2 devices/objects, all objects in the
+    same container/DPRC share the same 'device-id'.
+    For ARM-based SoC this is the same as the stream ID.
+
+
+DPAA2 Linux Driver Overview
+---------------------------
+
+This section provides an overview of the Linux kernel drivers for
+DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure"
+drivers and 2) functional object drivers (such as Ethernet).
+
+As described previously, a DPRC is a container that holds the other
+types of DPAA2 objects.  It is functionally similar to a plug-and-play
+bus controller.
+
+Each object in the DPRC is a Linux "device" and is bound to a driver.
+The diagram below shows the Linux drivers involved in a networking
+scenario and the objects bound to each driver.  A brief description
+of each driver follows.
+
+                                             +------------+
+                                             | OS Network |
+                                             |   Stack    |
+                 +------------+              +------------+
+                 | Allocator  |. . . . . . . |  Ethernet  |
+                 |(dpmcp,dpbp)|              |   (dpni)   |
+                 +-.----------+              +---+---+----+
+                  .          .                   ^   |
+                 .            .     <data avail, |   |<enqueue,
+                .              .     tx confirm> |   | dequeue>
+    +-------------+             .                |   |
+    | DPRC driver |              .           +---+---V----+     +---------+
+    |   (dprc)    |               . . . . . .| DPIO driver|     |   MAC   |
+    +----------+--+                          |  (dpio)    |     | (dpmac) |
+               |                             +------+-----+     +-----+---+
+               |<dev add/remove>                    |                 |
+               |                                    |                 |
+          +----+--------------+                     |              +--+---+
+          |   mc-bus driver   |                     |              | PHY  |
+          |                   |                     |              |driver|
+          | /fsl-mc@80c000000 |                     |              +--+---+
+          +-------------------+                     |                 |
+                                                    |                 |
+ ================================ HARDWARE =========|=================|======
+                                                  DPIO                |
+                                                    |                 |
+                                                  DPNI---DPBP         |
+                                                    |                 |
+                                                  DPMAC               |
+                                                    |                 |
+                                                   PHY ---------------+
+ ===================================================|========================
+
+A brief description of each driver is provided below.
+
+    mc-bus driver
+    -------------
+    The mc-bus driver is a platform driver and is probed from an
+    "/fsl-mc@xxxx" node in the device tree passed in by boot firmware.
+    It is responsible for bootstrapping the DPAA2 kernel infrastructure.
+    Key functions include:
+       -registering a new bus type named "fsl-mc" with the kernel,
+        and implementing bus call-backs (e.g. match/uevent/dev_groups)
+       -implemeting APIs for DPAA2 driver registration and for device
+        add/remove
+       -creates an MSI irq domain
+       -do a device add of the 'root' DPRC device, which is needed
+        to bootstrap things
+
+    DPRC driver
+    -----------
+    The dprc-driver is bound DPRC objects and does runtime management
+    of a bus instance.  It performs the initial bus scan of the DPRC
+    and handles interrupts for container events such as hot plug.
+
+    Allocator
+    ----------
+    Certain objects such as DPMCP and DPBP are generic and fungible,
+    and are intended to be used by other drivers.  For example,
+    the DPAA2 Ethernet driver needs:
+       -DPMCPs to send MC commands, to configure network interfaces
+       -DPBPs for network buffer pools
+
+    The allocator driver registers for these allocatable object types
+    and those objects are bound to the allocator when the bus is probed.
+    The allocator maintains a pool of objects that are available for
+    allocation by other DPAA2 drivers.
+
+    DPIO driver
+    -----------
+    The DPIO driver is bound to DPIO objects and provides services that allow
+    other drivers such as the Ethernet driver to receive and transmit data.
+    Key services include:
+        -data availability notifications
+        -hardware queuing operations (enqueue and dequeue of data)
+        -hardware buffer pool management
+
+    There is typically one DPIO object per physical CPU for optimum
+    performance, allowing each CPU to simultaneously enqueue
+    and dequeue data.
+
+    The DPIO driver operates on behalf of all DPAA2 drivers
+    active in the kernel--  Ethernet, crypto, compression,
+    etc.
+
+    Ethernet
+    --------
+    The Ethernet driver is bound to a DPNI and implements the kernel
+    interfaces needed to connect the DPAA2 network interface to
+    the network stack.
+
+    Each DPNI corresponds to a Linux network interface.
+
+    MAC driver
+    ----------
+    An Ethernet PHY is an off-chip, board specific component and is managed
+    by the appropriate PHY driver via an mdio bus.  The MAC driver
+    plays a role of being a proxy between the PHY driver and the
+    MC.  It does this proxy via the MC commands to a DPMAC object.
index d78288b4e72174547a93736bde1821341ed9a7ca..389436891b93b40367c4e3727d9729370e0c5511 100644 (file)
@@ -1,13 +1,31 @@
-* Add README file (with ASCII art) describing relationships between
-  DPAA2 objects and how combine them to make a NIC, an LS2 switch, etc.
-  Also, define all acronyms used.
-
 * Decide if multiple root fsl-mc buses will be supported per Linux instance,
   and if so add support for this.
 
 * Add at least one device driver for a DPAA2 object (child device of the
-  fsl-mc bus).
+  fsl-mc bus).  Most likely candidate for this is adding DPAA2 Ethernet
+  driver support, which depends on drivers for several objects: DPNI,
+  DPIO, DPMAC.  Other pre-requisites include:
+
+     * interrupt support. for meaningful driver support we need
+       interrupts, and thus need message interrupt support by the bus
+       driver.
+          -Note: this has dependencies on generic MSI support work
+           in process upstream, see [1] and [2].
+
+     * Management Complex (MC) command serialization. locking mechanisms
+       are needed by drivers to serialize commands sent to the MC, including
+       from atomic context.
+
+     * MC firmware uprev.  The MC firmware upon which the fsl-mc
+       bus driver and DPAA2 object drivers are based is continuing
+       to evolve, so minor updates are needed to keep in sync with binary
+       interface changes to the MC.
+
+* Cleanup
 
 Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
 german.rivera@freescale.com, devel@driverdev.osuosl.org,
 linux-kernel@vger.kernel.org
+
+[1] https://lkml.org/lkml/2015/7/9/93
+[2] https://lkml.org/lkml/2015/7/7/712
index 5992670f77473bed55c935262e20a8a9b05f1c11..e1861cf5de738bd8de20c84eaed4bf4769713dfc 100644 (file)
@@ -42,17 +42,16 @@ struct ft1000_pcmcia {
 
 struct pcmcia_device;
 struct net_device;
-extern struct net_device *init_ft1000_card(struct pcmcia_device *link,
-                                          void *ft1000_reset);
-extern void stop_ft1000_card(struct net_device *dev);
-extern int card_download(struct net_device *dev, const u8 *pFileStart,
-                        size_t FileLength);
+struct net_device *init_ft1000_card(struct pcmcia_device *link,
+                                   void *ft1000_reset);
+void stop_ft1000_card(struct net_device *dev);
+int card_download(struct net_device *dev, const u8 *pFileStart,
+                 size_t FileLength);
 
-extern u16 ft1000_read_dpram(struct net_device *dev, int offset);
-extern void card_bootload(struct net_device *dev);
-extern u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset,
-                                   int Index);
-extern u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
+u16 ft1000_read_dpram(struct net_device *dev, int offset);
+void card_bootload(struct net_device *dev);
+u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index);
+u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
 void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value);
 
 /* Read the value of a given ASIC register. */
index 409266b1a886f7cb6e8136d10f050743f3d168a6..f241a3a5a684b8b4d639bf58815f5724b8147285 100644 (file)
@@ -260,7 +260,8 @@ void ft1000_destroy_dev(struct net_device *netdev)
                /* Make sure we free any memory reserve for slow Queue */
                for (i = 0; i < MAX_NUM_APP; i++) {
                        while (list_empty(&dev->app_info[i].app_sqlist) == 0) {
-                               pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
+                               pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next,
+                                                       struct dpram_blk, list);
                                list_del(&pdpram_blk->list);
                                ft1000_free_buffer(pdpram_blk, &freercvpool);
 
@@ -415,12 +416,19 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
        struct timeval tv;
        struct IOCTL_GET_VER get_ver_data;
        struct IOCTL_GET_DSP_STAT get_stat_data;
-       u8 ConnectionMsg[] = {0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
-                             0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                             0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
-                             0x00, 0x01, 0x00, 0x00};
+       u8 ConnectionMsg[] = {
+               0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
+               0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08,
+               0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
+               0x00, 0x01, 0x00, 0x00
+       };
 
        unsigned short ledStat = 0;
        unsigned short conStat = 0;
@@ -495,10 +503,12 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                memcpy(get_stat_data.eui64, info->eui64, EUISZ);
 
                if (info->ProgConStat != 0xFF) {
-                       ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
+                       ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED,
+                                           (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
                        get_stat_data.LedStat = ntohs(ledStat);
                        pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
-                       ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
+                       ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE,
+                                           (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
                        get_stat_data.ConStat = ntohs(conStat);
                        pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
                } else {
@@ -689,7 +699,8 @@ static long ft1000_ioctl(struct file *file, unsigned int command,
                if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
                        /* pr_debug("Message detected in slow queue\n"); */
                        spin_lock_irqsave(&free_buff_lock, flags);
-                       pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
+                       pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next,
+                                               struct dpram_blk, list);
                        list_del(&pdpram_blk->list);
                        ft1000dev->app_info[i].NumOfMsg--;
                        /* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
index 5def347beb082df3bd442e9f8c9a47713c47feaf..297b7aece5062a17531043a477eda4ee2cc61130 100644 (file)
@@ -95,7 +95,6 @@ struct dsp_file_hdr {
        long              nDspImages;          /* Number of DSP images in file. */
 };
 
-#pragma pack(1)
 struct dsp_image_info {
        long              coff_date;           /* Date/time when DSP Coff image was built. */
        long              begin_offset;        /* Offset in file where image begins. */
@@ -105,7 +104,7 @@ struct dsp_image_info {
        long              version;             /* Embedded version # of DSP code. */
        unsigned short    checksum;            /* DSP File checksum */
        unsigned short    pad1;
-};
+} __packed;
 
 
 /* checks if the doorbell register is cleared */
@@ -180,7 +179,8 @@ static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value)
                }
 
                status = ft1000_read_dpram16(ft1000dev,
-                                            DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
+                                            DWNLD_MAG1_HANDSHAKE_LOC,
+                                            (u8 *)&handshake, 1);
                handshake = ntohs(handshake);
 
                if (status)
@@ -281,12 +281,14 @@ static u16 get_request_type(struct ft1000_usb *ft1000dev)
 
        if (ft1000dev->bootmode == 1) {
                status = fix_ft1000_read_dpram32(ft1000dev,
-                                                DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
+                                                DWNLD_MAG1_TYPE_LOC,
+                                                (u8 *)&tempx);
                tempx = ntohl(tempx);
        } else {
                tempx = 0;
                status = ft1000_read_dpram16(ft1000dev,
-                                            DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
+                                            DWNLD_MAG1_TYPE_LOC,
+                                            (u8 *)&tempword, 1);
                tempx |= (tempword << 16);
                tempx = ntohl(tempx);
        }
@@ -304,7 +306,8 @@ static u16 get_request_type_usb(struct ft1000_usb *ft1000dev)
 
        if (ft1000dev->bootmode == 1) {
                status = fix_ft1000_read_dpram32(ft1000dev,
-                                                DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
+                                                DWNLD_MAG1_TYPE_LOC,
+                                                (u8 *)&tempx);
                tempx = ntohl(tempx);
        } else {
                if (ft1000dev->usbboot == 2) {
@@ -332,14 +335,17 @@ static long get_request_value(struct ft1000_usb *ft1000dev)
 
        if (ft1000dev->bootmode == 1) {
                status = fix_ft1000_read_dpram32(ft1000dev,
-                                                DWNLD_MAG1_SIZE_LOC, (u8 *)&value);
+                                                DWNLD_MAG1_SIZE_LOC,
+                                                (u8 *)&value);
                value = ntohl(value);
        } else  {
                status = ft1000_read_dpram16(ft1000dev,
-                                            DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0);
+                                            DWNLD_MAG1_SIZE_LOC,
+                                            (u8 *)&tempword, 0);
                value = tempword;
                status = ft1000_read_dpram16(ft1000dev,
-                                            DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
+                                            DWNLD_MAG1_SIZE_LOC,
+                                            (u8 *)&tempword, 1);
                value |= (tempword << 16);
                value = ntohl(value);
        }
index e6b5976a09e3bd5e438b13446d894f3566bbbe92..96209703ba257772bf4daaa8010fe198f0d6b762 100644 (file)
@@ -842,7 +842,6 @@ static int ft1000_copy_up_pkt(struct urb *urb)
        skb = dev_alloc_skb(len + 12 + 2);
 
        if (skb == NULL) {
-               pr_debug("No Network buffers available\n");
                info->stats.rx_errors++;
                ft1000_submit_rx_urb(info);
                return -1;
index fea60d5651a7bbd0593e93e1b0e64ab8f6acca87..9b5050fcbb660ae229b60f23fe95bbe8c254f94f 100644 (file)
@@ -134,8 +134,8 @@ extern spinlock_t free_buff_lock;
 
 int ft1000_create_dev(struct ft1000_usb *dev);
 void ft1000_destroy_dev(struct net_device *dev);
-extern int card_send_command(struct ft1000_usb *ft1000dev,
-                            void *ptempbuffer, int size);
+int card_send_command(struct ft1000_usb *ft1000dev,
+                     void *ptempbuffer, int size);
 
 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist);
 void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist);
index 8ce544de73427ac2afc2e293693c1520952eb9d6..7afb9ba5fdba97b71d08e5cdcdbacdc032bd342a 100644 (file)
@@ -32,7 +32,9 @@
 #define BL_PID_MASK            0xffc0
 
 #define USB_DEVICE_BOOTLOADER(vid, pid)        \
-       {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD)},    \
+       {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD)}
+
+#define USB_DEVICE_BOOTLOADER_DRV(vid, pid)    \
        {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD|B_DIFF_DL_DRV)}
 
 #define USB_DEVICE_CDC_DATA(vid, pid)  \
@@ -40,6 +42,7 @@
 
 static const struct usb_device_id id_table[] = {
        USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID1),
+       USB_DEVICE_BOOTLOADER_DRV(GCT_VID, GCT_PID1),
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1),
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x1),
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x2),
@@ -58,6 +61,7 @@ static const struct usb_device_id id_table[] = {
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xf),
 
        USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID2),
+       USB_DEVICE_BOOTLOADER_DRV(GCT_VID, GCT_PID2),
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2),
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x1),
        USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x2),
index d7c5223f1c3e78abfe759cca374873bda0b70068..3f7715c9968b83b25d6d1a4f6099c29b051db5fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Freescale i.MX28 LRADC driver
+ * Freescale MXS LRADC driver
  *
  * Copyright (c) 2012 DENX Software Engineering, GmbH.
  * Marek Vasut <marex@denx.de>
  * GNU General Public License for more details.
  */
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/device.h>
 #include <linux/err.h>
+#include <linux/input.h>
 #include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
+#include <linux/slab.h>
 #include <linux/stmp_device.h>
-#include <linux/bitops.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/clk.h>
+#include <linux/sysfs.h>
 
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
+#include <linux/iio/sysfs.h>
 
 #define DRIVER_NAME            "mxs-lradc"
 
  * Once the pen touches the touchscreen, the touchscreen switches from
  * IRQ-driven mode to polling mode to prevent interrupt storm. The polling
  * is realized by worker thread, which is called every 20 or so milliseconds.
- * This gives the touchscreen enough fluence and does not strain the system
+ * This gives the touchscreen enough fluency and does not strain the system
  * too much.
  */
 #define LRADC_TS_SAMPLE_DELAY_MS       5
 
 /*
  * The LRADC reads the following amount of samples from each touchscreen
- * channel and the driver then computes avarage of these.
+ * channel and the driver then computes average of these.
  */
 #define LRADC_TS_SAMPLE_AMOUNT         4
 
@@ -238,7 +234,7 @@ struct mxs_lradc {
         * CH5 -- Touch screen YNLR
         * CH6 -- Touch screen WIPER (5-wire only)
         *
-        * The bitfields below represents which parts of the LRADC block are
+        * The bit fields below represents which parts of the LRADC block are
         * switched into special mode of operation. These channels can not
         * be sampled as regular LRADC channels. The driver will refuse any
         * attempt to sample these channels.
@@ -252,7 +248,7 @@ struct mxs_lradc {
        struct input_dev        *ts_input;
 
        enum mxs_lradc_id       soc;
-       enum lradc_ts_plate     cur_plate; /* statemachine */
+       enum lradc_ts_plate     cur_plate; /* state machine */
        bool                    ts_valid;
        unsigned                ts_x_pos;
        unsigned                ts_y_pos;
@@ -812,7 +808,7 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
        int ret;
 
        /*
-        * See if there is no buffered operation in progess. If there is, simply
+        * See if there is no buffered operation in progress. If there is, simply
         * bail out. This can be improved to support both buffered and raw IO at
         * the same time, yet the code becomes horribly complicated. Therefore I
         * applied KISS principle here.
@@ -1369,7 +1365,7 @@ static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
  * Driver initialization
  */
 
-#define MXS_ADC_CHAN(idx, chan_type) {                         \
+#define MXS_ADC_CHAN(idx, chan_type, name) {                   \
        .type = (chan_type),                                    \
        .indexed = 1,                                           \
        .scan_index = (idx),                                    \
@@ -1382,17 +1378,18 @@ static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
                .realbits = LRADC_RESOLUTION,                   \
                .storagebits = 32,                              \
        },                                                      \
+       .datasheet_name = (name),                               \
 }
 
-static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
-       MXS_ADC_CHAN(0, IIO_VOLTAGE),
-       MXS_ADC_CHAN(1, IIO_VOLTAGE),
-       MXS_ADC_CHAN(2, IIO_VOLTAGE),
-       MXS_ADC_CHAN(3, IIO_VOLTAGE),
-       MXS_ADC_CHAN(4, IIO_VOLTAGE),
-       MXS_ADC_CHAN(5, IIO_VOLTAGE),
-       MXS_ADC_CHAN(6, IIO_VOLTAGE),
-       MXS_ADC_CHAN(7, IIO_VOLTAGE),   /* VBATT */
+static const struct iio_chan_spec mx23_lradc_chan_spec[] = {
+       MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"),
+       MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"),
+       MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"),
+       MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"),
+       MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"),
+       MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"),
+       MXS_ADC_CHAN(6, IIO_VOLTAGE, "VDDIO"),
+       MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"),
        /* Combined Temperature sensors */
        {
                .type = IIO_TEMP,
@@ -1403,6 +1400,7 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
                                      BIT(IIO_CHAN_INFO_SCALE),
                .channel = 8,
                .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
+               .datasheet_name = "TEMP_DIE",
        },
        /* Hidden channel to keep indexes */
        {
@@ -1411,12 +1409,48 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
                .scan_index = -1,
                .channel = 9,
        },
-       MXS_ADC_CHAN(10, IIO_VOLTAGE),  /* VDDIO */
-       MXS_ADC_CHAN(11, IIO_VOLTAGE),  /* VTH */
-       MXS_ADC_CHAN(12, IIO_VOLTAGE),  /* VDDA */
-       MXS_ADC_CHAN(13, IIO_VOLTAGE),  /* VDDD */
-       MXS_ADC_CHAN(14, IIO_VOLTAGE),  /* VBG */
-       MXS_ADC_CHAN(15, IIO_VOLTAGE),  /* VDD5V */
+       MXS_ADC_CHAN(10, IIO_VOLTAGE, NULL),
+       MXS_ADC_CHAN(11, IIO_VOLTAGE, NULL),
+       MXS_ADC_CHAN(12, IIO_VOLTAGE, "USB_DP"),
+       MXS_ADC_CHAN(13, IIO_VOLTAGE, "USB_DN"),
+       MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"),
+       MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
+};
+
+static const struct iio_chan_spec mx28_lradc_chan_spec[] = {
+       MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"),
+       MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"),
+       MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"),
+       MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"),
+       MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"),
+       MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"),
+       MXS_ADC_CHAN(6, IIO_VOLTAGE, "LRADC6"),
+       MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"),
+       /* Combined Temperature sensors */
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .scan_index = 8,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_OFFSET) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .channel = 8,
+               .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
+               .datasheet_name = "TEMP_DIE",
+       },
+       /* Hidden channel to keep indexes */
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .scan_index = -1,
+               .channel = 9,
+       },
+       MXS_ADC_CHAN(10, IIO_VOLTAGE, "VDDIO"),
+       MXS_ADC_CHAN(11, IIO_VOLTAGE, "VTH"),
+       MXS_ADC_CHAN(12, IIO_VOLTAGE, "VDDA"),
+       MXS_ADC_CHAN(13, IIO_VOLTAGE, "VDDD"),
+       MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"),
+       MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
 };
 
 static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
@@ -1612,10 +1646,16 @@ static int mxs_lradc_probe(struct platform_device *pdev)
        iio->dev.parent = &pdev->dev;
        iio->info = &mxs_lradc_iio_info;
        iio->modes = INDIO_DIRECT_MODE;
-       iio->channels = mxs_lradc_chan_spec;
-       iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec);
        iio->masklength = LRADC_MAX_TOTAL_CHANS;
 
+       if (lradc->soc == IMX23_LRADC) {
+               iio->channels = mx23_lradc_chan_spec;
+               iio->num_channels = ARRAY_SIZE(mx23_lradc_chan_spec);
+       } else {
+               iio->channels = mx28_lradc_chan_spec;
+               iio->num_channels = ARRAY_SIZE(mx28_lradc_chan_spec);
+       }
+
        ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
                                &mxs_lradc_trigger_handler,
                                &mxs_lradc_buffer_ops);
@@ -1707,6 +1747,6 @@ static struct platform_driver mxs_lradc_driver = {
 module_platform_driver(mxs_lradc_driver);
 
 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
-MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
+MODULE_DESCRIPTION("Freescale MXS LRADC driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 75ddd4f801a3daf9346c186e3a7dc9510b36817a..78fe0b55728020ed7d2c2c4ed90e0c152d45ec01 100644 (file)
@@ -124,7 +124,6 @@ static struct i2c_driver adt7316_driver = {
        .driver = {
                .name = "adt7316",
                .pm = ADT7316_PM_OPS,
-               .owner  = THIS_MODULE,
        },
        .probe = adt7316_i2c_probe,
        .id_table = adt7316_i2c_id,
index c54d5b5443a637ac10c40678f7aa54fdf8349700..6d38854c38c89a1032da9aedcc4bf65fec90e216 100644 (file)
@@ -214,6 +214,7 @@ static struct device iio_evgen_dev = {
        .groups = iio_evgen_groups,
        .release = &iio_evgen_release,
 };
+
 static __init int iio_dummy_evgen_init(void)
 {
        int ret = iio_dummy_evgen_create();
index 1629a8a6bf269ef672b35820f7746c5f767039a7..381f90ff468a983ca6ff7b318dadca61a7a168b6 100644 (file)
@@ -611,7 +611,6 @@ static int iio_dummy_probe(int index)
         */
        iio_dummy_devs[index] = indio_dev;
 
-
        /*
         * Set the device name.
         *
@@ -675,7 +674,6 @@ static void iio_dummy_remove(int index)
         */
        struct iio_dev *indio_dev = iio_dummy_devs[index];
 
-
        /* Unregister the device */
        iio_device_unregister(indio_dev);
 
index e877a99540abced251ef937f70a4abe7cab89f4a..8d00224e6fadb2ba8cd37debf0bf2e17d28ed27d 100644 (file)
@@ -119,6 +119,7 @@ static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
 {
        return 0;
 };
+
 static inline
 void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev)
 {};
index a651b8922d0a93039eb8ef6c71a35e7dd9ea0f48..00ed7745f3c5b768df4c707f78c0e2ea5c388326 100644 (file)
@@ -32,6 +32,7 @@ static const s16 fakedata[] = {
        [diffvoltage3m4] = -2,
        [accelx] = 344,
 };
+
 /**
  * iio_simple_dummy_trigger_h() - the trigger handler function
  * @irq: the interrupt number
@@ -178,7 +179,6 @@ error_free_buffer:
        iio_kfifo_free(indio_dev->buffer);
 error_ret:
        return ret;
-
 }
 
 /**
index ecc563cb6cb9ad236601b5b0e70fcf4c7d24ab3f..73108baf80adffe09bf84cee11d34e1b6bee6963 100644 (file)
@@ -120,7 +120,7 @@ int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
                                      const struct iio_chan_spec *chan,
                                      enum iio_event_type type,
                                      enum iio_event_direction dir,
-                                         enum iio_event_info info,
+                                     enum iio_event_info info,
                                      int *val, int *val2)
 {
        struct iio_dummy_state *st = iio_priv(indio_dev);
@@ -143,7 +143,7 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
                                       const struct iio_chan_spec *chan,
                                       enum iio_event_type type,
                                       enum iio_event_direction dir,
-                                          enum iio_event_info info,
+                                      enum iio_event_info info,
                                       int val, int val2)
 {
        struct iio_dummy_state *st = iio_priv(indio_dev);
index e646c5d2400460c40016e21167452d962d688cad..019ba5245c2363ac2e671dcde9c4378eb19dcc02 100644 (file)
@@ -838,7 +838,6 @@ static struct i2c_driver isl29018_driver = {
                        .name = "isl29018",
                        .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
                        .pm = ISL29018_PM_OPS,
-                       .owner = THIS_MODULE,
                        .of_match_table = isl29018_of_match,
                    },
        .probe   = isl29018_probe,
index e5b2fdc2334b71792355b718b209606be04c73f6..cd6f2727aa58739b329acc46ee49a3321f8daa39 100644 (file)
@@ -547,7 +547,6 @@ static struct i2c_driver isl29028_driver = {
        .class  = I2C_CLASS_HWMON,
        .driver  = {
                .name = "isl29028",
-               .owner = THIS_MODULE,
                .of_match_table = isl29028_of_match,
        },
        .probe   = isl29028_probe,
index 52ca5412a18d4bb68ee93e69c5422e801473fa8d..52f4195cf6f4bb25acea9cf93b3b6af063d3d373 100644 (file)
@@ -168,7 +168,7 @@ struct ade7854_state {
 
 };
 
-extern int ade7854_probe(struct iio_dev *indio_dev, struct device *dev);
-extern int ade7854_remove(struct iio_dev *indio_dev);
+int ade7854_probe(struct iio_dev *indio_dev, struct device *dev);
+int ade7854_remove(struct iio_dev *indio_dev);
 
 #endif
index 3c1c8c6c4a6c8ea224edab37c1f64f8d87f8d9e2..9fe48ef11473c204fae7e8a3fb542ded85226eee 100644 (file)
@@ -79,7 +79,8 @@ static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state)
 }
 
 static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
+                                           struct device_attribute *attr,
+                                           const char *buf, size_t count)
 {
        struct iio_trigger *trig = to_iio_trigger(dev);
        struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
@@ -116,8 +117,8 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
 }
 
 static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
-                                struct device_attribute *attr,
-                                char *buf)
+                                          struct device_attribute *attr,
+                                          char *buf)
 {
        struct iio_trigger *trig = to_iio_trigger(dev);
        struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
index 0c1976ddee7489c6d4165e3e4e01990e0b7952e3..2db885750fb84384653a54ab97089c835f479dca 100644 (file)
@@ -37,7 +37,7 @@ static int iio_trig_periodic_rtc_set_state(struct iio_trigger *trig, bool state)
        if (trig_info->frequency == 0 && state)
                return -EINVAL;
        dev_dbg(&trig_info->rtc->dev, "trigger frequency is %u\n",
-                       trig_info->frequency);
+               trig_info->frequency);
        ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
        if (ret == 0)
                trig_info->state = state;
@@ -74,8 +74,9 @@ static ssize_t iio_trig_periodic_write_freq(struct device *dev,
                if (ret == 0 && trig_info->state && trig_info->frequency == 0)
                        ret = rtc_irq_set_state(trig_info->rtc,
                                                &trig_info->task, 1);
-       } else
+       } else {
                ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 0);
+       }
        if (ret)
                goto error_ret;
 
index 5dd9cdfae30ccb9b793c167ae7275ac7ca7b07f9..01961d9e6c363c25ba4764415f842dc3334c56ed 100644 (file)
@@ -134,7 +134,7 @@ void cfs_get_random_bytes(void *buf, int size);
 /* container_of depends on "likely" which is defined in libcfs_private.h */
 static inline void *__container_of(void *ptr, unsigned long shift)
 {
-       if (unlikely(IS_ERR(ptr) || ptr == NULL))
+       if (IS_ERR_OR_NULL(ptr))
                return ptr;
        return (char *)ptr - shift;
 }
@@ -148,4 +148,17 @@ void *libcfs_kvzalloc(size_t size, gfp_t flags);
 void *libcfs_kvzalloc_cpt(struct cfs_cpt_table *cptab, int cpt, size_t size,
                          gfp_t flags);
 
+extern struct miscdevice libcfs_dev;
+/**
+ * The path of debug log dump upcall script.
+ */
+extern char lnet_upcall[1024];
+extern char lnet_debug_log_upcall[1024];
+
+extern void libcfs_init_nidstrings(void);
+
+extern struct cfs_psdev_ops libcfs_psdev_ops;
+
+extern struct cfs_wi_sched *cfs_sched_rehash;
+
 #endif /* _LIBCFS_H */
index 8251ac932e37b22110c0cf5deacde6c53ecc4e78..a3aa644154e24a578b84d125d26e811479656f2b 100644 (file)
@@ -50,7 +50,6 @@ extern unsigned int libcfs_stack;
 extern unsigned int libcfs_debug;
 extern unsigned int libcfs_printk;
 extern unsigned int libcfs_console_ratelimit;
-extern unsigned int libcfs_watchdog_ratelimit;
 extern unsigned int libcfs_console_max_delay;
 extern unsigned int libcfs_console_min_delay;
 extern unsigned int libcfs_console_backoff;
index eea55d94e6be696d844e08fed58988f41c0b9d69..aa69c6a33d19dc0a6635213c55d177b64aa29f8c 100644 (file)
@@ -79,14 +79,16 @@ static inline int cfs_fail_check_set(__u32 id, __u32 value,
 {
        int ret = 0;
 
-       if (unlikely(CFS_FAIL_PRECHECK(id) &&
-                    (ret = __cfs_fail_check_set(id, value, set)))) {
-               if (quiet) {
-                       CDEBUG(D_INFO, "*** cfs_fail_loc=%x, val=%u***\n",
-                              id, value);
-               } else {
-                       LCONSOLE_INFO("*** cfs_fail_loc=%x, val=%u***\n",
-                                     id, value);
+       if (unlikely(CFS_FAIL_PRECHECK(id))) {
+               ret = __cfs_fail_check_set(id, value, set);
+               if (ret) {
+                       if (quiet) {
+                               CDEBUG(D_INFO, "*** cfs_fail_loc=%x, val=%u***\n",
+                                      id, value);
+                       } else {
+                               LCONSOLE_INFO("*** cfs_fail_loc=%x, val=%u***\n",
+                                             id, value);
+                       }
                }
        }
 
index ed37d26eb20df8217a4c8d99f45d8f9463f4eba8..9544860e32920a851dd35f20757a199ea5346fef 100644 (file)
@@ -87,24 +87,6 @@ do {                                                             \
        lbug_with_loc(&msgdata);                                        \
 } while (0)
 
-extern atomic_t libcfs_kmemory;
-/*
- * Memory
- */
-
-# define libcfs_kmem_inc(ptr, size)            \
-do {                                           \
-       atomic_add(size, &libcfs_kmemory);      \
-} while (0)
-
-# define libcfs_kmem_dec(ptr, size)            \
-do {                                           \
-       atomic_sub(size, &libcfs_kmemory);      \
-} while (0)
-
-# define libcfs_kmem_read()                    \
-       atomic_read(&libcfs_kmemory)
-
 #ifndef LIBCFS_VMALLOC_SIZE
 #define LIBCFS_VMALLOC_SIZE    (2 << PAGE_CACHE_SHIFT) /* 2 pages */
 #endif
@@ -121,14 +103,9 @@ do {                                                                           \
        if (unlikely((ptr) == NULL)) {                                      \
                CERROR("LNET: out of memory at %s:%d (tried to alloc '"     \
                       #ptr "' = %d)\n", __FILE__, __LINE__, (int)(size));  \
-               CERROR("LNET: %d total bytes allocated by lnet\n",          \
-                      libcfs_kmem_read());                                 \
        } else {                                                            \
                memset((ptr), 0, (size));                                   \
-               libcfs_kmem_inc((ptr), (size));                             \
-               CDEBUG(D_MALLOC, "alloc '" #ptr "': %d at %p (tot %d).\n",  \
-                      (int)(size), (ptr), libcfs_kmem_read());             \
-       }                                                                  \
+       }                                                                   \
 } while (0)
 
 /**
@@ -180,9 +157,6 @@ do {                                                                    \
                       "%s:%d\n", s, __FILE__, __LINE__);              \
                break;                                            \
        }                                                              \
-       libcfs_kmem_dec((ptr), s);                                    \
-       CDEBUG(D_MALLOC, "kfreed '" #ptr "': %d at %p (tot %d).\n",     \
-              s, (ptr), libcfs_kmem_read());                           \
        if (unlikely(s > LIBCFS_VMALLOC_SIZE))                    \
                vfree(ptr);                                 \
        else                                                        \
index 509dc1e5c3b1850f4d140584b64a00e3fa685a09..478e9582ff5414bf63e7e27ac963413f2d22bb46 100644 (file)
@@ -102,6 +102,4 @@ int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
 int cfs_ip_addr_match(__u32 addr, struct list_head *list);
 void cfs_ip_addr_free(struct list_head *list);
 
-#define        strtoul(str, endp, base)        simple_strtoul(str, endp, base)
-
 #endif
index 4eb24a11b02a33ece27e487c1b1f81e6ceebfb45..c29d2ced258ce4339f684da4e83bf57050f5f6c1 100644 (file)
@@ -1390,7 +1390,7 @@ static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps,
                .max_pages_per_fmr = LNET_MAX_PAYLOAD/PAGE_SIZE,
                .page_shift        = PAGE_SHIFT,
                .access            = (IB_ACCESS_LOCAL_WRITE |
-                                     IB_ACCESS_REMOTE_WRITE),
+                                     IB_ACCESS_REMOTE_WRITE),
                .pool_size         = fps->fps_pool_size,
                .dirty_watermark   = fps->fps_flush_trigger,
                .flush_function    = NULL,
@@ -1789,140 +1789,6 @@ struct list_head *kiblnd_pool_alloc_node(kib_poolset_t *ps)
        goto again;
 }
 
-void kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr)
-{
-       kib_pmr_pool_t *ppo = pmr->pmr_pool;
-       struct ib_mr *mr = pmr->pmr_mr;
-
-       pmr->pmr_mr = NULL;
-       kiblnd_pool_free_node(&ppo->ppo_pool, &pmr->pmr_list);
-       if (mr != NULL)
-               ib_dereg_mr(mr);
-}
-
-int kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev,
-                   kib_rdma_desc_t *rd, __u64 *iova, kib_phys_mr_t **pp_pmr)
-{
-       kib_phys_mr_t *pmr;
-       struct list_head *node;
-       int rc;
-       int i;
-
-       node = kiblnd_pool_alloc_node(&pps->pps_poolset);
-       if (node == NULL) {
-               CERROR("Failed to allocate PMR descriptor\n");
-               return -ENOMEM;
-       }
-
-       pmr = container_of(node, kib_phys_mr_t, pmr_list);
-       if (pmr->pmr_pool->ppo_hdev != hdev) {
-               kiblnd_pool_free_node(&pmr->pmr_pool->ppo_pool, node);
-               return -EAGAIN;
-       }
-
-       for (i = 0; i < rd->rd_nfrags; i++) {
-               pmr->pmr_ipb[i].addr = rd->rd_frags[i].rf_addr;
-               pmr->pmr_ipb[i].size = rd->rd_frags[i].rf_nob;
-       }
-
-       pmr->pmr_mr = ib_reg_phys_mr(hdev->ibh_pd,
-                                    pmr->pmr_ipb, rd->rd_nfrags,
-                                    IB_ACCESS_LOCAL_WRITE |
-                                    IB_ACCESS_REMOTE_WRITE,
-                                    iova);
-       if (!IS_ERR(pmr->pmr_mr)) {
-               pmr->pmr_iova = *iova;
-               *pp_pmr = pmr;
-               return 0;
-       }
-
-       rc = PTR_ERR(pmr->pmr_mr);
-       CERROR("Failed ib_reg_phys_mr: %d\n", rc);
-
-       pmr->pmr_mr = NULL;
-       kiblnd_pool_free_node(&pmr->pmr_pool->ppo_pool, node);
-
-       return rc;
-}
-
-static void kiblnd_destroy_pmr_pool(kib_pool_t *pool)
-{
-       kib_pmr_pool_t *ppo = container_of(pool, kib_pmr_pool_t, ppo_pool);
-       kib_phys_mr_t *pmr;
-       kib_phys_mr_t *tmp;
-
-       LASSERT(pool->po_allocated == 0);
-
-       list_for_each_entry_safe(pmr, tmp, &pool->po_free_list, pmr_list) {
-               LASSERT(pmr->pmr_mr == NULL);
-               list_del(&pmr->pmr_list);
-
-               if (pmr->pmr_ipb != NULL) {
-                       LIBCFS_FREE(pmr->pmr_ipb,
-                                   IBLND_MAX_RDMA_FRAGS *
-                                   sizeof(struct ib_phys_buf));
-               }
-
-               LIBCFS_FREE(pmr, sizeof(kib_phys_mr_t));
-       }
-
-       kiblnd_fini_pool(pool);
-       if (ppo->ppo_hdev != NULL)
-               kiblnd_hdev_decref(ppo->ppo_hdev);
-
-       LIBCFS_FREE(ppo, sizeof(kib_pmr_pool_t));
-}
-
-static inline int kiblnd_pmr_pool_size(int ncpts)
-{
-       int size = *kiblnd_tunables.kib_pmr_pool_size / ncpts;
-
-       return max(IBLND_PMR_POOL, size);
-}
-
-static int kiblnd_create_pmr_pool(kib_poolset_t *ps, int size,
-                                 kib_pool_t **pp_po)
-{
-       struct kib_pmr_pool *ppo;
-       struct kib_pool *pool;
-       kib_phys_mr_t *pmr;
-       int i;
-
-       LIBCFS_CPT_ALLOC(ppo, lnet_cpt_table(),
-                        ps->ps_cpt, sizeof(kib_pmr_pool_t));
-       if (ppo == NULL) {
-               CERROR("Failed to allocate PMR pool\n");
-               return -ENOMEM;
-       }
-
-       pool = &ppo->ppo_pool;
-       kiblnd_init_pool(ps, pool, size);
-
-       for (i = 0; i < size; i++) {
-               LIBCFS_CPT_ALLOC(pmr, lnet_cpt_table(),
-                                ps->ps_cpt, sizeof(kib_phys_mr_t));
-               if (pmr == NULL)
-                       break;
-
-               pmr->pmr_pool = ppo;
-               LIBCFS_CPT_ALLOC(pmr->pmr_ipb, lnet_cpt_table(), ps->ps_cpt,
-                                IBLND_MAX_RDMA_FRAGS * sizeof(*pmr->pmr_ipb));
-               if (pmr->pmr_ipb == NULL)
-                       break;
-
-               list_add(&pmr->pmr_list, &pool->po_free_list);
-       }
-
-       if (i < size) {
-               ps->ps_pool_destroy(pool);
-               return -ENOMEM;
-       }
-
-       ppo->ppo_hdev = kiblnd_current_hdev(ps->ps_net->ibn_dev);
-       *pp_po = pool;
-       return 0;
-}
-
 static void kiblnd_destroy_tx_pool(kib_pool_t *pool)
 {
        kib_tx_pool_t *tpo = container_of(pool, kib_tx_pool_t, tpo_pool);
@@ -2078,7 +1944,6 @@ static void kiblnd_net_fini_pools(kib_net_t *net)
        cfs_cpt_for_each(i, lnet_cpt_table()) {
                kib_tx_poolset_t *tps;
                kib_fmr_poolset_t *fps;
-               kib_pmr_poolset_t *pps;
 
                if (net->ibn_tx_ps != NULL) {
                        tps = net->ibn_tx_ps[i];
@@ -2089,11 +1954,6 @@ static void kiblnd_net_fini_pools(kib_net_t *net)
                        fps = net->ibn_fmr_ps[i];
                        kiblnd_fini_fmr_poolset(fps);
                }
-
-               if (net->ibn_pmr_ps != NULL) {
-                       pps = net->ibn_pmr_ps[i];
-                       kiblnd_fini_poolset(&pps->pps_poolset);
-               }
        }
 
        if (net->ibn_tx_ps != NULL) {
@@ -2105,18 +1965,13 @@ static void kiblnd_net_fini_pools(kib_net_t *net)
                cfs_percpt_free(net->ibn_fmr_ps);
                net->ibn_fmr_ps = NULL;
        }
-
-       if (net->ibn_pmr_ps != NULL) {
-               cfs_percpt_free(net->ibn_pmr_ps);
-               net->ibn_pmr_ps = NULL;
-       }
 }
 
 static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
 {
        unsigned long flags;
        int cpt;
-       int rc;
+       int             rc = 0;
        int i;
 
        read_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
@@ -2137,12 +1992,16 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
                goto failed;
        }
 
-       /* TX pool must be created later than FMR/PMR, see LU-2268
-        * for details */
+       /*
+        * TX pool must be created later than FMR, see LU-2268
+        * for details
+        */
        LASSERT(net->ibn_tx_ps == NULL);
 
-       /* premapping can fail if ibd_nmr > 1, so we always create
-        * FMR/PMR pool and map-on-demand if premapping failed */
+       /*
+        * premapping can fail if ibd_nmr > 1, so we always create
+        * FMR pool and map-on-demand if premapping failed
+        */
 
        net->ibn_fmr_ps = cfs_percpt_alloc(lnet_cpt_table(),
                                           sizeof(kib_fmr_poolset_t));
@@ -2158,7 +2017,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
                                             kiblnd_fmr_pool_size(ncpts),
                                             kiblnd_fmr_flush_trigger(ncpts));
                if (rc == -ENOSYS && i == 0) /* no FMR */
-                       break; /* create PMR pool */
+                       break;
 
                if (rc != 0) { /* a real error */
                        CERROR("Can't initialize FMR pool for CPT %d: %d\n",
@@ -2175,38 +2034,8 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
        cfs_percpt_free(net->ibn_fmr_ps);
        net->ibn_fmr_ps = NULL;
 
-       CWARN("Device does not support FMR, failing back to PMR\n");
-
-       if (*kiblnd_tunables.kib_pmr_pool_size <
-           *kiblnd_tunables.kib_ntx / 4) {
-               CERROR("Can't set pmr pool size (%d) < ntx / 4(%d)\n",
-                      *kiblnd_tunables.kib_pmr_pool_size,
-                      *kiblnd_tunables.kib_ntx / 4);
-               rc = -EINVAL;
-               goto failed;
-       }
-
-       net->ibn_pmr_ps = cfs_percpt_alloc(lnet_cpt_table(),
-                                          sizeof(kib_pmr_poolset_t));
-       if (net->ibn_pmr_ps == NULL) {
-               CERROR("Failed to allocate PMR pool array\n");
-               rc = -ENOMEM;
-               goto failed;
-       }
-
-       for (i = 0; i < ncpts; i++) {
-               cpt = (cpts == NULL) ? i : cpts[i];
-               rc = kiblnd_init_poolset(&net->ibn_pmr_ps[cpt]->pps_poolset,
-                                        cpt, net, "PMR",
-                                        kiblnd_pmr_pool_size(ncpts),
-                                        kiblnd_create_pmr_pool,
-                                        kiblnd_destroy_pmr_pool, NULL, NULL);
-               if (rc != 0) {
-                       CERROR("Can't initialize PMR pool for CPT %d: %d\n",
-                              cpt, rc);
+       CWARN("Device does not support FMR\n");
                        goto failed;
-               }
-       }
 
  create_tx_pool:
        net->ibn_tx_ps = cfs_percpt_alloc(lnet_cpt_table(),
@@ -2318,17 +2147,13 @@ void kiblnd_hdev_destroy(kib_hca_dev_t *hdev)
 static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
 {
        struct ib_mr *mr;
-       int i;
        int rc;
-       __u64 mm_size;
-       __u64 mr_size;
        int acflags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE;
 
        rc = kiblnd_hdev_get_attr(hdev);
        if (rc != 0)
                return rc;
 
-       if (hdev->ibh_mr_shift == 64) {
                LIBCFS_ALLOC(hdev->ibh_mrs, 1 * sizeof(*hdev->ibh_mrs));
                if (hdev->ibh_mrs == NULL) {
                        CERROR("Failed to allocate MRs table\n");
@@ -2347,53 +2172,6 @@ static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
 
                hdev->ibh_mrs[0] = mr;
 
-               goto out;
-       }
-
-       mr_size = 1ULL << hdev->ibh_mr_shift;
-       mm_size = (unsigned long)high_memory - PAGE_OFFSET;
-
-       hdev->ibh_nmrs = (int)((mm_size + mr_size - 1) >> hdev->ibh_mr_shift);
-
-       if (hdev->ibh_mr_shift < 32 || hdev->ibh_nmrs > 1024) {
-               /* it's 4T..., assume we will re-code at that time */
-               CERROR("Can't support memory size: x%#llx with MR size: x%#llx\n",
-                      mm_size, mr_size);
-               return -EINVAL;
-       }
-
-       /* create an array of MRs to cover all memory */
-       LIBCFS_ALLOC(hdev->ibh_mrs, sizeof(*hdev->ibh_mrs) * hdev->ibh_nmrs);
-       if (hdev->ibh_mrs == NULL) {
-               CERROR("Failed to allocate MRs' table\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < hdev->ibh_nmrs; i++) {
-               struct ib_phys_buf ipb;
-               __u64 iova;
-
-               ipb.size = hdev->ibh_mr_size;
-               ipb.addr = i * mr_size;
-               iova = ipb.addr;
-
-               mr = ib_reg_phys_mr(hdev->ibh_pd, &ipb, 1, acflags, &iova);
-               if (IS_ERR(mr)) {
-                       CERROR("Failed ib_reg_phys_mr addr %#llx size %#llx : %ld\n",
-                              ipb.addr, ipb.size, PTR_ERR(mr));
-                       kiblnd_hdev_cleanup_mrs(hdev);
-                       return PTR_ERR(mr);
-               }
-
-               LASSERT(iova == ipb.addr);
-
-               hdev->ibh_mrs[i] = mr;
-       }
-
-out:
-       if (hdev->ibh_mr_size != ~0ULL || hdev->ibh_nmrs != 1)
-               LCONSOLE_INFO("Register global MR array, MR size: %#llx, array size: %d\n",
-                             hdev->ibh_mr_size, hdev->ibh_nmrs);
        return 0;
 }
 
@@ -2564,14 +2342,9 @@ int kiblnd_dev_failover(kib_dev_t *dev)
                        kiblnd_fail_poolset(&net->ibn_tx_ps[i]->tps_poolset,
                                            &zombie_tpo);
 
-                       if (net->ibn_fmr_ps != NULL) {
+                       if (net->ibn_fmr_ps)
                                kiblnd_fail_fmr_poolset(net->ibn_fmr_ps[i],
                                                        &zombie_fpo);
-
-                       } else if (net->ibn_pmr_ps != NULL) {
-                               kiblnd_fail_poolset(&net->ibn_pmr_ps[i]->
-                                                   pps_poolset, &zombie_ppo);
-                       }
                }
        }
 
@@ -2667,9 +2440,6 @@ static void kiblnd_base_shutdown(void)
 
        LASSERT(list_empty(&kiblnd_data.kib_devs));
 
-       CDEBUG(D_MALLOC, "before LND base cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
-
        switch (kiblnd_data.kib_init) {
        default:
                LBUG();
@@ -2720,9 +2490,6 @@ static void kiblnd_base_shutdown(void)
        if (kiblnd_data.kib_scheds != NULL)
                cfs_percpt_free(kiblnd_data.kib_scheds);
 
-       CDEBUG(D_MALLOC, "after LND base cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
-
        kiblnd_data.kib_init = IBLND_INIT_NOTHING;
        module_put(THIS_MODULE);
 }
@@ -2739,9 +2506,6 @@ void kiblnd_shutdown(lnet_ni_t *ni)
        if (net == NULL)
                goto out;
 
-       CDEBUG(D_MALLOC, "before LND net cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
-
        write_lock_irqsave(g_lock, flags);
        net->ibn_shutdown = 1;
        write_unlock_irqrestore(g_lock, flags);
@@ -2786,9 +2550,6 @@ void kiblnd_shutdown(lnet_ni_t *ni)
                break;
        }
 
-       CDEBUG(D_MALLOC, "after LND net cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
-
        net->ibn_init = IBLND_INIT_NOTHING;
        ni->ni_data = NULL;
 
index f5d1d9f8f1ed3e6f0ea1745094f8cb250304d637..f4b6c33ac318ca3b9a5623d7665dc5a2d07b123f 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <linux/fs.h>
 #include <linux/file.h>
@@ -104,7 +104,6 @@ typedef struct {
        int          *kib_map_on_demand;     /* map-on-demand if RD has more
                                              * fragments than this value, 0
                                              * disable map-on-demand */
-       int          *kib_pmr_pool_size;     /* # physical MR in pool */
        int          *kib_fmr_pool_size;     /* # FMRs in pool */
        int          *kib_fmr_flush_trigger; /* When to trigger FMR flush */
        int          *kib_fmr_cache;         /* enable FMR pool cache? */
@@ -120,7 +119,7 @@ extern kib_tunables_t  kiblnd_tunables;
 #define IBLND_CREDIT_HIGHWATER_V1 7 /* V1 only : when eagerly to return credits */
 
 #define IBLND_CREDITS_DEFAULT     8 /* default # of peer credits */
-#define IBLND_CREDITS_MAX        ((typeof(((kib_msg_t*) 0)->ibm_credits)) - 1)  /* Max # of peer credits */
+#define IBLND_CREDITS_MAX        ((typeof(((kib_msg_t *) 0)->ibm_credits)) - 1)  /* Max # of peer credits */
 
 #define IBLND_MSG_QUEUE_SIZE(v)    ((v) == IBLND_MSG_VERSION_1 ? \
                                     IBLND_MSG_QUEUE_SIZE_V1 :   \
@@ -163,7 +162,6 @@ kiblnd_concurrent_sends_v1(void)
 /* Pools (shared by connections on each CPT) */
 /* These pools can grow at runtime, so don't need give a very large value */
 #define IBLND_TX_POOL                  256
-#define IBLND_PMR_POOL                 256
 #define IBLND_FMR_POOL                 256
 #define IBLND_FMR_POOL_FLUSH           192
 
@@ -232,17 +230,6 @@ typedef struct {
        struct page        *ibp_pages[0];       /* page array */
 } kib_pages_t;
 
-struct kib_pmr_pool;
-
-typedef struct {
-       struct list_head    pmr_list;           /* chain node */
-       struct ib_phys_buf  *pmr_ipb;           /* physical buffer */
-       struct ib_mr        *pmr_mr;            /* IB MR */
-       struct kib_pmr_pool *pmr_pool;          /* owner of this MR */
-       __u64               pmr_iova;           /* Virtual I/O address */
-       int                 pmr_refcount;       /* reference count */
-} kib_phys_mr_t;
-
 struct kib_pool;
 struct kib_poolset;
 
@@ -298,15 +285,6 @@ typedef struct {
        kib_pages_t           *tpo_tx_pages;      /* premapped tx msg pages */
 } kib_tx_pool_t;
 
-typedef struct {
-       kib_poolset_t         pps_poolset;        /* pool-set */
-} kib_pmr_poolset_t;
-
-typedef struct kib_pmr_pool {
-       struct kib_hca_dev    *ppo_hdev;          /* device for this pool */
-       kib_pool_t            ppo_pool;           /* pool */
-} kib_pmr_pool_t;
-
 typedef struct {
        spinlock_t            fps_lock;            /* serialize */
        struct kib_net        *fps_net;            /* IB network */
@@ -347,7 +325,6 @@ typedef struct kib_net {
 
        kib_tx_poolset_t      **ibn_tx_ps;    /* tx pool-set */
        kib_fmr_poolset_t     **ibn_fmr_ps;   /* fmr pool-set */
-       kib_pmr_poolset_t     **ibn_pmr_ps;   /* pmr pool-set */
 
        kib_dev_t             *ibn_dev;       /* underlying IB device */
 } kib_net_t;
@@ -519,7 +496,7 @@ typedef struct kib_rx                         /* receive message */
        enum ib_wc_status      rx_status;     /* completion status */
        kib_msg_t              *rx_msg;       /* message buffer (host vaddr) */
        __u64                  rx_msgaddr;    /* message buffer (I/O addr) */
-       DECLARE_PCI_UNMAP_ADDR (rx_msgunmap); /* for dma_unmap_single() */
+       DECLARE_PCI_UNMAP_ADDR(rx_msgunmap);  /* for dma_unmap_single() */
        struct ib_recv_wr      rx_wrq;        /* receive work item... */
        struct ib_sge          rx_sge;        /* ...and its memory */
 } kib_rx_t;
@@ -546,7 +523,7 @@ typedef struct kib_tx                         /* transmit message */
                                               * completion */
        kib_msg_t              *tx_msg;       /* message buffer (host vaddr) */
        __u64                  tx_msgaddr;    /* message buffer (I/O addr) */
-       DECLARE_PCI_UNMAP_ADDR (tx_msgunmap); /* for dma_unmap_single() */
+       DECLARE_PCI_UNMAP_ADDR(tx_msgunmap);  /* for dma_unmap_single() */
        int                    tx_nwrq;       /* # send work items */
        struct ib_send_wr      *tx_wrq;       /* send work items... */
        struct ib_sge          *tx_sge;       /* ...and their memory */
@@ -554,10 +531,7 @@ typedef struct kib_tx                         /* transmit message */
        int                    tx_nfrags;     /* # entries in... */
        struct scatterlist     *tx_frags;     /* dma_map_sg descriptor */
        __u64                  *tx_pages;     /* rdma phys page addrs */
-       union {
-               kib_phys_mr_t  *pmr;          /* MR for physical buffer */
-               kib_fmr_t      fmr;           /* FMR */
-       }                      tx_u;
+       kib_fmr_t               fmr;          /* FMR */
        int                    tx_dmadir;     /* dma direction */
 } kib_tx_t;
 
@@ -642,19 +616,19 @@ typedef struct kib_peer {
 
 extern kib_data_t kiblnd_data;
 
-extern void kiblnd_hdev_destroy(kib_hca_dev_t *hdev);
+void kiblnd_hdev_destroy(kib_hca_dev_t *hdev);
 
 static inline void
 kiblnd_hdev_addref_locked(kib_hca_dev_t *hdev)
 {
-       LASSERT (atomic_read(&hdev->ibh_ref) > 0);
+       LASSERT(atomic_read(&hdev->ibh_ref) > 0);
        atomic_inc(&hdev->ibh_ref);
 }
 
 static inline void
 kiblnd_hdev_decref(kib_hca_dev_t *hdev)
 {
-       LASSERT (atomic_read(&hdev->ibh_ref) > 0);
+       LASSERT(atomic_read(&hdev->ibh_ref) > 0);
        if (atomic_dec_and_test(&hdev->ibh_ref))
                kiblnd_hdev_destroy(hdev);
 }
@@ -701,7 +675,7 @@ do {                                                                        \
 do {                                                       \
        CDEBUG(D_NET, "peer[%p] -> %s (%d)++\n",                \
               (peer), libcfs_nid2str((peer)->ibp_nid),  \
-              atomic_read (&(peer)->ibp_refcount));    \
+              atomic_read(&(peer)->ibp_refcount));     \
        atomic_inc(&(peer)->ibp_refcount);                \
 } while (0)
 
@@ -709,32 +683,32 @@ do {                                                          \
 do {                                                       \
        CDEBUG(D_NET, "peer[%p] -> %s (%d)--\n",                \
               (peer), libcfs_nid2str((peer)->ibp_nid),  \
-              atomic_read (&(peer)->ibp_refcount));    \
+              atomic_read(&(peer)->ibp_refcount));     \
        LASSERT_ATOMIC_POS(&(peer)->ibp_refcount);            \
        if (atomic_dec_and_test(&(peer)->ibp_refcount))     \
                kiblnd_destroy_peer(peer);                    \
 } while (0)
 
 static inline struct list_head *
-kiblnd_nid2peerlist (lnet_nid_t nid)
+kiblnd_nid2peerlist(lnet_nid_t nid)
 {
        unsigned int hash =
                ((unsigned int)nid) % kiblnd_data.kib_peer_hash_size;
 
-       return (&kiblnd_data.kib_peers [hash]);
+       return &kiblnd_data.kib_peers[hash];
 }
 
 static inline int
-kiblnd_peer_active (kib_peer_t *peer)
+kiblnd_peer_active(kib_peer_t *peer)
 {
        /* Am I in the peer hash table? */
-       return (!list_empty(&peer->ibp_list));
+       return !list_empty(&peer->ibp_list);
 }
 
 static inline kib_conn_t *
-kiblnd_get_conn_locked (kib_peer_t *peer)
+kiblnd_get_conn_locked(kib_peer_t *peer)
 {
-       LASSERT (!list_empty(&peer->ibp_conns));
+       LASSERT(!list_empty(&peer->ibp_conns));
 
        /* just return the first connection */
        return list_entry(peer->ibp_conns.next, kib_conn_t, ibc_list);
@@ -751,7 +725,7 @@ kiblnd_send_keepalive(kib_conn_t *conn)
 static inline int
 kiblnd_need_noop(kib_conn_t *conn)
 {
-       LASSERT (conn->ibc_state >= IBLND_CONN_ESTABLISHED);
+       LASSERT(conn->ibc_state >= IBLND_CONN_ESTABLISHED);
 
        if (conn->ibc_outstanding_credits <
            IBLND_CREDITS_HIGHWATER(conn->ibc_version) &&
@@ -788,7 +762,7 @@ kiblnd_abort_receives(kib_conn_t *conn)
 }
 
 static inline const char *
-kiblnd_queue2str (kib_conn_t *conn, struct list_head *q)
+kiblnd_queue2str(kib_conn_t *conn, struct list_head *q)
 {
        if (q == &conn->ibc_tx_queue)
                return "tx_queue";
@@ -815,43 +789,43 @@ kiblnd_queue2str (kib_conn_t *conn, struct list_head *q)
 #define IBLND_WID_MASK  3UL
 
 static inline __u64
-kiblnd_ptr2wreqid (void *ptr, int type)
+kiblnd_ptr2wreqid(void *ptr, int type)
 {
        unsigned long lptr = (unsigned long)ptr;
 
-       LASSERT ((lptr & IBLND_WID_MASK) == 0);
-       LASSERT ((type & ~IBLND_WID_MASK) == 0);
+       LASSERT((lptr & IBLND_WID_MASK) == 0);
+       LASSERT((type & ~IBLND_WID_MASK) == 0);
        return (__u64)(lptr | type);
 }
 
 static inline void *
-kiblnd_wreqid2ptr (__u64 wreqid)
+kiblnd_wreqid2ptr(__u64 wreqid)
 {
        return (void *)(((unsigned long)wreqid) & ~IBLND_WID_MASK);
 }
 
 static inline int
-kiblnd_wreqid2type (__u64 wreqid)
+kiblnd_wreqid2type(__u64 wreqid)
 {
-       return (wreqid & IBLND_WID_MASK);
+       return wreqid & IBLND_WID_MASK;
 }
 
 static inline void
-kiblnd_set_conn_state (kib_conn_t *conn, int state)
+kiblnd_set_conn_state(kib_conn_t *conn, int state)
 {
        conn->ibc_state = state;
        mb();
 }
 
 static inline void
-kiblnd_init_msg (kib_msg_t *msg, int type, int body_nob)
+kiblnd_init_msg(kib_msg_t *msg, int type, int body_nob)
 {
        msg->ibm_type = type;
        msg->ibm_nob  = offsetof(kib_msg_t, ibm_u) + body_nob;
 }
 
 static inline int
-kiblnd_rd_size (kib_rdma_desc_t *rd)
+kiblnd_rd_size(kib_rdma_desc_t *rd)
 {
        int   i;
        int   size;
@@ -887,7 +861,7 @@ kiblnd_rd_consume_frag(kib_rdma_desc_t *rd, int index, __u32 nob)
                rd->rd_frags[index].rf_addr += nob;
                rd->rd_frags[index].rf_nob  -= nob;
        } else {
-               index ++;
+               index++;
        }
 
        return index;
@@ -896,8 +870,8 @@ kiblnd_rd_consume_frag(kib_rdma_desc_t *rd, int index, __u32 nob)
 static inline int
 kiblnd_rd_msg_size(kib_rdma_desc_t *rd, int msgtype, int n)
 {
-       LASSERT (msgtype == IBLND_MSG_GET_REQ ||
-                msgtype == IBLND_MSG_PUT_ACK);
+       LASSERT(msgtype == IBLND_MSG_GET_REQ ||
+               msgtype == IBLND_MSG_PUT_ACK);
 
        return msgtype == IBLND_MSG_GET_REQ ?
               offsetof(kib_get_msg_t, ibgm_rd.rd_frags[n]) :
@@ -978,57 +952,53 @@ int  kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages,
                         int npages, __u64 iov, kib_fmr_t *fmr);
 void kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status);
 
-int  kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev,
-                        kib_rdma_desc_t *rd, __u64 *iova, kib_phys_mr_t **pp_pmr);
-void kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr);
-
-int  kiblnd_startup (lnet_ni_t *ni);
-void kiblnd_shutdown (lnet_ni_t *ni);
-int  kiblnd_ctl (lnet_ni_t *ni, unsigned int cmd, void *arg);
-void kiblnd_query (struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
+int  kiblnd_startup(lnet_ni_t *ni);
+void kiblnd_shutdown(lnet_ni_t *ni);
+int  kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg);
+void kiblnd_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
 
 int  kiblnd_tunables_init(void);
 void kiblnd_tunables_fini(void);
 
-int  kiblnd_connd (void *arg);
+int  kiblnd_connd(void *arg);
 int  kiblnd_scheduler(void *arg);
 int  kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name);
-int  kiblnd_failover_thread (void *arg);
+int  kiblnd_failover_thread(void *arg);
 
 int  kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages);
-void kiblnd_free_pages (kib_pages_t *p);
+void kiblnd_free_pages(kib_pages_t *p);
 
 int  kiblnd_cm_callback(struct rdma_cm_id *cmid,
                        struct rdma_cm_event *event);
 int  kiblnd_translate_mtu(int value);
 
 int  kiblnd_dev_failover(kib_dev_t *dev);
-int  kiblnd_create_peer (lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid);
-void kiblnd_destroy_peer (kib_peer_t *peer);
-void kiblnd_destroy_dev (kib_dev_t *dev);
-void kiblnd_unlink_peer_locked (kib_peer_t *peer);
-void kiblnd_peer_alive (kib_peer_t *peer);
-kib_peer_t *kiblnd_find_peer_locked (lnet_nid_t nid);
-void kiblnd_peer_connect_failed (kib_peer_t *peer, int active, int error);
-int  kiblnd_close_stale_conns_locked (kib_peer_t *peer,
+int  kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid);
+void kiblnd_destroy_peer(kib_peer_t *peer);
+void kiblnd_destroy_dev(kib_dev_t *dev);
+void kiblnd_unlink_peer_locked(kib_peer_t *peer);
+void kiblnd_peer_alive(kib_peer_t *peer);
+kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid);
+void kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error);
+int  kiblnd_close_stale_conns_locked(kib_peer_t *peer,
                                      int version, __u64 incarnation);
-int  kiblnd_close_peer_conns_locked (kib_peer_t *peer, int why);
+int  kiblnd_close_peer_conns_locked(kib_peer_t *peer, int why);
 
 void kiblnd_connreq_done(kib_conn_t *conn, int status);
-kib_conn_t *kiblnd_create_conn (kib_peer_t *peer, struct rdma_cm_id *cmid,
+kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
                                int state, int version);
-void kiblnd_destroy_conn (kib_conn_t *conn);
-void kiblnd_close_conn (kib_conn_t *conn, int error);
-void kiblnd_close_conn_locked (kib_conn_t *conn, int error);
+void kiblnd_destroy_conn(kib_conn_t *conn);
+void kiblnd_close_conn(kib_conn_t *conn, int error);
+void kiblnd_close_conn_locked(kib_conn_t *conn, int error);
 
-int  kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type,
+int  kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type,
                       int nob, kib_rdma_desc_t *dstrd, __u64 dstcookie);
 
-void kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid);
-void kiblnd_queue_tx_locked (kib_tx_t *tx, kib_conn_t *conn);
-void kiblnd_queue_tx (kib_tx_t *tx, kib_conn_t *conn);
-void kiblnd_init_tx_msg (lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob);
-void kiblnd_txlist_done (lnet_ni_t *ni, struct list_head *txlist,
+void kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid);
+void kiblnd_queue_tx_locked(kib_tx_t *tx, kib_conn_t *conn);
+void kiblnd_queue_tx(kib_tx_t *tx, kib_conn_t *conn);
+void kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob);
+void kiblnd_txlist_done(lnet_ni_t *ni, struct list_head *txlist,
                         int status);
 void kiblnd_check_sends (kib_conn_t *conn);
 
@@ -1036,10 +1006,10 @@ void kiblnd_qp_event(struct ib_event *event, void *arg);
 void kiblnd_cq_event(struct ib_event *event, void *arg);
 void kiblnd_cq_completion(struct ib_cq *cq, void *arg);
 
-void kiblnd_pack_msg (lnet_ni_t *ni, kib_msg_t *msg, int version,
+void kiblnd_pack_msg(lnet_ni_t *ni, kib_msg_t *msg, int version,
                      int credits, lnet_nid_t dstnid, __u64 dststamp);
 int  kiblnd_unpack_msg(kib_msg_t *msg, int nob);
-int  kiblnd_post_rx (kib_rx_t *rx, int credit);
+int  kiblnd_post_rx(kib_rx_t *rx, int credit);
 
 int  kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
 int  kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
index 477aa8b76f327a56cc20a1aa47d6868418a28ed9..a23a6d956a4d02efd2552db614706cd45ea2849b 100644 (file)
@@ -121,7 +121,6 @@ kiblnd_get_idle_tx(lnet_ni_t *ni, lnet_nid_t target)
        LASSERT(tx->tx_conn == NULL);
        LASSERT(tx->tx_lntmsg[0] == NULL);
        LASSERT(tx->tx_lntmsg[1] == NULL);
-       LASSERT(tx->tx_u.pmr == NULL);
        LASSERT(tx->tx_nfrags == 0);
 
        return tx;
@@ -575,7 +574,7 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
        cpt = tx->tx_pool->tpo_pool.po_owner->ps_cpt;
 
        fps = net->ibn_fmr_ps[cpt];
-       rc = kiblnd_fmr_pool_map(fps, pages, npages, 0, &tx->tx_u.fmr);
+       rc = kiblnd_fmr_pool_map(fps, pages, npages, 0, &tx->fmr);
        if (rc != 0) {
                CERROR("Can't map %d pages: %d\n", npages, rc);
                return rc;
@@ -583,8 +582,8 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
 
        /* If rd is not tx_rd, it's going to get sent to a peer, who will need
         * the rkey */
-       rd->rd_key = (rd != tx->tx_rd) ? tx->tx_u.fmr.fmr_pfmr->fmr->rkey :
-                                        tx->tx_u.fmr.fmr_pfmr->fmr->lkey;
+       rd->rd_key = (rd != tx->tx_rd) ? tx->fmr.fmr_pfmr->fmr->rkey :
+                                        tx->fmr.fmr_pfmr->fmr->lkey;
        rd->rd_frags[0].rf_addr &= ~hdev->ibh_page_mask;
        rd->rd_frags[0].rf_nob = nob;
        rd->rd_nfrags = 1;
@@ -592,42 +591,6 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
        return 0;
 }
 
-static int
-kiblnd_pmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
-{
-       kib_hca_dev_t *hdev;
-       kib_pmr_poolset_t *pps;
-       __u64 iova;
-       int cpt;
-       int rc;
-
-       LASSERT(tx->tx_pool != NULL);
-       LASSERT(tx->tx_pool->tpo_pool.po_owner != NULL);
-
-       hdev = tx->tx_pool->tpo_hdev;
-
-       iova = rd->rd_frags[0].rf_addr & ~hdev->ibh_page_mask;
-
-       cpt = tx->tx_pool->tpo_pool.po_owner->ps_cpt;
-
-       pps = net->ibn_pmr_ps[cpt];
-       rc = kiblnd_pmr_pool_map(pps, hdev, rd, &iova, &tx->tx_u.pmr);
-       if (rc != 0) {
-               CERROR("Failed to create MR by phybuf: %d\n", rc);
-               return rc;
-       }
-
-       /* If rd is not tx_rd, it's going to get sent to a peer, who will need
-        * the rkey */
-       rd->rd_key = (rd != tx->tx_rd) ? tx->tx_u.pmr->pmr_mr->rkey :
-                                        tx->tx_u.pmr->pmr_mr->lkey;
-       rd->rd_nfrags = 1;
-       rd->rd_frags[0].rf_addr = iova;
-       rd->rd_frags[0].rf_nob = nob;
-
-       return 0;
-}
-
 void
 kiblnd_unmap_tx(lnet_ni_t *ni, kib_tx_t *tx)
 {
@@ -635,13 +598,9 @@ kiblnd_unmap_tx(lnet_ni_t *ni, kib_tx_t *tx)
 
        LASSERT(net != NULL);
 
-       if (net->ibn_fmr_ps != NULL && tx->tx_u.fmr.fmr_pfmr != NULL) {
-               kiblnd_fmr_pool_unmap(&tx->tx_u.fmr, tx->tx_status);
-               tx->tx_u.fmr.fmr_pfmr = NULL;
-
-       } else if (net->ibn_pmr_ps != NULL && tx->tx_u.pmr != NULL) {
-               kiblnd_pmr_pool_unmap(tx->tx_u.pmr);
-               tx->tx_u.pmr = NULL;
+       if (net->ibn_fmr_ps && tx->fmr.fmr_pfmr) {
+               kiblnd_fmr_pool_unmap(&tx->fmr, tx->tx_status);
+               tx->fmr.fmr_pfmr = NULL;
        }
 
        if (tx->tx_nfrags != 0) {
@@ -687,8 +646,6 @@ kiblnd_map_tx(lnet_ni_t *ni, kib_tx_t *tx,
 
        if (net->ibn_fmr_ps != NULL)
                return kiblnd_fmr_map_tx(net, tx, rd, nob);
-       else if (net->ibn_pmr_ps != NULL)
-               return kiblnd_pmr_map_tx(net, tx, rd, nob);
 
        return -EINVAL;
 }
@@ -3133,8 +3090,7 @@ kiblnd_connd(void *arg)
                dropped_lock = 0;
 
                if (!list_empty(&kiblnd_data.kib_connd_zombies)) {
-                       conn = list_entry(kiblnd_data. \
-                                             kib_connd_zombies.next,
+                       conn = list_entry(kiblnd_data.kib_connd_zombies.next,
                                              kib_conn_t, ibc_list);
                        list_del(&conn->ibc_list);
 
index b0e00361cfcefae6994ef777a107df8ca9534300..b3d1b5d627cbd85015695107a824b71da7dc85e9 100644 (file)
@@ -126,11 +126,6 @@ static int fmr_cache = 1;
 module_param(fmr_cache, int, 0444);
 MODULE_PARM_DESC(fmr_cache, "non-zero to enable FMR caching");
 
-/* NB: this value is shared by all CPTs, it can grow at runtime */
-static int pmr_pool_size = 512;
-module_param(pmr_pool_size, int, 0444);
-MODULE_PARM_DESC(pmr_pool_size, "size of MR cache pmr pool on each CPT");
-
 /*
  * 0: disable failover
  * 1: enable failover if necessary
@@ -170,7 +165,6 @@ kib_tunables_t kiblnd_tunables = {
        .kib_fmr_pool_size     = &fmr_pool_size,
        .kib_fmr_flush_trigger = &fmr_flush_trigger,
        .kib_fmr_cache         = &fmr_cache,
-       .kib_pmr_pool_size     = &pmr_pool_size,
        .kib_require_priv_port = &require_privileged_port,
        .kib_use_priv_port     = &use_privileged_port,
        .kib_nscheds           = &nscheds
index 4128a92218a99c3a789a3236aadf1ec9e1c768f1..d8bfcadd184a8bb94001b65619e63b6104e71e64 100644 (file)
@@ -2252,8 +2252,6 @@ ksocknal_base_shutdown(void)
        int i;
        int j;
 
-       CDEBUG(D_MALLOC, "before NAL cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
        LASSERT(ksocknal_data.ksnd_nnets == 0);
 
        switch (ksocknal_data.ksnd_init) {
@@ -2331,9 +2329,6 @@ ksocknal_base_shutdown(void)
                break;
        }
 
-       CDEBUG(D_MALLOC, "after NAL cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
-
        module_put(THIS_MODULE);
 }
 
index 8a9d4a0de1298777d522a368a1ca6177cfdee06b..a0fcbc39f86b918ba052329ff1073ef346e219af 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/sysctl.h>
 #include <linux/uio.h>
 #include <linux/unistd.h>
+#include <asm/irq.h>
 #include <net/sock.h>
 #include <net/tcp.h>
 
@@ -519,8 +520,8 @@ ksocknal_conn_addref(ksock_conn_t *conn)
        atomic_inc(&conn->ksnc_conn_refcount);
 }
 
-extern void ksocknal_queue_zombie_conn(ksock_conn_t *conn);
-extern void ksocknal_finalize_zcreq(ksock_conn_t *conn);
+void ksocknal_queue_zombie_conn(ksock_conn_t *conn);
+void ksocknal_finalize_zcreq(ksock_conn_t *conn);
 
 static inline void
 ksocknal_conn_decref(ksock_conn_t *conn)
@@ -565,8 +566,8 @@ ksocknal_tx_addref(ksock_tx_t *tx)
        atomic_inc(&tx->tx_refcount);
 }
 
-extern void ksocknal_tx_prep(ksock_conn_t *, ksock_tx_t *tx);
-extern void ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx);
+void ksocknal_tx_prep(ksock_conn_t *, ksock_tx_t *tx);
+void ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx);
 
 static inline void
 ksocknal_tx_decref(ksock_tx_t *tx)
@@ -583,7 +584,7 @@ ksocknal_route_addref(ksock_route_t *route)
        atomic_inc(&route->ksnr_refcount);
 }
 
-extern void ksocknal_destroy_route(ksock_route_t *route);
+void ksocknal_destroy_route(ksock_route_t *route);
 
 static inline void
 ksocknal_route_decref(ksock_route_t *route)
@@ -600,7 +601,7 @@ ksocknal_peer_addref(ksock_peer_t *peer)
        atomic_inc(&peer->ksnp_refcount);
 }
 
-extern void ksocknal_destroy_peer(ksock_peer_t *peer);
+void ksocknal_destroy_peer(ksock_peer_t *peer);
 
 static inline void
 ksocknal_peer_decref(ksock_peer_t *peer)
@@ -620,70 +621,69 @@ int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg,
                  unsigned int offset, unsigned int mlen, unsigned int rlen);
 int ksocknal_accept(lnet_ni_t *ni, struct socket *sock);
 
-extern int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port);
-extern ksock_peer_t *ksocknal_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id);
-extern ksock_peer_t *ksocknal_find_peer(lnet_ni_t *ni, lnet_process_id_t id);
-extern void ksocknal_peer_failed(ksock_peer_t *peer);
-extern int ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route,
-                                struct socket *sock, int type);
-extern void ksocknal_close_conn_locked(ksock_conn_t *conn, int why);
-extern void ksocknal_terminate_conn(ksock_conn_t *conn);
-extern void ksocknal_destroy_conn(ksock_conn_t *conn);
-extern int  ksocknal_close_peer_conns_locked(ksock_peer_t *peer,
-                                             __u32 ipaddr, int why);
-extern int ksocknal_close_conn_and_siblings(ksock_conn_t *conn, int why);
-extern int ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr);
-extern ksock_conn_t *ksocknal_find_conn_locked(ksock_peer_t *peer,
-                                              ksock_tx_t *tx, int nonblk);
-
-extern int  ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx,
-                                  lnet_process_id_t id);
-extern ksock_tx_t *ksocknal_alloc_tx(int type, int size);
-extern void ksocknal_free_tx(ksock_tx_t *tx);
-extern ksock_tx_t *ksocknal_alloc_tx_noop(__u64 cookie, int nonblk);
-extern void ksocknal_next_tx_carrier(ksock_conn_t *conn);
-extern void ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn);
-extern void ksocknal_txlist_done(lnet_ni_t *ni, struct list_head *txlist,
-                                 int error);
-extern void ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive);
-extern void ksocknal_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
-extern int ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name);
-extern void ksocknal_thread_fini(void);
-extern void ksocknal_launch_all_connections_locked(ksock_peer_t *peer);
-extern ksock_route_t *ksocknal_find_connectable_route_locked(ksock_peer_t *peer);
-extern ksock_route_t *ksocknal_find_connecting_route_locked(ksock_peer_t *peer);
-extern int ksocknal_new_packet(ksock_conn_t *conn, int skip);
-extern int ksocknal_scheduler(void *arg);
-extern int ksocknal_connd(void *arg);
-extern int ksocknal_reaper(void *arg);
-extern int ksocknal_send_hello(lnet_ni_t *ni, ksock_conn_t *conn,
-                               lnet_nid_t peer_nid, ksock_hello_msg_t *hello);
-extern int ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn,
-                               ksock_hello_msg_t *hello, lnet_process_id_t *id,
-                               __u64 *incarnation);
-extern void ksocknal_read_callback(ksock_conn_t *conn);
-extern void ksocknal_write_callback(ksock_conn_t *conn);
-
-extern int ksocknal_lib_zc_capable(ksock_conn_t *conn);
-extern void ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn);
-extern void ksocknal_lib_set_callback(struct socket *sock,  ksock_conn_t *conn);
-extern void ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn);
-extern void ksocknal_lib_push_conn(ksock_conn_t *conn);
-extern int ksocknal_lib_get_conn_addrs(ksock_conn_t *conn);
-extern int ksocknal_lib_setup_sock(struct socket *so);
-extern int ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx);
-extern int ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx);
-extern void ksocknal_lib_eager_ack(ksock_conn_t *conn);
-extern int ksocknal_lib_recv_iov(ksock_conn_t *conn);
-extern int ksocknal_lib_recv_kiov(ksock_conn_t *conn);
-extern int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem,
-                                          int *rxmem, int *nagle);
-
-extern int ksocknal_tunables_init(void);
-
-extern void ksocknal_lib_csum_tx(ksock_tx_t *tx);
-
-extern int ksocknal_lib_memory_pressure(ksock_conn_t *conn);
-extern int ksocknal_lib_bind_thread_to_cpu(int id);
+int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port);
+ksock_peer_t *ksocknal_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id);
+ksock_peer_t *ksocknal_find_peer(lnet_ni_t *ni, lnet_process_id_t id);
+void ksocknal_peer_failed(ksock_peer_t *peer);
+int ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route,
+                        struct socket *sock, int type);
+void ksocknal_close_conn_locked(ksock_conn_t *conn, int why);
+void ksocknal_terminate_conn(ksock_conn_t *conn);
+void ksocknal_destroy_conn(ksock_conn_t *conn);
+int  ksocknal_close_peer_conns_locked(ksock_peer_t *peer,
+                                     __u32 ipaddr, int why);
+int ksocknal_close_conn_and_siblings(ksock_conn_t *conn, int why);
+int ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr);
+ksock_conn_t *ksocknal_find_conn_locked(ksock_peer_t *peer,
+                                       ksock_tx_t *tx, int nonblk);
+
+int  ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx,
+                           lnet_process_id_t id);
+ksock_tx_t *ksocknal_alloc_tx(int type, int size);
+void ksocknal_free_tx(ksock_tx_t *tx);
+ksock_tx_t *ksocknal_alloc_tx_noop(__u64 cookie, int nonblk);
+void ksocknal_next_tx_carrier(ksock_conn_t *conn);
+void ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn);
+void ksocknal_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int error);
+void ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive);
+void ksocknal_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
+int ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name);
+void ksocknal_thread_fini(void);
+void ksocknal_launch_all_connections_locked(ksock_peer_t *peer);
+ksock_route_t *ksocknal_find_connectable_route_locked(ksock_peer_t *peer);
+ksock_route_t *ksocknal_find_connecting_route_locked(ksock_peer_t *peer);
+int ksocknal_new_packet(ksock_conn_t *conn, int skip);
+int ksocknal_scheduler(void *arg);
+int ksocknal_connd(void *arg);
+int ksocknal_reaper(void *arg);
+int ksocknal_send_hello(lnet_ni_t *ni, ksock_conn_t *conn,
+                       lnet_nid_t peer_nid, ksock_hello_msg_t *hello);
+int ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn,
+                       ksock_hello_msg_t *hello, lnet_process_id_t *id,
+                       __u64 *incarnation);
+void ksocknal_read_callback(ksock_conn_t *conn);
+void ksocknal_write_callback(ksock_conn_t *conn);
+
+int ksocknal_lib_zc_capable(ksock_conn_t *conn);
+void ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn);
+void ksocknal_lib_set_callback(struct socket *sock,  ksock_conn_t *conn);
+void ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn);
+void ksocknal_lib_push_conn(ksock_conn_t *conn);
+int ksocknal_lib_get_conn_addrs(ksock_conn_t *conn);
+int ksocknal_lib_setup_sock(struct socket *so);
+int ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx);
+int ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx);
+void ksocknal_lib_eager_ack(ksock_conn_t *conn);
+int ksocknal_lib_recv_iov(ksock_conn_t *conn);
+int ksocknal_lib_recv_kiov(ksock_conn_t *conn);
+int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem,
+                                  int *rxmem, int *nagle);
+
+int ksocknal_tunables_init(void);
+
+void ksocknal_lib_csum_tx(ksock_tx_t *tx);
+
+int ksocknal_lib_memory_pressure(ksock_conn_t *conn);
+int ksocknal_lib_bind_thread_to_cpu(int id);
 
 #endif /* _SOCKLND_SOCKLND_H_ */
index fe2a83a540cdb040adbb795ecfa0e5d3a53489c8..0d5aac6a2bb3c4c6e941588e378a794ff5559859 100644 (file)
@@ -526,8 +526,7 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx)
 
                counter++;   /* exponential backoff warnings */
                if ((counter & (-counter)) == counter)
-                       CWARN("%u ENOMEM tx %p (%u allocated)\n",
-                             counter, conn, atomic_read(&libcfs_kmemory));
+                       CWARN("%u ENOMEM tx %p\n", counter, conn);
 
                /* Queue on ksnd_enomem_conns for retry after a timeout */
                spin_lock_bh(&ksocknal_data.ksnd_reaper_lock);
index ee902dc43823ff201cf1a3d41530b47008a29184..40f418b82960746b5cde2324a7a40d57ae43c775 100644 (file)
 
 static struct ctl_table_header *lnet_table_header;
 
-#define CTL_LNET        (0x100)
-enum {
-       PSDEV_LNET_STATS = 100,
-       PSDEV_LNET_ROUTES,
-       PSDEV_LNET_ROUTERS,
-       PSDEV_LNET_PEERS,
-       PSDEV_LNET_BUFFERS,
-       PSDEV_LNET_NIS,
-       PSDEV_LNET_PTL_ROTOR,
-};
-
 #define LNET_LOFFT_BITS                (sizeof(loff_t) * 8)
 /*
  * NB: max allowed LNET_CPT_BITS is 8 on 64-bit system and 2 on 32-bit system
index c4cf0aed80e1840ada08b627b79239dd1078d2f4..cdce2dd6be7c4b8809a0554e080d05df1d69245b 100644 (file)
@@ -187,51 +187,49 @@ lstcon_id2hash (lnet_process_id_t id, struct list_head *hash)
 int lstcon_console_init(void);
 int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data);
 int lstcon_console_fini(void);
-extern int lstcon_session_match(lst_sid_t sid);
-extern int lstcon_session_new(char *name, int key, unsigned version,
-                             int timeout, int flags, lst_sid_t *sid_up);
-extern int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp,
-                              lstcon_ndlist_ent_t *entp, char *name_up, int len);
-extern int lstcon_session_end(void);
-extern int lstcon_session_debug(int timeout, struct list_head *result_up);
-extern int lstcon_session_feats_check(unsigned feats);
-extern int lstcon_batch_debug(int timeout, char *name,
-                             int client, struct list_head *result_up);
-extern int lstcon_group_debug(int timeout, char *name,
-                             struct list_head *result_up);
-extern int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t *nds_up,
-                             struct list_head *result_up);
-extern int lstcon_group_add(char *name);
-extern int lstcon_group_del(char *name);
-extern int lstcon_group_clean(char *name, int args);
-extern int lstcon_group_refresh(char *name, struct list_head *result_up);
-extern int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up,
-                           unsigned *featp, struct list_head *result_up);
-extern int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up,
-                              struct list_head *result_up);
-extern int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up,
-                            int *index_p, int *ndent_p, lstcon_node_ent_t *ndents_up);
-extern int lstcon_group_list(int idx, int len, char *name_up);
-extern int lstcon_batch_add(char *name);
-extern int lstcon_batch_run(char *name, int timeout,
+int lstcon_session_match(lst_sid_t sid);
+int lstcon_session_new(char *name, int key, unsigned version,
+                      int timeout, int flags, lst_sid_t *sid_up);
+int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp,
+                       lstcon_ndlist_ent_t *entp, char *name_up, int len);
+int lstcon_session_end(void);
+int lstcon_session_debug(int timeout, struct list_head *result_up);
+int lstcon_session_feats_check(unsigned feats);
+int lstcon_batch_debug(int timeout, char *name,
+                      int client, struct list_head *result_up);
+int lstcon_group_debug(int timeout, char *name,
+                      struct list_head *result_up);
+int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t *nds_up,
+                      struct list_head *result_up);
+int lstcon_group_add(char *name);
+int lstcon_group_del(char *name);
+int lstcon_group_clean(char *name, int args);
+int lstcon_group_refresh(char *name, struct list_head *result_up);
+int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up,
+                    unsigned *featp, struct list_head *result_up);
+int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up,
+                       struct list_head *result_up);
+int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up,
+                     int *index_p, int *ndent_p, lstcon_node_ent_t *ndents_up);
+int lstcon_group_list(int idx, int len, char *name_up);
+int lstcon_batch_add(char *name);
+int lstcon_batch_run(char *name, int timeout, struct list_head *result_up);
+int lstcon_batch_stop(char *name, int force, struct list_head *result_up);
+int lstcon_test_batch_query(char *name, int testidx,
+                           int client, int timeout,
                            struct list_head *result_up);
-extern int lstcon_batch_stop(char *name, int force,
-                            struct list_head *result_up);
-extern int lstcon_test_batch_query(char *name, int testidx,
-                                  int client, int timeout,
-                                  struct list_head *result_up);
-extern int lstcon_batch_del(char *name);
-extern int lstcon_batch_list(int idx, int namelen, char *name_up);
-extern int lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up,
-                            int server, int testidx, int *index_p,
-                            int *ndent_p, lstcon_node_ent_t *dents_up);
-extern int lstcon_group_stat(char *grp_name, int timeout,
-                            struct list_head *result_up);
-extern int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
-                            int timeout, struct list_head *result_up);
-extern int lstcon_test_add(char *batch_name, int type, int loop,
-                          int concur, int dist, int span,
-                          char *src_name, char *dst_name,
-                          void *param, int paramlen, int *retp,
-                          struct list_head *result_up);
+int lstcon_batch_del(char *name);
+int lstcon_batch_list(int idx, int namelen, char *name_up);
+int lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up,
+                     int server, int testidx, int *index_p,
+                     int *ndent_p, lstcon_node_ent_t *dents_up);
+int lstcon_group_stat(char *grp_name, int timeout,
+                     struct list_head *result_up);
+int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
+                     int timeout, struct list_head *result_up);
+int lstcon_test_add(char *batch_name, int type, int loop,
+                   int concur, int dist, int span,
+                   char *src_name, char *dst_name,
+                   void *param, int paramlen, int *retp,
+                   struct list_head *result_up);
 #endif
index 7c5185a2a7950bc1833ccd2cb25d0c204f443512..257de353767192d626ba8822b9e99caceb416e8b 100644 (file)
@@ -203,7 +203,8 @@ sfw_deactivate_session(void)
        sfw_batch_t *tsb;
        sfw_test_case_t *tsc;
 
-       if (sn == NULL) return;
+       if (sn == NULL)
+               return;
 
        LASSERT(!sn->sn_timer_active);
 
@@ -613,7 +614,8 @@ sfw_destroy_test_instance(sfw_test_instance_t *tsi)
        srpc_client_rpc_t *rpc;
        sfw_test_unit_t *tsu;
 
-       if (!tsi->tsi_is_client) goto clean;
+       if (!tsi->tsi_is_client)
+               goto clean;
 
        tsi->tsi_ops->tso_fini(tsi);
 
@@ -1700,7 +1702,8 @@ sfw_startup(void)
 
        for (i = 0; ; i++) {
                sv = &sfw_services[i];
-               if (sv->sv_name == NULL) break;
+               if (sv->sv_name == NULL)
+                       break;
 
                sv->sv_bulk_ready = NULL;
                sv->sv_handler    = sfw_handle_server_rpc;
@@ -1717,7 +1720,8 @@ sfw_startup(void)
                }
 
                /* about to sfw_shutdown, no need to add buffer */
-               if (error) continue;
+               if (error)
+                       continue;
 
                rc = srpc_service_add_buffers(sv, sv->sv_wi_total);
                if (rc != 0) {
index 1362783b7eab362a8df204826449c4aac50e47c0..a16d577c6cb184071dd0d015d5e8c9ab79c9b4d4 100644 (file)
@@ -498,11 +498,11 @@ int client_fid_init(struct obd_device *obd,
        int rc;
 
        cli->cl_seq = kzalloc(sizeof(*cli->cl_seq), GFP_NOFS);
-       if (cli->cl_seq == NULL)
+       if (!cli->cl_seq)
                return -ENOMEM;
 
        prefix = kzalloc(MAX_OBD_NAME + 5, GFP_NOFS);
-       if (prefix == NULL) {
+       if (!prefix) {
                rc = -ENOMEM;
                goto out_free_seq;
        }
index ec2fc4339a2e752e1b29d04d7c1cdf9ae352915d..1b1066b2461ceadb6aeb01e7d12fe76d1b89fa83 100644 (file)
@@ -70,7 +70,7 @@ struct fld_cache *fld_cache_init(const char *name,
        LASSERT(cache_threshold < cache_size);
 
        cache = kzalloc(sizeof(*cache), GFP_NOFS);
-       if (cache == NULL)
+       if (!cache)
                return ERR_PTR(-ENOMEM);
 
        INIT_LIST_HEAD(&cache->fci_entries_head);
index c3b47f2346df6bd2e0a074869545e6ee0b7056ae..1e450bf953838ef75a996f21a71b3d487cce189d 100644 (file)
@@ -222,7 +222,7 @@ int fld_client_add_target(struct lu_client_fld *fld,
                        fld->lcf_name, name, tar->ft_idx);
 
        target = kzalloc(sizeof(*target), GFP_NOFS);
-       if (target == NULL)
+       if (!target)
                return -ENOMEM;
 
        spin_lock(&fld->lcf_lock);
index 513c81f43d6e87926a2d368fc023525a6a37b338..6b14406b2920daa640b68f6b80f01cba0fa68aa8 100644 (file)
 
 #define LTIME_S(time)             (time.tv_sec)
 
-/* inode_dio_wait(i) use as-is for write lock */
-# define inode_dio_write_done(i)       do {} while (0) /* for write unlock */
-# define inode_dio_read(i)             atomic_inc(&(i)->i_dio_count)
-/* inode_dio_done(i) use as-is for read unlock */
-
-
-#ifndef FS_HAS_FIEMAP
-#define FS_HAS_FIEMAP                  (0)
-#endif
-
-#define ll_vfs_rmdir(dir, entry, mnt)       vfs_rmdir(dir, entry)
-#define ll_vfs_mkdir(inode, dir, mnt, mode)    vfs_mkdir(inode, dir, mode)
-#define ll_vfs_link(old, mnt, dir, new, mnt1)       vfs_link(old, dir, new)
-#define ll_vfs_unlink(inode, entry, mnt)         vfs_unlink(inode, entry)
-#define ll_vfs_mknod(dir, entry, mnt, mode, dev) \
-                    vfs_mknod(dir, entry, mode, dev)
-#define ll_security_inode_unlink(dir, entry, mnt) \
-                                security_inode_unlink(dir, entry)
-#define ll_vfs_rename(old, old_dir, mnt, new, new_dir, mnt1) \
-               vfs_rename(old, old_dir, new, new_dir, NULL, 0)
-
-#define cfs_bio_io_error(a, b)   bio_io_error((a))
-#define cfs_bio_endio(a, b, c)    bio_endio((a), (c))
-
-#define cfs_path_put(nd)     path_put(&(nd)->path)
-
-
-#ifndef SLAB_DESTROY_BY_RCU
-#define SLAB_DESTROY_BY_RCU 0
-#endif
-
-
-
-static inline int
-ll_quota_on(struct super_block *sb, int off, int ver, char *name, int remount)
-{
-       int rc;
-
-       if (sb->s_qcop->quota_on) {
-               struct path path;
-
-               rc = kern_path(name, LOOKUP_FOLLOW, &path);
-               if (!rc)
-                       return rc;
-               rc = sb->s_qcop->quota_on(sb, off, ver
-                                           , &path
-                                          );
-               path_put(&path);
-               return rc;
-       } else
-               return -ENOSYS;
-}
-
-static inline int ll_quota_off(struct super_block *sb, int off, int remount)
-{
-       if (sb->s_qcop->quota_off) {
-               return sb->s_qcop->quota_off(sb, off
-                                           );
-       } else
-               return -ENOSYS;
-}
-
-
-# define ll_vfs_dq_init             dquot_initialize
-# define ll_vfs_dq_drop             dquot_drop
-# define ll_vfs_dq_transfer     dquot_transfer
-# define ll_vfs_dq_off(sb, remount) dquot_suspend(sb, -1)
-
-
-
-
-
-#define queue_max_phys_segments(rq)       queue_max_segments(rq)
-#define queue_max_hw_segments(rq)       queue_max_segments(rq)
-
-
-#define ll_d_hlist_node hlist_node
-#define ll_d_hlist_empty(list) hlist_empty(list)
-#define ll_d_hlist_entry(ptr, type, name) hlist_entry(ptr.first, type, name)
-#define ll_d_hlist_for_each(tmp, i_dentry) hlist_for_each(tmp, i_dentry)
-#define ll_d_hlist_for_each_entry(dentry, p, i_dentry, alias) \
-       p = NULL; hlist_for_each_entry(dentry, i_dentry, alias)
-
-
-#define bio_hw_segments(q, bio) 0
-
-
-#define ll_pagevec_init(pv, cold)       do {} while (0)
-#define ll_pagevec_add(pv, pg)   (0)
-#define ll_pagevec_lru_add_file(pv)     do {} while (0)
-
-
 #ifndef QUOTA_OK
 # define QUOTA_OK 0
 #endif
@@ -163,17 +71,6 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount)
 # define NO_QUOTA (-EDQUOT)
 #endif
 
-#ifndef SEEK_DATA
-#define SEEK_DATA      3       /* seek to the next data */
-#endif
-#ifndef SEEK_HOLE
-#define SEEK_HOLE      4       /* seek to the next hole */
-#endif
-
-#ifndef FMODE_UNSIGNED_OFFSET
-#define FMODE_UNSIGNED_OFFSET  ((__force fmode_t)0x2000)
-#endif
-
 #if !defined(_ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_) && !defined(ext2_set_bit)
 # define ext2_set_bit       __test_and_set_bit_le
 # define ext2_clear_bit           __test_and_clear_bit_le
@@ -182,20 +79,4 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount)
 # define ext2_find_next_zero_bit  find_next_zero_bit_le
 #endif
 
-#ifdef ATTR_TIMES_SET
-# define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
-#else
-# define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET)
-#endif
-
-
-#include <linux/version.h>
-#include <linux/fs.h>
-
-# define ll_umode_t    umode_t
-
-#include <linux/dcache.h>
-
-# define ll_dirty_inode(inode, flag)   (inode)->i_sb->s_op->dirty_inode((inode), flag)
-
 #endif /* _COMPAT25_H */
index 14562788e4e059eca40f57ee85fd74a5c9f41fa0..ebe8d68ed813f854126c3b21407ff3c7c187a37b 100644 (file)
@@ -60,18 +60,6 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
        ll_delete_from_page_cache(page);
 }
 
-#ifdef ATTR_OPEN
-# define ATTR_FROM_OPEN ATTR_OPEN
-#else
-# ifndef ATTR_FROM_OPEN
-#  define ATTR_FROM_OPEN 0
-# endif
-#endif /* ATTR_OPEN */
-
-#ifndef ATTR_RAW
-#define ATTR_RAW 0
-#endif
-
 #ifndef ATTR_CTIME_SET
 /*
  * set ATTR_CTIME_SET to a high value to avoid any risk of collision with other
index 8ede2a00ca4f5c51fa7c9242f70be5493d5fd0bf..fd3c4df319c205c221a67aba32a6df7b98b1c08c 100644 (file)
@@ -375,12 +375,11 @@ static inline void s2dhms(struct dhms *ts, time_t secs)
 #define JOBSTATS_PROCNAME_UID          "procname_uid"
 #define JOBSTATS_NODELOCAL             "nodelocal"
 
-extern int lprocfs_write_frac_helper(const char __user *buffer,
-                                    unsigned long count, int *val, int mult);
-extern int lprocfs_read_frac_helper(char *buffer, unsigned long count,
-                                   long val, int mult);
-extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats,
-                                  unsigned int cpuid);
+int lprocfs_write_frac_helper(const char __user *buffer,
+                             unsigned long count, int *val, int mult);
+int lprocfs_read_frac_helper(char *buffer, unsigned long count,
+                            long val, int mult);
+int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid);
 /*
  * \return value
  *      < 0     : on error (only possible for opc as LPROCFS_GET_SMP_ID)
@@ -497,20 +496,18 @@ lprocfs_stats_counter_get(struct lprocfs_stats *stats, unsigned int cpuid,
  * count itself to reside within a single cache line.
  */
 
-extern void lprocfs_counter_add(struct lprocfs_stats *stats, int idx,
-                               long amount);
-extern void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx,
-                               long amount);
+void lprocfs_counter_add(struct lprocfs_stats *stats, int idx, long amount);
+void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx, long amount);
 
 #define lprocfs_counter_incr(stats, idx) \
        lprocfs_counter_add(stats, idx, 1)
 #define lprocfs_counter_decr(stats, idx) \
        lprocfs_counter_sub(stats, idx, 1)
 
-extern __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
-                                struct lprocfs_counter_header *header,
-                                enum lprocfs_stats_flags flags,
-                                enum lprocfs_fields_flags field);
+__s64 lprocfs_read_helper(struct lprocfs_counter *lc,
+                         struct lprocfs_counter_header *header,
+                         enum lprocfs_stats_flags flags,
+                         enum lprocfs_fields_flags field);
 static inline __u64 lprocfs_stats_collector(struct lprocfs_stats *stats,
                                            int idx,
                                            enum lprocfs_fields_flags field)
@@ -537,107 +534,103 @@ static inline __u64 lprocfs_stats_collector(struct lprocfs_stats *stats,
 
 extern struct lprocfs_stats *
 lprocfs_alloc_stats(unsigned int num, enum lprocfs_stats_flags flags);
-extern void lprocfs_clear_stats(struct lprocfs_stats *stats);
-extern void lprocfs_free_stats(struct lprocfs_stats **stats);
-extern void lprocfs_init_ops_stats(int num_private_stats,
-                                  struct lprocfs_stats *stats);
-extern void lprocfs_init_mps_stats(int num_private_stats,
-                                  struct lprocfs_stats *stats);
-extern void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats);
-extern int lprocfs_alloc_obd_stats(struct obd_device *obddev,
-                                  unsigned int num_private_stats);
-extern int lprocfs_alloc_md_stats(struct obd_device *obddev,
-                                 unsigned int num_private_stats);
-extern void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
-                                unsigned conf, const char *name,
-                                const char *units);
-extern void lprocfs_free_obd_stats(struct obd_device *obddev);
-extern void lprocfs_free_md_stats(struct obd_device *obddev);
+void lprocfs_clear_stats(struct lprocfs_stats *stats);
+void lprocfs_free_stats(struct lprocfs_stats **stats);
+void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats);
+void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats);
+void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats);
+int lprocfs_alloc_obd_stats(struct obd_device *obddev,
+                           unsigned int num_private_stats);
+int lprocfs_alloc_md_stats(struct obd_device *obddev,
+                          unsigned int num_private_stats);
+void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
+                         unsigned conf, const char *name, const char *units);
+void lprocfs_free_obd_stats(struct obd_device *obddev);
+void lprocfs_free_md_stats(struct obd_device *obddev);
 struct obd_export;
-extern int lprocfs_exp_cleanup(struct obd_export *exp);
-extern struct dentry *ldebugfs_add_simple(struct dentry *root,
-                                         char *name,
-                                         void *data,
-                                         struct file_operations *fops);
-extern struct dentry *
+int lprocfs_exp_cleanup(struct obd_export *exp);
+struct dentry *ldebugfs_add_simple(struct dentry *root,
+                                  char *name,
+                                  void *data,
+                                  struct file_operations *fops);
+struct dentry *
 ldebugfs_add_symlink(const char *name, struct dentry *parent,
-                   const char *format, ...);
+                    const char *format, ...);
 
-extern int ldebugfs_register_stats(struct dentry *parent,
-                                  const char *name,
-                                  struct lprocfs_stats *stats);
+int ldebugfs_register_stats(struct dentry *parent,
+                           const char *name,
+                           struct lprocfs_stats *stats);
 
 /* lprocfs_status.c */
-extern int ldebugfs_add_vars(struct dentry *parent,
-                            struct lprocfs_vars *var,
-                            void *data);
-
-extern struct dentry *ldebugfs_register(const char *name,
-                                       struct dentry *parent,
-                                       struct lprocfs_vars *list,
-                                       void *data);
-
-extern void ldebugfs_remove(struct dentry **entryp);
-
-extern int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
-                            struct attribute_group *attrs);
-extern int lprocfs_obd_cleanup(struct obd_device *obd);
-
-extern int ldebugfs_seq_create(struct dentry *parent,
-                              const char *name,
-                              umode_t mode,
-                              const struct file_operations *seq_fops,
-                              void *data);
-extern int ldebugfs_obd_seq_create(struct obd_device *dev,
-                                  const char *name,
-                                  umode_t mode,
-                                  const struct file_operations *seq_fops,
-                                  void *data);
+int ldebugfs_add_vars(struct dentry *parent,
+                     struct lprocfs_vars *var,
+                     void *data);
+
+struct dentry *ldebugfs_register(const char *name,
+                                struct dentry *parent,
+                                struct lprocfs_vars *list,
+                                void *data);
+
+void ldebugfs_remove(struct dentry **entryp);
+
+int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
+                     struct attribute_group *attrs);
+int lprocfs_obd_cleanup(struct obd_device *obd);
+
+int ldebugfs_seq_create(struct dentry *parent,
+                       const char *name,
+                       umode_t mode,
+                       const struct file_operations *seq_fops,
+                       void *data);
+int ldebugfs_obd_seq_create(struct obd_device *dev,
+                           const char *name,
+                           umode_t mode,
+                           const struct file_operations *seq_fops,
+                           void *data);
 
 /* Generic callbacks */
 
-extern int lprocfs_rd_u64(struct seq_file *m, void *data);
-extern int lprocfs_rd_atomic(struct seq_file *m, void *data);
-extern int lprocfs_wr_atomic(struct file *file, const char __user *buffer,
-                            unsigned long count, void *data);
-extern int lprocfs_rd_uint(struct seq_file *m, void *data);
-extern int lprocfs_wr_uint(struct file *file, const char __user *buffer,
-                          unsigned long count, void *data);
-extern int lprocfs_rd_name(struct seq_file *m, void *data);
-extern int lprocfs_rd_server_uuid(struct seq_file *m, void *data);
-extern int lprocfs_rd_conn_uuid(struct seq_file *m, void *data);
-extern int lprocfs_rd_import(struct seq_file *m, void *data);
-extern int lprocfs_rd_state(struct seq_file *m, void *data);
-extern int lprocfs_rd_connect_flags(struct seq_file *m, void *data);
+int lprocfs_rd_u64(struct seq_file *m, void *data);
+int lprocfs_rd_atomic(struct seq_file *m, void *data);
+int lprocfs_wr_atomic(struct file *file, const char __user *buffer,
+                     unsigned long count, void *data);
+int lprocfs_rd_uint(struct seq_file *m, void *data);
+int lprocfs_wr_uint(struct file *file, const char __user *buffer,
+                   unsigned long count, void *data);
+int lprocfs_rd_name(struct seq_file *m, void *data);
+int lprocfs_rd_server_uuid(struct seq_file *m, void *data);
+int lprocfs_rd_conn_uuid(struct seq_file *m, void *data);
+int lprocfs_rd_import(struct seq_file *m, void *data);
+int lprocfs_rd_state(struct seq_file *m, void *data);
+int lprocfs_rd_connect_flags(struct seq_file *m, void *data);
 
 struct adaptive_timeout;
-extern int lprocfs_at_hist_helper(struct seq_file *m,
-                                 struct adaptive_timeout *at);
-extern int lprocfs_rd_timeouts(struct seq_file *m, void *data);
-extern int lprocfs_wr_timeouts(struct file *file, const char __user *buffer,
-                              unsigned long count, void *data);
-extern int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
+int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at);
+int lprocfs_rd_timeouts(struct seq_file *m, void *data);
+int lprocfs_wr_timeouts(struct file *file, const char __user *buffer,
+                       unsigned long count, void *data);
+int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
                            size_t count, loff_t *off);
-extern int lprocfs_wr_ping(struct file *file, const char __user *buffer,
-                          size_t count, loff_t *off);
-extern int lprocfs_wr_import(struct file *file, const char __user *buffer,
+int lprocfs_wr_ping(struct file *file, const char __user *buffer,
+                   size_t count, loff_t *off);
+int lprocfs_wr_import(struct file *file, const char __user *buffer,
                      size_t count, loff_t *off);
-extern int lprocfs_rd_pinger_recov(struct seq_file *m, void *n);
-extern int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer,
-                                  size_t count, loff_t *off);
+int lprocfs_rd_pinger_recov(struct seq_file *m, void *n);
+int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer,
+                           size_t count, loff_t *off);
 
 /* Statfs helpers */
 
-extern int lprocfs_write_helper(const char __user *buffer, unsigned long count,
-                               int *val);
-extern int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult);
-extern int lprocfs_write_u64_helper(const char __user *buffer,
-                               unsigned long count, __u64 *val);
-extern int lprocfs_write_frac_u64_helper(const char *buffer,
-                                        unsigned long count,
-                                        __u64 *val, int mult);
-extern char *lprocfs_find_named_value(const char *buffer, const char *name,
-                                     size_t *count);
+int lprocfs_write_helper(const char __user *buffer, unsigned long count,
+                        int *val);
+int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult);
+int lprocfs_write_u64_helper(const char __user *buffer,
+                            unsigned long count, __u64 *val);
+int lprocfs_write_frac_u64_helper(const char *buffer,
+                                 unsigned long count,
+                                 __u64 *val, int mult);
+char *lprocfs_find_named_value(const char *buffer, const char *name,
+                              size_t *count);
 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value);
 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value);
 void lprocfs_oh_clear(struct obd_histogram *oh);
@@ -646,8 +639,8 @@ unsigned long lprocfs_oh_sum(struct obd_histogram *oh);
 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
                           struct lprocfs_counter *cnt);
 
-extern int lprocfs_single_release(struct inode *, struct file *);
-extern int lprocfs_seq_release(struct inode *, struct file *);
+int lprocfs_single_release(struct inode *, struct file *);
+int lprocfs_seq_release(struct inode *, struct file *);
 
 /* You must use these macros when you want to refer to
  * the import in a client obd_device for a lprocfs entry */
@@ -746,7 +739,7 @@ extern const struct sysfs_ops lustre_sysfs_ops;
 
 /* lproc_ptlrpc.c */
 struct ptlrpc_request;
-extern void target_print_req(void *seq_file, struct ptlrpc_request *req);
+void target_print_req(void *seq_file, struct ptlrpc_request *req);
 
 /* lproc_status.c */
 int lprocfs_obd_rd_max_pages_per_rpc(struct seq_file *m, void *data);
@@ -754,62 +747,62 @@ int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer,
                                     size_t count, loff_t *off);
 
 /* all quota proc functions */
-extern int lprocfs_quota_rd_bunit(char *page, char **start,
-                                 loff_t off, int count,
-                                 int *eof, void *data);
-extern int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
-                                 unsigned long count, void *data);
-extern int lprocfs_quota_rd_btune(char *page, char **start,
-                                 loff_t off, int count,
-                                 int *eof, void *data);
-extern int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
-                                 unsigned long count, void *data);
-extern int lprocfs_quota_rd_iunit(char *page, char **start,
-                                 loff_t off, int count,
-                                 int *eof, void *data);
-extern int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
-                                 unsigned long count, void *data);
-extern int lprocfs_quota_rd_itune(char *page, char **start,
-                                 loff_t off, int count,
-                                 int *eof, void *data);
-extern int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
-                                 unsigned long count, void *data);
-extern int lprocfs_quota_rd_type(char *page, char **start, loff_t off, int count,
-                                int *eof, void *data);
-extern int lprocfs_quota_wr_type(struct file *file, const char *buffer,
-                                unsigned long count, void *data);
-extern int lprocfs_quota_rd_switch_seconds(char *page, char **start, loff_t off,
-                                          int count, int *eof, void *data);
-extern int lprocfs_quota_wr_switch_seconds(struct file *file,
-                                          const char *buffer,
-                                          unsigned long count, void *data);
-extern int lprocfs_quota_rd_sync_blk(char *page, char **start, loff_t off,
+int lprocfs_quota_rd_bunit(char *page, char **start,
+                          loff_t off, int count,
+                          int *eof, void *data);
+int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
+                          unsigned long count, void *data);
+int lprocfs_quota_rd_btune(char *page, char **start,
+                          loff_t off, int count,
+                          int *eof, void *data);
+int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
+                          unsigned long count, void *data);
+int lprocfs_quota_rd_iunit(char *page, char **start,
+                          loff_t off, int count,
+                          int *eof, void *data);
+int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
+                          unsigned long count, void *data);
+int lprocfs_quota_rd_itune(char *page, char **start,
+                          loff_t off, int count,
+                          int *eof, void *data);
+int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
+                          unsigned long count, void *data);
+int lprocfs_quota_rd_type(char *page, char **start, loff_t off, int count,
+                         int *eof, void *data);
+int lprocfs_quota_wr_type(struct file *file, const char *buffer,
+                         unsigned long count, void *data);
+int lprocfs_quota_rd_switch_seconds(char *page, char **start, loff_t off,
+                                   int count, int *eof, void *data);
+int lprocfs_quota_wr_switch_seconds(struct file *file,
+                                   const char *buffer,
+                                   unsigned long count, void *data);
+int lprocfs_quota_rd_sync_blk(char *page, char **start, loff_t off,
+                             int count, int *eof, void *data);
+int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
+                             unsigned long count, void *data);
+int lprocfs_quota_rd_switch_qs(char *page, char **start, loff_t off,
+                              int count, int *eof, void *data);
+int lprocfs_quota_wr_switch_qs(struct file *file,
+                              const char *buffer, unsigned long count,
+                              void *data);
+int lprocfs_quota_rd_boundary_factor(char *page, char **start, loff_t off,
                                     int count, int *eof, void *data);
-extern int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
-                                    unsigned long count, void *data);
-extern int lprocfs_quota_rd_switch_qs(char *page, char **start, loff_t off,
-                                     int count, int *eof, void *data);
-extern int lprocfs_quota_wr_switch_qs(struct file *file,
-                                     const char *buffer,
-                                     unsigned long count, void *data);
-extern int lprocfs_quota_rd_boundary_factor(char *page, char **start, loff_t off,
-                                           int count, int *eof, void *data);
-extern int lprocfs_quota_wr_boundary_factor(struct file *file,
-                                           const char *buffer,
-                                           unsigned long count, void *data);
-extern int lprocfs_quota_rd_least_bunit(char *page, char **start, loff_t off,
-                                       int count, int *eof, void *data);
-extern int lprocfs_quota_wr_least_bunit(struct file *file,
-                                       const char *buffer,
-                                       unsigned long count, void *data);
-extern int lprocfs_quota_rd_least_iunit(char *page, char **start, loff_t off,
-                                       int count, int *eof, void *data);
-extern int lprocfs_quota_wr_least_iunit(struct file *file,
-                                       const char *buffer,
-                                       unsigned long count, void *data);
-extern int lprocfs_quota_rd_qs_factor(char *page, char **start, loff_t off,
-                                     int count, int *eof, void *data);
-extern int lprocfs_quota_wr_qs_factor(struct file *file,
-                                     const char *buffer,
-                                     unsigned long count, void *data);
+int lprocfs_quota_wr_boundary_factor(struct file *file,
+                                    const char *buffer, unsigned long count,
+                                    void *data);
+int lprocfs_quota_rd_least_bunit(char *page, char **start, loff_t off,
+                                int count, int *eof, void *data);
+int lprocfs_quota_wr_least_bunit(struct file *file,
+                                const char *buffer, unsigned long count,
+                                void *data);
+int lprocfs_quota_rd_least_iunit(char *page, char **start, loff_t off,
+                                int count, int *eof, void *data);
+int lprocfs_quota_wr_least_iunit(struct file *file,
+                                const char *buffer, unsigned long count,
+                                void *data);
+int lprocfs_quota_rd_qs_factor(char *page, char **start, loff_t off,
+                              int count, int *eof, void *data);
+int lprocfs_quota_wr_qs_factor(struct file *file,
+                              const char *buffer, unsigned long count,
+                              void *data);
 #endif /* LPROCFS_SNMP_H */
index 4d72d6ed26b03ffeddecfb744cdf2f6a051a59d8..ac78dbc38b9f3485a3bc32cad305748592c7b21d 100644 (file)
@@ -747,7 +747,7 @@ static inline ino_t lu_igif_ino(const struct lu_fid *fid)
        return fid_seq(fid);
 }
 
-extern void lustre_swab_ost_id(struct ost_id *oid);
+void lustre_swab_ost_id(struct ost_id *oid);
 
 /**
  * Get inode generation from a igif.
@@ -814,8 +814,8 @@ static inline int fid_is_zero(const struct lu_fid *fid)
        return fid_seq(fid) == 0 && fid_oid(fid) == 0;
 }
 
-extern void lustre_swab_lu_fid(struct lu_fid *fid);
-extern void lustre_swab_lu_seq_range(struct lu_seq_range *range);
+void lustre_swab_lu_fid(struct lu_fid *fid);
+void lustre_swab_lu_seq_range(struct lu_seq_range *range);
 
 static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1)
 {
@@ -1131,7 +1131,7 @@ struct ptlrpc_body_v2 {
        __u64 pb_padding[4];
 };
 
-extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
+void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
 
 /* message body offset for lustre_msg_v2 */
 /* ptlrpc body offset in all request/reply messages */
@@ -1395,7 +1395,7 @@ struct obd_connect_data {
  * reserve the flag for future use. */
 
 
-extern void lustre_swab_connect(struct obd_connect_data *ocd);
+void lustre_swab_connect(struct obd_connect_data *ocd);
 
 /*
  * Supported checksum algorithms. Up to 32 checksum types are supported.
@@ -1737,10 +1737,10 @@ struct hsm_state_set {
        __u64   hss_clearmask;
 };
 
-extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
-extern void lustre_swab_hsm_state_set(struct hsm_state_set *hss);
+void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
+void lustre_swab_hsm_state_set(struct hsm_state_set *hss);
 
-extern void lustre_swab_obd_statfs (struct obd_statfs *os);
+void lustre_swab_obd_statfs(struct obd_statfs *os);
 
 /* ost_body.data values for OST_BRW */
 
@@ -1780,7 +1780,7 @@ struct obd_ioobj {
 #define ioobj_max_brw_set(ioo, num)                                    \
 do { (ioo)->ioo_max_brw = ((num) - 1) << IOOBJ_MAX_BRW_BITS; } while (0)
 
-extern void lustre_swab_obd_ioobj (struct obd_ioobj *ioo);
+void lustre_swab_obd_ioobj(struct obd_ioobj *ioo);
 
 /* multiple of 8 bytes => can array */
 struct niobuf_remote {
@@ -1789,7 +1789,7 @@ struct niobuf_remote {
        __u32 flags;
 };
 
-extern void lustre_swab_niobuf_remote (struct niobuf_remote *nbr);
+void lustre_swab_niobuf_remote(struct niobuf_remote *nbr);
 
 /* lock value block communicated between the filter and llite */
 
@@ -1811,7 +1811,7 @@ struct ost_lvb_v1 {
        __u64           lvb_blocks;
 };
 
-extern void lustre_swab_ost_lvb_v1(struct ost_lvb_v1 *lvb);
+void lustre_swab_ost_lvb_v1(struct ost_lvb_v1 *lvb);
 
 struct ost_lvb {
        __u64           lvb_size;
@@ -1825,7 +1825,7 @@ struct ost_lvb {
        __u32           lvb_padding;
 };
 
-extern void lustre_swab_ost_lvb(struct ost_lvb *lvb);
+void lustre_swab_ost_lvb(struct ost_lvb *lvb);
 
 /*
  *   lquota data structures
@@ -1864,7 +1864,7 @@ struct obd_quotactl {
        struct obd_dqblk        qc_dqblk;
 };
 
-extern void lustre_swab_obd_quotactl(struct obd_quotactl *q);
+void lustre_swab_obd_quotactl(struct obd_quotactl *q);
 
 #define Q_QUOTACHECK   0x800100 /* deprecated as of 2.4 */
 #define Q_INITQUOTA    0x800101 /* deprecated as of 2.4  */
@@ -1913,7 +1913,7 @@ struct quota_body {
 #define QUOTA_DQACQ_FL_REL     0x4  /* release quota */
 #define QUOTA_DQACQ_FL_REPORT  0x8  /* report usage */
 
-extern void lustre_swab_quota_body(struct quota_body *b);
+void lustre_swab_quota_body(struct quota_body *b);
 
 /* Quota types currently supported */
 enum {
@@ -1993,7 +1993,7 @@ struct lquota_lvb {
        __u64   lvb_pad1;
 };
 
-extern void lustre_swab_lquota_lvb(struct lquota_lvb *lvb);
+void lustre_swab_lquota_lvb(struct lquota_lvb *lvb);
 
 /* LVB used with global quota lock */
 #define lvb_glb_ver  lvb_id_may_rel /* current version of the global index */
@@ -2072,7 +2072,7 @@ typedef enum {
        REINT_MAX
 } mds_reint_t, mdt_reint_t;
 
-extern void lustre_swab_generic_32s (__u32 *val);
+void lustre_swab_generic_32s(__u32 *val);
 
 /* the disposition of the intent outlines what was executed */
 #define DISP_IT_EXECD  0x00000001
@@ -2112,7 +2112,7 @@ extern void lustre_swab_generic_32s (__u32 *val);
 /* This FULL lock is useful to take on unlink sort of operations */
 #define MDS_INODELOCK_FULL ((1<<(MDS_INODELOCK_MAXSHIFT+1))-1)
 
-extern void lustre_swab_ll_fid (struct ll_fid *fid);
+void lustre_swab_ll_fid(struct ll_fid *fid);
 
 /* NOTE: until Lustre 1.8.7/2.1.1 the fid_ver() was packed into name[2],
  * but was moved into name[1] along with the OID to avoid consuming the
@@ -2231,7 +2231,7 @@ struct mdt_body {
        __u64     padding_10;
 }; /* 216 */
 
-extern void lustre_swab_mdt_body (struct mdt_body *b);
+void lustre_swab_mdt_body(struct mdt_body *b);
 
 struct mdt_ioepoch {
        struct lustre_handle handle;
@@ -2240,7 +2240,7 @@ struct mdt_ioepoch {
        __u32  padding;
 };
 
-extern void lustre_swab_mdt_ioepoch (struct mdt_ioepoch *b);
+void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b);
 
 /* permissions for md_perm.mp_perm */
 enum {
@@ -2264,7 +2264,7 @@ struct mdt_remote_perm {
        __u32      rp_padding;
 };
 
-extern void lustre_swab_mdt_remote_perm(struct mdt_remote_perm *p);
+void lustre_swab_mdt_remote_perm(struct mdt_remote_perm *p);
 
 struct mdt_rec_setattr {
        __u32      sa_opcode;
@@ -2294,7 +2294,7 @@ struct mdt_rec_setattr {
        __u32      sa_padding_5;
 };
 
-extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
+void lustre_swab_mdt_rec_setattr(struct mdt_rec_setattr *sa);
 
 /*
  * Attribute flags used in mdt_rec_setattr::sa_valid.
@@ -2584,7 +2584,7 @@ struct mdt_rec_reint {
        __u32      rr_padding_4; /* also fix lustre_swab_mdt_rec_reint */
 };
 
-extern void lustre_swab_mdt_rec_reint(struct mdt_rec_reint *rr);
+void lustre_swab_mdt_rec_reint(struct mdt_rec_reint *rr);
 
 struct lmv_desc {
        __u32 ld_tgt_count;             /* how many MDS's */
@@ -2600,7 +2600,7 @@ struct lmv_desc {
        struct obd_uuid ld_uuid;
 };
 
-extern void lustre_swab_lmv_desc (struct lmv_desc *ld);
+void lustre_swab_lmv_desc(struct lmv_desc *ld);
 
 /* TODO: lmv_stripe_md should contain mds capabilities for all slave fids */
 struct lmv_stripe_md {
@@ -2612,7 +2612,7 @@ struct lmv_stripe_md {
        struct lu_fid mea_ids[0];
 };
 
-extern void lustre_swab_lmv_stripe_md(struct lmv_stripe_md *mea);
+void lustre_swab_lmv_stripe_md(struct lmv_stripe_md *mea);
 
 /* lmv structures */
 #define MEA_MAGIC_LAST_CHAR      0xb2221ca1
@@ -2670,7 +2670,7 @@ struct lov_desc {
 
 #define ld_magic ld_active_tgt_count       /* for swabbing from llogs */
 
-extern void lustre_swab_lov_desc (struct lov_desc *ld);
+void lustre_swab_lov_desc(struct lov_desc *ld);
 
 /*
  *   LDLM requests:
@@ -2697,7 +2697,7 @@ struct ldlm_res_id {
 #define PLDLMRES(res)  (res)->lr_name.name[0], (res)->lr_name.name[1], \
                        (res)->lr_name.name[2], (res)->lr_name.name[3]
 
-extern void lustre_swab_ldlm_res_id (struct ldlm_res_id *id);
+void lustre_swab_ldlm_res_id(struct ldlm_res_id *id);
 
 static inline int ldlm_res_eq(const struct ldlm_res_id *res0,
                              const struct ldlm_res_id *res1)
@@ -2774,19 +2774,19 @@ typedef union {
        struct ldlm_inodebits l_inodebits;
 } ldlm_wire_policy_data_t;
 
-extern void lustre_swab_ldlm_policy_data (ldlm_wire_policy_data_t *d);
+void lustre_swab_ldlm_policy_data(ldlm_wire_policy_data_t *d);
 
 union ldlm_gl_desc {
        struct ldlm_gl_lquota_desc      lquota_desc;
 };
 
-extern void lustre_swab_gl_desc(union ldlm_gl_desc *);
+void lustre_swab_gl_desc(union ldlm_gl_desc *);
 
 struct ldlm_intent {
        __u64 opc;
 };
 
-extern void lustre_swab_ldlm_intent (struct ldlm_intent *i);
+void lustre_swab_ldlm_intent(struct ldlm_intent *i);
 
 struct ldlm_resource_desc {
        ldlm_type_t lr_type;
@@ -2794,7 +2794,7 @@ struct ldlm_resource_desc {
        struct ldlm_res_id lr_name;
 };
 
-extern void lustre_swab_ldlm_resource_desc (struct ldlm_resource_desc *r);
+void lustre_swab_ldlm_resource_desc(struct ldlm_resource_desc *r);
 
 struct ldlm_lock_desc {
        struct ldlm_resource_desc l_resource;
@@ -2803,7 +2803,7 @@ struct ldlm_lock_desc {
        ldlm_wire_policy_data_t l_policy_data;
 };
 
-extern void lustre_swab_ldlm_lock_desc (struct ldlm_lock_desc *l);
+void lustre_swab_ldlm_lock_desc(struct ldlm_lock_desc *l);
 
 #define LDLM_LOCKREQ_HANDLES 2
 #define LDLM_ENQUEUE_CANCEL_OFF 1
@@ -2815,7 +2815,7 @@ struct ldlm_request {
        struct lustre_handle lock_handle[LDLM_LOCKREQ_HANDLES];
 };
 
-extern void lustre_swab_ldlm_request (struct ldlm_request *rq);
+void lustre_swab_ldlm_request(struct ldlm_request *rq);
 
 /* If LDLM_ENQUEUE, 1 slot is already occupied, 1 is available.
  * Otherwise, 2 are available. */
@@ -2837,7 +2837,7 @@ struct ldlm_reply {
        __u64  lock_policy_res2;
 };
 
-extern void lustre_swab_ldlm_reply (struct ldlm_reply *r);
+void lustre_swab_ldlm_reply(struct ldlm_reply *r);
 
 #define ldlm_flags_to_wire(flags)    ((__u32)(flags))
 #define ldlm_flags_from_wire(flags)  ((__u64)(flags))
@@ -2881,7 +2881,8 @@ struct mgs_target_info {
        __u64       mti_nids[MTI_NIDS_MAX];     /* host nids (lnet_nid_t)*/
        char         mti_params[MTI_PARAM_MAXLEN];
 };
-extern void lustre_swab_mgs_target_info(struct mgs_target_info *oinfo);
+
+void lustre_swab_mgs_target_info(struct mgs_target_info *oinfo);
 
 struct mgs_nidtbl_entry {
        __u64      mne_version;    /* table version of this entry */
@@ -2896,7 +2897,8 @@ struct mgs_nidtbl_entry {
                lnet_nid_t nids[0];     /* variable size buffer for NIDs. */
        } u;
 };
-extern void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *oinfo);
+
+void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *oinfo);
 
 struct mgs_config_body {
        char     mcb_name[MTI_NAME_MAXLEN]; /* logname */
@@ -2906,13 +2908,15 @@ struct mgs_config_body {
        __u8     mcb_bits;      /* bits unit size of config log */
        __u32    mcb_units;     /* # of units for bulk transfer */
 };
-extern void lustre_swab_mgs_config_body(struct mgs_config_body *body);
+
+void lustre_swab_mgs_config_body(struct mgs_config_body *body);
 
 struct mgs_config_res {
        __u64    mcr_offset;    /* index of last config log */
        __u64    mcr_size;      /* size of the log */
 };
-extern void lustre_swab_mgs_config_res(struct mgs_config_res *body);
+
+void lustre_swab_mgs_config_res(struct mgs_config_res *body);
 
 /* Config marker flags (in config log) */
 #define CM_START       0x01
@@ -2933,8 +2937,7 @@ struct cfg_marker {
        char          cm_comment[MTI_NAME_MAXLEN];
 };
 
-extern void lustre_swab_cfg_marker(struct cfg_marker *marker,
-                                  int swab, int size);
+void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size);
 
 /*
  * Opcodes for multiple servers.
@@ -3334,7 +3337,7 @@ static inline void lustre_get_wire_obdo(struct obd_connect_data *ocd,
        }
 }
 
-extern void lustre_swab_obdo (struct obdo *o);
+void lustre_swab_obdo(struct obdo *o);
 
 /* request structure for OST's */
 struct ost_body {
@@ -3348,25 +3351,25 @@ struct ll_fiemap_info_key {
        struct  ll_user_fiemap fiemap;
 };
 
-extern void lustre_swab_ost_body (struct ost_body *b);
-extern void lustre_swab_ost_last_id(__u64 *id);
-extern void lustre_swab_fiemap(struct ll_user_fiemap *fiemap);
+void lustre_swab_ost_body(struct ost_body *b);
+void lustre_swab_ost_last_id(__u64 *id);
+void lustre_swab_fiemap(struct ll_user_fiemap *fiemap);
 
-extern void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum);
-extern void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum);
-extern void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
-                                           int stripe_count);
-extern void lustre_swab_lov_mds_md(struct lov_mds_md *lmm);
+void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum);
+void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum);
+void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
+                                    int stripe_count);
+void lustre_swab_lov_mds_md(struct lov_mds_md *lmm);
 
 /* llog_swab.c */
-extern void lustre_swab_llogd_body (struct llogd_body *d);
-extern void lustre_swab_llog_hdr (struct llog_log_hdr *h);
-extern void lustre_swab_llogd_conn_body (struct llogd_conn_body *d);
-extern void lustre_swab_llog_rec(struct llog_rec_hdr *rec);
-extern void lustre_swab_llog_id(struct llog_logid *lid);
+void lustre_swab_llogd_body(struct llogd_body *d);
+void lustre_swab_llog_hdr(struct llog_log_hdr *h);
+void lustre_swab_llogd_conn_body(struct llogd_conn_body *d);
+void lustre_swab_llog_rec(struct llog_rec_hdr *rec);
+void lustre_swab_llog_id(struct llog_logid *lid);
 
 struct lustre_cfg;
-extern void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg);
+void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg);
 
 /* Functions for dumping PTLRPC fields */
 void dump_rniobuf(struct niobuf_remote *rnb);
@@ -3418,7 +3421,8 @@ struct idx_info {
        __u64           ii_pad2;
        __u64           ii_pad3;
 };
-extern void lustre_swab_idx_info(struct idx_info *ii);
+
+void lustre_swab_idx_info(struct idx_info *ii);
 
 #define II_END_OFF     MDS_DIR_END_OFF /* all entries have been read */
 
@@ -3450,7 +3454,8 @@ struct lu_idxpage {
         * For the time being, we only support fixed-size key & record. */
        char    lip_entries[0];
 };
-extern void lustre_swab_lip_header(struct lu_idxpage *lip);
+
+void lustre_swab_lip_header(struct lu_idxpage *lip);
 
 #define LIP_HDR_SIZE (offsetof(struct lu_idxpage, lip_entries))
 
@@ -3490,7 +3495,7 @@ struct lustre_capa {
        __u8        lc_hmac[CAPA_HMAC_MAX_LEN];   /** HMAC */
 } __attribute__((packed));
 
-extern void lustre_swab_lustre_capa(struct lustre_capa *c);
+void lustre_swab_lustre_capa(struct lustre_capa *c);
 
 /** lustre_capa::lc_opc */
 enum {
@@ -3548,7 +3553,7 @@ struct lustre_capa_key {
        __u8    lk_key[CAPA_HMAC_KEY_MAX_LEN];    /**< key */
 } __attribute__((packed));
 
-extern void lustre_swab_lustre_capa_key(struct lustre_capa_key *k);
+void lustre_swab_lustre_capa_key(struct lustre_capa_key *k);
 
 /** The link ea holds 1 \a link_ea_entry for each hardlink */
 #define LINK_EA_MAGIC 0x11EAF1DFUL
@@ -3620,12 +3625,12 @@ struct hsm_progress_kernel {
        __u64                   hpk_padding2;
 } __attribute__((packed));
 
-extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
-extern void lustre_swab_hsm_current_action(struct hsm_current_action *action);
-extern void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk);
-extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
-extern void lustre_swab_hsm_user_item(struct hsm_user_item *hui);
-extern void lustre_swab_hsm_request(struct hsm_request *hr);
+void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
+void lustre_swab_hsm_current_action(struct hsm_current_action *action);
+void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk);
+void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
+void lustre_swab_hsm_user_item(struct hsm_user_item *hui);
+void lustre_swab_hsm_request(struct hsm_request *hr);
 
 /**
  * These are object update opcode under UPDATE_OBJ, which is currently
index e095ada40ed2ed5dfdd841805c51a67413740337..9b1bb23c4d3c00ac89185d3c52a69d7f5808b2c1 100644 (file)
@@ -406,7 +406,7 @@ static inline int lmv_user_md_size(int stripes, int lmm_magic)
                      stripes * sizeof(struct lmv_user_mds_data);
 }
 
-extern void lustre_swab_lmv_user_md(struct lmv_user_md *lum);
+void lustre_swab_lmv_user_md(struct lmv_user_md *lum);
 
 struct ll_recreate_obj {
        __u64 lrc_id;
index f6f4c037fb301b87b381f9bf53d16a5ba3a35f24..355254689dee0b7c21a4e4851a0f6b02f4868849 100644 (file)
@@ -1017,7 +1017,7 @@ extern struct obd_ops ldlm_obd_ops;
 
 extern char *ldlm_lockname[];
 extern char *ldlm_typename[];
-extern char *ldlm_it2str(int it);
+char *ldlm_it2str(int it);
 
 /**
  * Just a fancy CDEBUG call with log level preset to LDLM_DEBUG.
index 3b992b42fd91b83f92839452ba872f530a6275c0..5189fad0b73cb3b146383f43837c30a175fcb2ff 100644 (file)
@@ -368,8 +368,8 @@ static inline bool imp_connect_disp_stripe(struct obd_import *imp)
        return ocd->ocd_connect_flags & OBD_CONNECT_DISP_STRIPE;
 }
 
-extern struct obd_export *class_conn2export(struct lustre_handle *conn);
-extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
+struct obd_export *class_conn2export(struct lustre_handle *conn);
+struct obd_device *class_conn2obd(struct lustre_handle *conn);
 
 /** @} export */
 
index dcc807676c490ec44e09467795e3c3f2c3aed863..5a38f3d5e011e522e12792be1afa666ba00a99d1 100644 (file)
@@ -375,8 +375,8 @@ extern unsigned int at_max;
 
 /* genops.c */
 struct obd_export;
-extern struct obd_import *class_exp2cliimp(struct obd_export *);
-extern struct obd_import *class_conn2cliimp(struct lustre_handle *);
+struct obd_import *class_exp2cliimp(struct obd_export *);
+struct obd_import *class_conn2cliimp(struct lustre_handle *);
 
 /** @} import */
 
index 77a7de98fc8ef18cecc1d0e0fe4a04278362a36d..48ad60b221223b1c85864bb534244fbb2eb9afab 100644 (file)
@@ -2183,7 +2183,7 @@ struct ptlrpcd_ctl {
         */
        struct ptlrpc_request_set  *pc_set;
        /**
-        * Thread name used in cfs_daemonize()
+        * Thread name used in kthread_run()
         */
        char                    pc_name[16];
        /**
@@ -2277,18 +2277,18 @@ static inline bool nrs_policy_compat_one(const struct ptlrpc_service *svc,
 
 /* ptlrpc/events.c */
 extern lnet_handle_eq_t ptlrpc_eq_h;
-extern int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
-                              lnet_process_id_t *peer, lnet_nid_t *self);
+int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
+                       lnet_process_id_t *peer, lnet_nid_t *self);
 /**
  * These callbacks are invoked by LNet when something happened to
  * underlying buffer
  * @{
  */
-extern void request_out_callback(lnet_event_t *ev);
-extern void reply_in_callback(lnet_event_t *ev);
-extern void client_bulk_callback(lnet_event_t *ev);
-extern void request_in_callback(lnet_event_t *ev);
-extern void reply_out_callback(lnet_event_t *ev);
+void request_out_callback(lnet_event_t *ev);
+void reply_in_callback(lnet_event_t *ev);
+void client_bulk_callback(lnet_event_t *ev);
+void request_in_callback(lnet_event_t *ev);
+void reply_out_callback(lnet_event_t *ev);
 /** @} */
 
 /* ptlrpc/connection.c */
@@ -2299,7 +2299,7 @@ int ptlrpc_connection_put(struct ptlrpc_connection *c);
 struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *);
 int ptlrpc_connection_init(void);
 void ptlrpc_connection_fini(void);
-extern lnet_pid_t ptl_get_pid(void);
+lnet_pid_t ptl_get_pid(void);
 
 /* ptlrpc/niobuf.c */
 /**
index 55452e562bd4823213025279264044e9d31d99c6..9ad8c268da10efe512aff7b530297faaf6d11aed 100644 (file)
@@ -1472,7 +1472,7 @@ static inline bool filename_is_volatile(const char *name, int namelen, int *idx)
        }
        /* we have an idx, read it */
        start = name + LUSTRE_VOLATILE_HDR_LEN + 1;
-       *idx = strtoul(start, &end, 0);
+       *idx = simple_strtoul(start, &end, 0);
        /* error cases:
         * no digit, no trailing :, negative value
         */
index 36ed78127830b001d574baad59f9da04e5d12b28..87bb2cedca7d0002621e334cdf2447ca1b175721 100644 (file)
@@ -64,10 +64,10 @@ extern struct obd_device *obd_devs[MAX_OBD_DEVICES];
 extern rwlock_t obd_dev_lock;
 
 /* OBD Operations Declarations */
-extern struct obd_device *class_conn2obd(struct lustre_handle *);
-extern struct obd_device *class_exp2obd(struct obd_export *);
-extern int class_handle_ioctl(unsigned int cmd, unsigned long arg);
-extern int lustre_get_jobid(char *jobid);
+struct obd_device *class_conn2obd(struct lustre_handle *);
+struct obd_device *class_exp2obd(struct obd_export *);
+int class_handle_ioctl(unsigned int cmd, unsigned long arg);
+int lustre_get_jobid(char *jobid);
 
 struct lu_device_type;
 
@@ -139,7 +139,7 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg);
 int class_add_uuid(const char *uuid, __u64 nid);
 
 /*obdecho*/
-extern void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
+void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
 
 #define CFG_F_START     0x01   /* Set when we start updating from a log */
 #define CFG_F_MARKER    0x02   /* We are within a maker */
@@ -1823,8 +1823,8 @@ static inline int md_revalidate_lock(struct obd_export *exp,
 
 /* OBD Metadata Support */
 
-extern int obd_init_caches(void);
-extern void obd_cleanup_caches(void);
+int obd_init_caches(void);
+void obd_cleanup_caches(void);
 
 /* support routines */
 extern struct kmem_cache *obdo_cachep;
@@ -1869,8 +1869,7 @@ extern int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
 /* obd_mount.c */
 
 /* sysctl.c */
-extern void obd_sysctl_init (void);
-extern void obd_sysctl_clean (void);
+int obd_sysctl_init(void);
 
 /* uuid.c  */
 typedef __u8 class_uuid_t[16];
index 73e2d4880b9b392c924b7f1e6e8e0fb7bd8648f3..18aec796a724a77b2a84b2217913d353293a4a8e 100644 (file)
@@ -56,9 +56,7 @@ extern unsigned int obd_dump_on_eviction;
 /* obd_timeout should only be used for recovery, not for
    networking / disk / timings affected by load (use Adaptive Timeouts) */
 extern unsigned int obd_timeout;         /* seconds */
-extern unsigned int ldlm_timeout;       /* seconds */
 extern unsigned int obd_timeout_set;
-extern unsigned int ldlm_timeout_set;
 extern unsigned int at_min;
 extern unsigned int at_max;
 extern unsigned int at_history;
@@ -105,8 +103,6 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type,
 
 /* Timeout definitions */
 #define OBD_TIMEOUT_DEFAULT         100
-#define LDLM_TIMEOUT_DEFAULT       20
-#define MDS_LDLM_TIMEOUT_DEFAULT       6
 /* Time to wait for all clients to reconnect during recovery (hard limit) */
 #define OBD_RECOVERY_TIME_HARD   (obd_timeout * 9)
 /* Time to wait for all clients to reconnect during recovery (soft limit) */
@@ -505,9 +501,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type,
 #define OBD_FAIL_ONCE                     CFS_FAIL_ONCE
 #define OBD_FAILED                           CFS_FAILED
 
-extern atomic_t libcfs_kmemory;
-
-extern void obd_update_maxusage(void);
+void obd_update_maxusage(void);
 
 #define obd_memory_add(size)                                             \
        lprocfs_counter_add(obd_memory, OBD_MEMORY_STAT, (long)(size))
@@ -526,8 +520,8 @@ extern void obd_update_maxusage(void);
        lprocfs_stats_collector(obd_memory, OBD_MEMORY_PAGES_STAT,          \
                                LPROCFS_FIELDS_FLAGS_SUM)
 
-extern __u64 obd_memory_max(void);
-extern __u64 obd_pages_max(void);
+__u64 obd_memory_max(void);
+__u64 obd_pages_max(void);
 
 #define OBD_DEBUG_MEMUSAGE (1)
 
@@ -622,8 +616,8 @@ do {                                                                              \
        if (unlikely((ptr) == NULL)) {                                  \
                CERROR("vmalloc of '" #ptr "' (%d bytes) failed\n",        \
                       (int)(size));                                      \
-               CERROR("%llu total bytes allocated by Lustre, %d by LNET\n", \
-                      obd_memory_sum(), atomic_read(&libcfs_kmemory));   \
+               CERROR("%llu total bytes allocated by Lustre\n",              \
+                      obd_memory_sum());                                     \
        } else {                                                              \
                OBD_ALLOC_POST(ptr, size, "vmalloced");                \
        }                                                                    \
@@ -769,12 +763,10 @@ do {                                                                            \
                       "failed\n", (int)1,                                  \
                       (__u64)(1 << PAGE_CACHE_SHIFT));                  \
                CERROR("%llu total bytes and %llu total pages "    \
-                      "(%llu bytes) allocated by Lustre, "             \
-                      "%d total bytes by LNET\n",                          \
+                      "(%llu bytes) allocated by Lustre\n",                  \
                       obd_memory_sum(),                                      \
                       obd_pages_sum() << PAGE_CACHE_SHIFT,                  \
-                      obd_pages_sum(),                                \
-                      atomic_read(&libcfs_kmemory));                \
+                      obd_pages_sum());                                       \
        } else {                                                              \
                obd_pages_add(0);                                            \
                CDEBUG(D_MALLOC, "alloc_pages '" #ptr "': %d page(s) / "      \
index e0c1ccafbd63562f2be3e7ae11b24995091fdc79..9053f811629874f72f479d20c630b6946a12f3f6 100644 (file)
@@ -203,7 +203,7 @@ struct lu_device *ccc_device_alloc(const struct lu_env *env,
        int rc;
 
        vdv = kzalloc(sizeof(*vdv), GFP_NOFS);
-       if (vdv == NULL)
+       if (!vdv)
                return ERR_PTR(-ENOMEM);
 
        lud = &vdv->cdv_cl.cd_lu_dev;
index 6601e6b12c32df7c917e07d56c0e716545f39f6d..fa4b7c760d496c6f4a53550676218576cba799a7 100644 (file)
@@ -209,7 +209,7 @@ struct ldlm_state {
 
 /* interval tree, for LDLM_EXTENT. */
 extern struct kmem_cache *ldlm_interval_slab; /* slab cache for ldlm_interval */
-extern void ldlm_interval_attach(struct ldlm_interval *n, struct ldlm_lock *l);
+void ldlm_interval_attach(struct ldlm_interval *n, struct ldlm_lock *l);
 struct ldlm_interval *ldlm_interval_detach(struct ldlm_lock *l);
 struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock);
 void ldlm_interval_free(struct ldlm_interval *node);
index 764f98684d74ef294b30942de737a5dbe3f2c420..badd227e4f67a0732982a73f8555fa69b5927f4d 100644 (file)
@@ -656,7 +656,8 @@ int target_pack_pool_reply(struct ptlrpc_request *req)
 }
 EXPORT_SYMBOL(target_pack_pool_reply);
 
-int target_send_reply_msg(struct ptlrpc_request *req, int rc, int fail_id)
+static int
+target_send_reply_msg(struct ptlrpc_request *req, int rc, int fail_id)
 {
        if (OBD_FAIL_CHECK_ORSET(fail_id & ~OBD_FAIL_ONCE, OBD_FAIL_ONCE)) {
                DEBUG_REQ(D_ERROR, req, "dropping reply");
index bb2246d3b22b51978ef00122710c6c01c67e3f61..cd340fc8ceab45238e51449434f130973b61cda4 100644 (file)
@@ -1528,7 +1528,7 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns,
        if (lvb_len) {
                lock->l_lvb_len = lvb_len;
                lock->l_lvb_data = kzalloc(lvb_len, GFP_NOFS);
-               if (lock->l_lvb_data == NULL)
+               if (!lock->l_lvb_data)
                        goto out;
        }
 
@@ -1813,7 +1813,7 @@ int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
                return 0;
 
        arg = kzalloc(sizeof(*arg), GFP_NOFS);
-       if (arg == NULL)
+       if (!arg)
                return -ENOMEM;
 
        atomic_set(&arg->restart, 0);
index b7b6ca1196b7fba3f291b7f4afa7193d07b49e30..ac79db952da78babfedf328047d798526e74780a 100644 (file)
@@ -76,15 +76,6 @@ inline unsigned long round_timeout(unsigned long timeout)
        return cfs_time_seconds((int)cfs_duration_sec(cfs_time_sub(timeout, 0)) + 1);
 }
 
-/* timeout for initial callback (AST) reply (bz10399) */
-static inline unsigned int ldlm_get_rq_timeout(void)
-{
-       /* Non-AT value */
-       unsigned int timeout = min(ldlm_timeout, obd_timeout / 3);
-
-       return timeout < 1 ? 1 : timeout;
-}
-
 #define ELT_STOPPED   0
 #define ELT_READY     1
 #define ELT_TERMINATE 2
@@ -225,7 +216,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req,
                        void *lvb_data;
 
                        lvb_data = kzalloc(lvb_len, GFP_NOFS);
-                       if (lvb_data == NULL) {
+                       if (!lvb_data) {
                                LDLM_ERROR(lock, "No memory: %d.\n", lvb_len);
                                rc = -ENOMEM;
                                goto out;
@@ -453,7 +444,7 @@ static int ldlm_bl_to_thread(struct ldlm_namespace *ns,
                struct ldlm_bl_work_item *blwi;
 
                blwi = kzalloc(sizeof(*blwi), GFP_NOFS);
-               if (blwi == NULL)
+               if (!blwi)
                        return -ENOMEM;
                init_blwi(blwi, ns, ld, cancels, count, lock, cancel_flags);
 
@@ -1053,7 +1044,7 @@ static int ldlm_setup(void)
                return -EALREADY;
 
        ldlm_state = kzalloc(sizeof(*ldlm_state), GFP_NOFS);
-       if (ldlm_state == NULL)
+       if (!ldlm_state)
                return -ENOMEM;
 
        ldlm_kobj = kobject_create_and_add("ldlm", lustre_kobj);
@@ -1123,7 +1114,7 @@ static int ldlm_setup(void)
 
 
        blp = kzalloc(sizeof(*blp), GFP_NOFS);
-       if (blp == NULL) {
+       if (!blp) {
                rc = -ENOMEM;
                goto out;
        }
index 1605b9c692715512109da73215a7e9ec1c597738..c234acb85f10063cef7aa0a8c9b8f71c8519b8b2 100644 (file)
@@ -1422,7 +1422,7 @@ static int ldlm_pools_thread_start(void)
                return -EALREADY;
 
        ldlm_pools_thread = kzalloc(sizeof(*ldlm_pools_thread), GFP_NOFS);
-       if (ldlm_pools_thread == NULL)
+       if (!ldlm_pools_thread)
                return -ENOMEM;
 
        init_completion(&ldlm_pools_comp);
@@ -1486,8 +1486,10 @@ EXPORT_SYMBOL(ldlm_pools_init);
 
 void ldlm_pools_fini(void)
 {
-       unregister_shrinker(&ldlm_pools_srv_shrinker);
-       unregister_shrinker(&ldlm_pools_cli_shrinker);
+       if (ldlm_pools_thread) {
+               unregister_shrinker(&ldlm_pools_srv_shrinker);
+               unregister_shrinker(&ldlm_pools_cli_shrinker);
+       }
        ldlm_pools_thread_stop();
 }
 EXPORT_SYMBOL(ldlm_pools_fini);
index cdb63665a11389ba685dc6e7b05462f0158cee17..4bb3173bcd5f18d0c7d4467b0b330f59e892e401 100644 (file)
@@ -939,6 +939,7 @@ void ldlm_namespace_free_post(struct ldlm_namespace *ns)
        ldlm_pool_fini(&ns->ns_pool);
 
        ldlm_namespace_debugfs_unregister(ns);
+       ldlm_namespace_sysfs_unregister(ns);
        cfs_hash_putref(ns->ns_rs_hash);
        /* Namespace \a ns should be not on list at this time, otherwise
         * this will cause issues related to using freed \a ns in poold
index 021c92fa0333f2cd92c91b10762fcbceac7ed723..e93f556fac0dde68da054320fc320815c1025258 100644 (file)
@@ -57,8 +57,42 @@ module_param(libcfs_debug, int, 0644);
 MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask");
 EXPORT_SYMBOL(libcfs_debug);
 
+static int libcfs_param_debug_mb_set(const char *val,
+                                    const struct kernel_param *kp)
+{
+       int rc;
+       unsigned num;
+
+       rc = kstrtouint(val, 0, &num);
+       if (rc < 0)
+               return rc;
+
+       if (!*((unsigned int *)kp->arg)) {
+               *((unsigned int *)kp->arg) = num;
+               return 0;
+       }
+
+       rc = cfs_trace_set_debug_mb(num);
+
+       if (!rc)
+               *((unsigned int *)kp->arg) = cfs_trace_get_debug_mb();
+
+       return rc;
+}
+
+/* While debug_mb setting look like unsigned int, in fact
+ * it needs quite a bunch of extra processing, so we define special
+ * debugmb parameter type with corresponding methods to handle this case */
+static struct kernel_param_ops param_ops_debugmb = {
+       .set = libcfs_param_debug_mb_set,
+       .get = param_get_uint,
+};
+
+#define param_check_debugmb(name, p) \
+               __param_check(name, p, unsigned int)
+
 static unsigned int libcfs_debug_mb;
-module_param(libcfs_debug_mb, uint, 0644);
+module_param(libcfs_debug_mb, debugmb, 0644);
 MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size.");
 EXPORT_SYMBOL(libcfs_debug_mb);
 
@@ -72,18 +106,106 @@ module_param(libcfs_console_ratelimit, uint, 0644);
 MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)");
 EXPORT_SYMBOL(libcfs_console_ratelimit);
 
+static int param_set_delay_minmax(const char *val,
+                                 const struct kernel_param *kp,
+                                 long min, long max)
+{
+       long d;
+       int sec;
+       int rc;
+
+       rc = kstrtoint(val, 0, &sec);
+       if (rc)
+               return -EINVAL;
+
+       d = cfs_time_seconds(sec) / 100;
+       if (d < min || d > max)
+               return -EINVAL;
+
+       *((unsigned int *)kp->arg) = d;
+
+       return 0;
+}
+
+static int param_get_delay(char *buffer, const struct kernel_param *kp)
+{
+       unsigned int d = *(unsigned int *)kp->arg;
+
+       return sprintf(buffer, "%u", (unsigned int)cfs_duration_sec(d * 100));
+}
+
 unsigned int libcfs_console_max_delay;
-module_param(libcfs_console_max_delay, uint, 0644);
-MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)");
 EXPORT_SYMBOL(libcfs_console_max_delay);
-
 unsigned int libcfs_console_min_delay;
-module_param(libcfs_console_min_delay, uint, 0644);
-MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)");
 EXPORT_SYMBOL(libcfs_console_min_delay);
 
+static int param_set_console_max_delay(const char *val,
+                                      const struct kernel_param *kp)
+{
+       return param_set_delay_minmax(val, kp,
+                                     libcfs_console_min_delay, INT_MAX);
+}
+
+static struct kernel_param_ops param_ops_console_max_delay = {
+       .set = param_set_console_max_delay,
+       .get = param_get_delay,
+};
+
+#define param_check_console_max_delay(name, p) \
+               __param_check(name, p, unsigned int)
+
+module_param(libcfs_console_max_delay, console_max_delay, 0644);
+MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)");
+
+static int param_set_console_min_delay(const char *val,
+                                      const struct kernel_param *kp)
+{
+       return param_set_delay_minmax(val, kp,
+                                     1, libcfs_console_max_delay);
+}
+
+static struct kernel_param_ops param_ops_console_min_delay = {
+       .set = param_set_console_min_delay,
+       .get = param_get_delay,
+};
+
+#define param_check_console_min_delay(name, p) \
+               __param_check(name, p, unsigned int)
+
+module_param(libcfs_console_min_delay, console_min_delay, 0644);
+MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)");
+
+static int param_set_uint_minmax(const char *val,
+                                const struct kernel_param *kp,
+                                unsigned int min, unsigned int max)
+{
+       unsigned int num;
+       int ret;
+
+       if (!val)
+               return -EINVAL;
+       ret = kstrtouint(val, 0, &num);
+       if (ret < 0 || num < min || num > max)
+               return -EINVAL;
+       *((unsigned int *)kp->arg) = num;
+       return 0;
+}
+
+static int param_set_uintpos(const char *val, const struct kernel_param *kp)
+{
+       return param_set_uint_minmax(val, kp, 1, -1);
+}
+
+static struct kernel_param_ops param_ops_uintpos = {
+       .set = param_set_uintpos,
+       .get = param_get_uint,
+};
+
+#define param_check_uintpos(name, p) \
+               __param_check(name, p, unsigned int)
+
 unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
-module_param(libcfs_console_backoff, uint, 0644);
+module_param(libcfs_console_backoff, uintpos, 0644);
 MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor");
 EXPORT_SYMBOL(libcfs_console_backoff);
 
@@ -93,23 +215,14 @@ EXPORT_SYMBOL(libcfs_debug_binary);
 unsigned int libcfs_stack = 3 * THREAD_SIZE / 4;
 EXPORT_SYMBOL(libcfs_stack);
 
-static unsigned int portal_enter_debugger;
-EXPORT_SYMBOL(portal_enter_debugger);
-
 unsigned int libcfs_catastrophe;
 EXPORT_SYMBOL(libcfs_catastrophe);
 
-unsigned int libcfs_watchdog_ratelimit = 300;
-EXPORT_SYMBOL(libcfs_watchdog_ratelimit);
-
 unsigned int libcfs_panic_on_lbug = 1;
 module_param(libcfs_panic_on_lbug, uint, 0644);
 MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG");
 EXPORT_SYMBOL(libcfs_panic_on_lbug);
 
-atomic_t libcfs_kmemory = ATOMIC_INIT(0);
-EXPORT_SYMBOL(libcfs_kmemory);
-
 static wait_queue_head_t debug_ctlwq;
 
 char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT;
@@ -414,8 +527,10 @@ int libcfs_debug_init(unsigned long bufsize)
        }
        rc = cfs_tracefile_init(max);
 
-       if (rc == 0)
+       if (rc == 0) {
                libcfs_register_panic_notifier();
+               libcfs_debug_mb = cfs_trace_get_debug_mb();
+       }
 
        return rc;
 }
index 7b7fc215e633298025042a650cb86f0985552444..42d615fbd664f9ba90552690dfd614a52ac2ea8d 100644 (file)
@@ -123,7 +123,7 @@ EXPORT_SYMBOL(__cfs_fail_check_set);
 
 int __cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set)
 {
-       int ret = 0;
+       int ret;
 
        ret = __cfs_fail_check_set(id, value, set);
        if (ret) {
index 31a558115a96b427d9453dd6bc1ac385a278fa73..933525c73da1ba24e1e35b69e6358171d31bd8fb 100644 (file)
@@ -78,7 +78,7 @@ EXPORT_SYMBOL(cfs_cpt_table_free);
 int
 cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len)
 {
-       int     rc = 0;
+       int     rc;
 
        rc = snprintf(buf, len, "%d\t: %d\n", 0, 0);
        len -= rc;
index 76d4392bd28249c1d2611c2989be7ffd3c87d342..efe5e667a2e56292d2557492b0290fe0b38f7adc 100644 (file)
@@ -231,7 +231,7 @@ cfs_str2num_check(char *str, int nob, unsigned *num,
        char    *endp;
 
        str = cfs_trimwhite(str);
-       *num = strtoul(str, &endp, 0);
+       *num = simple_strtoul(str, &endp, 0);
        if (endp == str)
                return 0;
 
@@ -400,7 +400,7 @@ cfs_expr_list_free(struct cfs_expr_list *expr_list)
                struct cfs_range_expr *expr;
 
                expr = list_entry(expr_list->el_exprs.next,
-                                     struct cfs_range_expr, re_link),
+                                     struct cfs_range_expr, re_link);
                list_del(&expr->re_link);
                LIBCFS_FREE(expr, sizeof(*expr));
        }
index aa3fffed1519fa85441435361fe95320db53190f..fbbc8a7e308dc40f5e5d714723a0849951509a07 100644 (file)
@@ -114,7 +114,7 @@ int cfs_crypto_hash_digest(unsigned char alg_id,
                crypto_free_hash(hdesc.tfm);
                return -ENOSPC;
        }
-       sg_init_one(&sl, (void *)buf, buf_len);
+       sg_init_one(&sl, buf, buf_len);
 
        hdesc.flags = 0;
        err = crypto_hash_digest(&hdesc, &sl, sl.length, hash);
@@ -165,7 +165,7 @@ int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *hdesc,
 {
        struct scatterlist sl;
 
-       sg_init_one(&sl, (void *)buf, buf_len);
+       sg_init_one(&sl, buf, buf_len);
 
        return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length);
 }
index e962f89683a60cdb68ee67b3070bc185d783027e..64a984b42845ddb840e0512a1327bcc0a49bcb44 100644 (file)
@@ -49,7 +49,7 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
        hdr = (struct libcfs_ioctl_hdr *)buf;
        data = (struct libcfs_ioctl_data *)buf;
 
-       if (copy_from_user(buf, (void *)arg, sizeof(*hdr)))
+       if (copy_from_user(buf, arg, sizeof(*hdr)))
                return -EFAULT;
 
        if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) {
@@ -69,7 +69,7 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
        }
 
        orig_len = hdr->ioc_len;
-       if (copy_from_user(buf, (void *)arg, hdr->ioc_len))
+       if (copy_from_user(buf, arg, hdr->ioc_len))
                return -EFAULT;
        if (orig_len != data->ioc_len)
                return -EINVAL;
@@ -96,8 +96,6 @@ int libcfs_ioctl_popdata(void *arg, void *data, int size)
        return 0;
 }
 
-extern struct cfs_psdev_ops      libcfs_psdev_ops;
-
 static int
 libcfs_psdev_open(struct inode *inode, struct file *file)
 {
index e60b2e9b91944ad1f2d22a7cc4d9d59f872f12f9..806f9747a3a299ead2f07d18da2a38c9aadff88a 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/list.h>
 
 #include <linux/sysctl.h>
+#include <linux/debugfs.h>
 
 # define DEBUG_SUBSYSTEM S_LNET
 
@@ -65,48 +66,12 @@ MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
 MODULE_DESCRIPTION("Portals v3.1");
 MODULE_LICENSE("GPL");
 
-extern struct miscdevice libcfs_dev;
-extern struct cfs_wi_sched *cfs_sched_rehash;
-extern void libcfs_init_nidstrings(void);
+static void insert_debugfs(void);
+static void remove_debugfs(void);
 
-static int insert_proc(void);
-static void remove_proc(void);
+static struct dentry *lnet_debugfs_root;
 
-static struct ctl_table_header *lnet_table_header;
-extern char lnet_upcall[1024];
-/**
- * The path of debug log dump upcall script.
- */
-extern char lnet_debug_log_upcall[1024];
-
-#define CTL_LNET       (0x100)
-
-enum {
-       PSDEV_DEBUG = 1,          /* control debugging */
-       PSDEV_SUBSYSTEM_DEBUG,    /* control debugging */
-       PSDEV_PRINTK,        /* force all messages to console */
-       PSDEV_CONSOLE_RATELIMIT,  /* ratelimit console messages */
-       PSDEV_CONSOLE_MAX_DELAY_CS, /* maximum delay over which we skip messages */
-       PSDEV_CONSOLE_MIN_DELAY_CS, /* initial delay over which we skip messages */
-       PSDEV_CONSOLE_BACKOFF,    /* delay increase factor */
-       PSDEV_DEBUG_PATH,        /* crashdump log location */
-       PSDEV_DEBUG_DUMP_PATH,    /* crashdump tracelog location */
-       PSDEV_CPT_TABLE,          /* information about cpu partitions */
-       PSDEV_LNET_UPCALL,      /* User mode upcall script  */
-       PSDEV_LNET_MEMUSED,       /* bytes currently PORTAL_ALLOCated */
-       PSDEV_LNET_CATASTROPHE,   /* if we have LBUGged or panic'd */
-       PSDEV_LNET_PANIC_ON_LBUG, /* flag to panic on LBUG */
-       PSDEV_LNET_DUMP_KERNEL,   /* snapshot kernel debug buffer to file */
-       PSDEV_LNET_DAEMON_FILE,   /* spool kernel debug buffer to file */
-       PSDEV_LNET_DEBUG_MB,      /* size of debug buffer */
-       PSDEV_LNET_DEBUG_LOG_UPCALL, /* debug log upcall script */
-       PSDEV_LNET_WATCHDOG_RATELIMIT,  /* ratelimit watchdog messages  */
-       PSDEV_LNET_FORCE_LBUG,    /* hook to force an LBUG */
-       PSDEV_LNET_FAIL_LOC,      /* control test failures instrumentation */
-       PSDEV_LNET_FAIL_VAL,      /* userdata for fail loc */
-};
-
-static void kportal_memhog_free (struct libcfs_device_userstate *ldu)
+static void kportal_memhog_free(struct libcfs_device_userstate *ldu)
 {
        struct page **level0p = &ldu->ldu_memhog_root_page;
        struct page **level1p;
@@ -146,7 +111,7 @@ static void kportal_memhog_free (struct libcfs_device_userstate *ldu)
                *level0p = NULL;
        }
 
-       LASSERT (ldu->ldu_memhog_pages == 0);
+       LASSERT(ldu->ldu_memhog_pages == 0);
 }
 
 static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages,
@@ -158,8 +123,8 @@ static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages,
        int        count1;
        int        count2;
 
-       LASSERT (ldu->ldu_memhog_pages == 0);
-       LASSERT (ldu->ldu_memhog_root_page == NULL);
+       LASSERT(ldu->ldu_memhog_pages == 0);
+       LASSERT(ldu->ldu_memhog_root_page == NULL);
 
        if (npages < 0)
                return -EINVAL;
@@ -338,7 +303,7 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd,
                        if (err != -EINVAL) {
                                if (err == 0)
                                        err = libcfs_ioctl_popdata(arg,
-                                                       data, sizeof (*data));
+                                                       data, sizeof(*data));
                                break;
                        }
                }
@@ -361,7 +326,7 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *a
                return -ENOMEM;
 
        /* 'cmd' and permissions get checked in our arch-specific caller */
-       if (libcfs_ioctl_getdata(buf, buf + 800, (void *)arg)) {
+       if (libcfs_ioctl_getdata(buf, buf + 800, arg)) {
                CERROR("PORTALS ioctl: data error\n");
                err = -EINVAL;
                goto out;
@@ -428,17 +393,10 @@ static int init_libcfs_module(void)
                goto cleanup_wi;
        }
 
+       insert_debugfs();
 
-       rc = insert_proc();
-       if (rc) {
-               CERROR("insert_proc: error %d\n", rc);
-               goto cleanup_crypto;
-       }
-
-       CDEBUG (D_OTHER, "portals setup OK\n");
+       CDEBUG(D_OTHER, "portals setup OK\n");
        return 0;
- cleanup_crypto:
-       cfs_crypto_unregister();
  cleanup_wi:
        cfs_wi_shutdown();
  cleanup_deregister:
@@ -454,10 +412,7 @@ static void exit_libcfs_module(void)
 {
        int rc;
 
-       remove_proc();
-
-       CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
-              atomic_read(&libcfs_kmemory));
+       remove_debugfs();
 
        if (cfs_sched_rehash != NULL) {
                cfs_wi_sched_destroy(cfs_sched_rehash);
@@ -467,16 +422,10 @@ static void exit_libcfs_module(void)
        cfs_crypto_unregister();
        cfs_wi_shutdown();
 
-       rc = misc_deregister(&libcfs_dev);
-       if (rc)
-               CERROR("misc_deregister error %d\n", rc);
+       misc_deregister(&libcfs_dev);
 
        cfs_cpu_fini();
 
-       if (atomic_read(&libcfs_kmemory) != 0)
-               CERROR("Portals memory leaked: %d bytes\n",
-                      atomic_read(&libcfs_kmemory));
-
        rc = libcfs_debug_cleanup();
        if (rc)
                pr_err("LustreError: libcfs_debug_cleanup: %d\n", rc);
@@ -551,9 +500,6 @@ static int proc_dobitmasks(struct ctl_table *table, int write,
                                 __proc_dobitmasks);
 }
 
-static int min_watchdog_ratelimit;       /* disable ratelimiting */
-static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
-
 static int __proc_dump_kernel(void *data, int write,
                              loff_t pos, void __user *buffer, int nob)
 {
@@ -593,125 +539,6 @@ static int proc_daemon_file(struct ctl_table *table, int write,
                                 __proc_daemon_file);
 }
 
-static int __proc_debug_mb(void *data, int write,
-                          loff_t pos, void __user *buffer, int nob)
-{
-       if (!write) {
-               char tmpstr[32];
-               int  len = snprintf(tmpstr, sizeof(tmpstr), "%d",
-                                   cfs_trace_get_debug_mb());
-
-               if (pos >= len)
-                       return 0;
-
-               return cfs_trace_copyout_string(buffer, nob, tmpstr + pos,
-                      "\n");
-       }
-
-       return cfs_trace_set_debug_mb_usrstr(buffer, nob);
-}
-
-static int proc_debug_mb(struct ctl_table *table, int write,
-                        void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return proc_call_handler(table->data, write, ppos, buffer, lenp,
-                                __proc_debug_mb);
-}
-
-static int proc_console_max_delay_cs(struct ctl_table *table, int write,
-                                    void __user *buffer, size_t *lenp,
-                                    loff_t *ppos)
-{
-       int rc, max_delay_cs;
-       struct ctl_table dummy = *table;
-       long d;
-
-       dummy.data = &max_delay_cs;
-       dummy.proc_handler = &proc_dointvec;
-
-       if (!write) { /* read */
-               max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100);
-               rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
-               return rc;
-       }
-
-       /* write */
-       max_delay_cs = 0;
-       rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
-       if (rc < 0)
-               return rc;
-       if (max_delay_cs <= 0)
-               return -EINVAL;
-
-       d = cfs_time_seconds(max_delay_cs) / 100;
-       if (d == 0 || d < libcfs_console_min_delay)
-               return -EINVAL;
-       libcfs_console_max_delay = d;
-
-       return rc;
-}
-
-static int proc_console_min_delay_cs(struct ctl_table *table, int write,
-                                    void __user *buffer, size_t *lenp,
-                                    loff_t *ppos)
-{
-       int rc, min_delay_cs;
-       struct ctl_table dummy = *table;
-       long d;
-
-       dummy.data = &min_delay_cs;
-       dummy.proc_handler = &proc_dointvec;
-
-       if (!write) { /* read */
-               min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100);
-               rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
-               return rc;
-       }
-
-       /* write */
-       min_delay_cs = 0;
-       rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
-       if (rc < 0)
-               return rc;
-       if (min_delay_cs <= 0)
-               return -EINVAL;
-
-       d = cfs_time_seconds(min_delay_cs) / 100;
-       if (d == 0 || d > libcfs_console_max_delay)
-               return -EINVAL;
-       libcfs_console_min_delay = d;
-
-       return rc;
-}
-
-static int proc_console_backoff(struct ctl_table *table, int write,
-                               void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       int rc, backoff;
-       struct ctl_table dummy = *table;
-
-       dummy.data = &backoff;
-       dummy.proc_handler = &proc_dointvec;
-
-       if (!write) { /* read */
-               backoff = libcfs_console_backoff;
-               rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
-               return rc;
-       }
-
-       /* write */
-       backoff = 0;
-       rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
-       if (rc < 0)
-               return rc;
-       if (backoff <= 0)
-               return -EINVAL;
-
-       libcfs_console_backoff = backoff;
-
-       return rc;
-}
-
 static int libcfs_force_lbug(struct ctl_table *table, int write,
                             void __user *buffer,
                             size_t *lenp, loff_t *ppos)
@@ -808,40 +635,6 @@ static struct ctl_table lnet_table[] = {
                .mode     = 0644,
                .proc_handler = &proc_dobitmasks,
        },
-       {
-               .procname = "console_ratelimit",
-               .data     = &libcfs_console_ratelimit,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec
-       },
-       {
-               .procname = "console_max_delay_centisecs",
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_console_max_delay_cs
-       },
-       {
-               .procname = "console_min_delay_centisecs",
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_console_min_delay_cs
-       },
-       {
-               .procname = "console_backoff",
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_console_backoff
-       },
-
-       {
-               .procname = "debug_path",
-               .data     = libcfs_debug_file_path_arr,
-               .maxlen   = sizeof(libcfs_debug_file_path_arr),
-               .mode     = 0644,
-               .proc_handler = &proc_dostring,
-       },
-
        {
                .procname = "cpu_partition_table",
                .maxlen   = 128,
@@ -863,13 +656,6 @@ static struct ctl_table lnet_table[] = {
                .mode     = 0644,
                .proc_handler = &proc_dostring,
        },
-       {
-               .procname = "lnet_memused",
-               .data     = (int *)&libcfs_kmemory.counter,
-               .maxlen   = sizeof(int),
-               .mode     = 0444,
-               .proc_handler = &proc_dointvec,
-       },
        {
                .procname = "catastrophe",
                .data     = &libcfs_catastrophe,
@@ -877,13 +663,6 @@ static struct ctl_table lnet_table[] = {
                .mode     = 0444,
                .proc_handler = &proc_dointvec,
        },
-       {
-               .procname = "panic_on_lbug",
-               .data     = &libcfs_panic_on_lbug,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec,
-       },
        {
                .procname = "dump_kernel",
                .maxlen   = 256,
@@ -896,20 +675,6 @@ static struct ctl_table lnet_table[] = {
                .maxlen   = 256,
                .proc_handler = &proc_daemon_file,
        },
-       {
-               .procname = "debug_mb",
-               .mode     = 0644,
-               .proc_handler = &proc_debug_mb,
-       },
-       {
-               .procname = "watchdog_ratelimit",
-               .data     = &libcfs_watchdog_ratelimit,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec_minmax,
-               .extra1   = &min_watchdog_ratelimit,
-               .extra2   = &max_watchdog_ratelimit,
-       },
        {
                .procname = "force_lbug",
                .data     = NULL,
@@ -935,31 +700,93 @@ static struct ctl_table lnet_table[] = {
        }
 };
 
-static struct ctl_table top_table[] = {
-       {
-               .procname = "lnet",
-               .mode     = 0555,
-               .data     = NULL,
-               .maxlen   = 0,
-               .child    = lnet_table,
-       },
-       {
-       }
+struct lnet_debugfs_symlink_def {
+       char *name;
+       char *target;
+};
+
+static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = {
+       { "console_ratelimit",
+         "/sys/module/libcfs/parameters/libcfs_console_ratelimit"},
+       { "debug_path",
+         "/sys/module/libcfs/parameters/libcfs_debug_file_path"},
+       { "panic_on_lbug",
+         "/sys/module/libcfs/parameters/libcfs_panic_on_lbug"},
+       { "libcfs_console_backoff",
+         "/sys/module/libcfs/parameters/libcfs_console_backoff"},
+       { "debug_mb",
+         "/sys/module/libcfs/parameters/libcfs_debug_mb"},
+       { "console_min_delay_centisecs",
+         "/sys/module/libcfs/parameters/libcfs_console_min_delay"},
+       { "console_max_delay_centisecs",
+         "/sys/module/libcfs/parameters/libcfs_console_max_delay"},
+       {},
 };
 
-static int insert_proc(void)
+static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
+                                size_t count, loff_t *ppos)
 {
-       if (lnet_table_header == NULL)
-               lnet_table_header = register_sysctl_table(top_table);
-       return 0;
+       struct ctl_table *table = filp->private_data;
+       int error;
+
+       error = table->proc_handler(table, 0, (void __user *)buf, &count, ppos);
+       if (!error)
+               error = count;
+
+       return error;
+}
+
+static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct ctl_table *table = filp->private_data;
+       int error;
+
+       error = table->proc_handler(table, 1, (void __user *)buf, &count, ppos);
+       if (!error)
+               error = count;
+
+       return error;
+}
+
+static const struct file_operations lnet_debugfs_file_operations = {
+       .open           = simple_open,
+       .read           = lnet_debugfs_read,
+       .write          = lnet_debugfs_write,
+       .llseek         = default_llseek,
+};
+
+static void insert_debugfs(void)
+{
+       struct ctl_table *table;
+       struct dentry *entry;
+       const struct lnet_debugfs_symlink_def *symlinks;
+
+       if (lnet_debugfs_root == NULL)
+               lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
+
+       /* Even if we cannot create, just ignore it altogether) */
+       if (IS_ERR_OR_NULL(lnet_debugfs_root))
+               return;
+
+       for (table = lnet_table; table->procname; table++)
+               entry = debugfs_create_file(table->procname, table->mode,
+                                           lnet_debugfs_root, table,
+                                           &lnet_debugfs_file_operations);
+
+       for (symlinks = lnet_debugfs_symlinks; symlinks->name; symlinks++)
+               entry = debugfs_create_symlink(symlinks->name,
+                                              lnet_debugfs_root,
+                                              symlinks->target);
+
 }
 
-static void remove_proc(void)
+static void remove_debugfs(void)
 {
-       if (lnet_table_header != NULL)
-               unregister_sysctl_table(lnet_table_header);
+       if (lnet_debugfs_root != NULL)
+               debugfs_remove_recursive(lnet_debugfs_root);
 
-       lnet_table_header = NULL;
+       lnet_debugfs_root = NULL;
 }
 
 MODULE_VERSION("1.0.0");
index 6ee2adcf8890a5b444346333f4fdd9f718333362..effa2af58c13a905a60f108cae21a8af8a79eead 100644 (file)
@@ -937,18 +937,6 @@ int cfs_trace_set_debug_mb(int mb)
        return 0;
 }
 
-int cfs_trace_set_debug_mb_usrstr(void __user *usr_str, int usr_str_nob)
-{
-       char     str[32];
-       int      rc;
-
-       rc = cfs_trace_copyin_string(str, sizeof(str), usr_str, usr_str_nob);
-       if (rc < 0)
-               return rc;
-
-       return cfs_trace_set_debug_mb(simple_strtoul(str, NULL, 0));
-}
-
 int cfs_trace_get_debug_mb(void)
 {
        int i;
index 0601476e1dc32a64d4fca214a2ddd35e3e9c2774..e931f6d98de9632383b1afd5fb61052d1253a2ee 100644 (file)
@@ -47,7 +47,7 @@
 extern char      cfs_tracefile[TRACEFILE_NAME_SIZE];
 extern long long cfs_tracefile_size;
 
-extern void libcfs_run_debug_log_upcall(char *file);
+void libcfs_run_debug_log_upcall(char *file);
 
 int  cfs_tracefile_init_arch(void);
 void cfs_tracefile_fini_arch(void);
@@ -77,14 +77,13 @@ int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob);
 int cfs_trace_daemon_command(char *str);
 int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob);
 int cfs_trace_set_debug_mb(int mb);
-int cfs_trace_set_debug_mb_usrstr(void __user *usr_str, int usr_str_nob);
 int cfs_trace_get_debug_mb(void);
 
-extern void libcfs_debug_dumplog_internal(void *arg);
-extern void libcfs_register_panic_notifier(void);
-extern void libcfs_unregister_panic_notifier(void);
+void libcfs_debug_dumplog_internal(void *arg);
+void libcfs_register_panic_notifier(void);
+void libcfs_unregister_panic_notifier(void);
 extern int  libcfs_panic_in_progress;
-extern int  cfs_trace_max_debug_mb(void);
+int cfs_trace_max_debug_mb(void);
 
 #define TCD_MAX_PAGES (5 << (20 - PAGE_CACHE_SHIFT))
 #define TCD_STOCK_PAGES (TCD_MAX_PAGES)
@@ -253,15 +252,15 @@ struct cfs_trace_page {
        unsigned short       type;
 };
 
-extern void cfs_set_ptldebug_header(struct ptldebug_header *header,
-                                   struct libcfs_debug_msg_data *m,
-                                   unsigned long stack);
-extern void cfs_print_to_console(struct ptldebug_header *hdr, int mask,
-                                const char *buf, int len, const char *file,
-                                const char *fn);
+void cfs_set_ptldebug_header(struct ptldebug_header *header,
+                            struct libcfs_debug_msg_data *m,
+                            unsigned long stack);
+void cfs_print_to_console(struct ptldebug_header *hdr, int mask,
+                         const char *buf, int len, const char *file,
+                         const char *fn);
 
-extern int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
-extern void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
+int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
+void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
 
 /**
  * trace_buf_type_t, trace_buf_idx_get() and trace_console_buffers[][]
@@ -271,7 +270,7 @@ extern void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
  */
 
 extern char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX];
-extern cfs_trace_buf_type_t cfs_trace_buf_idx_get(void);
+cfs_trace_buf_type_t cfs_trace_buf_idx_get(void);
 
 static inline char *
 cfs_trace_get_console_buffer(void)
@@ -314,8 +313,8 @@ int cfs_trace_refill_stock(struct cfs_trace_cpu_data *tcd, gfp_t gfp,
 int cfs_tcd_owns_tage(struct cfs_trace_cpu_data *tcd,
                      struct cfs_trace_page *tage);
 
-extern void cfs_trace_assertion_failed(const char *str,
-                                      struct libcfs_debug_msg_data *m);
+void cfs_trace_assertion_failed(const char *str,
+                               struct libcfs_debug_msg_data *m);
 
 /* ASSERTION that is safe to use within the debug system */
 #define __LASSERT(cond)                                                 \
index 7b008a64707d7adb5b5ccc0163be5745bc5fd8f0..b86685912d28c9dc74c0e62743dd441dbd2773e0 100644 (file)
@@ -250,7 +250,6 @@ void ll_intent_release(struct lookup_intent *it)
 void ll_invalidate_aliases(struct inode *inode)
 {
        struct dentry *dentry;
-       struct ll_d_hlist_node *p;
 
        LASSERT(inode != NULL);
 
@@ -258,7 +257,7 @@ void ll_invalidate_aliases(struct inode *inode)
               inode->i_ino, inode->i_generation, inode);
 
        ll_lock_dcache(inode);
-       ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                CDEBUG(D_DENTRY, "dentry in drop %pd (%p) parent %p inode %p flags %d\n",
                       dentry, dentry, dentry->d_parent,
                       d_inode(dentry), dentry->d_flags);
index 3d746a94f92edc66d5d9057836d85e4fa1e0460c..769b61193d87ef29c7868465c50e9b8ab87ee045 100644 (file)
@@ -203,7 +203,6 @@ static int ll_dir_filler(void *_hash, struct page *page0)
 
        CDEBUG(D_VFSTRACE, "read %d/%d pages\n", nrdpgs, npages);
 
-       ll_pagevec_init(&lru_pvec, 0);
        for (i = 1; i < npages; i++) {
                unsigned long offset;
                int ret;
@@ -228,15 +227,12 @@ static int ll_dir_filler(void *_hash, struct page *page0)
                                            GFP_KERNEL);
                if (ret == 0) {
                        unlock_page(page);
-                       if (ll_pagevec_add(&lru_pvec, page) == 0)
-                               ll_pagevec_lru_add_file(&lru_pvec);
                } else {
                        CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: %d\n",
                               offset, ret);
                }
                page_cache_release(page);
        }
-       ll_pagevec_lru_add_file(&lru_pvec);
 
        if (page_pool != &page0)
                kfree(page_pool);
index 3075db211106a12e9b27c77a9fdb848f389349e7..dcd0c6d65efbcb4f475a92458b013c67a6c1d9c1 100644 (file)
@@ -702,8 +702,7 @@ out_och_free:
 out_openerr:
                if (opendir_set != 0)
                        ll_stop_statahead(inode, lli->lli_opendir_key);
-               if (fd != NULL)
-                       ll_file_data_put(fd);
+               ll_file_data_put(fd);
        } else {
                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1);
        }
@@ -3005,7 +3004,7 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
        struct inode *inode = d_inode(de);
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ll_inode_info *lli = ll_i2info(inode);
-       int res = 0;
+       int res;
 
        res = ll_inode_revalidate(de, MDS_INODELOCK_UPDATE |
                                      MDS_INODELOCK_LOOKUP);
index a6268718b76e6f067f66a7abd8adc4435cf94fbd..24590ae36090f1070c537273e7dd963702b27d5c 100644 (file)
@@ -70,7 +70,8 @@ static unsigned long long ll_capa_renewal_retries;
 
 static int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa);
 
-static inline void update_capa_timer(struct obd_capa *ocapa, unsigned long expiry)
+static inline void update_capa_timer(struct obd_capa *ocapa,
+                                    unsigned long expiry)
 {
        if (time_before(expiry, ll_capa_timer.expires) ||
            !timer_pending(&ll_capa_timer)) {
@@ -102,13 +103,13 @@ static inline int have_expired_capa(void)
        spin_lock(&capa_lock);
        if (!list_empty(ll_capa_list)) {
                ocapa = list_entry(ll_capa_list->next, struct obd_capa,
-                                      c_list);
+                                  c_list);
                expired = capa_is_to_expire(ocapa);
                if (!expired)
                        update_capa_timer(ocapa, capa_renewal_time(ocapa));
        } else if (!list_empty(&ll_idle_capas)) {
                ocapa = list_entry(ll_idle_capas.next, struct obd_capa,
-                                      c_list);
+                                  c_list);
                expired = capa_is_expired(ocapa);
                if (!expired)
                        update_capa_timer(ocapa, ocapa->c_expiry);
@@ -165,7 +166,8 @@ static void ll_delete_capa(struct obd_capa *ocapa)
 /* three places where client capa is deleted:
  * 1. capa_thread_main(), main place to delete expired capa.
  * 2. ll_clear_inode_capas() in ll_clear_inode().
- * 3. ll_truncate_free_capa() delete truncate capa explicitly in ll_setattr_ost().
+ * 3. ll_truncate_free_capa() delete truncate capa explicitly in
+ *    ll_setattr_ost().
  */
 static int capa_thread_main(void *unused)
 {
@@ -206,7 +208,8 @@ static int capa_thread_main(void *unused)
                         * lock.
                         */
                        /* ibits may be changed by ll_have_md_lock() so we have
-                        * to set it each time */
+                        * to set it each time
+                        */
                        ibits = MDS_INODELOCK_LOOKUP;
                        if (capa_for_mds(&ocapa->c_capa) &&
                            !S_ISDIR(ocapa->u.cli.inode->i_mode) &&
@@ -225,14 +228,15 @@ static int capa_thread_main(void *unused)
                        if (capa_for_oss(&ocapa->c_capa) &&
                            obd_capa_open_count(ocapa) == 0) {
                                /* oss capa with open count == 0 won't renew,
-                                * move to idle list */
+                                * move to idle list
+                                */
                                sort_add_capa(ocapa, &ll_idle_capas);
                                continue;
                        }
 
                        /* NB iput() is in ll_update_capa() */
                        inode = igrab(ocapa->u.cli.inode);
-                       if (inode == NULL) {
+                       if (!inode) {
                                DEBUG_CAPA(D_ERROR, &ocapa->c_capa,
                                           "igrab failed for");
                                continue;
@@ -255,7 +259,7 @@ static int capa_thread_main(void *unused)
                        update_capa_timer(next, capa_renewal_time(next));
 
                list_for_each_entry_safe(ocapa, tmp, &ll_idle_capas,
-                                            c_list) {
+                                        c_list) {
                        if (!capa_is_expired(ocapa)) {
                                if (!next)
                                        update_capa_timer(ocapa,
@@ -299,11 +303,11 @@ int ll_capa_thread_start(void)
        task = kthread_run(capa_thread_main, NULL, "ll_capa");
        if (IS_ERR(task)) {
                CERROR("cannot start expired capa thread: rc %ld\n",
-                       PTR_ERR(task));
+                      PTR_ERR(task));
                return PTR_ERR(task);
        }
        wait_event(ll_capa_thread.t_ctl_waitq,
-                      thread_is_running(&ll_capa_thread));
+                  thread_is_running(&ll_capa_thread));
 
        return 0;
 }
@@ -313,7 +317,7 @@ void ll_capa_thread_stop(void)
        thread_set_flags(&ll_capa_thread, SVC_STOPPING);
        wake_up(&ll_capa_thread.t_ctl_waitq);
        wait_event(ll_capa_thread.t_ctl_waitq,
-                      thread_is_stopped(&ll_capa_thread));
+                  thread_is_stopped(&ll_capa_thread));
 }
 
 struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc)
@@ -360,7 +364,7 @@ struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc)
                ocapa = NULL;
 
                if (atomic_read(&ll_capa_debug)) {
-                       CERROR("no capability for "DFID" opc %#llx\n",
+                       CERROR("no capability for " DFID " opc %#llx\n",
                               PFID(&lli->lli_fid), opc);
                        atomic_set(&ll_capa_debug, 0);
                }
@@ -376,7 +380,7 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode)
        struct ll_inode_info *lli = ll_i2info(inode);
        struct obd_capa *ocapa;
 
-       LASSERT(inode != NULL);
+       LASSERT(inode);
 
        if ((ll_i2sbi(inode)->ll_flags & LL_SBI_MDS_CAPA) == 0)
                return NULL;
@@ -385,7 +389,7 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode)
        ocapa = capa_get(lli->lli_mds_capa);
        spin_unlock(&capa_lock);
        if (!ocapa && atomic_read(&ll_capa_debug)) {
-               CERROR("no mds capability for "DFID"\n", PFID(&lli->lli_fid));
+               CERROR("no mds capability for " DFID "\n", PFID(&lli->lli_fid));
                atomic_set(&ll_capa_debug, 0);
        }
 
@@ -447,7 +451,8 @@ static inline void inode_add_oss_capa(struct inode *inode,
        struct list_head *next = NULL;
 
        /* capa is sorted in lli_oss_capas so lookup can always find the
-        * latest one */
+        * latest one
+        */
        list_for_each_entry(tmp, &lli->lli_oss_capas, u.cli.lli_list) {
                if (cfs_time_after(ocapa->c_expiry, tmp->c_expiry)) {
                        next = &tmp->u.cli.lli_list;
@@ -537,7 +542,8 @@ static int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa)
                        ll_capa_renewal_failed++;
 
                        /* failed capa won't be renewed any longer, but if -EIO,
-                        * client might be doing recovery, retry in 2 min. */
+                        * client might be doing recovery, retry in 2 min.
+                        */
                        if (rc == -EIO && !capa_is_expired(ocapa)) {
                                delay_capa_renew(ocapa, 120);
                                DEBUG_CAPA(D_ERROR, &ocapa->c_capa,
@@ -638,7 +644,7 @@ void ll_clear_inode_capas(struct inode *inode)
                ll_delete_capa(ocapa);
 
        list_for_each_entry_safe(ocapa, tmp, &lli->lli_oss_capas,
-                                    u.cli.lli_list)
+                                u.cli.lli_list)
                ll_delete_capa(ocapa);
        spin_unlock(&capa_lock);
 }
index f097d4d167d525c2054858fa59345d5f8ad94ed6..ec8fff4632085a9652581b7b6fec3c8573c99365 100644 (file)
@@ -456,7 +456,6 @@ struct eacl_table {
 };
 
 struct ll_sb_info {
-       struct list_head                  ll_list;
        /* this protects pglist and ra_info.  It isn't safe to
         * grab from interrupt contexts */
        spinlock_t                ll_lock;
@@ -711,11 +710,11 @@ extern struct file_operations ll_file_operations;
 extern struct file_operations ll_file_operations_flock;
 extern struct file_operations ll_file_operations_noflock;
 extern struct inode_operations ll_file_inode_operations;
-extern int ll_have_md_lock(struct inode *inode, __u64 *bits,
-                          ldlm_mode_t l_req_mode);
-extern ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
-                                  struct lustre_handle *lockh, __u64 flags,
-                                  ldlm_mode_t mode);
+int ll_have_md_lock(struct inode *inode, __u64 *bits,
+                   ldlm_mode_t l_req_mode);
+ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
+                           struct lustre_handle *lockh, __u64 flags,
+                           ldlm_mode_t mode);
 int ll_file_open(struct inode *inode, struct file *file);
 int ll_file_release(struct inode *inode, struct file *file);
 int ll_glimpse_ioctl(struct ll_sb_info *sbi,
@@ -1376,9 +1375,9 @@ static inline void cl_stats_tally(struct cl_device *dev, enum cl_req_type crt,
        ll_stats_ops_tally(ll_s2sbi(cl2ccc_dev(dev)->cdv_sb), opc, rc);
 }
 
-extern ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
-                                 int rw, struct inode *inode,
-                                 struct ll_dio_pages *pv);
+ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
+                          int rw, struct inode *inode,
+                          struct ll_dio_pages *pv);
 
 static inline int ll_file_nolock(const struct file *file)
 {
index 25139885b5a769eeedab0fd2859986c1c4684d19..b4ed6c89af3d4c4129d89f1c84c01b1da1fed28d 100644 (file)
@@ -60,9 +60,6 @@ struct kmem_cache *ll_file_data_slab;
 struct dentry *llite_root;
 struct kset *llite_kset;
 
-static LIST_HEAD(ll_super_blocks);
-static DEFINE_SPINLOCK(ll_sb_lock);
-
 #ifndef log2
 #define log2(n) ffz(~(n))
 #endif
@@ -112,10 +109,6 @@ static struct ll_sb_info *ll_init_sbi(struct super_block *sb)
        class_uuid_unparse(uuid, &sbi->ll_sb_uuid);
        CDEBUG(D_CONFIG, "generated uuid: %s\n", sbi->ll_sb_uuid.uuid);
 
-       spin_lock(&ll_sb_lock);
-       list_add_tail(&sbi->ll_list, &ll_super_blocks);
-       spin_unlock(&ll_sb_lock);
-
        sbi->ll_flags |= LL_SBI_VERBOSE;
        sbi->ll_flags |= LL_SBI_CHECKSUM;
 
@@ -144,12 +137,7 @@ static void ll_free_sbi(struct super_block *sb)
 {
        struct ll_sb_info *sbi = ll_s2sbi(sb);
 
-       if (sbi != NULL) {
-               spin_lock(&ll_sb_lock);
-               list_del(&sbi->ll_list);
-               spin_unlock(&ll_sb_lock);
-               kfree(sbi);
-       }
+       kfree(sbi);
 }
 
 static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
@@ -1114,7 +1102,7 @@ void ll_clear_inode(struct inode *inode)
        if (lli->lli_mds_read_och)
                ll_md_real_close(inode, FMODE_READ);
 
-       if (S_ISLNK(inode->i_mode) && lli->lli_symlink_name) {
+       if (S_ISLNK(inode->i_mode)) {
                kfree(lli->lli_symlink_name);
                lli->lli_symlink_name = NULL;
        }
@@ -1150,6 +1138,8 @@ void ll_clear_inode(struct inode *inode)
        lli->lli_has_smd = false;
 }
 
+#define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
+
 static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
                  struct md_open_data **mod)
 {
@@ -1354,11 +1344,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
        if (!op_data)
                return -ENOMEM;
 
-       if (!S_ISDIR(inode->i_mode)) {
-               if (attr->ia_valid & ATTR_SIZE)
-                       inode_dio_write_done(inode);
+       if (!S_ISDIR(inode->i_mode))
                mutex_unlock(&inode->i_mutex);
-       }
 
        memcpy(&op_data->op_attr, attr, sizeof(*attr));
 
index cc00fd10fbcf77654479b2aadf6fda7c75cff91a..06f5e51ecd9e1a8141c275232278dd6f081ef68a 100644 (file)
@@ -162,7 +162,7 @@ static int max_loop = MAX_LOOP_DEFAULT;
 static struct lloop_device *loop_dev;
 static struct gendisk **disks;
 static struct mutex lloop_mutex;
-static void *ll_iocontrol_magic = NULL;
+static void *ll_iocontrol_magic;
 
 static loff_t get_loop_size(struct lloop_device *lo, struct file *file)
 {
@@ -365,7 +365,7 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
        loop_add_bio(lo, old_bio);
        return;
 err:
-       cfs_bio_io_error(old_bio, old_bio->bi_iter.bi_size);
+       bio_io_error(old_bio);
 }
 
 
@@ -376,7 +376,7 @@ static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio)
        while (bio) {
                struct bio *tmp = bio->bi_next;
                bio->bi_next = NULL;
-               cfs_bio_endio(bio, bio->bi_iter.bi_size, ret);
+               bio_endio(bio, ret);
                bio = tmp;
        }
 }
index 72ce6e72845fddb1ea575aca3ae867b39184dcc9..05e7dc85989edde49566857d9fec19d6539b3f94 100644 (file)
@@ -144,10 +144,9 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash,
 static void ll_invalidate_negative_children(struct inode *dir)
 {
        struct dentry *dentry, *tmp_subdir;
-       struct ll_d_hlist_node *p;
 
        ll_lock_dcache(dir);
-       ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) {
+       hlist_for_each_entry(dentry, &dir->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (!list_empty(&dentry->d_subdirs)) {
                        struct dentry *child;
@@ -334,15 +333,14 @@ void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2)
 static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry)
 {
        struct dentry *alias, *discon_alias, *invalid_alias;
-       struct ll_d_hlist_node *p;
 
-       if (ll_d_hlist_empty(&inode->i_dentry))
+       if (hlist_empty(&inode->i_dentry))
                return NULL;
 
        discon_alias = invalid_alias = NULL;
 
        ll_lock_dcache(inode);
-       ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                LASSERT(alias != dentry);
 
                spin_lock(&alias->d_lock);
@@ -690,7 +688,7 @@ static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it)
                goto out;
        }
 
-       LASSERT(ll_d_hlist_empty(&inode->i_dentry));
+       LASSERT(hlist_empty(&inode->i_dentry));
 
        /* We asked for a lock on the directory, but were granted a
         * lock on the inode.  Since we finally have an inode pointer,
@@ -1008,7 +1006,7 @@ static int ll_unlink(struct inode *dir, struct dentry *dentry)
        return rc;
 }
 
-static int ll_mkdir(struct inode *dir, struct dentry *dentry, ll_umode_t mode)
+static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        int err;
 
index a58182600daef492df3597d0082699d39e99cca0..39022ea88b5f5744f8b61fca48701225e6ce3e65 100644 (file)
@@ -54,8 +54,8 @@
 #include "../include/lustre_param.h"
 #include "llite_internal.h"
 
-struct kmem_cache *ll_remote_perm_cachep = NULL;
-struct kmem_cache *ll_rmtperm_hash_cachep = NULL;
+struct kmem_cache *ll_remote_perm_cachep;
+struct kmem_cache *ll_rmtperm_hash_cachep;
 
 static inline struct ll_remote_perm *alloc_ll_remote_perm(void)
 {
@@ -104,8 +104,7 @@ void free_rmtperm_hash(struct hlist_head *hash)
                return;
 
        for (i = 0; i < REMOTE_PERM_HASHSIZE; i++)
-               hlist_for_each_entry_safe(lrp, next, hash + i,
-                                             lrp_list)
+               hlist_for_each_entry_safe(lrp, next, hash + i, lrp_list)
                        free_ll_remote_perm(lrp);
        OBD_SLAB_FREE(hash, ll_rmtperm_hash_cachep,
                      REMOTE_PERM_HASHSIZE * sizeof(*hash));
@@ -117,7 +116,8 @@ static inline int remote_perm_hashfunc(uid_t uid)
 }
 
 /* NB: setxid permission is not checked here, instead it's done on
- * MDT when client get remote permission. */
+ * MDT when client get remote permission.
+ */
 static int do_check_remote_perm(struct ll_inode_info *lli, int mask)
 {
        struct hlist_head *head;
@@ -184,7 +184,7 @@ int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm)
 
        if (!lli->lli_remote_perms) {
                perm_hash = alloc_rmtperm_hash();
-               if (perm_hash == NULL) {
+               if (!perm_hash) {
                        CERROR("alloc lli_remote_perms failed!\n");
                        return -ENOMEM;
                }
@@ -287,7 +287,7 @@ int lustre_check_remote_perm(struct inode *inode, int mask)
 
                perm = req_capsule_server_swab_get(&req->rq_pill, &RMF_ACL,
                                                   lustre_swab_mdt_remote_perm);
-               if (unlikely(perm == NULL)) {
+               if (unlikely(!perm)) {
                        mutex_unlock(&lli->lli_rmtperm_mutex);
                        rc = -EPROTO;
                        break;
@@ -321,8 +321,7 @@ void ll_free_remote_perms(struct inode *inode)
        spin_lock(&lli->lli_lock);
 
        for (i = 0; i < REMOTE_PERM_HASHSIZE; i++) {
-               hlist_for_each_entry_safe(lrp, node, next, hash + i,
-                                             lrp_list)
+               hlist_for_each_entry_safe(lrp, node, next, hash + i, lrp_list)
                        free_ll_remote_perm(lrp);
        }
 
index 91bba79678cf7da1f1cd303c114648ea76c8e53d..a659962e09c8a49146b80ac74a4ad13356cfa2cb 100644 (file)
@@ -455,12 +455,11 @@ static void vvp_io_setattr_end(const struct lu_env *env,
        struct cl_io *io    = ios->cis_io;
        struct inode *inode = ccc_object_inode(io->ci_obj);
 
-       if (cl_io_is_trunc(io)) {
+       if (cl_io_is_trunc(io))
                /* Truncate in memory pages - they must be clean pages
                 * because osc has already notified to destroy osc_extents. */
                vvp_do_vmtruncate(inode, io->u.ci_setattr.sa_attr.lvb_size);
-               inode_dio_write_done(inode);
-       }
+
        mutex_unlock(&inode->i_mutex);
 }
 
index 954ed08c6af2f740cb879a85468d872d4e9fd110..a3cf5ad20c6036b215092ee3c91bc5a7d2145770 100644 (file)
@@ -227,11 +227,16 @@ static int vvp_page_prep_write(const struct lu_env *env,
                               struct cl_io *unused)
 {
        struct page *vmpage = cl2vm_page(slice);
+       struct cl_page *pg = slice->cpl_page;
 
        LASSERT(PageLocked(vmpage));
        LASSERT(!PageDirty(vmpage));
 
-       set_page_writeback(vmpage);
+       /* ll_writepage path is not a sync write, so need to set page writeback
+        * flag */
+       if (!pg->cp_sync_io)
+               set_page_writeback(vmpage);
+
        vvp_write_pending(cl2ccc(slice->cpl_obj), cl2ccc_page(slice));
 
        return 0;
@@ -298,9 +303,6 @@ static void vvp_page_completion_write(const struct lu_env *env,
        struct cl_page  *pg     = slice->cpl_page;
        struct page      *vmpage = cp->cpg_page;
 
-       LASSERT(ergo(pg->cp_sync_io != NULL, PageLocked(vmpage)));
-       LASSERT(PageWriteback(vmpage));
-
        CL_PAGE_HEADER(D_PAGE, env, pg, "completing WRITE with %d\n", ioret);
 
        /*
@@ -316,14 +318,19 @@ static void vvp_page_completion_write(const struct lu_env *env,
        cp->cpg_write_queued = 0;
        vvp_write_complete(cl2ccc(slice->cpl_obj), cp);
 
-       /*
-        * Only mark the page error only when it's an async write because
-        * applications won't wait for IO to finish.
-        */
-       if (pg->cp_sync_io == NULL)
+       if (pg->cp_sync_io != NULL) {
+               LASSERT(PageLocked(vmpage));
+               LASSERT(!PageWriteback(vmpage));
+       } else {
+               LASSERT(PageWriteback(vmpage));
+               /*
+                * Only mark the page error only when it's an async write
+                * because applications won't wait for IO to finish.
+                */
                vvp_vmpage_error(ccc_object_inode(pg->cp_obj), vmpage, ioret);
 
-       end_page_writeback(vmpage);
+               end_page_writeback(vmpage);
+       }
 }
 
 /**
index 6956dec53fcc5d4f0bff56833e13743b129475de..9e763ce244e3d14d2799ec6440b3b3f0b4bda16b 100644 (file)
@@ -357,7 +357,7 @@ static int ll_xattr_cache_refill(struct inode *inode, struct lookup_intent *oit)
        struct ll_inode_info *lli = ll_i2info(inode);
        struct mdt_body *body;
        __u32 *xsizes;
-       int rc = 0, i;
+       int rc, i;
 
 
 
index cb35f6341fb2d93050d814e77429dbe56aaf8bf6..eebe45bdceb62c1a01b5299456544a472bccd07f 100644 (file)
@@ -100,7 +100,7 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm,
        }
 
        op_data = kzalloc(sizeof(*op_data), GFP_NOFS);
-       if (op_data == NULL) {
+       if (!op_data) {
                rc = -ENOMEM;
                goto out;
        }
index ac5053cd5da5b7ff61ff382bc1dba756657a2369..c9e0536e9f2a18948b8c9b2aeed7418355cc0604 100644 (file)
@@ -716,7 +716,7 @@ repeat_fid2path:
        if (remote_gf == NULL) {
                remote_gf_size = sizeof(*remote_gf) + PATH_MAX;
                remote_gf = kzalloc(remote_gf_size, GFP_NOFS);
-               if (remote_gf == NULL) {
+               if (!remote_gf) {
                        rc = -ENOMEM;
                        goto out_fid2path;
                }
@@ -1398,7 +1398,7 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp,
                return rc;
 
        temp = kzalloc(sizeof(*temp), GFP_NOFS);
-       if (temp == NULL)
+       if (!temp)
                return -ENOMEM;
 
        for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
@@ -1730,7 +1730,7 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo,
        }
 
        rdata = kzalloc(sizeof(*rdata), GFP_NOFS);
-       if (rdata == NULL) {
+       if (!rdata) {
                rc = -ENOMEM;
                goto out;
        }
@@ -1993,7 +1993,7 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data,
        struct obd_device       *obd = exp->exp_obd;
        struct lmv_obd    *lmv = &obd->u.lmv;
        struct lmv_tgt_desc     *tgt;
-       int                   rc = 0;
+       int                   rc;
 
        rc = lmv_check_connect(obd);
        if (rc)
index 504b24a468fc13bbd614d52aed9040e09eb16033..8c3bbe574723cc54f4a4d1adf104560d4981ea24 100644 (file)
@@ -478,7 +478,7 @@ static struct lu_device *lov_device_alloc(const struct lu_env *env,
        int rc;
 
        ld = kzalloc(sizeof(*ld), GFP_NOFS);
-       if (ld == NULL)
+       if (!ld)
                return ERR_PTR(-ENOMEM);
 
        cl_device_init(&ld->ld_cl, t);
index 11c1081b1d3df9f7935fba82376c357e81bdd5ed..bf3629151d6879b2ba6c99aadb5a6c90aaede52d 100644 (file)
@@ -181,7 +181,7 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
                        } else {
                                sub->sub_io = kzalloc(sizeof(*sub->sub_io),
                                                      GFP_NOFS);
-                               if (sub->sub_io == NULL)
+                               if (!sub->sub_io)
                                        result = -ENOMEM;
                        }
                }
index b7e7bfabe382e8878b1578940f469a970e35aa0a..dd1cf3d2d039d4e36539fe98c61877d6a0400cf2 100644 (file)
@@ -123,6 +123,7 @@ int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm,
        if (shrink) {
                for (; stripe < lsm->lsm_stripe_count; stripe++) {
                        struct lov_oinfo *loi = lsm->lsm_oinfo[stripe];
+
                        kms = lov_size_to_stripe(lsm, size, stripe);
                        CDEBUG(D_INODE,
                               "stripe %d KMS %sing %llu->%llu\n",
index 96c55acd52aed50a898e7006d8936a4595a7587d..c5c67d982ef2387c73cb247aef6a9fa96cf4db31 100644 (file)
@@ -107,6 +107,10 @@ static void lov_putref(struct obd_device *obd)
                        /* Disconnect */
                        __lov_del_obd(obd, tgt);
                }
+
+               if (lov->lov_tgts_kobj)
+                       kobject_put(lov->lov_tgts_kobj);
+
        } else {
                mutex_unlock(&lov->lov_lock);
        }
@@ -322,9 +326,6 @@ static int lov_disconnect(struct obd_export *exp)
                }
        }
 
-       if (lov->lov_tgts_kobj)
-               kobject_put(lov->lov_tgts_kobj);
-
        obd_putref(obd);
 
 out:
@@ -976,7 +977,7 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa,
                src_oa->o_flags & OBD_FL_RECREATE_OBJS);
 
        obj_mdp = kzalloc(sizeof(*obj_mdp), GFP_NOFS);
-       if (obj_mdp == NULL)
+       if (!obj_mdp)
                return -ENOMEM;
 
        ost_idx = src_oa->o_nlink;
@@ -1439,7 +1440,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                __u32 *genp;
 
                len = 0;
-               if (obd_ioctl_getdata(&buf, &len, (void *)uarg))
+               if (obd_ioctl_getdata(&buf, &len, uarg))
                        return -EINVAL;
 
                data = (struct obd_ioctl_data *)buf;
@@ -1472,7 +1473,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                        *genp = lov->lov_tgts[i]->ltd_gen;
                }
 
-               if (copy_to_user((void *)uarg, buf, len))
+               if (copy_to_user(uarg, buf, len))
                        rc = -EFAULT;
                obd_ioctl_freedata(buf, len);
                break;
index 1e4d3fbee323b6f4bed59947eae8506c9889e3be..c59b1402616e23e7c6e8521c1d1414149608924c 100644 (file)
@@ -431,7 +431,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname)
                return -ENAMETOOLONG;
 
        new_pool = kzalloc(sizeof(*new_pool), GFP_NOFS);
-       if (new_pool == NULL)
+       if (!new_pool)
                return -ENOMEM;
 
        strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME);
index f4de8b84c5c25188503c2672b3818a474ad0db9c..416e42ed779252314820661f908bfa244a351259 100644 (file)
@@ -275,7 +275,7 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
        int rc = 0, i;
 
        set = kzalloc(sizeof(*set), GFP_NOFS);
-       if (set == NULL)
+       if (!set)
                return -ENOMEM;
        lov_init_set(set);
 
@@ -301,7 +301,7 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo,
                }
 
                req = kzalloc(sizeof(*req), GFP_NOFS);
-               if (req == NULL) {
+               if (!req) {
                        rc = -ENOMEM;
                        goto out_set;
                }
@@ -358,7 +358,7 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
        int rc = 0, i;
 
        set = kzalloc(sizeof(*set), GFP_NOFS);
-       if (set == NULL)
+       if (!set)
                return -ENOMEM;
        lov_init_set(set);
 
@@ -384,7 +384,7 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo,
                }
 
                req = kzalloc(sizeof(*req), GFP_NOFS);
-               if (req == NULL) {
+               if (!req) {
                        rc = -ENOMEM;
                        goto out_set;
                }
@@ -477,7 +477,7 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
        int rc = 0, i;
 
        set = kzalloc(sizeof(*set), GFP_NOFS);
-       if (set == NULL)
+       if (!set)
                return -ENOMEM;
        lov_init_set(set);
 
@@ -500,7 +500,7 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo,
                }
 
                req = kzalloc(sizeof(*req), GFP_NOFS);
-               if (req == NULL) {
+               if (!req) {
                        rc = -ENOMEM;
                        goto out_set;
                }
@@ -704,7 +704,7 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
        int rc = 0, i;
 
        set = kzalloc(sizeof(*set), GFP_NOFS);
-       if (set == NULL)
+       if (!set)
                return -ENOMEM;
        lov_init_set(set);
 
@@ -730,14 +730,14 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo,
                }
 
                req = kzalloc(sizeof(*req), GFP_NOFS);
-               if (req == NULL) {
+               if (!req) {
                        rc = -ENOMEM;
                        goto out_set;
                }
 
                req->rq_oi.oi_osfs = kzalloc(sizeof(*req->rq_oi.oi_osfs),
                                             GFP_NOFS);
-               if (req->rq_oi.oi_osfs == NULL) {
+               if (!req->rq_oi.oi_osfs) {
                        kfree(req);
                        rc = -ENOMEM;
                        goto out_set;
index d3234cb1ea22ae8190ec64fcfe246658c6f82f49..1a850ea2684945411a66fc46e38a272b3ccb2105 100644 (file)
@@ -286,7 +286,7 @@ static inline __u64 attr_pack(unsigned int ia_valid)
                sa_valid |= MDS_ATTR_KILL_SGID;
        if (ia_valid & ATTR_CTIME_SET)
                sa_valid |= MDS_ATTR_CTIME_SET;
-       if (ia_valid & ATTR_FROM_OPEN)
+       if (ia_valid & ATTR_OPEN)
                sa_valid |= MDS_ATTR_FROM_OPEN;
        if (ia_valid & ATTR_BLOCKS)
                sa_valid |= MDS_ATTR_BLOCKS;
index 7f208a6621e6c8bdce60889763e17256b297d3b0..204d512625607fa7e3fa483a0cd3f185f5bc45b2 100644 (file)
@@ -1202,7 +1202,7 @@ static int mdc_ioc_fid2path(struct obd_export *exp, struct getinfo_fid2path *gf)
        /* Key is KEY_FID2PATH + getinfo_fid2path description */
        keylen = cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*gf);
        key = kzalloc(keylen, GFP_NOFS);
-       if (key == NULL)
+       if (!key)
                return -ENOMEM;
        memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
        memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
@@ -1605,7 +1605,7 @@ static int mdc_changelog_send_thread(void *csdata)
               cs->cs_fp, cs->cs_startrec);
 
        cs->cs_buf = kzalloc(KUC_CHANGELOG_MSG_MAXSIZE, GFP_NOFS);
-       if (cs->cs_buf == NULL) {
+       if (!cs->cs_buf) {
                rc = -ENOMEM;
                goto out;
        }
@@ -1934,7 +1934,7 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                struct obd_quotactl *oqctl;
 
                oqctl = kzalloc(sizeof(*oqctl), GFP_NOFS);
-               if (oqctl == NULL) {
+               if (!oqctl) {
                        rc = -ENOMEM;
                        goto out;
                }
index 174dfc32876b5860b5131b31a1b36f330e0ddbba..019ee2f256aa1b94b90f7c0f23af9aeebbe2a585 100644 (file)
@@ -1128,7 +1128,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc,
        LASSERT(cfg->cfg_sb == cfg->cfg_instance);
 
        inst = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
-       if (inst == NULL)
+       if (!inst)
                return -ENOMEM;
 
        if (!IS_SERVER(lsi)) {
@@ -1232,7 +1232,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc,
                pos += sprintf(obdname + pos, "-%s%04x",
                                  is_ost ? "OST" : "MDT", entry->mne_index);
 
-               cname = is_ost ? "osc" : "mdc",
+               cname = is_ost ? "osc" : "mdc";
                pos += sprintf(obdname + pos, "-%s-%s", cname, inst);
                lustre_cfg_bufs_reset(&bufs, obdname);
 
@@ -1493,7 +1493,7 @@ static int mgc_process_cfg_log(struct obd_device *mgc,
                lsi = s2lsi(cld->cld_cfg.cfg_sb);
 
        env = kzalloc(sizeof(*env), GFP_NOFS);
-       if (env == NULL)
+       if (!env)
                return -ENOMEM;
 
        rc = lu_env_init(env, LCT_MG_THREAD);
index bc3fc4780cb9e53f7faf61ac5f75d395943de8b8..933456c502d1ce2bfd9797ff7fad3dfea1946db0 100644 (file)
@@ -104,11 +104,10 @@ static int lustre_posix_acl_xattr_reduce_space(posix_acl_xattr_header **header,
        if (unlikely(old_count <= new_count))
                return old_size;
 
-       new = kzalloc(new_size, GFP_NOFS);
+       new = kmemdup(*header, new_size, GFP_NOFS);
        if (unlikely(new == NULL))
                return -ENOMEM;
 
-       memcpy(new, *header, new_size);
        kfree(*header);
        *header = new;
        return new_size;
@@ -125,11 +124,10 @@ static int lustre_ext_acl_xattr_reduce_space(ext_acl_xattr_header **header,
        if (unlikely(old_count <= ext_count))
                return 0;
 
-       new = kzalloc(ext_size, GFP_NOFS);
+       new = kmemdup(*header, ext_size, GFP_NOFS);
        if (unlikely(new == NULL))
                return -ENOMEM;
 
-       memcpy(new, *header, ext_size);
        kfree(*header);
        *header = new;
        return 0;
index a7f3032f34dd83bb92184976b1c26e1f6da1d182..d5fb81f84cd4effa1d625206ec39255c636dde04 100644 (file)
 static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg,
                            int radix);
 
-# define PASSERT(env, page, expr)                                     \
-  do {                                                             \
-         if (unlikely(!(expr))) {                                    \
-                 CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n");    \
-                 LASSERT(0);                                      \
-         }                                                          \
-  } while (0)
+# define PASSERT(env, page, expr)                                         \
+       do {                                                               \
+               if (unlikely(!(expr))) {                                   \
+                       CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n"); \
+                       LASSERT(0);                                        \
+               }                                                          \
+       } while (0)
 
 # define PINVRNT(env, page, exp) \
        ((void)sizeof(env), (void)sizeof(page), (void)sizeof !!(exp))
@@ -169,6 +169,7 @@ int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj,
        while ((nr = radix_tree_gang_lookup(&hdr->coh_tree, (void **)pvec,
                                            idx, CLT_PVEC_SIZE)) > 0) {
                int end_of_region = 0;
+
                idx = pvec[nr - 1]->cp_index + 1;
                for (i = 0, j = 0; i < nr; ++i) {
                        page = pvec[i];
@@ -286,6 +287,7 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env,
                        GFP_NOFS);
        if (page != NULL) {
                int result = 0;
+
                atomic_set(&page->cp_ref, 1);
                if (type == CPT_CACHEABLE) /* for radix tree */
                        atomic_inc(&page->cp_ref);
@@ -352,8 +354,10 @@ static struct cl_page *cl_page_find0(const struct lu_env *env,
               idx, PFID(&hdr->coh_lu.loh_fid), vmpage, vmpage->private, type);
        /* fast path. */
        if (type == CPT_CACHEABLE) {
-               /* vmpage lock is used to protect the child/parent
-                * relationship */
+               /*
+                * vmpage lock is used to protect the child/parent
+                * relationship
+                */
                KLASSERT(PageLocked(vmpage));
                /*
                 * cl_vmpage_page() can be called here without any locks as
@@ -372,9 +376,8 @@ static struct cl_page *cl_page_find0(const struct lu_env *env,
                                                       idx) == page));
        }
 
-       if (page != NULL) {
+       if (page != NULL)
                return page;
-       }
 
        /* allocate and initialize cl_page */
        page = cl_page_alloc(env, o, idx, vmpage, type);
@@ -1189,9 +1192,6 @@ int cl_page_prep(const struct lu_env *env, struct cl_io *io,
        if (result == 0)
                cl_page_io_start(env, pg, crt);
 
-       KLASSERT(ergo(crt == CRT_WRITE && pg->cp_type == CPT_CACHEABLE,
-                     equi(result == 0,
-                          PageWriteback(cl_page_vmpage(env, pg)))));
        CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result);
        return result;
 }
@@ -1425,7 +1425,7 @@ void cl_page_clip(const struct lu_env *env, struct cl_page *pg,
        CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", from, to);
        CL_PAGE_INVOID(env, pg, CL_PAGE_OP(cpo_clip),
                       (const struct lu_env *,
-                       const struct cl_page_slice *,int, int),
+                       const struct cl_page_slice *, int, int),
                       from, to);
 }
 EXPORT_SYMBOL(cl_page_clip);
index 1bc37566b3a50a3dbe106b26a7eb1793346aa9f1..2c705d76211f88b84a52e71bc790009c5139f84e 100644 (file)
@@ -78,12 +78,8 @@ atomic_t obd_dirty_pages;
 EXPORT_SYMBOL(obd_dirty_pages);
 unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT;   /* seconds */
 EXPORT_SYMBOL(obd_timeout);
-unsigned int ldlm_timeout = LDLM_TIMEOUT_DEFAULT; /* seconds */
-EXPORT_SYMBOL(ldlm_timeout);
 unsigned int obd_timeout_set;
 EXPORT_SYMBOL(obd_timeout_set);
-unsigned int ldlm_timeout_set;
-EXPORT_SYMBOL(ldlm_timeout_set);
 /* Adaptive timeout defs here instead of ptlrpc module for /proc/sys/ access */
 unsigned int at_min = 0;
 EXPORT_SYMBOL(at_min);
@@ -144,11 +140,11 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type,
                CERROR("%s%salloc of %s (%llu bytes) failed at %s:%d\n",
                       ptr ? "force " :"", type, name, (__u64)size, file,
                       line);
-               CERROR("%llu total bytes and %llu total pages (%llu bytes) allocated by Lustre, %d total bytes by LNET\n",
+               CERROR("%llu total bytes and %llu total pages"
+                       " (%llu bytes) allocated by Lustre\n",
                       obd_memory_sum(),
                       obd_pages_sum() << PAGE_CACHE_SHIFT,
-                      obd_pages_sum(),
-                      atomic_read(&libcfs_kmemory));
+                      obd_pages_sum());
                return 1;
        }
        return 0;
@@ -232,7 +228,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg)
                        goto out;
                }
                lcfg = kzalloc(data->ioc_plen1, GFP_NOFS);
-               if (lcfg == NULL) {
+               if (!lcfg) {
                        err = -ENOMEM;
                        goto out;
                }
@@ -571,12 +567,14 @@ static int __init init_obdclass(void)
        if (err)
                return err;
 
-       obd_sysctl_init();
-
        err = class_procfs_init();
        if (err)
                return err;
 
+       err = obd_sysctl_init();
+       if (err)
+               return err;
+
        err = lu_global_init();
        if (err)
                return err;
@@ -661,7 +659,6 @@ static void cleanup_obdclass(void)
        lu_global_fini();
 
        obd_cleanup_caches();
-       obd_sysctl_clean();
 
        class_procfs_clean();
 
index 978c3c5c460a15b25d06bcabe96e19f4077ab344..0ca730948f7adbea81ecccba24f18db198e20835 100644 (file)
@@ -45,7 +45,7 @@
 
 spinlock_t obd_types_lock;
 
-struct kmem_cache *obd_device_cachep;
+static struct kmem_cache *obd_device_cachep;
 struct kmem_cache *obdo_cachep;
 EXPORT_SYMBOL(obdo_cachep);
 static struct kmem_cache *import_cachep;
@@ -71,9 +71,8 @@ static struct obd_device *obd_device_alloc(void)
        struct obd_device *obd;
 
        OBD_SLAB_ALLOC_PTR_GFP(obd, obd_device_cachep, GFP_NOFS);
-       if (obd != NULL) {
+       if (obd != NULL)
                obd->obd_magic = OBD_DEVICE_MAGIC;
-       }
        return obd;
 }
 
@@ -172,7 +171,7 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
 
        rc = -ENOMEM;
        type = kzalloc(sizeof(*type), GFP_NOFS);
-       if (type == NULL)
+       if (!type)
                return rc;
 
        type->typ_dt_ops = kzalloc(sizeof(*type->typ_dt_ops), GFP_NOFS);
@@ -294,7 +293,7 @@ struct obd_device *class_newdev(const char *type_name, const char *name)
        }
 
        type = class_get_type(type_name);
-       if (type == NULL){
+       if (type == NULL) {
                CERROR("OBD: unknown type: %s\n", type_name);
                return ERR_PTR(-ENODEV);
        }
@@ -999,7 +998,8 @@ void class_import_put(struct obd_import *imp)
 }
 EXPORT_SYMBOL(class_import_put);
 
-static void init_imp_at(struct imp_at *at) {
+static void init_imp_at(struct imp_at *at)
+{
        int i;
        at_init(&at->iat_net_latency, 0, 0);
        for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
@@ -1016,7 +1016,7 @@ struct obd_import *class_new_import(struct obd_device *obd)
        struct obd_import *imp;
 
        imp = kzalloc(sizeof(*imp), GFP_NOFS);
-       if (imp == NULL)
+       if (!imp)
                return NULL;
 
        INIT_LIST_HEAD(&imp->imp_pinger_chain);
@@ -1642,7 +1642,8 @@ static int obd_zombie_impexp_check(void *arg)
 /**
  * Add export to the obd_zombie thread and notify it.
  */
-static void obd_zombie_export_add(struct obd_export *exp) {
+static void obd_zombie_export_add(struct obd_export *exp)
+{
        spin_lock(&exp->exp_obd->obd_dev_lock);
        LASSERT(!list_empty(&exp->exp_obd_chain));
        list_del_init(&exp->exp_obd_chain);
@@ -1658,7 +1659,8 @@ static void obd_zombie_export_add(struct obd_export *exp) {
 /**
  * Add import to the obd_zombie thread and notify it.
  */
-static void obd_zombie_import_add(struct obd_import *imp) {
+static void obd_zombie_import_add(struct obd_import *imp)
+{
        LASSERT(imp->imp_sec == NULL);
        LASSERT(imp->imp_rq_pool == NULL);
        spin_lock(&obd_zombie_impexp_lock);
@@ -1819,7 +1821,7 @@ void *kuc_alloc(int payload_len, int transport, int type)
        int len = kuc_len(payload_len);
 
        lh = kzalloc(len, GFP_NOFS);
-       if (lh == NULL)
+       if (!lh)
                return ERR_PTR(-ENOMEM);
 
        lh->kuc_magic = KUC_MAGIC;
index 84f75dce0d4cc7b26692afa35dd460b188c94725..6218ef34ee801521a21cac7005f47bba50b07511 100644 (file)
@@ -385,7 +385,7 @@ static int obd_device_list_seq_show(struct seq_file *p, void *v)
        return 0;
 }
 
-struct seq_operations obd_device_list_sops = {
+static const struct seq_operations obd_device_list_sops = {
        .start = obd_device_list_seq_start,
        .stop = obd_device_list_seq_stop,
        .next = obd_device_list_seq_next,
@@ -406,7 +406,7 @@ static int obd_device_list_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-struct file_operations obd_device_list_fops = {
+static const struct file_operations obd_device_list_fops = {
        .owner   = THIS_MODULE,
        .open    = obd_device_list_open,
        .read    = seq_read,
@@ -423,7 +423,7 @@ static struct attribute_group lustre_attr_group = {
 
 int class_procfs_init(void)
 {
-       int rc = 0;
+       int rc = -ENOMEM;
        struct dentry *file;
 
        lustre_kobj = kobject_create_and_add("lustre", fs_kobj);
index 54f0a81f7b518dfa7b2d20a5dab8d70002578bbc..1515163a81a5385f5e183c12f3bd4e573d042605 100644 (file)
 #include "../../include/obd_support.h"
 #include "../../include/lprocfs_status.h"
 
-#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *obd_table_header;
-#endif
+struct static_lustre_uintvalue_attr {
+       struct {
+               struct attribute attr;
+               ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
+                               char *buf);
+               ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
+                                const char *buf, size_t len);
+       } u;
+       int *value;
+};
 
-#ifdef CONFIG_SYSCTL
-static int proc_set_timeout(struct ctl_table *table, int write,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
+static ssize_t static_uintvalue_show(struct kobject *kobj,
+                                   struct attribute *attr,
+                                   char *buf)
 {
-       int rc;
+       struct static_lustre_uintvalue_attr *lattr = (void *)attr;
 
-       rc = proc_dointvec(table, write, buffer, lenp, ppos);
-       if (ldlm_timeout >= obd_timeout)
-               ldlm_timeout = max(obd_timeout / 3, 1U);
-       return rc;
+       return sprintf(buf, "%d\n", *lattr->value);
 }
 
-static int proc_memory_alloc(struct ctl_table *table, int write,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
+static ssize_t static_uintvalue_store(struct kobject *kobj,
+                                    struct attribute *attr,
+                                    const char *buffer, size_t count)
 {
-       char buf[22];
-       int len;
-
-       if (!*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-       if (write)
-               return -EINVAL;
+       struct static_lustre_uintvalue_attr *lattr  = (void *)attr;
+       int rc;
+       unsigned int val;
 
-       len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_sum());
-       if (len > *lenp)
-               len = *lenp;
-       buf[len] = '\0';
-       if (copy_to_user(buffer, buf, len))
-               return -EFAULT;
-       *lenp = len;
-       *ppos += *lenp;
-       return 0;
-}
+       rc = kstrtouint(buffer, 10, &val);
+       if (rc)
+               return rc;
 
-static int proc_pages_alloc(struct ctl_table *table, int write,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       char buf[22];
-       int len;
+       *lattr->value = val;
 
-       if (!*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-       if (write)
-               return -EINVAL;
-
-       len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_sum());
-       if (len > *lenp)
-               len = *lenp;
-       buf[len] = '\0';
-       if (copy_to_user(buffer, buf, len))
-               return -EFAULT;
-       *lenp = len;
-       *ppos += *lenp;
-       return 0;
+       return count;
 }
 
-static int proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
-                size_t *lenp, loff_t *ppos)
-{
-       char buf[22];
-       int len;
+#define LUSTRE_STATIC_UINT_ATTR(name, value) \
+static struct static_lustre_uintvalue_attr lustre_sattr_##name =       \
+                                       {__ATTR(name, 0644,             \
+                                               static_uintvalue_show,  \
+                                               static_uintvalue_store),\
+                                         value }
 
-       if (!*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-       if (write)
-               return -EINVAL;
+LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout);
 
-       len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_max());
-       if (len > *lenp)
-               len = *lenp;
-       buf[len] = '\0';
-       if (copy_to_user(buffer, buf, len))
-               return -EFAULT;
-       *lenp = len;
-       *ppos += *lenp;
-       return 0;
+static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr,
+                                char *buf)
+{
+       return sprintf(buf, "%ul\n",
+                       obd_max_dirty_pages / (1 << (20 - PAGE_CACHE_SHIFT)));
 }
 
-static int proc_pages_max(struct ctl_table *table, int write,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
+static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr,
+                                 const char *buffer, size_t count)
 {
-       char buf[22];
-       int len;
+       int rc;
+       unsigned long val;
 
-       if (!*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-       if (write)
-               return -EINVAL;
+       rc = kstrtoul(buffer, 10, &val);
+       if (rc)
+               return rc;
 
-       len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_max());
-       if (len > *lenp)
-               len = *lenp;
-       buf[len] = '\0';
-       if (copy_to_user(buffer, buf, len))
-               return -EFAULT;
-       *lenp = len;
-       *ppos += *lenp;
-       return 0;
-}
+       val *= 1 << (20 - PAGE_CACHE_SHIFT); /* convert to pages */
 
-static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
-                              void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       int rc = 0;
-
-       if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
+       if (val > ((totalram_pages / 10) * 9)) {
+               /* Somebody wants to assign too much memory to dirty pages */
+               return -EINVAL;
        }
-       if (write) {
-               rc = lprocfs_write_frac_helper(buffer, *lenp,
-                                              (unsigned int *)table->data,
-                                              1 << (20 - PAGE_CACHE_SHIFT));
-               /* Don't allow them to let dirty pages exceed 90% of system
-                * memory and set a hard minimum of 4MB. */
-               if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
-                       CERROR("Refusing to set max dirty pages to %u, which is more than 90%% of available RAM; setting to %lu\n",
-                              obd_max_dirty_pages,
-                              ((totalram_pages / 10) * 9));
-                       obd_max_dirty_pages = (totalram_pages / 10) * 9;
-               } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
-                       obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
-               }
-       } else {
-               char buf[21];
-               int len;
 
-               len = lprocfs_read_frac_helper(buf, sizeof(buf),
-                                              *(unsigned int *)table->data,
-                                              1 << (20 - PAGE_CACHE_SHIFT));
-               if (len > *lenp)
-                       len = *lenp;
-               buf[len] = '\0';
-               if (copy_to_user(buffer, buf, len))
-                       return -EFAULT;
-               *lenp = len;
+       if (val < 4 << (20 - PAGE_CACHE_SHIFT)) {
+               /* Less than 4 Mb for dirty cache is also bad */
+               return -EINVAL;
        }
-       *ppos += *lenp;
-       return rc;
-}
 
-static int proc_alloc_fail_rate(struct ctl_table *table, int write,
-                        void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       int rc    = 0;
+       obd_max_dirty_pages = val;
 
-       if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-       if (write) {
-               rc = lprocfs_write_frac_helper(buffer, *lenp,
-                                              (unsigned int *)table->data,
-                                              OBD_ALLOC_FAIL_MULT);
-       } else {
-               char buf[21];
-               int  len;
-
-               len = lprocfs_read_frac_helper(buf, 21,
-                                              *(unsigned int *)table->data,
-                                              OBD_ALLOC_FAIL_MULT);
-               if (len > *lenp)
-                       len = *lenp;
-               buf[len] = '\0';
-               if (copy_to_user(buffer, buf, len))
-                       return -EFAULT;
-               *lenp = len;
-       }
-       *ppos += *lenp;
-       return rc;
+       return count;
 }
-
-static struct ctl_table obd_table[] = {
-       {
-               .procname = "timeout",
-               .data     = &obd_timeout,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_set_timeout
-       },
-       {
-               .procname = "debug_peer_on_timeout",
-               .data     = &obd_debug_peer_on_timeout,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec
-       },
-       {
-               .procname = "dump_on_timeout",
-               .data     = &obd_dump_on_timeout,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec
-       },
-       {
-               .procname = "dump_on_eviction",
-               .data     = &obd_dump_on_eviction,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec
-       },
-       {
-               .procname = "memused",
-               .data     = NULL,
-               .maxlen   = 0,
-               .mode     = 0444,
-               .proc_handler = &proc_memory_alloc
-       },
-       {
-               .procname = "pagesused",
-               .data     = NULL,
-               .maxlen   = 0,
-               .mode     = 0444,
-               .proc_handler = &proc_pages_alloc
-       },
-       {
-               .procname = "memused_max",
-               .data     = NULL,
-               .maxlen   = 0,
-               .mode     = 0444,
-               .proc_handler = &proc_mem_max
-       },
-       {
-               .procname = "pagesused_max",
-               .data     = NULL,
-               .maxlen   = 0,
-               .mode     = 0444,
-               .proc_handler = &proc_pages_max
-       },
-       {
-               .procname = "ldlm_timeout",
-               .data     = &ldlm_timeout,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_set_timeout
-       },
-       {
-               .procname = "alloc_fail_rate",
-               .data     = &obd_alloc_fail_rate,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_alloc_fail_rate
-       },
-       {
-               .procname = "max_dirty_mb",
-               .data     = &obd_max_dirty_pages,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_max_dirty_pages_in_mb
-       },
-       {
-               .procname = "at_min",
-               .data     = &at_min,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec,
-       },
-       {
-               .procname = "at_max",
-               .data     = &at_max,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec,
-       },
-       {
-               .procname = "at_extra",
-               .data     = &at_extra,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec,
-       },
-       {
-               .procname = "at_early_margin",
-               .data     = &at_early_margin,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec,
-       },
-       {
-               .procname = "at_history",
-               .data     = &at_history,
-               .maxlen   = sizeof(int),
-               .mode     = 0644,
-               .proc_handler = &proc_dointvec,
-       },
-       {}
+LUSTRE_RW_ATTR(max_dirty_mb);
+
+LUSTRE_STATIC_UINT_ATTR(debug_peer_on_timeout, &obd_debug_peer_on_timeout);
+LUSTRE_STATIC_UINT_ATTR(dump_on_timeout, &obd_dump_on_timeout);
+LUSTRE_STATIC_UINT_ATTR(dump_on_eviction, &obd_dump_on_eviction);
+LUSTRE_STATIC_UINT_ATTR(at_min, &at_min);
+LUSTRE_STATIC_UINT_ATTR(at_max, &at_max);
+LUSTRE_STATIC_UINT_ATTR(at_extra, &at_extra);
+LUSTRE_STATIC_UINT_ATTR(at_early_margin, &at_early_margin);
+LUSTRE_STATIC_UINT_ATTR(at_history, &at_history);
+
+static struct attribute *lustre_attrs[] = {
+       &lustre_sattr_timeout.u.attr,
+       &lustre_attr_max_dirty_mb.attr,
+       &lustre_sattr_debug_peer_on_timeout.u.attr,
+       &lustre_sattr_dump_on_timeout.u.attr,
+       &lustre_sattr_dump_on_eviction.u.attr,
+       &lustre_sattr_at_min.u.attr,
+       &lustre_sattr_at_max.u.attr,
+       &lustre_sattr_at_extra.u.attr,
+       &lustre_sattr_at_early_margin.u.attr,
+       &lustre_sattr_at_history.u.attr,
+       NULL,
 };
 
-static struct ctl_table parent_table[] = {
-       {
-               .procname = "lustre",
-               .data     = NULL,
-               .maxlen   = 0,
-               .mode     = 0555,
-               .child    = obd_table
-       },
-       {}
+static struct attribute_group lustre_attr_group = {
+       .attrs = lustre_attrs,
 };
-#endif
 
-void obd_sysctl_init(void)
+int obd_sysctl_init(void)
 {
-#ifdef CONFIG_SYSCTL
-       if (!obd_table_header)
-               obd_table_header = register_sysctl_table(parent_table);
-#endif
+       return sysfs_create_group(lustre_kobj, &lustre_attr_group);
 }
 
 void obd_sysctl_clean(void)
 {
-#ifdef CONFIG_SYSCTL
-       if (obd_table_header)
-               unregister_sysctl_table(obd_table_header);
-       obd_table_header = NULL;
-#endif
 }
index 4fa52d1b79d1221b569fa8a0c6520bbcce084747..facc8351fcea50163c83b2c12b29ad31500f3800 100644 (file)
@@ -61,7 +61,7 @@ static struct llog_handle *llog_alloc_handle(void)
        struct llog_handle *loghandle;
 
        loghandle = kzalloc(sizeof(*loghandle), GFP_NOFS);
-       if (loghandle == NULL)
+       if (!loghandle)
                return NULL;
 
        init_rwsem(&loghandle->lgh_lock);
@@ -208,7 +208,7 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle,
        LASSERT(handle->lgh_hdr == NULL);
 
        llh = kzalloc(sizeof(*llh), GFP_NOFS);
-       if (llh == NULL)
+       if (!llh)
                return -ENOMEM;
        handle->lgh_hdr = llh;
        /* first assign flags to use llog_client_ops */
@@ -435,7 +435,7 @@ int llog_process_or_fork(const struct lu_env *env,
        int                   rc;
 
        lpi = kzalloc(sizeof(*lpi), GFP_NOFS);
-       if (lpi == NULL) {
+       if (!lpi) {
                CERROR("cannot alloc pointer\n");
                return -ENOMEM;
        }
@@ -907,7 +907,7 @@ int llog_is_empty(const struct lu_env *env, struct llog_ctxt *ctxt,
                  char *name)
 {
        struct llog_handle      *llh;
-       int                      rc = 0;
+       int                      rc;
 
        rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
        if (rc < 0) {
index 17e7c18078639d946f2a3ad7eb45d862358f5d81..08d1f0edf98d1008c26eca3a02ee02d407715ee3 100644 (file)
@@ -275,7 +275,7 @@ struct dentry *ldebugfs_add_symlink(const char *name, struct dentry *parent,
                return NULL;
 
        dest = kzalloc(MAX_STRING_SIZE + 1, GFP_KERNEL);
-       if (dest == NULL)
+       if (!dest)
                return NULL;
 
        va_start(ap, format);
@@ -329,7 +329,7 @@ EXPORT_SYMBOL(ldebugfs_add_vars);
 
 void ldebugfs_remove(struct dentry **entryp)
 {
-       debugfs_remove(*entryp);
+       debugfs_remove_recursive(*entryp);
        *entryp = NULL;
 }
 EXPORT_SYMBOL(ldebugfs_remove);
index 4d9b6333eeae856af9115a56b6b21357b1cc7e19..8e472327c880e3201992b3995456785227bcf4f6 100644 (file)
@@ -602,7 +602,7 @@ static struct lu_object *lu_object_new(const struct lu_env *env,
        struct lu_site_bkt_data *bkt;
 
        o = lu_object_alloc(env, dev, f, conf);
-       if (unlikely(IS_ERR(o)))
+       if (IS_ERR(o))
                return o;
 
        hs = dev->ld_site->ls_obj_hash;
@@ -666,7 +666,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
         * operations, including fld queries, inode loading, etc.
         */
        o = lu_object_alloc(env, dev, f, conf);
-       if (unlikely(IS_ERR(o)))
+       if (IS_ERR(o))
                return o;
 
        LASSERT(lu_fid_eq(lu_object_fid(o), f));
@@ -674,7 +674,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env,
        cfs_hash_bd_lock(hs, &bd, 1);
 
        shadow = htable_lookup(s, &bd, f, waiter, &version);
-       if (likely(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT)) {
+       if (likely(PTR_ERR(shadow) == -ENOENT)) {
                struct lu_site_bkt_data *bkt;
 
                bkt = cfs_hash_bd_extra_get(hs, &bd);
@@ -1558,7 +1558,7 @@ static int keys_fill(struct lu_context *ctx)
                        LINVRNT(key->lct_index == i);
 
                        value = key->lct_init(ctx, key);
-                       if (unlikely(IS_ERR(value)))
+                       if (IS_ERR(value))
                                return PTR_ERR(value);
 
                        if (!(ctx->lc_tags & LCT_NOREF))
index 5cc6435cc47a2ca8cd82a06211f686cae860b1c3..d6184f821cd0e919859f3e3cc14de2f12b3c5089 100644 (file)
@@ -105,7 +105,7 @@ int class_add_uuid(const char *uuid, __u64 nid)
                return -EOVERFLOW;
 
        data = kzalloc(sizeof(*data), GFP_NOFS);
-       if (data == NULL)
+       if (!data)
                return -ENOMEM;
 
        obd_str2uuid(&data->un_uuid, uuid);
index fbdb748a36b9e2f45c0b7b40f0ec06c0fd404f55..93805ac93c5a8e78f31189db7277ab329c705210 100644 (file)
@@ -835,7 +835,7 @@ int class_add_profile(int proflen, char *prof, int osclen, char *osc,
        CDEBUG(D_CONFIG, "Add profile %s\n", prof);
 
        lprof = kzalloc(sizeof(*lprof), GFP_NOFS);
-       if (lprof == NULL)
+       if (!lprof)
                return -ENOMEM;
        INIT_LIST_HEAD(&lprof->lp_list);
 
@@ -979,7 +979,7 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
        new_len = LUSTRE_CFG_BUFLEN(cfg, 1) + strlen(new_name) - name_len;
 
        new_param = kzalloc(new_len, GFP_NOFS);
-       if (new_param == NULL)
+       if (!new_param)
                return ERR_PTR(-ENOMEM);
 
        strcpy(new_param, new_name);
@@ -987,7 +987,7 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg,
                strcat(new_param, value);
 
        bufs = kzalloc(sizeof(*bufs), GFP_NOFS);
-       if (bufs == NULL) {
+       if (!bufs) {
                kfree(new_param);
                return ERR_PTR(-ENOMEM);
        }
@@ -1123,12 +1123,7 @@ int class_process_config(struct lustre_cfg *lcfg)
                goto out;
        }
        case LCFG_SET_LDLM_TIMEOUT: {
-               CDEBUG(D_IOCTL, "changing lustre ldlm_timeout from %d to %d\n",
-                      ldlm_timeout, lcfg->lcfg_num);
-               ldlm_timeout = max(lcfg->lcfg_num, 1U);
-               if (ldlm_timeout >= obd_timeout)
-                       ldlm_timeout = max(obd_timeout / 3, 1U);
-               ldlm_timeout_set = 1;
+               /* ldlm_timeout is not used on the client */
                err = 0;
                goto out;
        }
@@ -1461,7 +1456,7 @@ int class_config_llog_handler(const struct lu_env *env,
                        inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
                                   sizeof(clli->cfg_instance) * 2 + 4;
                        inst_name = kzalloc(inst_len, GFP_NOFS);
-                       if (inst_name == NULL) {
+                       if (!inst_name) {
                                rc = -ENOMEM;
                                goto out;
                        }
@@ -1639,7 +1634,7 @@ int class_config_dump_handler(const struct lu_env *env,
        int      rc = 0;
 
        outstr = kzalloc(256, GFP_NOFS);
-       if (outstr == NULL)
+       if (!outstr)
                return -ENOMEM;
 
        if (rec->lrh_type == OBD_CFG_REC) {
index ce4a71f7171abb060679ad9d648f20481e07c0a5..7c5bab377f5cc27b4dfb30f53b6fb7157b9a40df 100644 (file)
@@ -85,7 +85,7 @@ int lustre_process_log(struct super_block *sb, char *logname,
        LASSERT(cfg);
 
        bufs = kzalloc(sizeof(*bufs), GFP_NOFS);
-       if (bufs == NULL)
+       if (!bufs)
                return -ENOMEM;
 
        /* mgc_process_config */
@@ -247,18 +247,18 @@ int lustre_start_mgc(struct super_block *sb)
        mutex_lock(&mgc_start_lock);
 
        len = strlen(LUSTRE_MGC_OBDNAME) + strlen(libcfs_nid2str(nid)) + 1;
-       mgcname = kzalloc(len, GFP_NOFS);
-       niduuid = kzalloc(len + 2, GFP_NOFS);
+       mgcname = kasprintf(GFP_NOFS,
+                           "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
+       niduuid = kasprintf(GFP_NOFS, "%s_%x", mgcname, i);
        if (!mgcname || !niduuid) {
                rc = -ENOMEM;
                goto out_free;
        }
-       sprintf(mgcname, "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
 
        mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";
 
        data = kzalloc(sizeof(*data), GFP_NOFS);
-       if (data == NULL) {
+       if (!data) {
                rc = -ENOMEM;
                goto out_free;
        }
@@ -326,7 +326,6 @@ int lustre_start_mgc(struct super_block *sb)
 
        /* Add the primary nids for the MGS */
        i = 0;
-       sprintf(niduuid, "%s_%x", mgcname, i);
        if (IS_SERVER(lsi)) {
                ptr = lsi->lsi_lmd->lmd_mgs;
                if (IS_MGS(lsi)) {
@@ -885,7 +884,7 @@ static int lmd_parse_mgssec(struct lustre_mount_data *lmd, char *ptr)
                length = tail - ptr;
 
        lmd->lmd_mgssec = kzalloc(length + 1, GFP_NOFS);
-       if (lmd->lmd_mgssec == NULL)
+       if (!lmd->lmd_mgssec)
                return -ENOMEM;
 
        memcpy(lmd->lmd_mgssec, ptr, length);
@@ -911,7 +910,7 @@ static int lmd_parse_string(char **handle, char *ptr)
                length = tail - ptr;
 
        *handle = kzalloc(length + 1, GFP_NOFS);
-       if (*handle == NULL)
+       if (!*handle)
                return -ENOMEM;
 
        memcpy(*handle, ptr, length);
@@ -941,7 +940,7 @@ static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
                oldlen = strlen(lmd->lmd_mgs) + 1;
 
        mgsnid = kzalloc(oldlen + length + 1, GFP_NOFS);
-       if (mgsnid == NULL)
+       if (!mgsnid)
                return -ENOMEM;
 
        if (lmd->lmd_mgs != NULL) {
@@ -983,7 +982,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
        lmd->lmd_magic = LMD_MAGIC;
 
        lmd->lmd_params = kzalloc(4096, GFP_NOFS);
-       if (lmd->lmd_params == NULL)
+       if (!lmd->lmd_params)
                return -ENOMEM;
        lmd->lmd_params[0] = '\0';
 
@@ -1120,10 +1119,9 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd)
                /* Remove leading /s from fsname */
                while (*++s1 == '/') ;
                /* Freed in lustre_free_lsi */
-               lmd->lmd_profile = kzalloc(strlen(s1) + 8, GFP_NOFS);
+               lmd->lmd_profile = kasprintf(GFP_NOFS, "%s-client", s1);
                if (!lmd->lmd_profile)
                        return -ENOMEM;
-               sprintf(lmd->lmd_profile, "%s-client", s1);
        }
 
        /* Freed in lustre_free_lsi */
@@ -1281,7 +1279,7 @@ struct file_system_type lustre_fs_type = {
        .mount  = lustre_mount,
        .kill_sb      = lustre_kill_super,
        .fs_flags     = FS_BINARY_MOUNTDATA | FS_REQUIRES_DEV |
-                       FS_HAS_FIEMAP | FS_RENAME_DOES_D_MOVE,
+                       FS_RENAME_DOES_D_MOVE,
 };
 MODULE_ALIAS_FS("lustre");
 
index ff0a01bcf8dacd4b674080bebfb95a007458a747..b0b0157a6334c152ddcafc8a0b46cd9f8de189f4 100644 (file)
 #include "../include/obd_support.h"
 #include "../include/obd_class.h"
 
-
-static inline __u32 consume(int nob, __u8 **ptr)
-{
-       __u32 value;
-
-       LASSERT(nob <= sizeof(value));
-
-       for (value = 0; nob > 0; --nob)
-               value = (value << 8) | *((*ptr)++);
-       return value;
-}
-
-#define CONSUME(val, ptr) (val) = consume(sizeof(val), (ptr))
-
-static void uuid_unpack(class_uuid_t in, __u16 *uu, int nr)
-{
-       __u8 *ptr = in;
-
-       LASSERT(nr * sizeof(*uu) == sizeof(class_uuid_t));
-
-       while (nr-- > 0)
-               CONSUME(uu[nr], &ptr);
-}
-
 void class_uuid_unparse(class_uuid_t uu, struct obd_uuid *out)
 {
-       /* uu as an array of __u16's */
-       __u16 uuid[sizeof(class_uuid_t) / sizeof(__u16)];
-
-       CLASSERT(ARRAY_SIZE(uuid) == 8);
-
-       uuid_unpack(uu, uuid, ARRAY_SIZE(uuid));
-       sprintf(out->uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
-               uuid[0], uuid[1], uuid[2], uuid[3],
-               uuid[4], uuid[5], uuid[6], uuid[7]);
+       sprintf(out->uuid, "%pU", uu);
 }
 EXPORT_SYMBOL(class_uuid_unparse);
index 0222fd2e475743d9efb09fb47d62e3f9c76ab747..27bd170c3a2831c6e2c1c9a5980cdb956900d569 100644 (file)
@@ -480,11 +480,11 @@ static int echo_alloc_memmd(struct echo_device *ed,
 
        LASSERT(*lsmp == NULL);
        *lsmp = kzalloc(lsm_size, GFP_NOFS);
-       if (*lsmp == NULL)
+       if (!*lsmp)
                return -ENOMEM;
 
        (*lsmp)->lsm_oinfo[0] = kzalloc(sizeof(struct lov_oinfo), GFP_NOFS);
-       if ((*lsmp)->lsm_oinfo[0] == NULL) {
+       if (!(*lsmp)->lsm_oinfo[0]) {
                kfree(*lsmp);
                return -ENOMEM;
        }
@@ -701,7 +701,7 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env,
        int cleanup = 0;
 
        ed = kzalloc(sizeof(*ed), GFP_NOFS);
-       if (ed == NULL) {
+       if (!ed) {
                rc = -ENOMEM;
                goto out;
        }
@@ -1878,7 +1878,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
                return rc;
 
        env = kzalloc(sizeof(*env), GFP_NOFS);
-       if (env == NULL)
+       if (!env)
                return -ENOMEM;
 
        rc = lu_env_init(env, LCT_DT_THREAD);
@@ -2049,7 +2049,7 @@ static int echo_client_setup(const struct lu_env *env,
        ec->ec_nstripes = 0;
 
        ocd = kzalloc(sizeof(*ocd), GFP_NOFS);
-       if (ocd == NULL) {
+       if (!ocd) {
                CERROR("Can't alloc ocd connecting to %s\n",
                       lustre_cfg_string(lcfg, 1));
                return -ENOMEM;
@@ -2139,7 +2139,7 @@ static struct obd_ops echo_client_obd_ops = {
        .o_disconnect  = echo_client_disconnect
 };
 
-int echo_client_init(void)
+static int echo_client_init(void)
 {
        int rc;
 
@@ -2154,7 +2154,7 @@ int echo_client_init(void)
        return rc;
 }
 
-void echo_client_exit(void)
+static void echo_client_exit(void)
 {
        class_unregister_type(LUSTRE_ECHO_CLIENT_NAME);
        lu_kmem_fini(echo_caches);
index 5592d32a1a95645b76d348ff15b2bf7678654ae2..c72035e048aa9842d25af105ae0d6cab749a49ed 100644 (file)
@@ -1837,12 +1837,6 @@ static int try_to_add_extent_for_io(struct client_obd *cli,
                oap2 = list_first_entry(&tmp->oe_pages, struct osc_async_page,
                                        oap_pending_item);
                EASSERT(tmp->oe_owner == current, tmp);
-#if 0
-               if (overlapped(tmp, ext)) {
-                       OSC_EXTENT_DUMP(D_ERROR, tmp, "overlapped %p.\n", ext);
-                       EASSERT(0, ext);
-               }
-#endif
                if (oap2cl_page(oap)->cp_type != oap2cl_page(oap2)->cp_type) {
                        CDEBUG(D_CACHE, "Do not permit different type of IO"
                                        " for a same RPC\n");
index 9222c9f4faae5c15298750646e27377ca99bae28..91fdec44792b097edf45b7a2d80bcdc2dd7e90b8 100644 (file)
@@ -218,7 +218,7 @@ static struct lu_device *osc_device_alloc(const struct lu_env *env,
        int rc;
 
        od = kzalloc(sizeof(*od), GFP_NOFS);
-       if (od == NULL)
+       if (!od)
                return ERR_PTR(-ENOMEM);
 
        cl_device_init(&od->od_cl, t);
index 43dfa73dd3a61747c30dfbb37ddb66955edce28d..f9cf5cea643d8f846a4b10ca243818fd6c4def32 100644 (file)
@@ -471,7 +471,7 @@ static int osc_page_flush(const struct lu_env *env,
                          struct cl_io *io)
 {
        struct osc_page *opg = cl2osc_page(slice);
-       int rc = 0;
+       int rc;
 
        rc = osc_flush_async_page(env, io, opg);
        return rc;
index f84b4c78a8a0a3f3ef8f2351115225e2f948ddd9..12113dfd87b8e614f948a9162442ba44b6f61894 100644 (file)
@@ -119,7 +119,7 @@ static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
 
        if (*lmmp == NULL) {
                *lmmp = kzalloc(lmm_size, GFP_NOFS);
-               if (*lmmp == NULL)
+               if (!*lmmp)
                        return -ENOMEM;
        }
 
@@ -1909,7 +1909,7 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli,
                mpflag = cfs_memory_pressure_get_and_set();
 
        crattr = kzalloc(sizeof(*crattr), GFP_NOFS);
-       if (crattr == NULL) {
+       if (!crattr) {
                rc = -ENOMEM;
                goto out;
        }
@@ -2665,7 +2665,7 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
                buf = NULL;
                len = 0;
-               if (obd_ioctl_getdata(&buf, &len, (void *)uarg)) {
+               if (obd_ioctl_getdata(&buf, &len, uarg)) {
                        err = -EINVAL;
                        goto out;
                }
@@ -2695,7 +2695,7 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
 
                memcpy(data->ioc_inlbuf2, &obd->obd_uuid, sizeof(uuid));
 
-               err = copy_to_user((void *)uarg, buf, len);
+               err = copy_to_user(uarg, buf, len);
                if (err)
                        err = -EFAULT;
                obd_ioctl_freedata(buf, len);
index a12cd66b23650db841853e165e6331c903cfcb6b..c83a34a01e659cea3b2d583d1d1711e97f2d953b 100644 (file)
@@ -971,7 +971,7 @@ int ptlrpc_set_add_cb(struct ptlrpc_request_set *set,
        struct ptlrpc_set_cbdata *cbdata;
 
        cbdata = kzalloc(sizeof(*cbdata), GFP_NOFS);
-       if (cbdata == NULL)
+       if (!cbdata)
                return -ENOMEM;
 
        cbdata->psc_interpret = fn;
index 8cb1929fd31df652a1b031cb7dd04a0cdfb5d676..c8ef9e57826326c62019a7d76eadce99d367a2e7 100644 (file)
@@ -485,7 +485,7 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
        return rc;
 }
 
-void ptlrpc_ni_fini(void)
+static void ptlrpc_ni_fini(void)
 {
        wait_queue_head_t waitq;
        struct l_wait_info lwi;
@@ -529,7 +529,7 @@ lnet_pid_t ptl_get_pid(void)
        return pid;
 }
 
-int ptlrpc_ni_init(void)
+static int ptlrpc_ni_init(void)
 {
        int rc;
        lnet_pid_t pid;
index c9b8481dd38462b51d580b05914fdb9078cc3869..1eae3896c0375ce6f2d7ed0c6856b000f2a487f3 100644 (file)
@@ -555,14 +555,12 @@ static int import_select_connection(struct obd_import *imp)
        imp_conn->oic_last_attempt = cfs_time_current_64();
 
        /* switch connection, don't mind if it's same as the current one */
-       if (imp->imp_connection)
-               ptlrpc_connection_put(imp->imp_connection);
+       ptlrpc_connection_put(imp->imp_connection);
        imp->imp_connection = ptlrpc_connection_addref(imp_conn->oic_conn);
 
        dlmexp = class_conn2export(&imp->imp_dlm_handle);
        LASSERT(dlmexp != NULL);
-       if (dlmexp->exp_connection)
-               ptlrpc_connection_put(dlmexp->exp_connection);
+       ptlrpc_connection_put(dlmexp->exp_connection);
        dlmexp->exp_connection = ptlrpc_connection_addref(imp_conn->oic_conn);
        class_export_put(dlmexp);
 
index aaaabbf5f1b9807770d7e743e3c62035fd8809bf..53f9af1f2f3eaa109599b9a3e610171acf7ecd64 100644 (file)
@@ -652,7 +652,7 @@ static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file,
                return -EINVAL;
 
        cmd = kzalloc(LPROCFS_NRS_WR_MAX_CMD, GFP_NOFS);
-       if (cmd == NULL)
+       if (!cmd)
                return -ENOMEM;
        /**
         * strsep() modifies its argument, so keep a copy
@@ -819,7 +819,7 @@ ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos)
        }
 
        srhi = kzalloc(sizeof(*srhi), GFP_NOFS);
-       if (srhi == NULL)
+       if (!srhi)
                return NULL;
 
        srhi->srhi_seq = 0;
@@ -1219,7 +1219,7 @@ int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
        char *tmpbuf;
 
        kbuf = kzalloc(BUFLEN, GFP_NOFS);
-       if (kbuf == NULL)
+       if (!kbuf)
                return -ENOMEM;
 
        /*
@@ -1303,7 +1303,7 @@ int lprocfs_wr_import(struct file *file, const char __user *buffer,
                return -EINVAL;
 
        kbuf = kzalloc(count + 1, GFP_NOFS);
-       if (kbuf == NULL)
+       if (!kbuf)
                return -ENOMEM;
 
        if (copy_from_user(kbuf, buffer, count)) {
index 9516acadb7a16d5697f4b05bcd61565882ae3643..d37cdd5ac58065481ec7403c7d9962cef90df1c4 100644 (file)
@@ -1156,7 +1156,7 @@ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf)
        }
 
        desc = kzalloc(sizeof(*desc), GFP_NOFS);
-       if (desc == NULL) {
+       if (!desc) {
                rc = -ENOMEM;
                goto fail;
        }
index 2787bfd67165604094ad199ca71b60d0d60762f6..84937ad905709633f9d33ffb456e5ccd006c9f2e 100644 (file)
@@ -52,6 +52,8 @@
 #include "../include/obd_cksum.h"
 #include "../include/lustre/ll_fiemap.h"
 
+#include "ptlrpc_internal.h"
+
 static inline int lustre_msg_hdr_size_v2(int count)
 {
        return cfs_size_round(offsetof(struct lustre_msg_v2,
index d05c37c1fd30f3636185a3770e5d320aae1f4983..f8edb791a998bc0373fd398ed608a30ed8cdd4ac 100644 (file)
@@ -318,8 +318,6 @@ int ptlrpc_start_pinger(void)
 
        strcpy(pinger_thread.t_name, "ll_ping");
 
-       /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
-        * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
        rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, &pinger_thread,
                                 "%s", pinger_thread.t_name));
        if (IS_ERR_VALUE(rc)) {
index 5268887ca6b3468fc83afac01a7a22c754ecd04f..ae99180d6036f10647d0b4dbbf8b7e3bdbcb1589 100644 (file)
@@ -51,7 +51,7 @@ extern spinlock_t ptlrpc_rs_debug_lock;
 extern struct mutex pinger_mutex;
 extern struct mutex ptlrpcd_mutex;
 
-__init int ptlrpc_init(void)
+static int __init ptlrpc_init(void)
 {
        int rc, cleanup_phase = 0;
 
index e591cff323ece570c342ef32e0b7329e59a1c47d..17cc81d5074f3706c3ad97463ce0b15492cd791f 100644 (file)
@@ -739,7 +739,7 @@ static int ptlrpcd_init(void)
 
        size = offsetof(struct ptlrpcd, pd_threads[nthreads]);
        ptlrpcds = kzalloc(size, GFP_NOFS);
-       if (ptlrpcds == NULL) {
+       if (!ptlrpcds) {
                rc = -ENOMEM;
                goto out;
        }
index 69d73c43069636d310b5d7fc1c0a36162f6ae988..2ee3e8b2e879eac164aa73e7454fd5393d89c416 100644 (file)
@@ -415,7 +415,7 @@ static int enc_pools_add_pages(int npages)
 
        for (i = 0; i < npools; i++) {
                pools[i] = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
-               if (pools[i] == NULL)
+               if (!pools[i])
                        goto out_pools;
 
                for (j = 0; j < PAGES_PER_POOL && alloced < npages; j++) {
index 31da43e8b3c62942e01a53e328694ea0bd3e9100..e7f2f333257db9f964ac590aff1dad7b6979a064 100644 (file)
@@ -564,7 +564,7 @@ struct sptlrpc_conf *sptlrpc_conf_get(const char *fsname,
                return NULL;
 
        conf = kzalloc(sizeof(*conf), GFP_NOFS);
-       if (conf == NULL)
+       if (!conf)
                return NULL;
 
        strcpy(conf->sc_fsname, fsname);
index 53ce0d14bd469f5d172dd369509ae84110bf8c75..a243db60f69776ddc4b9c197d67e39d6a77b9a65 100644 (file)
@@ -444,7 +444,7 @@ struct ptlrpc_sec *plain_create_sec(struct obd_import *imp,
        LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN);
 
        plsec = kzalloc(sizeof(*plsec), GFP_NOFS);
-       if (plsec == NULL)
+       if (!plsec)
                return NULL;
 
        /*
index 9117f1c15a8e88dbacda3fa2b8e3afb3c94d9690..003344ccfffcde1d88a43556fa404be11072be36 100644 (file)
@@ -43,7 +43,7 @@
 #include "ptlrpc_internal.h"
 
 /* The following are visible and mutable through /sys/module/ptlrpc */
-int test_req_buffer_pressure = 0;
+int test_req_buffer_pressure;
 module_param(test_req_buffer_pressure, int, 0444);
 MODULE_PARM_DESC(test_req_buffer_pressure, "set non-zero to put pressure on request buffer pools");
 module_param(at_min, int, 0644);
@@ -69,7 +69,7 @@ LIST_HEAD(ptlrpc_all_services);
 /** Used to protect the \e ptlrpc_all_services list */
 struct mutex ptlrpc_all_services_mutex;
 
-struct ptlrpc_request_buffer_desc *
+static struct ptlrpc_request_buffer_desc *
 ptlrpc_alloc_rqbd(struct ptlrpc_service_part *svcpt)
 {
        struct ptlrpc_service *svc = svcpt->scp_service;
@@ -101,7 +101,7 @@ ptlrpc_alloc_rqbd(struct ptlrpc_service_part *svcpt)
        return rqbd;
 }
 
-void
+static void
 ptlrpc_free_rqbd(struct ptlrpc_request_buffer_desc *rqbd)
 {
        struct ptlrpc_service_part *svcpt = rqbd->rqbd_svcpt;
@@ -118,7 +118,7 @@ ptlrpc_free_rqbd(struct ptlrpc_request_buffer_desc *rqbd)
        kfree(rqbd);
 }
 
-int
+static int
 ptlrpc_grow_req_bufs(struct ptlrpc_service_part *svcpt, int post)
 {
        struct ptlrpc_service *svc = svcpt->scp_service;
@@ -732,7 +732,7 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
 
        service = kzalloc(offsetof(struct ptlrpc_service, srv_parts[ncpts]),
                          GFP_NOFS);
-       if (service == NULL) {
+       if (!service) {
                kfree(cpts);
                return ERR_PTR(-ENOMEM);
        }
@@ -2298,7 +2298,7 @@ static int ptlrpc_main(void *arg)
        }
 
        env = kzalloc(sizeof(*env), GFP_NOFS);
-       if (env == NULL) {
+       if (!env) {
                rc = -ENOMEM;
                goto out_srv_fini;
        }
@@ -2826,9 +2826,7 @@ void ptlrpc_hr_fini(void)
        ptlrpc_stop_hr_threads();
 
        cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) {
-               if (hrp->hrp_thrs != NULL) {
-                       kfree(hrp->hrp_thrs);
-               }
+               kfree(hrp->hrp_thrs);
        }
 
        cfs_percpt_free(ptlrpc_hr.hr_partitions);
@@ -3054,7 +3052,7 @@ EXPORT_SYMBOL(ptlrpc_unregister_service);
  * Right now, it just checks to make sure that requests aren't languishing
  * in the queue.  We'll use this health check to govern whether a node needs
  * to be shot, so it's intentionally non-aggressive. */
-int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt)
+static int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt)
 {
        struct ptlrpc_request *request = NULL;
        struct timeval right_now;
index 1e302e8516ce55ed57a7900d0ba2f2275ffe4d70..873e2cf312176cb1bceed54e27ec10d6909b9cd9 100644 (file)
@@ -40,6 +40,109 @@ Description:
                               e.g. dd.1253
                nodelocal - use jobid_name value from above.
 
+What:          /sys/fs/lustre/timeout
+Date:          June 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls "lustre timeout" variable, also known as obd_timeout
+               in some old manual. In the past obd_timeout was of paramount
+               importance as the timeout value used everywhere and where
+               other timeouts were derived from. These days it's much less
+               important as network timeouts are mostly determined by
+               AT (adaptive timeouts).
+               Unit: seconds, default: 100
+
+What:          /sys/fs/lustre/max_dirty_mb
+Date:          June 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls total number of dirty cache (in megabytes) allowed
+               across all mounted lustre filesystems.
+               Since writeout of dirty pages in Lustre is somewhat expensive,
+               when you allow to many dirty pages, this might lead to
+               performance degradations as kernel tries to desperately
+               find some pages to free/writeout.
+               Default 1/2 RAM. Min value 4, max value 9/10 of RAM.
+
+What:          /sys/fs/lustre/debug_peer_on_timeout
+Date:          June 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Control if lnet debug information should be printed when
+               an RPC timeout occurs.
+               0 disabled (default)
+               1 enabled
+
+What:          /sys/fs/lustre/dump_on_timeout
+Date:          June 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls if Lustre debug log should be dumped when an RPC
+               timeout occurs. This is useful if yout debug buffer typically
+               rolls over by the time you notice RPC timeouts.
+
+What:          /sys/fs/lustre/dump_on_eviction
+Date:          June 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls if Lustre debug log should be dumped when an this
+               client is evicted from one of the servers.
+               This is useful if yout debug buffer typically rolls over
+                by the time you notice the eviction event.
+
+What:          /sys/fs/lustre/at_min
+Date:          July 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls minimum adaptive timeout in seconds. If you encounter
+               a case where clients timeout due to server-reported processing
+               time being too short, you might consider increasing this value.
+               One common case of this if the underlying network has
+               unpredictable long delays.
+               Default: 0
+
+What:          /sys/fs/lustre/at_max
+Date:          July 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls maximum adaptive timeout in seconds. If at_max timeout
+               is reached for an RPC, the RPC will time out.
+               Some genuinuely slow network hardware might warrant increasing
+               this value.
+               Setting this value to 0 disables Adaptive Timeouts
+               functionality and old-style obd_timeout value is then used.
+               Default: 600
+
+What:          /sys/fs/lustre/at_extra
+Date:          July 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls how much extra time to request for unfinished requests
+               in processing in seconds. Normally a server-side parameter, it
+               is also used on the client for responses to various LDLM ASTs
+               that are handled with a special server thread on the client.
+               This is a way for the servers to ask the clients not to time
+               out the request that reached current servicing time estimate
+               yet and give it some more time.
+               Default: 30
+
+What:          /sys/fs/lustre/at_early_margin
+Date:          July 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls when to send the early reply for requests that are
+               about to timeout as an offset to the estimated service time in
+               seconds..
+               Default: 5
+
+What:          /sys/fs/lustre/at_history
+Date:          July 2015
+Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+               Controls for how many seconds to remember slowest events
+               encountered by adaptive timeouts code.
+               Default: 600
+
 What:          /sys/fs/lustre/llite/<fsname>-<uuid>/blocksize
 Date:          May 2015
 Contact:       "Oleg Drokin" <oleg.drokin@intel.com>
diff --git a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt
new file mode 100644 (file)
index 0000000..380c137
--- /dev/null
@@ -0,0 +1,181 @@
+What:          /sys/class/most/mostcore/aims
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               List of AIMs that have been loaded.
+Users:
+
+What:          /sys/class/most/mostcore/aims/<aim>/add_link
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to establish a connection of a channel and the
+               current AIM.
+Users:
+
+What:          /sys/class/most/mostcore/aims/<aim>/remove_link
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is used to remove a connected channel from the
+               current AIM.
+Users:
+
+What:          /sys/class/most/mostcore/devices
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               List of attached MOST interfaces.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/description
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Provides information about the interface type and the physical
+               location of the device. Hardware attached via USB, for instance,
+               might return <usb_device 1-1.1:1.0>
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/interface
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the type of peripherial interface the current device
+               uses.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               For every channel of the device a directory is created, whose
+               name is dictated by the HDM. This enables an application to
+               collect information about the channel's capabilities and
+               configure it.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/available_datatypes
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the data types the current channel can transport.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/available_directions
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the directions the current channel is capable of.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/number_of_packet_buffers
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the number of packet buffers the current channel can
+               handle.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/number_of_stream_buffers
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the number of streaming buffers the current channel can
+               handle.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/size_of_packet_buffer
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the size of a packet buffer the current channel can
+               handle.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/size_of_stream_buffer
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates the size of a streaming buffer the current channel can
+               handle.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/set_number_of_buffers
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the number of buffers of the current channel.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/set_buffer_size
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the size of a buffer of the current channel.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/set_direction
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the direction of the current channel.
+               The following strings will be accepted:
+                       'dir_tx',
+                       'dir_rx'
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/set_datatype
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the data type of the current channel.
+               The following strings will be accepted:
+                       'control',
+                       'async',
+                       'sync',
+                       'isoc_avp'
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/set_subbuffer_size
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the subbuffer size of the current channel.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/set_packets_per_xact
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               This is to configure the number of packets per transaction of
+               the current channel. This is only needed network interface
+               controller is attached via USB.
+Users:
+
+What:          /sys/class/most/mostcore/devices/<mdev>/<channel>/channel_starving
+Date:          June 2015
+KernelVersion: 4.3
+Contact:       Christian Gromm <christian.gromm@microchip.com>
+Description:
+               Indicates whether current channel ran out of buffers.
+Users:
diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt
new file mode 100644 (file)
index 0000000..a4dc0c3
--- /dev/null
@@ -0,0 +1,180 @@
+
+               Section 1 Overview
+
+The Media Oriented Systems Transport (MOST) driver gives Linux applications
+access a MOST network: The Automotive Information Backbone and the de-facto
+standard for high-bandwidth automotive multimedia networking.
+
+MOST defines the protocol, hardware and software layers necessary to allow
+for the efficient and low-cost transport of control, real-time and packet
+data using a single medium (physical layer). Media currently in use are
+fiber optics, unshielded twisted pair cables (UTP) and coax cables. MOST
+also supports various speed grades up to 150 Mbps.
+For more information on MOST, visit the MOST Cooperation website:
+www.mostcooperation.com.
+
+Cars continue to evolve into sophisticated consumer electronics platforms,
+increasing the demand for reliable and simple solutions to support audio,
+video and data communications. MOST can be used to connect multiple
+consumer devices via optical or electrical physical layers directly to one
+another or in a network configuration. As a synchronous network, MOST
+provides excellent Quality of Service and seamless connectivity for
+audio/video streaming. Therefore, the driver perfectly fits to the mission
+of Automotive Grade Linux to create open source software solutions for
+automotive applications.
+
+The driver consists basically of three layers. The hardware layer, the
+core layer and the application layer. The core layer consists of the core
+module only. This module handles the communication flow through all three
+layers, the configuration of the driver, the configuration interface
+representation in sysfs, and the buffer management.
+For each of the other two layers a selection of modules is provided. These
+modules can arbitrarily be combined to meet the needs of the desired
+system architecture. A module of the hardware layer is referred to as an
+HDM (hardware dependent module). Each module of this layer handles exactly
+one of the peripheral interfaces of a network interface controller (e.g.
+USB, MediaLB, I2C). A module of the application layer is referred to as an
+AIM (application interfacing module). The modules of this layer give access
+to MOST via one the following ways: character devices, ALSA, Networking or
+V4L2.
+
+To physically access MOST, an Intelligent Network Interface Controller
+(INIC) is needed. For more information on available controllers visit:
+www.microchip.com
+
+
+
+               Section 1.1 Hardware Layer
+
+The hardware layer contains so called hardware dependent modules (HDM). For each
+peripheral interface the hardware supports the driver has a suitable module
+that handles the interface.
+
+The HDMs encapsulate the peripheral interface specific knowledge of the driver
+and provides an easy way of extending the number of supported interfaces.
+Currently the following HDMs are available:
+
+       1) MediaLB (DIM2)
+          Host wants to communicate with hardware via MediaLB.
+
+       2) I2C
+          Host wants to communicate with the hardware via I2C.
+
+       3) USB
+          Host wants to communicate with the hardware via USB.
+
+
+               Section 1.2 Core Layer
+
+The core layer contains the mostcore module only, which processes the driver
+configuration via sysfs, buffer management and data forwarding.
+
+
+
+               Section 1.2 Application Layer
+
+The application layer contains so called application interfacing modules (AIM).
+Depending on how the driver should interface to the application, one or more
+suitable modules can be selected.
+
+The AIMs encapsulate the application interface specific knowledge of the driver
+and provides access to user space or other kernel subsystems.
+Currently the following AIMs are available
+
+       1) Character Device
+          Applications can access the driver by means of character devices.
+
+       2) Networking
+          Standard networking applications (e.g. iperf) can by used to access
+          the driver via the networking subsystem.
+
+       3) Video4Linux (v4l2)
+          Standard video applications (e.g. VLC) can by used to access the
+          driver via the V4L subsystem.
+
+       4) Advanced Linux Sound Architecture (ALSA)
+          Standard sound applications (e.g. aplay, arecord, audacity) can by
+          used to access the driver via the ALSA subsystem.
+
+
+
+               Section 2 Configuration
+
+See ABI/sysfs-class-most.txt
+
+
+
+               Section 3 USB Padding
+
+When transceiving synchronous or isochronous data, the number of packets per USB
+transaction and the sub-buffer size need to be configured. These values
+are needed for the driver to process buffer padding, as expected by hardware,
+which is for performance optimization purposes of the USB transmission.
+
+When transmitting synchronous data the allocated channel width needs to be
+written to 'set_subbuffer_size'. Additionally, the number of MOST frames that
+should travel to the host within one USB transaction need to be written to
+'packets_per_xact'.
+
+Internally the synchronous threshold is calculated as follows:
+
+       frame_size = set_subbuffer_size * packets_per_xact
+
+In case 'packets_per_xact' is set to 0xFF the maximum number of packets,
+allocated within one MOST frame, is calculated that fit into _one_ 512 byte
+USB full packet.
+
+       frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync
+
+This frame_size is the number of synchronous data within an USB transaction,
+which renders MTU_USB - frame_size bytes for padding.
+
+When transmitting isochronous AVP data the desired packet size needs to be
+written to 'set_subbuffer_size' and hardware will always expect two isochronous
+packets within one USB transaction. This renders
+
+       MTU_USB - (2 * set_subbuffer_size)
+
+bytes for padding.
+
+Note that at least 2 times set_subbuffer_size bytes for isochronous data or
+set_subbuffer_size times packts_per_xact bytes for synchronous data need to be
+put in the transmission buffer and passed to the driver.
+
+Since HDMs are allowed to change a chosen configuration to best fit its
+constraints, it is recommended to always double check the configuration and read
+back the previously written files.
+
+
+
+               Section 4 Routing Channels
+
+To connect a channel that has been configured as outlined above to an AIM and
+make it accessible to user space applications, the attribute file 'add_link' is
+used. To actually bind a channel to the AIM a string needs to be written to the
+file that complies with the following syntax:
+
+       "most_device:channel_name:link_name[.param]"
+
+The example above links the channel "channel_name" of the device "most_device"
+to the AIM. In case the AIM interfaces the VFS this would also create a device
+node "link_name" in the /dev directory. The parameter "param" is an AIM dependent
+string, which can be omitted in case the used AIM does not make any use of it.
+
+Cdev AIM example:
+        $ echo "mdev0:ep_81:my_rx_channel" >add_link
+        $ echo "mdev0:ep_81" >add_link
+
+
+Sound/ALSA AIM example:
+
+The sound/ALSA AIM needs an additional parameter to determine the audio resolution
+that is going to be used. The following strings can be used:
+
+       - "1x8" (Mono)
+       - "2x16" (16-bit stereo)
+       - "2x24" (24-bit stereo)
+       - "2x32" (32-bit stereo)
+
+        $ echo "mdev0:ep_81:audio_rx.2x16" >add_link
+        $ echo "mdev0:ep_81" >add_link
diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig
new file mode 100644 (file)
index 0000000..d50de03
--- /dev/null
@@ -0,0 +1,30 @@
+menuconfig MOST
+        tristate "MOST driver"
+        select MOSTCORE
+        default n
+        ---help---
+          This option allows you to enable support for MOST Network transceivers.
+
+          If in doubt, say N here.
+
+
+
+if MOST
+
+source "drivers/staging/most/mostcore/Kconfig"
+
+source "drivers/staging/most/aim-cdev/Kconfig"
+
+source "drivers/staging/most/aim-network/Kconfig"
+
+source "drivers/staging/most/aim-sound/Kconfig"
+
+source "drivers/staging/most/aim-v4l2/Kconfig"
+
+source "drivers/staging/most/hdm-dim2/Kconfig"
+
+source "drivers/staging/most/hdm-i2c/Kconfig"
+
+source "drivers/staging/most/hdm-usb/Kconfig"
+
+endif
diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile
new file mode 100644 (file)
index 0000000..9ee981c
--- /dev/null
@@ -0,0 +1,8 @@
+obj-$(CONFIG_MOSTCORE) += mostcore/
+obj-$(CONFIG_AIM_CDEV) += aim-cdev/
+obj-$(CONFIG_AIM_NETWORK)      += aim-network/
+obj-$(CONFIG_AIM_SOUND)        += aim-sound/
+obj-$(CONFIG_AIM_V4L2) += aim-v4l2/
+obj-$(CONFIG_HDM_DIM2) += hdm-dim2/
+obj-$(CONFIG_HDM_I2C)  += hdm-i2c/
+obj-$(CONFIG_HDM_USB)  += hdm-usb/
diff --git a/drivers/staging/most/TODO b/drivers/staging/most/TODO
new file mode 100644 (file)
index 0000000..4fa11a9
--- /dev/null
@@ -0,0 +1,8 @@
+* Get through code review with Greg Kroah-Hartman
+
+Contact:
+To:
+Christian Gromm <christian.gromm@microchip.com>
+Cc:
+Michael Fabry <Michael.Fabry@microchip.com>
+Christian Gromm <chris@engineersdelight.de>
diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/aim-cdev/Kconfig
new file mode 100644 (file)
index 0000000..3c59f1b
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# MOST Cdev configuration
+#
+
+config AIM_CDEV
+       tristate "Cdev AIM"
+
+       ---help---
+         Say Y here if you want to commumicate via character devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aim_cdev.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile
new file mode 100644 (file)
index 0000000..0bcc6c6
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_AIM_CDEV) += aim_cdev.o
+
+aim_cdev-objs := cdev.o
+ccflags-y += -Idrivers/staging/most/mostcore/
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c
new file mode 100644 (file)
index 0000000..0a13d8d
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * cdev.c - Application interfacing module for character devices
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/idr.h>
+#include "mostcore.h"
+
+static dev_t aim_devno;
+static struct class *aim_class;
+static struct ida minor_id;
+static unsigned int major;
+
+struct aim_channel {
+       wait_queue_head_t wq;
+       struct cdev cdev;
+       struct device *dev;
+       struct mutex io_mutex;
+       struct most_interface *iface;
+       struct most_channel_config *cfg;
+       unsigned int channel_id;
+       dev_t devno;
+       bool keep_mbo;
+       unsigned int mbo_offs;
+       struct mbo *stacked_mbo;
+       DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
+       atomic_t access_ref;
+       struct list_head list;
+};
+#define to_channel(d) container_of(d, struct aim_channel, cdev)
+static struct list_head channel_list;
+static spinlock_t ch_list_lock;
+
+
+static struct aim_channel *get_channel(struct most_interface *iface, int id)
+{
+       struct aim_channel *channel, *tmp;
+       unsigned long flags;
+       int found_channel = 0;
+
+       spin_lock_irqsave(&ch_list_lock, flags);
+       list_for_each_entry_safe(channel, tmp, &channel_list, list) {
+               if ((channel->iface == iface) && (channel->channel_id == id)) {
+                       found_channel = 1;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&ch_list_lock, flags);
+       if (!found_channel)
+               return NULL;
+       return channel;
+}
+
+/**
+ * aim_open - implements the syscall to open the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stores the channel pointer in the private data field of
+ * the file structure and activates the channel within the core.
+ */
+static int aim_open(struct inode *inode, struct file *filp)
+{
+       struct aim_channel *channel;
+       int ret;
+
+       channel = to_channel(inode->i_cdev);
+       filp->private_data = channel;
+
+       if (((channel->cfg->direction == MOST_CH_RX) &&
+            ((filp->f_flags & O_ACCMODE) != O_RDONLY))
+           || ((channel->cfg->direction == MOST_CH_TX) &&
+               ((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
+               pr_info("WARN: Access flags mismatch\n");
+               return -EACCES;
+       }
+       if (!atomic_inc_and_test(&channel->access_ref)) {
+               pr_info("WARN: Device is busy\n");
+               atomic_dec(&channel->access_ref);
+               return -EBUSY;
+       }
+
+       ret = most_start_channel(channel->iface, channel->channel_id);
+       if (ret)
+               atomic_dec(&channel->access_ref);
+       return ret;
+}
+
+/**
+ * aim_close - implements the syscall to close the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stops the channel within the core.
+ */
+static int aim_close(struct inode *inode, struct file *filp)
+{
+       int ret;
+       struct mbo *mbo;
+       struct aim_channel *channel = to_channel(inode->i_cdev);
+
+       mutex_lock(&channel->io_mutex);
+       if (!channel->dev) {
+               mutex_unlock(&channel->io_mutex);
+               atomic_dec(&channel->access_ref);
+               device_destroy(aim_class, channel->devno);
+               cdev_del(&channel->cdev);
+               kfifo_free(&channel->fifo);
+               list_del(&channel->list);
+               ida_simple_remove(&minor_id, MINOR(channel->devno));
+               wake_up_interruptible(&channel->wq);
+               kfree(channel);
+               return 0;
+       }
+       mutex_unlock(&channel->io_mutex);
+
+       while (0 != kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1))
+               most_put_mbo(mbo);
+       if (channel->keep_mbo == true)
+               most_put_mbo(channel->stacked_mbo);
+       ret = most_stop_channel(channel->iface, channel->channel_id);
+       atomic_dec(&channel->access_ref);
+       wake_up_interruptible(&channel->wq);
+       return ret;
+}
+
+/**
+ * aim_write - implements the syscall to write to the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to write
+ * @offset: offset from where to start writing
+ */
+static ssize_t aim_write(struct file *filp, const char __user *buf,
+                        size_t count, loff_t *offset)
+{
+       int ret, err;
+       size_t actual_len = 0;
+       size_t max_len = 0;
+       ssize_t retval;
+       struct mbo *mbo;
+       struct aim_channel *channel = filp->private_data;
+
+       mutex_lock(&channel->io_mutex);
+       if (unlikely(!channel->dev)) {
+               mutex_unlock(&channel->io_mutex);
+               return -EPIPE;
+       }
+       mutex_unlock(&channel->io_mutex);
+
+       mbo = most_get_mbo(channel->iface, channel->channel_id);
+
+       if (!mbo && channel->dev) {
+               if ((filp->f_flags & O_NONBLOCK))
+                       return -EAGAIN;
+               if (wait_event_interruptible(
+                           channel->wq,
+                           (mbo = most_get_mbo(channel->iface,
+                                               channel->channel_id)) ||
+                           (channel->dev == NULL)))
+                       return -ERESTARTSYS;
+       }
+
+       mutex_lock(&channel->io_mutex);
+       if (unlikely(!channel->dev)) {
+               mutex_unlock(&channel->io_mutex);
+               err = -EPIPE;
+               goto error;
+       }
+       mutex_unlock(&channel->io_mutex);
+
+       max_len = channel->cfg->buffer_size;
+       actual_len = min(count, max_len);
+       mbo->buffer_length = actual_len;
+
+       retval = copy_from_user(mbo->virt_address, buf, mbo->buffer_length);
+       if (retval) {
+               err = -EIO;
+               goto error;
+       }
+
+       ret = most_submit_mbo(mbo);
+       if (ret) {
+               pr_info("submitting MBO to core failed\n");
+               err = ret;
+               goto error;
+       }
+       return actual_len - retval;
+error:
+       if (mbo)
+               most_put_mbo(mbo);
+       return err;
+}
+
+/**
+ * aim_read - implements the syscall to read from the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to read
+ * @offset: offset from where to start reading
+ */
+static ssize_t
+aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
+{
+       ssize_t retval;
+       size_t not_copied, proc_len;
+       struct mbo *mbo;
+       struct aim_channel *channel = filp->private_data;
+
+       if (channel->keep_mbo == true) {
+               mbo = channel->stacked_mbo;
+               channel->keep_mbo = false;
+               goto start_copy;
+       }
+       while ((0 == kfifo_out(&channel->fifo, &mbo, 1))
+              && (channel->dev != NULL)) {
+               if (filp->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               if (wait_event_interruptible(channel->wq,
+                                            (!kfifo_is_empty(&channel->fifo) ||
+                                             (channel->dev == NULL))))
+                       return -ERESTARTSYS;
+       }
+
+start_copy:
+       /* make sure we don't submit to gone devices */
+       mutex_lock(&channel->io_mutex);
+       if (unlikely(!channel->dev)) {
+               mutex_unlock(&channel->io_mutex);
+               return -EIO;
+       }
+
+       if (count < mbo->processed_length)
+               channel->keep_mbo = true;
+
+       proc_len = min((int)count,
+                      (int)(mbo->processed_length - channel->mbo_offs));
+
+       not_copied = copy_to_user(buf,
+                                 mbo->virt_address + channel->mbo_offs,
+                                 proc_len);
+
+       retval = not_copied ? proc_len - not_copied : proc_len;
+
+       if (channel->keep_mbo == true) {
+               channel->mbo_offs = retval;
+               channel->stacked_mbo = mbo;
+       } else {
+               most_put_mbo(mbo);
+               channel->mbo_offs = 0;
+       }
+       mutex_unlock(&channel->io_mutex);
+       return retval;
+}
+
+/**
+ * Initialization of struct file_operations
+ */
+static const struct file_operations channel_fops = {
+       .owner = THIS_MODULE,
+       .read = aim_read,
+       .write = aim_write,
+       .open = aim_open,
+       .release = aim_close,
+};
+
+/**
+ * aim_disconnect_channel - disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the cdev that represents this
+ * channel in user space.
+ */
+static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
+{
+       struct aim_channel *channel;
+       unsigned long flags;
+
+       if (!iface) {
+               pr_info("Bad interface pointer\n");
+               return -EINVAL;
+       }
+
+       channel = get_channel(iface, channel_id);
+       if (channel == NULL)
+               return -ENXIO;
+
+       mutex_lock(&channel->io_mutex);
+       channel->dev = NULL;
+       mutex_unlock(&channel->io_mutex);
+
+       if (atomic_read(&channel->access_ref)) {
+               device_destroy(aim_class, channel->devno);
+               cdev_del(&channel->cdev);
+               kfifo_free(&channel->fifo);
+               ida_simple_remove(&minor_id, MINOR(channel->devno));
+               spin_lock_irqsave(&ch_list_lock, flags);
+               list_del(&channel->list);
+               spin_unlock_irqrestore(&ch_list_lock, flags);
+               kfree(channel);
+       } else {
+               wake_up_interruptible(&channel->wq);
+       }
+       return 0;
+}
+
+/**
+ * aim_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel linked to this MBO and stores it in the local
+ * fifo buffer.
+ */
+static int aim_rx_completion(struct mbo *mbo)
+{
+       struct aim_channel *channel;
+
+       if (!mbo)
+               return -EINVAL;
+
+       channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
+       if (channel == NULL)
+               return -ENXIO;
+
+       kfifo_in(&channel->fifo, &mbo, 1);
+#ifdef DEBUG_MESG
+       if (kfifo_is_full(&channel->fifo))
+               pr_info("WARN: Fifo is full\n");
+#endif
+       wake_up_interruptible(&channel->wq);
+       return 0;
+}
+
+/**
+ * aim_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This wakes sleeping processes in the wait-queue.
+ */
+static int aim_tx_completion(struct most_interface *iface, int channel_id)
+{
+       struct aim_channel *channel;
+
+       if (!iface) {
+               pr_info("Bad interface pointer\n");
+               return -EINVAL;
+       }
+       if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
+               pr_info("Channel ID out of range\n");
+               return -EINVAL;
+       }
+
+       channel = get_channel(iface, channel_id);
+       if (channel == NULL)
+               return -ENXIO;
+       wake_up_interruptible(&channel->wq);
+       return 0;
+}
+
+static struct most_aim cdev_aim;
+
+/**
+ * aim_probe - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @parent: pointer to kobject (needed for sysfs hook-up)
+ * @name: name of the device to be created
+ *
+ * This allocates achannel object and creates the device node in /dev
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int aim_probe(struct most_interface *iface, int channel_id,
+                    struct most_channel_config *cfg,
+                    struct kobject *parent, char *name)
+{
+       struct aim_channel *channel;
+       unsigned long cl_flags;
+       int retval;
+       int current_minor;
+
+       if ((!iface) || (!cfg) || (!parent) || (!name)) {
+               pr_info("Probing AIM with bad arguments");
+               return -EINVAL;
+       }
+       channel = get_channel(iface, channel_id);
+       if (channel)
+               return -EEXIST;
+
+       current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL);
+       if (current_minor < 0)
+               return current_minor;
+
+       channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+       if (!channel) {
+               pr_info("failed to alloc channel object\n");
+               retval = -ENOMEM;
+               goto error_alloc_channel;
+       }
+
+       channel->devno = MKDEV(major, current_minor);
+       cdev_init(&channel->cdev, &channel_fops);
+       channel->cdev.owner = THIS_MODULE;
+       cdev_add(&channel->cdev, channel->devno, 1);
+       channel->iface = iface;
+       channel->cfg = cfg;
+       channel->channel_id = channel_id;
+       channel->mbo_offs = 0;
+       atomic_set(&channel->access_ref, -1);
+       INIT_KFIFO(channel->fifo);
+       retval = kfifo_alloc(&channel->fifo, cfg->num_buffers, GFP_KERNEL);
+       if (retval) {
+               pr_info("failed to alloc channel kfifo");
+               goto error_alloc_kfifo;
+       }
+       init_waitqueue_head(&channel->wq);
+       mutex_init(&channel->io_mutex);
+       spin_lock_irqsave(&ch_list_lock, cl_flags);
+       list_add_tail(&channel->list, &channel_list);
+       spin_unlock_irqrestore(&ch_list_lock, cl_flags);
+       channel->dev = device_create(aim_class,
+                                    NULL,
+                                    channel->devno,
+                                    NULL,
+                                    "%s", name);
+
+       retval = IS_ERR(channel->dev);
+       if (retval) {
+               pr_info("failed to create new device node %s\n", name);
+               goto error_create_device;
+       }
+       kobject_uevent(&channel->dev->kobj, KOBJ_ADD);
+       return 0;
+
+error_create_device:
+       kfifo_free(&channel->fifo);
+       list_del(&channel->list);
+error_alloc_kfifo:
+       cdev_del(&channel->cdev);
+       kfree(channel);
+error_alloc_channel:
+       ida_simple_remove(&minor_id, current_minor);
+       return retval;
+}
+
+static struct most_aim cdev_aim = {
+       .name = "cdev",
+       .probe_channel = aim_probe,
+       .disconnect_channel = aim_disconnect_channel,
+       .rx_completion = aim_rx_completion,
+       .tx_completion = aim_tx_completion,
+};
+
+static int __init mod_init(void)
+{
+       pr_info("init()\n");
+
+       INIT_LIST_HEAD(&channel_list);
+       spin_lock_init(&ch_list_lock);
+       ida_init(&minor_id);
+
+       if (alloc_chrdev_region(&aim_devno, 0, 50, "cdev") < 0)
+               return -EIO;
+       major = MAJOR(aim_devno);
+
+       aim_class = class_create(THIS_MODULE, "most_cdev_aim");
+       if (IS_ERR(aim_class)) {
+               pr_err("no udev support\n");
+               goto free_cdev;
+       }
+
+       if (most_register_aim(&cdev_aim))
+               goto dest_class;
+       return 0;
+
+dest_class:
+       class_destroy(aim_class);
+free_cdev:
+       unregister_chrdev_region(aim_devno, 1);
+       return -EIO;
+}
+
+static void __exit mod_exit(void)
+{
+       struct aim_channel *channel, *tmp;
+
+       pr_info("exit module\n");
+
+       most_deregister_aim(&cdev_aim);
+
+       list_for_each_entry_safe(channel, tmp, &channel_list, list) {
+               device_destroy(aim_class, channel->devno);
+               cdev_del(&channel->cdev);
+               kfifo_free(&channel->fifo);
+               list_del(&channel->list);
+               ida_simple_remove(&minor_id, MINOR(channel->devno));
+               kfree(channel);
+       }
+       class_destroy(aim_class);
+       unregister_chrdev_region(aim_devno, 1);
+       ida_destroy(&minor_id);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("character device AIM for mostcore");
diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/aim-network/Kconfig
new file mode 100644 (file)
index 0000000..4c66b24
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# MOST Networking configuration
+#
+
+config AIM_NETWORK
+       tristate "Networking AIM"
+       depends on NET
+
+       ---help---
+         Say Y here if you want to commumicate via a networking device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aim_network.
diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile
new file mode 100644 (file)
index 0000000..840c1dd
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_AIM_NETWORK) += aim_network.o
+
+aim_network-objs := networking.o
+ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
new file mode 100644 (file)
index 0000000..c8ab239
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * Networking AIM - Networking Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include "mostcore.h"
+#include "networking.h"
+
+
+#define MEP_HDR_LEN 8
+#define MDP_HDR_LEN 16
+#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
+
+#define PMHL 5
+
+#define PMS_TELID_UNSEGM_MAMAC 0x0A
+#define PMS_FIFONO_MDP         0x01
+#define PMS_FIFONO_MEP         0x04
+#define PMS_MSGTYPE_DATA       0x04
+#define PMS_DEF_PRIO           0
+#define MEP_DEF_RETRY          15
+
+#define PMS_FIFONO_MASK                0x07
+#define PMS_FIFONO_SHIFT       3
+#define PMS_RETRY_SHIFT                4
+#define PMS_TELID_MASK         0x0F
+#define PMS_TELID_SHIFT                4
+
+#define HB(value)              ((u8)((u16)(value) >> 8))
+#define LB(value)              ((u8)(value))
+
+
+
+#define EXTRACT_BIT_SET(bitset_name, value) \
+       (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
+
+#define PMS_IS_MEP(buf, len) \
+       ((len) > MEP_HDR_LEN && \
+        EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
+
+#define PMS_IS_MAMAC(buf, len) \
+       ((len) > MDP_HDR_LEN && \
+        EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
+        EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)
+
+struct net_dev_channel {
+       bool linked;
+       int ch_id;
+};
+
+struct net_dev_context {
+       struct most_interface *iface;
+       bool channels_opened;
+       bool is_mamac;
+       unsigned char link_stat;
+       struct net_device *dev;
+       struct net_dev_channel rx;
+       struct net_dev_channel tx;
+       struct list_head list;
+};
+
+static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
+static struct spinlock list_lock;
+static struct most_aim aim;
+
+
+static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
+{
+       u8 *buff = mbo->virt_address;
+       const u8 broadcast[] = { 0x03, 0xFF };
+       const u8 *dest_addr = skb->data + 4;
+       const u8 *eth_type = skb->data + 12;
+       unsigned int payload_len = skb->len - ETH_HLEN;
+       unsigned int mdp_len = payload_len + MDP_HDR_LEN;
+
+       if (mbo->buffer_length < mdp_len) {
+               pr_err("drop: too small buffer! (%d for %d)\n",
+                      mbo->buffer_length, mdp_len);
+               return -EINVAL;
+       }
+
+       if (skb->len < ETH_HLEN) {
+               pr_err("drop: too small packet! (%d)\n", skb->len);
+               return -EINVAL;
+       }
+
+       if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
+               dest_addr = broadcast;
+
+       *buff++ = HB(mdp_len - 2);
+       *buff++ = LB(mdp_len - 2);
+
+       *buff++ = PMHL;
+       *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+       *buff++ = PMS_DEF_PRIO;
+       *buff++ = dest_addr[0];
+       *buff++ = dest_addr[1];
+       *buff++ = 0x00;
+
+       *buff++ = HB(payload_len + 6);
+       *buff++ = LB(payload_len + 6);
+
+       /* end of FPH here */
+
+       *buff++ = eth_type[0];
+       *buff++ = eth_type[1];
+       *buff++ = 0;
+       *buff++ = 0;
+
+       *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
+       *buff++ = LB(payload_len);
+
+       memcpy(buff, skb->data + ETH_HLEN, payload_len);
+       mbo->buffer_length = mdp_len;
+       return 0;
+}
+
+static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
+{
+       u8 *buff = mbo->virt_address;
+       unsigned int mep_len = skb->len + MEP_HDR_LEN;
+
+       if (mbo->buffer_length < mep_len) {
+               pr_err("drop: too small buffer! (%d for %d)\n",
+                      mbo->buffer_length, mep_len);
+               return -EINVAL;
+       }
+
+       *buff++ = HB(mep_len - 2);
+       *buff++ = LB(mep_len - 2);
+
+       *buff++ = PMHL;
+       *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+       *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
+       *buff++ = 0;
+       *buff++ = 0;
+       *buff++ = 0;
+
+       memcpy(buff, skb->data, skb->len);
+       mbo->buffer_length = mep_len;
+       return 0;
+}
+
+static int most_nd_set_mac_address(struct net_device *dev, void *p)
+{
+       struct net_dev_context *nd = dev->ml_priv;
+       int err = eth_mac_addr(dev, p);
+
+       if (err)
+               return err;
+
+       BUG_ON(nd->dev != dev);
+
+       nd->is_mamac =
+               (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
+                dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
+
+       /*
+        * Set default MTU for the given packet type.
+        * It is still possible to change MTU using ip tools afterwards.
+        */
+       dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
+
+       return 0;
+}
+
+static int most_nd_open(struct net_device *dev)
+{
+       struct net_dev_context *nd = dev->ml_priv;
+
+       pr_info("open net device %s\n", dev->name);
+
+       BUG_ON(nd->dev != dev);
+
+       if (nd->channels_opened)
+               return -EFAULT;
+
+       BUG_ON(!nd->tx.linked || !nd->rx.linked);
+
+       if (most_start_channel(nd->iface, nd->rx.ch_id)) {
+               pr_err("most_start_channel() failed\n");
+               return -EBUSY;
+       }
+
+       if (most_start_channel(nd->iface, nd->tx.ch_id)) {
+               pr_err("most_start_channel() failed\n");
+               most_stop_channel(nd->iface, nd->rx.ch_id);
+               return -EBUSY;
+       }
+
+       nd->channels_opened = true;
+
+       if (nd->is_mamac) {
+               nd->link_stat = 1;
+               netif_wake_queue(dev);
+       } else {
+               nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
+       }
+
+       return 0;
+}
+
+static int most_nd_stop(struct net_device *dev)
+{
+       struct net_dev_context *nd = dev->ml_priv;
+
+       pr_info("stop net device %s\n", dev->name);
+
+       BUG_ON(nd->dev != dev);
+       netif_stop_queue(dev);
+
+       if (nd->channels_opened) {
+               most_stop_channel(nd->iface, nd->rx.ch_id);
+               most_stop_channel(nd->iface, nd->tx.ch_id);
+               nd->channels_opened = false;
+       }
+
+       return 0;
+}
+
+static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
+                                     struct net_device *dev)
+{
+       struct net_dev_context *nd = dev->ml_priv;
+       struct mbo *mbo;
+       int ret;
+
+       BUG_ON(nd->dev != dev);
+
+       mbo = most_get_mbo(nd->iface, nd->tx.ch_id);
+
+       if (!mbo) {
+               netif_stop_queue(dev);
+               dev->stats.tx_fifo_errors++;
+               return NETDEV_TX_BUSY;
+       }
+
+       if (nd->is_mamac)
+               ret = skb_to_mamac(skb, mbo);
+       else
+               ret = skb_to_mep(skb, mbo);
+
+       if (ret) {
+               most_put_mbo(mbo);
+               dev->stats.tx_dropped++;
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
+       most_submit_mbo(mbo);
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
+       kfree_skb(skb);
+       return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops most_nd_ops = {
+       .ndo_open = most_nd_open,
+       .ndo_stop = most_nd_stop,
+       .ndo_start_xmit = most_nd_start_xmit,
+       .ndo_set_mac_address = most_nd_set_mac_address,
+};
+
+static void most_nd_setup(struct net_device *dev)
+{
+       pr_info("setup net device %s\n", dev->name);
+       ether_setup(dev);
+       dev->netdev_ops = &most_nd_ops;
+}
+
+static void most_net_rm_netdev_safe(struct net_dev_context *nd)
+{
+       if (!nd->dev)
+               return;
+
+       pr_info("remove net device %p\n", nd->dev);
+
+       unregister_netdev(nd->dev);
+       free_netdev(nd->dev);
+       nd->dev = 0;
+}
+
+static struct net_dev_context *get_net_dev_context(
+       struct most_interface *iface)
+{
+       struct net_dev_context *nd, *tmp;
+
+       spin_lock(&list_lock);
+       list_for_each_entry_safe(nd, tmp, &net_devices, list) {
+               if (nd->iface == iface) {
+                       spin_unlock(&list_lock);
+                       return nd;
+               }
+       }
+       spin_unlock(&list_lock);
+       return NULL;
+}
+
+static int aim_probe_channel(struct most_interface *iface, int channel_idx,
+                            struct most_channel_config *ccfg,
+                            struct kobject *parent, char *name)
+{
+       struct net_dev_context *nd;
+       struct net_dev_channel *ch;
+
+       if (!iface)
+               return -EINVAL;
+
+       if (ccfg->data_type != MOST_CH_ASYNC)
+               return -EINVAL;
+
+       nd = get_net_dev_context(iface);
+
+       if (!nd) {
+               nd = kzalloc(sizeof(*nd), GFP_KERNEL);
+               if (!nd)
+                       return -ENOMEM;
+
+               nd->iface = iface;
+
+               spin_lock(&list_lock);
+               list_add(&nd->list, &net_devices);
+               spin_unlock(&list_lock);
+       }
+
+       ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+       if (ch->linked) {
+               pr_err("only one channel per instance & direction allowed\n");
+               return -EINVAL;
+       }
+
+       if (nd->tx.linked || nd->rx.linked) {
+               struct net_device *dev =
+                       alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN, most_nd_setup);
+
+               if (!dev) {
+                       pr_err("no memory for net_device\n");
+                       return -ENOMEM;
+               }
+
+               nd->dev = dev;
+
+               dev->ml_priv = nd;
+               if (register_netdev(dev)) {
+                       pr_err("registering net device failed\n");
+                       free_netdev(dev);
+                       return -EINVAL;
+               }
+       }
+
+       ch->ch_id = channel_idx;
+       ch->linked = true;
+
+       return 0;
+}
+
+static int aim_disconnect_channel(struct most_interface *iface,
+                                 int channel_idx)
+{
+       struct net_dev_context *nd;
+       struct net_dev_channel *ch;
+
+       nd = get_net_dev_context(iface);
+       if (!nd)
+               return -EINVAL;
+
+       if (nd->rx.linked && channel_idx == nd->rx.ch_id)
+               ch = &nd->rx;
+       else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
+               ch = &nd->tx;
+       else
+               return -EINVAL;
+
+       ch->linked = false;
+
+       /*
+        * do not call most_stop_channel() here, because channels are
+        * going to be closed in ndo_stop() after unregister_netdev()
+        */
+       most_net_rm_netdev_safe(nd);
+
+       if (!nd->rx.linked && !nd->tx.linked) {
+               spin_lock(&list_lock);
+               list_del(&nd->list);
+               spin_unlock(&list_lock);
+               kfree(nd);
+       }
+
+       return 0;
+}
+
+static int aim_resume_tx_channel(struct most_interface *iface,
+                                int channel_idx)
+{
+       struct net_dev_context *nd;
+
+       nd = get_net_dev_context(iface);
+       if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx)
+               return 0;
+
+       if (!nd->dev)
+               return 0;
+
+       netif_wake_queue(nd->dev);
+       return 0;
+}
+
+static int aim_rx_data(struct mbo *mbo)
+{
+       const u32 zero = 0;
+       struct net_dev_context *nd;
+       char *buf = mbo->virt_address;
+       uint32_t len = mbo->processed_length;
+       struct sk_buff *skb;
+       struct net_device *dev;
+
+       nd = get_net_dev_context(mbo->ifp);
+       if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
+               return -EIO;
+
+       dev = nd->dev;
+       if (!dev) {
+               pr_err_once("drop packet: missing net_device\n");
+               return -EIO;
+       }
+
+       if (nd->is_mamac) {
+               if (!PMS_IS_MAMAC(buf, len))
+                       return -EIO;
+
+               skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
+       } else {
+               if (!PMS_IS_MEP(buf, len))
+                       return -EIO;
+
+               skb = dev_alloc_skb(len - MEP_HDR_LEN);
+       }
+
+       if (!skb) {
+               dev->stats.rx_dropped++;
+               pr_err_once("drop packet: no memory for skb\n");
+               goto out;
+       }
+
+       skb->dev = dev;
+
+       if (nd->is_mamac) {
+               /* dest */
+               memcpy(skb_put(skb, ETH_ALEN), dev->dev_addr, ETH_ALEN);
+
+               /* src */
+               memcpy(skb_put(skb, 4), &zero, 4);
+               memcpy(skb_put(skb, 2), buf + 5, 2);
+
+               /* eth type */
+               memcpy(skb_put(skb, 2), buf + 10, 2);
+
+               buf += MDP_HDR_LEN;
+               len -= MDP_HDR_LEN;
+       } else {
+               buf += MEP_HDR_LEN;
+               len -= MEP_HDR_LEN;
+       }
+
+       memcpy(skb_put(skb, len), buf, len);
+       skb->protocol = eth_type_trans(skb, dev);
+       dev->stats.rx_packets++;
+       dev->stats.rx_bytes += skb->len;
+       netif_rx(skb);
+
+out:
+       most_put_mbo(mbo);
+       return 0;
+}
+
+static int __init most_net_init(void)
+{
+       pr_info("most_net_init()\n");
+       spin_lock_init(&list_lock);
+       aim.name = "networking";
+       aim.probe_channel = aim_probe_channel;
+       aim.disconnect_channel = aim_disconnect_channel;
+       aim.tx_completion = aim_resume_tx_channel;
+       aim.rx_completion = aim_rx_data;
+       return most_register_aim(&aim);
+}
+
+static void __exit most_net_exit(void)
+{
+       struct net_dev_context *nd, *tmp;
+
+       spin_lock(&list_lock);
+       list_for_each_entry_safe(nd, tmp, &net_devices, list) {
+               list_del(&nd->list);
+               spin_unlock(&list_lock);
+               /*
+                * do not call most_stop_channel() here, because channels are
+                * going to be closed in ndo_stop() after unregister_netdev()
+                */
+               most_net_rm_netdev_safe(nd);
+               kfree(nd);
+               spin_lock(&list_lock);
+       }
+       spin_unlock(&list_lock);
+
+       most_deregister_aim(&aim);
+       pr_info("most_net_exit()\n");
+}
+
+/**
+ * most_deliver_netinfo - callback for HDM to be informed about HW's MAC
+ * @param iface - most interface instance
+ * @param link_stat - link status
+ * @param mac_addr - MAC address
+ */
+void most_deliver_netinfo(struct most_interface *iface,
+                         unsigned char link_stat, unsigned char *mac_addr)
+{
+       struct net_dev_context *nd;
+       struct net_device *dev;
+
+       pr_info("Received netinfo from %s\n", iface->description);
+
+       nd = get_net_dev_context(iface);
+       if (!nd)
+               return;
+
+       dev = nd->dev;
+       if (!dev)
+               return;
+
+       if (mac_addr)
+               memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+
+       if (nd->link_stat != link_stat) {
+               nd->link_stat = link_stat;
+               if (nd->link_stat)
+                       netif_wake_queue(dev);
+               else
+                       netif_stop_queue(dev);
+       }
+}
+EXPORT_SYMBOL(most_deliver_netinfo);
+
+module_init(most_net_init);
+module_exit(most_net_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-network/networking.h b/drivers/staging/most/aim-network/networking.h
new file mode 100644 (file)
index 0000000..1b8b434
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Networking AIM - Networking Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+#ifndef _NETWORKING_H_
+#define _NETWORKING_H_
+
+#include "mostcore.h"
+
+
+void most_deliver_netinfo(struct most_interface *iface,
+                         unsigned char link_stat, unsigned char *mac_addr);
+
+
+#endif
diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/aim-sound/Kconfig
new file mode 100644 (file)
index 0000000..3194c21
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# MOST ALSA configuration
+#
+
+config AIM_SOUND
+       tristate "ALSA AIM"
+       depends on SND
+       select SND_PCM
+       ---help---
+         Say Y here if you want to commumicate via ALSA/sound devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aim_sound.
diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile
new file mode 100644 (file)
index 0000000..beba958
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_AIM_SOUND) += aim_sound.o
+
+aim_sound-objs := sound.o
+ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c
new file mode 100644 (file)
index 0000000..860302e
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * sound.c - Audio Application Interface Module for Mostcore
+ *
+ * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <mostcore.h>
+
+#define DRIVER_NAME "sound"
+
+static struct list_head dev_list;
+
+/**
+ * struct channel - private structure to keep channel specific data
+ * @substream: stores the substream structure
+ * @iface: interface for which the channel belongs to
+ * @cfg: channel configuration
+ * @card: registered sound card
+ * @list: list for private use
+ * @id: channel index
+ * @period_pos: current period position (ring buffer)
+ * @buffer_pos: current buffer position (ring buffer)
+ * @is_stream_running: identifies whether a stream is running or not
+ * @opened: set when the stream is opened
+ * @playback_task: playback thread
+ * @playback_waitq: waitq used by playback thread
+ */
+struct channel {
+       struct snd_pcm_substream *substream;
+       struct most_interface *iface;
+       struct most_channel_config *cfg;
+       struct snd_card *card;
+       struct list_head list;
+       int id;
+       unsigned int period_pos;
+       unsigned int buffer_pos;
+       bool is_stream_running;
+
+       struct task_struct *playback_task;
+       wait_queue_head_t playback_waitq;
+
+       void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
+};
+
+#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
+                      SNDRV_PCM_INFO_MMAP_VALID | \
+                      SNDRV_PCM_INFO_BATCH | \
+                      SNDRV_PCM_INFO_INTERLEAVED | \
+                      SNDRV_PCM_INFO_BLOCK_TRANSFER)
+
+/**
+ * Initialization of struct snd_pcm_hardware
+ */
+static struct snd_pcm_hardware pcm_hardware_template = {
+       .info               = MOST_PCM_INFO,
+       .rates              = SNDRV_PCM_RATE_48000,
+       .rate_min           = 48000,
+       .rate_max           = 48000,
+       .channels_min       = 1,
+       .channels_max       = 8,
+};
+
+#define swap16(val) ( \
+       (((u16)(val) << 8) & (u16)0xFF00) | \
+       (((u16)(val) >> 8) & (u16)0x00FF))
+
+#define swap32(val) ( \
+       (((u32)(val) << 24) & (u32)0xFF000000) | \
+       (((u32)(val) <<  8) & (u32)0x00FF0000) | \
+       (((u32)(val) >>  8) & (u32)0x0000FF00) | \
+       (((u32)(val) >> 24) & (u32)0x000000FF))
+
+static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes)
+{
+       unsigned int i = 0;
+
+       while (i < (bytes / 2)) {
+               dest[i] = swap16(source[i]);
+               i++;
+       }
+}
+
+static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes)
+{
+       unsigned int i = 0;
+
+       while (i < bytes - 2) {
+               dest[i] = source[i + 2];
+               dest[i + 1] = source[i + 1];
+               dest[i + 2] = source[i];
+               i += 3;
+       }
+}
+
+static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes)
+{
+       unsigned int i = 0;
+
+       while (i < bytes / 4) {
+               dest[i] = swap32(source[i]);
+               i++;
+       }
+}
+
+static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+       memcpy(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy16(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy24(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy32(most, alsa, bytes);
+}
+
+static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+       memcpy(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy16(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy24(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes)
+{
+       swap_copy32(alsa, most, bytes);
+}
+
+/**
+ * get_channel - get pointer to channel
+ * @iface: interface structure
+ * @channel_id: channel ID
+ *
+ * This traverses the channel list and returns the channel matching the
+ * ID and interface.
+ *
+ * Returns pointer to channel on success or NULL otherwise.
+ */
+static struct channel *get_channel(struct most_interface *iface,
+                                  int channel_id)
+{
+       struct channel *channel, *tmp;
+
+       list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+               if ((channel->iface == iface) && (channel->id == channel_id))
+                       return channel;
+       }
+
+       return NULL;
+}
+
+/**
+ * copy_data - implements data copying function
+ * @channel: channel
+ * @mbo: MBO from core
+ *
+ * Copy data from/to ring buffer to/from MBO and update the buffer position
+ */
+static bool copy_data(struct channel *channel, struct mbo *mbo)
+{
+       struct snd_pcm_runtime *const runtime = channel->substream->runtime;
+       unsigned int const frame_bytes = channel->cfg->subbuffer_size;
+       unsigned int const buffer_size = runtime->buffer_size;
+       unsigned int frames;
+       unsigned int fr0;
+
+       if (channel->cfg->direction & MOST_CH_RX)
+               frames = mbo->processed_length / frame_bytes;
+       else
+               frames = mbo->buffer_length / frame_bytes;
+       fr0 = min(buffer_size - channel->buffer_pos, frames);
+
+       channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes,
+                        mbo->virt_address,
+                        fr0 * frame_bytes);
+
+       if (frames > fr0) {
+               /* wrap around at end of ring buffer */
+               channel->copy_fn(runtime->dma_area,
+                                mbo->virt_address + fr0 * frame_bytes,
+                                (frames - fr0) * frame_bytes);
+       }
+
+       channel->buffer_pos += frames;
+       if (channel->buffer_pos >= buffer_size)
+               channel->buffer_pos -= buffer_size;
+       channel->period_pos += frames;
+       if (channel->period_pos >= runtime->period_size) {
+               channel->period_pos -= runtime->period_size;
+               return true;
+       }
+
+       return false;
+}
+
+/**
+ * playback_thread - function implements the playback thread
+ * @data: private data
+ *
+ * Thread which does the playback functionality in a loop. It waits for a free
+ * MBO from mostcore for a particular channel and copy the data from ring buffer
+ * to MBO. Submit the MBO back to mostcore, after copying the data.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int playback_thread(void *data)
+{
+       struct channel *const channel = data;
+
+       pr_info("playback thread started\n");
+
+       while (!kthread_should_stop()) {
+               struct mbo *mbo = NULL;
+               bool period_elapsed = false;
+               int ret;
+
+               wait_event_interruptible(
+                       channel->playback_waitq,
+                       kthread_should_stop() ||
+                       (mbo = most_get_mbo(channel->iface, channel->id)));
+
+               if (!mbo)
+                       continue;
+
+               if (channel->is_stream_running)
+                       period_elapsed = copy_data(channel, mbo);
+               else
+                       memset(mbo->virt_address, 0, mbo->buffer_length);
+
+               ret = most_submit_mbo(mbo);
+               if (ret)
+                       channel->is_stream_running = false;
+
+               if (period_elapsed)
+                       snd_pcm_period_elapsed(channel->substream);
+       }
+
+       return 0;
+}
+
+/**
+ * pcm_open - implements open callback function for PCM middle layer
+ * @substream: pointer to ALSA PCM substream
+ *
+ * This is called when a PCM substream is opened. At least, the function should
+ * initialize the runtime->hw record.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_open(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct most_channel_config *cfg = channel->cfg;
+
+       pr_info("pcm_open(), %s\n", substream->name);
+
+       channel->substream = substream;
+
+       if (cfg->direction == MOST_CH_TX) {
+               init_waitqueue_head(&channel->playback_waitq);
+               channel->playback_task = kthread_run(&playback_thread, channel,
+                                                    "most_audio_playback");
+               if (IS_ERR(channel->playback_task))
+                       return PTR_ERR(channel->playback_task);
+       }
+
+       if (most_start_channel(channel->iface, channel->id)) {
+               pr_err("most_start_channel() failed!\n");
+               if (cfg->direction == MOST_CH_TX)
+                       kthread_stop(channel->playback_task);
+               return -EBUSY;
+       }
+
+       runtime->hw = pcm_hardware_template;
+       runtime->hw.buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
+       runtime->hw.period_bytes_min = cfg->buffer_size;
+       runtime->hw.period_bytes_max = cfg->buffer_size;
+       runtime->hw.periods_min = 1;
+       runtime->hw.periods_max = cfg->num_buffers;
+
+       return 0;
+}
+
+/**
+ * pcm_close - implements close callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ *
+ * Obviously, this is called when a PCM substream is closed. Any private
+ * instance for a PCM substream allocated in the open callback will be
+ * released here.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+
+       pr_info("pcm_close(), %s\n", substream->name);
+
+       if (channel->cfg->direction == MOST_CH_TX)
+               kthread_stop(channel->playback_task);
+       most_stop_channel(channel->iface, channel->id);
+
+       return 0;
+}
+
+/**
+ * pcm_hw_params - implements hw_params callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ * @hw_params: contains the hardware parameters set by the application
+ *
+ * This is called when the hardware parameters is set by the application, that
+ * is, once when the buffer size, the period size, the format, etc. are defined
+ * for the PCM substream. Many hardware setups should be done is this callback,
+ * including the allocation of buffers.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *hw_params)
+{
+       pr_info("pcm_hw_params()\n");
+
+       return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+                                               params_buffer_bytes(hw_params));
+}
+
+/**
+ * pcm_hw_free - implements hw_free callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This is called to release the resources allocated via hw_params.
+ * This function will be always called before the close callback is called.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       pr_info("pcm_hw_free()\n");
+
+       return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+/**
+ * pcm_prepare - implements prepare callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM is "prepared". Format rate, sample rate,
+ * etc., can be set here. This callback can be called many times at each setup.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct most_channel_config *cfg = channel->cfg;
+       int width = snd_pcm_format_physical_width(runtime->format);
+
+       channel->copy_fn = NULL;
+
+       if (cfg->direction == MOST_CH_TX) {
+               if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+                       channel->copy_fn = alsa_to_most_memcpy;
+               else if (width == 16)
+                       channel->copy_fn = alsa_to_most_copy16;
+               else if (width == 24)
+                       channel->copy_fn = alsa_to_most_copy24;
+               else if (width == 32)
+                       channel->copy_fn = alsa_to_most_copy32;
+       } else {
+               if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+                       channel->copy_fn = most_to_alsa_memcpy;
+               else if (width == 16)
+                       channel->copy_fn = most_to_alsa_copy16;
+               else if (width == 24)
+                       channel->copy_fn = most_to_alsa_copy24;
+               else if (width == 32)
+                       channel->copy_fn = most_to_alsa_copy32;
+       }
+
+       if (!channel->copy_fn) {
+               pr_err("unsupported format\n");
+               return -EINVAL;
+       }
+
+       channel->period_pos = 0;
+       channel->buffer_pos = 0;
+
+       return 0;
+}
+
+/**
+ * pcm_trigger - implements trigger callback function for PCM middle layer
+ * @substream: substream pointer
+ * @cmd: action to perform
+ *
+ * This is called when the PCM is started, stopped or paused. The action will be
+ * specified in the second argument, SNDRV_PCM_TRIGGER_XXX
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct channel *channel = substream->private_data;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               channel->is_stream_running = true;
+               return 0;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+               channel->is_stream_running = false;
+               return 0;
+
+       default:
+               pr_info("pcm_trigger(), invalid\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * pcm_pointer - implements pointer callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM middle layer inquires the current
+ * hardware position on the buffer. The position must be returned in frames,
+ * ranging from 0 to buffer_size-1.
+ */
+static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct channel *channel = substream->private_data;
+
+       return channel->buffer_pos;
+}
+
+/**
+ * Initialization of struct snd_pcm_ops
+ */
+static struct snd_pcm_ops pcm_ops = {
+       .open       = pcm_open,
+       .close      = pcm_close,
+       .ioctl      = snd_pcm_lib_ioctl,
+       .hw_params  = pcm_hw_params,
+       .hw_free    = pcm_hw_free,
+       .prepare    = pcm_prepare,
+       .trigger    = pcm_trigger,
+       .pointer    = pcm_pointer,
+       .page       = snd_pcm_lib_get_vmalloc_page,
+       .mmap       = snd_pcm_lib_mmap_vmalloc,
+};
+
+
+int split_arg_list(char *buf, char **card_name, char **pcm_format)
+{
+       *card_name = strsep(&buf, ".");
+       if (!*card_name)
+               return -EIO;
+       *pcm_format = strsep(&buf, ".\n");
+       if (!*pcm_format)
+               return -EIO;
+       return 0;
+}
+
+int audio_set_pcm_format(char *pcm_format, struct most_channel_config *cfg)
+{
+       if (!strcmp(pcm_format, "1x8")) {
+               if (cfg->subbuffer_size != 1)
+                       goto error;
+               pr_info("PCM format is 8-bit mono\n");
+               pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S8;
+       } else if (!strcmp(pcm_format, "2x16")) {
+               if (cfg->subbuffer_size != 4)
+                       goto error;
+               pr_info("PCM format is 16-bit stereo\n");
+               pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S16_LE |
+                                               SNDRV_PCM_FMTBIT_S16_BE;
+       } else if (!strcmp(pcm_format, "2x24")) {
+               if (cfg->subbuffer_size != 6)
+                       goto error;
+               pr_info("PCM format is 24-bit stereo\n");
+               pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S24_3LE |
+                                               SNDRV_PCM_FMTBIT_S24_3BE;
+       } else if (!strcmp(pcm_format, "2x32")) {
+               if (cfg->subbuffer_size != 8)
+                       goto error;
+               pr_info("PCM format is 32-bit stereo\n");
+               pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S32_LE |
+                                               SNDRV_PCM_FMTBIT_S32_BE;
+       } else {
+               pr_err("PCM format %s not supported\n", pcm_format);
+               return -EIO;
+       }
+       return 0;
+error:
+       pr_err("Audio resolution doesn't fit subbuffer size\n");
+       return -EINVAL;
+}
+
+/**
+ * audio_probe_channel - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @parent: pointer to kobject (needed for sysfs hook-up)
+ * @arg_list: string that provides the name of the device to be created in /dev
+ *           plus the desired audio resolution
+ *
+ * Creates sound card, pcm device, sets pcm ops and registers sound card.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_probe_channel(struct most_interface *iface, int channel_id,
+                              struct most_channel_config *cfg,
+                              struct kobject *parent, char *arg_list)
+{
+       struct channel *channel;
+       struct snd_card *card;
+       struct snd_pcm *pcm;
+       int playback_count = 0;
+       int capture_count = 0;
+       int ret;
+       int direction;
+       char *card_name;
+       char *pcm_format;
+
+       pr_info("sound_probe_channel()\n");
+
+       if (!iface)
+               return -EINVAL;
+
+       if (cfg->data_type != MOST_CH_SYNC) {
+               pr_err("Incompatible channel type\n");
+               return -EINVAL;
+       }
+
+       if (get_channel(iface, channel_id)) {
+               pr_err("channel (%s:%d) is already linked\n",
+                      iface->description, channel_id);
+               return -EINVAL;
+       }
+
+       if (cfg->direction == MOST_CH_TX) {
+               playback_count = 1;
+               direction = SNDRV_PCM_STREAM_PLAYBACK;
+       } else {
+               capture_count = 1;
+               direction = SNDRV_PCM_STREAM_CAPTURE;
+       }
+
+       ret = split_arg_list(arg_list, &card_name, &pcm_format);
+       if (ret < 0) {
+               pr_info("PCM format missing\n");
+               return ret;
+       }
+       if (audio_set_pcm_format(pcm_format, cfg))
+               return ret;
+
+       ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
+                          sizeof(*channel), &card);
+       if (ret < 0)
+               return ret;
+
+       channel = card->private_data;
+       channel->card = card;
+       channel->cfg = cfg;
+       channel->iface = iface;
+       channel->id = channel_id;
+
+       snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
+       snprintf(card->shortname, sizeof(card->shortname), "MOST:%d",
+                card->number);
+       snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
+                card->shortname, iface->description, channel_id);
+
+       ret = snd_pcm_new(card, card_name, 0, playback_count,
+                         capture_count, &pcm);
+       if (ret < 0)
+               goto err_free_card;
+
+       pcm->private_data = channel;
+
+       snd_pcm_set_ops(pcm, direction, &pcm_ops);
+
+       ret = snd_card_register(card);
+       if (ret < 0)
+               goto err_free_card;
+
+       list_add_tail(&channel->list, &dev_list);
+
+       return 0;
+
+err_free_card:
+       snd_card_free(card);
+       return ret;
+}
+
+/**
+ * audio_disconnect_channel - function to disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the sound card from ALSA
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_disconnect_channel(struct most_interface *iface,
+                                   int channel_id)
+{
+       struct channel *channel;
+
+       pr_info("sound_disconnect_channel()\n");
+
+       channel = get_channel(iface, channel_id);
+       if (!channel) {
+               pr_err("sound_disconnect_channel(), invalid channel %d\n",
+                      channel_id);
+               return -EINVAL;
+       }
+
+       list_del(&channel->list);
+       snd_card_free(channel->card);
+
+       return 0;
+}
+
+/**
+ * audio_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel this MBO belongs to and copy the data from MBO
+ * to ring buffer
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_rx_completion(struct mbo *mbo)
+{
+       struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
+       bool period_elapsed = false;
+
+       if (!channel) {
+               pr_err("sound_rx_completion(), invalid channel %d\n",
+                      mbo->hdm_channel_id);
+               return -EINVAL;
+       }
+
+       if (channel->is_stream_running)
+               period_elapsed = copy_data(channel, mbo);
+
+       most_put_mbo(mbo);
+
+       if (period_elapsed)
+               snd_pcm_period_elapsed(channel->substream);
+
+       return 0;
+}
+
+/**
+ * audio_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This searches the channel that belongs to this combination of interface
+ * pointer and channel ID and wakes a process sitting in the wait queue of
+ * this channel.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_tx_completion(struct most_interface *iface, int channel_id)
+{
+       struct channel *channel = get_channel(iface, channel_id);
+
+       if (!channel) {
+               pr_err("sound_tx_completion(), invalid channel %d\n",
+                      channel_id);
+               return -EINVAL;
+       }
+
+       wake_up_interruptible(&channel->playback_waitq);
+
+       return 0;
+}
+
+/**
+ * Initialization of the struct most_aim
+ */
+static struct most_aim audio_aim = {
+       .name = DRIVER_NAME,
+       .probe_channel = audio_probe_channel,
+       .disconnect_channel = audio_disconnect_channel,
+       .rx_completion = audio_rx_completion,
+       .tx_completion = audio_tx_completion,
+};
+
+static int __init audio_init(void)
+{
+       pr_info("init()\n");
+
+       INIT_LIST_HEAD(&dev_list);
+
+       return most_register_aim(&audio_aim);
+}
+
+static void __exit audio_exit(void)
+{
+       struct channel *channel, *tmp;
+
+       pr_info("exit()\n");
+
+       list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+               list_del(&channel->list);
+               snd_card_free(channel->card);
+       }
+
+       most_deregister_aim(&audio_aim);
+}
+
+module_init(audio_init);
+module_exit(audio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Audio Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/aim-v4l2/Kconfig
new file mode 100644 (file)
index 0000000..d70eaaf
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# MOST V4L2 configuration
+#
+
+config AIM_V4L2
+       tristate "V4L2 AIM"
+       depends on VIDEO_V4L2
+       ---help---
+         Say Y here if you want to commumicate via Video 4 Linux.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aim_v4l2.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile
new file mode 100644 (file)
index 0000000..28aa948
--- /dev/null
@@ -0,0 +1,6 @@
+obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o
+
+aim_v4l2-objs := video.o
+
+ccflags-y += -Idrivers/staging/most/mostcore/
+ccflags-y += -Idrivers/media/video
diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c
new file mode 100644 (file)
index 0000000..d968791
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * V4L2 AIM - V4L2 Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+
+#include "mostcore.h"
+
+
+#define V4L2_AIM_MAX_INPUT  1
+
+
+struct most_video_dev {
+       struct most_interface *iface;
+       int ch_idx;
+       struct list_head list;
+       bool mute;
+
+       struct list_head pending_mbos;
+       spinlock_t list_lock;
+
+       struct v4l2_device v4l2_dev;
+       atomic_t access_ref;
+       struct video_device *vdev;
+       unsigned int ctrl_input;
+
+       struct mutex lock;
+
+       wait_queue_head_t wait_data;
+};
+
+struct aim_fh {
+       /* must be the first field of this struct! */
+       struct v4l2_fh fh;
+       struct most_video_dev *mdev;
+       u32 offs;
+};
+
+
+static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
+static struct spinlock list_lock;
+static struct most_aim aim_info;
+
+
+static inline bool data_ready(struct most_video_dev *mdev)
+{
+       return !list_empty(&mdev->pending_mbos);
+}
+
+static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
+{
+       return list_first_entry(&mdev->pending_mbos, struct mbo, list);
+}
+
+
+static int aim_vdev_open(struct file *filp)
+{
+       int ret;
+       struct video_device *vdev = video_devdata(filp);
+       struct most_video_dev *mdev = video_drvdata(filp);
+       struct aim_fh *fh;
+
+       pr_info("aim_vdev_open()\n");
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       fh = kzalloc(sizeof(struct aim_fh), GFP_KERNEL);
+       if (!fh)
+               return -ENOMEM;
+
+       if (!atomic_inc_and_test(&mdev->access_ref)) {
+               pr_err("too many clients\n");
+               ret = -EBUSY;
+               goto err_dec;
+       }
+
+       fh->mdev = mdev;
+       v4l2_fh_init(&fh->fh, vdev);
+       filp->private_data = fh;
+
+       v4l2_fh_add(&fh->fh);
+
+       ret = most_start_channel(mdev->iface, mdev->ch_idx);
+       if (ret) {
+               pr_err("most_start_channel() failed\n");
+               goto err_rm;
+       }
+
+       return 0;
+
+err_rm:
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+
+err_dec:
+       atomic_dec(&mdev->access_ref);
+       kfree(fh);
+       return ret;
+}
+
+static int aim_vdev_close(struct file *filp)
+{
+       struct aim_fh *fh = filp->private_data;
+       struct most_video_dev *mdev = fh->mdev;
+       struct mbo *mbo, *tmp;
+
+       pr_info("aim_vdev_close()\n");
+
+       /*
+        * We need to put MBOs back before we call most_stop_channel()
+        * to deallocate MBOs.
+        * From the other hand mostcore still calling rx_completion()
+        * to deliver MBOs until most_stop_channel() is called.
+        * Use mute to work around this issue.
+        * This must be implemented in core.
+        */
+
+       spin_lock(&mdev->list_lock);
+       mdev->mute = true;
+       list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) {
+               list_del(&mbo->list);
+               spin_unlock(&mdev->list_lock);
+               most_put_mbo(mbo);
+               spin_lock(&mdev->list_lock);
+       }
+       spin_unlock(&mdev->list_lock);
+       most_stop_channel(mdev->iface, mdev->ch_idx);
+       mdev->mute = false;
+
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+
+       atomic_dec(&mdev->access_ref);
+       kfree(fh);
+       return 0;
+}
+
+static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
+                            size_t count, loff_t *pos)
+{
+       struct aim_fh *fh = filp->private_data;
+       struct most_video_dev *mdev = fh->mdev;
+       int ret = 0;
+
+       if (*pos)
+               return -ESPIPE;
+
+       if (!mdev)
+               return -ENODEV;
+
+       /* wait for the first buffer */
+       if (!(filp->f_flags & O_NONBLOCK)) {
+               if (wait_event_interruptible(mdev->wait_data, data_ready(mdev)))
+                       return -ERESTARTSYS;
+       }
+
+       if (!data_ready(mdev))
+               return -EAGAIN;
+
+       while (count > 0 && data_ready(mdev)) {
+               struct mbo *const mbo = get_top_mbo(mdev);
+               int const rem = mbo->processed_length - fh->offs;
+               int const cnt = rem < count ? rem : count;
+
+               if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) {
+                       pr_err("read: copy_to_user failed\n");
+                       if (!ret)
+                               ret = -EFAULT;
+                       return ret;
+               }
+
+               fh->offs += cnt;
+               count -= cnt;
+               buf += cnt;
+               ret += cnt;
+
+               if (cnt >= rem) {
+                       fh->offs = 0;
+                       spin_lock(&mdev->list_lock);
+                       list_del(&mbo->list);
+                       spin_unlock(&mdev->list_lock);
+                       most_put_mbo(mbo);
+               }
+       }
+       return ret;
+}
+
+static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait)
+{
+       struct aim_fh *fh = filp->private_data;
+       struct most_video_dev *mdev = fh->mdev;
+       unsigned int mask = 0;
+
+       /* only wait if no data is available */
+       if (!data_ready(mdev))
+               poll_wait(filp, &mdev->wait_data, wait);
+       if (data_ready(mdev))
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+static void aim_set_format_struct(struct v4l2_format *f)
+{
+       f->fmt.pix.width = 8;
+       f->fmt.pix.height = 8;
+       f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage = 188 * 2;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.priv = 0;
+}
+
+static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
+                         struct v4l2_format *format)
+{
+#if 0
+       u32 const pixfmt = format->fmt.pix.pixelformat;
+       const char *fmt;
+
+       if (pixfmt != V4L2_PIX_FMT_MPEG) {
+               if (cmd == VIDIOC_TRY_FMT)
+                       fmt = KERN_ERR "try %c%c%c%c failed\n";
+               else
+                       fmt = KERN_ERR "set %c%c%c%c failed\n";
+       } else {
+               if (cmd == VIDIOC_TRY_FMT)
+                       fmt = KERN_ERR "try %c%c%c%c\n";
+               else
+                       fmt = KERN_ERR "set %c%c%c%c\n";
+       }
+       printk(fmt,
+              (pixfmt) & 255,
+              (pixfmt >> 8) & 255,
+              (pixfmt >> 16) & 255,
+              (pixfmt >> 24) & 255);
+#endif
+
+       if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
+               return -EINVAL;
+
+       if (cmd == VIDIOC_TRY_FMT)
+               return 0;
+
+       aim_set_format_struct(format);
+
+       return 0;
+}
+
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                          struct v4l2_capability *cap)
+{
+       struct aim_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       pr_info("vidioc_querycap()\n");
+
+       strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver));
+       strlcpy(cap->card, "my_card", sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                "%s", mdev->iface->description);
+
+       cap->capabilities =
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_TUNER |
+               V4L2_CAP_VIDEO_CAPTURE;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       pr_info("vidioc_enum_fmt_vid_cap() %d\n", f->index);
+
+       if (f->index)
+               return -EINVAL;
+
+       strcpy(f->description, "MPEG");
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       pr_info("vidioc_g_fmt_vid_cap()\n");
+
+       aim_set_format_struct(f);
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct aim_fh *fh  = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       return aim_set_format(mdev, VIDIOC_TRY_FMT, f);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct aim_fh *fh  = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       return aim_set_format(mdev, VIDIOC_S_FMT, f);
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       pr_info("vidioc_g_std()\n");
+
+       *norm = V4L2_STD_UNKNOWN;
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                            struct v4l2_input *input)
+{
+       struct aim_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       if (input->index >= V4L2_AIM_MAX_INPUT)
+               return -EINVAL;
+
+       strcpy(input->name, "MOST Video");
+       input->type |= V4L2_INPUT_TYPE_CAMERA;
+       input->audioset = 0;
+
+       input->std = mdev->vdev->tvnorms;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct aim_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+       *i = mdev->ctrl_input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+{
+       struct aim_fh *fh = priv;
+       struct most_video_dev *mdev = fh->mdev;
+
+       pr_info("vidioc_s_input(%d)\n", index);
+
+       if (index >= V4L2_AIM_MAX_INPUT)
+               return -EINVAL;
+       mdev->ctrl_input = index;
+       return 0;
+}
+
+static struct v4l2_file_operations aim_fops = {
+       .owner      = THIS_MODULE,
+       .open       = aim_vdev_open,
+       .release    = aim_vdev_close,
+       .read       = aim_vdev_read,
+       .poll       = aim_vdev_poll,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap            = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
+       .vidioc_g_std               = vidioc_g_std,
+       .vidioc_enum_input          = vidioc_enum_input,
+       .vidioc_g_input             = vidioc_g_input,
+       .vidioc_s_input             = vidioc_s_input,
+};
+
+static const struct video_device aim_videodev_template = {
+       .fops = &aim_fops,
+       .release = video_device_release,
+       .ioctl_ops = &video_ioctl_ops,
+       .tvnorms = V4L2_STD_UNKNOWN,
+};
+
+/**************************************************************************/
+
+static struct most_video_dev *get_aim_dev(
+       struct most_interface *iface, int channel_idx)
+{
+       struct most_video_dev *mdev, *tmp;
+
+       spin_lock(&list_lock);
+       list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
+               if (mdev->iface == iface && mdev->ch_idx == channel_idx) {
+                       spin_unlock(&list_lock);
+                       return mdev;
+               }
+       }
+       spin_unlock(&list_lock);
+       return 0;
+}
+
+static int aim_rx_data(struct mbo *mbo)
+{
+       struct most_video_dev *mdev =
+               get_aim_dev(mbo->ifp, mbo->hdm_channel_id);
+
+       if (!mdev)
+               return -EIO;
+
+       spin_lock(&mdev->list_lock);
+       if (unlikely(mdev->mute)) {
+               spin_unlock(&mdev->list_lock);
+               return -EIO;
+       }
+
+       list_add_tail(&mbo->list, &mdev->pending_mbos);
+       spin_unlock(&mdev->list_lock);
+       wake_up_interruptible(&mdev->wait_data);
+       return 0;
+}
+
+static int aim_register_videodev(struct most_video_dev *mdev)
+{
+       int retval = -ENOMEM;
+       int ret;
+
+       pr_info("aim_register_videodev()\n");
+
+       init_waitqueue_head(&mdev->wait_data);
+
+       /* allocate and fill v4l2 video struct */
+       mdev->vdev = video_device_alloc();
+       if (!mdev->vdev)
+               return -ENOMEM;
+
+       /* Fill the video capture device struct */
+       *mdev->vdev = aim_videodev_template;
+       mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
+       mdev->vdev->lock = &mdev->lock;
+       strcpy(mdev->vdev->name, "most v4l2 aim video");
+
+       /* Register the v4l2 device */
+       video_set_drvdata(mdev->vdev, mdev);
+       retval = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1);
+       if (retval != 0) {
+               pr_err("video_register_device failed (%d)\n", retval);
+               ret = -ENODEV;
+               goto err_vbi_dev;
+       }
+
+       return 0;
+
+err_vbi_dev:
+       video_device_release(mdev->vdev);
+       return ret;
+}
+
+static void aim_unregister_videodev(struct most_video_dev *mdev)
+{
+       pr_info("aim_unregister_videodev()\n");
+
+       video_unregister_device(mdev->vdev);
+}
+
+
+static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
+{
+       struct most_video_dev *mdev =
+               container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
+
+       v4l2_device_unregister(v4l2_dev);
+       kfree(mdev);
+}
+
+static int aim_probe_channel(struct most_interface *iface, int channel_idx,
+                            struct most_channel_config *ccfg,
+                            struct kobject *parent, char *name)
+{
+       int ret;
+       struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+
+       pr_info("aim_probe_channel()\n");
+
+       if (mdev) {
+               pr_err("channel already linked\n");
+               return -EEXIST;
+       }
+
+       if (ccfg->direction != MOST_CH_RX) {
+               pr_err("wrong direction, expect rx\n");
+               return -EINVAL;
+       }
+
+       if (ccfg->data_type != MOST_CH_SYNC &&
+           ccfg->data_type != MOST_CH_ISOC_AVP) {
+               pr_err("wrong channel type, expect sync or isoc_avp\n");
+               return -EINVAL;
+       }
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return -ENOMEM;
+
+       mutex_init(&mdev->lock);
+       atomic_set(&mdev->access_ref, -1);
+       spin_lock_init(&mdev->list_lock);
+       INIT_LIST_HEAD(&mdev->pending_mbos);
+       mdev->iface = iface;
+       mdev->ch_idx = channel_idx;
+       mdev->v4l2_dev.release = aim_v4l2_dev_release;
+
+       /* Create the v4l2_device */
+       strlcpy(mdev->v4l2_dev.name, "most_video_device",
+               sizeof(mdev->v4l2_dev.name));
+       ret = v4l2_device_register(NULL, &mdev->v4l2_dev);
+       if (ret) {
+               pr_err("v4l2_device_register() failed\n");
+               kfree(mdev);
+               return ret;
+       }
+
+       ret = aim_register_videodev(mdev);
+       if (ret)
+               goto err_unreg;
+
+       spin_lock(&list_lock);
+       list_add(&mdev->list, &video_devices);
+       spin_unlock(&list_lock);
+       return 0;
+
+err_unreg:
+       v4l2_device_disconnect(&mdev->v4l2_dev);
+       v4l2_device_put(&mdev->v4l2_dev);
+       return ret;
+}
+
+static int aim_disconnect_channel(struct most_interface *iface,
+                                 int channel_idx)
+{
+       struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+
+       pr_info("aim_disconnect_channel()\n");
+
+       if (!mdev) {
+               pr_err("no such channel is linked\n");
+               return -ENOENT;
+       }
+
+       spin_lock(&list_lock);
+       list_del(&mdev->list);
+       spin_unlock(&list_lock);
+
+       aim_unregister_videodev(mdev);
+       v4l2_device_disconnect(&mdev->v4l2_dev);
+       v4l2_device_put(&mdev->v4l2_dev);
+       return 0;
+}
+
+static int __init aim_init(void)
+{
+       spin_lock_init(&list_lock);
+
+       aim_info.name = "v4l";
+       aim_info.probe_channel = aim_probe_channel;
+       aim_info.disconnect_channel = aim_disconnect_channel;
+       aim_info.rx_completion = aim_rx_data;
+       return most_register_aim(&aim_info);
+}
+
+static void __exit aim_exit(void)
+{
+       struct most_video_dev *mdev, *tmp;
+
+       /*
+        * As the mostcore currently doesn't call disconnect_channel()
+        * for linked channels while we call most_deregister_aim()
+        * we simulate this call here.
+        * This must be fixed in core.
+        */
+       spin_lock(&list_lock);
+       list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
+               list_del(&mdev->list);
+               spin_unlock(&list_lock);
+
+               aim_unregister_videodev(mdev);
+               v4l2_device_disconnect(&mdev->v4l2_dev);
+               v4l2_device_put(&mdev->v4l2_dev);
+               spin_lock(&list_lock);
+       }
+       spin_unlock(&list_lock);
+
+       most_deregister_aim(&aim_info);
+       BUG_ON(!list_empty(&video_devices));
+}
+
+module_init(aim_init);
+module_exit(aim_exit);
+
+MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
new file mode 100644 (file)
index 0000000..1d4ad1d
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# MediaLB configuration
+#
+
+config HDM_DIM2
+       tristate "DIM2 HDM"
+       depends on AIM_NETWORK
+
+       ---help---
+         Say Y here if you want to connect via MediaLB to network transceiver.
+         This device driver is platform dependent and needs an addtional
+         platform driver to be installed. For more information contact
+         maintainer of this driver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hdm_dim2.
diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile
new file mode 100644 (file)
index 0000000..6bbee87
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o
+
+hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o
+ccflags-y += -Idrivers/staging/most/mostcore/
+ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h
new file mode 100644 (file)
index 0000000..314f7de
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * dim2_errors.h - Definitions of errors for DIM2 HAL API
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef _MOST_DIM_ERRORS_H
+#define _MOST_DIM_ERRORS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * MOST DIM errors.
+ */
+enum dim_errors_t {
+       /** Not an error */
+       DIM_NO_ERROR = 0,
+
+       /** Bad base address for DIM2 IP */
+       DIM_INIT_ERR_DIM_ADDR = 0x10,
+
+       /**< Bad MediaLB clock */
+       DIM_INIT_ERR_MLB_CLOCK,
+
+       /** Bad channel address */
+       DIM_INIT_ERR_CHANNEL_ADDRESS,
+
+       /** Out of DBR memory */
+       DIM_INIT_ERR_OUT_OF_MEMORY,
+
+       /** DIM API is called while DIM is not initialized successfully */
+       DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
+
+       /**
+        * Configuration does not respect hardware limitations
+        * for isochronous or synchronous channels
+        */
+       DIM_ERR_BAD_CONFIG,
+
+       /**
+        * Buffer size does not respect hardware limitations
+        * for isochronous or synchronous channels
+        */
+       DIM_ERR_BAD_BUFFER_SIZE,
+
+       DIM_ERR_UNDERFLOW,
+
+       DIM_ERR_OVERFLOW,
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MOST_DIM_ERRORS_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
new file mode 100644 (file)
index 0000000..a54cf2c
--- /dev/null
@@ -0,0 +1,919 @@
+/*
+ * dim2_hal.c - DIM2 HAL implementation
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#include "dim2_hal.h"
+#include "dim2_errors.h"
+#include "dim2_reg.h"
+#include <linux/stddef.h>
+
+
+/*
+ * The number of frames per sub-buffer for synchronous channels.
+ * Allowed values: 1, 2, 4, 8, 16, 32, 64.
+ */
+#define FRAMES_PER_SUBBUFF 16
+
+/*
+ * Size factor for synchronous DBR buffer.
+ * Minimal value is 4*FRAMES_PER_SUBBUFF.
+ */
+#define SYNC_DBR_FACTOR (4u * (u16)FRAMES_PER_SUBBUFF)
+
+/*
+ * Size factor for isochronous DBR buffer.
+ * Minimal value is 3.
+ */
+#define ISOC_DBR_FACTOR 3u
+
+/*
+ * Number of 32-bit units for DBR map.
+ *
+ * 1: block size is 512, max allocation is 16K
+ * 2: block size is 256, max allocation is 8K
+ * 4: block size is 128, max allocation is 4K
+ * 8: block size is 64, max allocation is 2K
+ *
+ * Min allocated space is block size.
+ * Max possible allocated space is 32 blocks.
+ */
+#define DBR_MAP_SIZE 2
+
+
+/* -------------------------------------------------------------------------- */
+/* not configurable area */
+
+#define CDT 0x00
+#define ADT 0x40
+#define MLB_CAT 0x80
+#define AHB_CAT 0x88
+
+#define DBR_SIZE  (16*1024) /* specified by IP */
+#define DBR_BLOCK_SIZE  (DBR_SIZE / 32 / DBR_MAP_SIZE)
+
+
+/* -------------------------------------------------------------------------- */
+/* generic helper functions and macros */
+
+#define MLBC0_FCNT_VAL_MACRO(n) MLBC0_FCNT_VAL_ ## n ## FPSB
+#define MLBC0_FCNT_VAL(fpsb) MLBC0_FCNT_VAL_MACRO(fpsb)
+
+static inline u32 bit_mask(u8 position)
+{
+       return (u32)1 << position;
+}
+
+static inline bool dim_on_error(u8 error_id, const char *error_message)
+{
+       DIMCB_OnError(error_id, error_message);
+       return false;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* types and local variables */
+
+struct lld_global_vars_t {
+       bool dim_is_initialized;
+       bool mcm_is_initialized;
+       struct dim2_regs *dim2; /* DIM2 core base address */
+       u32 dbr_map[DBR_MAP_SIZE];
+};
+
+static struct lld_global_vars_t g = { false };
+
+
+/* -------------------------------------------------------------------------- */
+
+static int dbr_get_mask_size(u16 size)
+{
+       int i;
+
+       for (i = 0; i < 6; i++)
+               if (size <= (DBR_BLOCK_SIZE << i))
+                       return 1 << i;
+       return 0;
+}
+
+/**
+ * Allocates DBR memory.
+ * @param size Allocating memory size.
+ * @return Offset in DBR memory by success or DBR_SIZE if out of memory.
+ */
+static int alloc_dbr(u16 size)
+{
+       int mask_size;
+       int i, block_idx = 0;
+
+       if (size <= 0)
+               return DBR_SIZE; /* out of memory */
+
+       mask_size = dbr_get_mask_size(size);
+       if (mask_size == 0)
+               return DBR_SIZE; /* out of memory */
+
+       for (i = 0; i < DBR_MAP_SIZE; i++) {
+               u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE;
+               u32 mask = ~((~(u32)0) << blocks);
+
+               do {
+                       if ((g.dbr_map[i] & mask) == 0) {
+                               g.dbr_map[i] |= mask;
+                               return block_idx * DBR_BLOCK_SIZE;
+                       }
+                       block_idx += mask_size;
+                       /* do shift left with 2 steps for case mask_size == 32 */
+                       mask <<= mask_size - 1;
+               } while ((mask <<= 1) != 0);
+       }
+
+       return DBR_SIZE; /* out of memory */
+}
+
+static void free_dbr(int offs, int size)
+{
+       int block_idx = offs / DBR_BLOCK_SIZE;
+       u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE;
+       u32 mask = ~((~(u32)0) << blocks);
+
+       mask <<= block_idx % 32;
+       g.dbr_map[block_idx / 32] &= ~mask;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
+{
+       DIMCB_IoWrite(&g.dim2->MADR, ctr_addr);
+
+       /* wait till transfer is completed */
+       while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1)
+               continue;
+
+       DIMCB_IoWrite(&g.dim2->MCTL, 0);   /* clear transfer complete */
+
+       return DIMCB_IoRead((&g.dim2->MDAT0) + mdat_idx);
+}
+
+static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
+{
+       enum { MADR_WNR_BIT = 31 };
+
+       DIMCB_IoWrite(&g.dim2->MCTL, 0);   /* clear transfer complete */
+
+       if (mask[0] != 0)
+               DIMCB_IoWrite(&g.dim2->MDAT0, value[0]);
+       if (mask[1] != 0)
+               DIMCB_IoWrite(&g.dim2->MDAT1, value[1]);
+       if (mask[2] != 0)
+               DIMCB_IoWrite(&g.dim2->MDAT2, value[2]);
+       if (mask[3] != 0)
+               DIMCB_IoWrite(&g.dim2->MDAT3, value[3]);
+
+       DIMCB_IoWrite(&g.dim2->MDWE0, mask[0]);
+       DIMCB_IoWrite(&g.dim2->MDWE1, mask[1]);
+       DIMCB_IoWrite(&g.dim2->MDWE2, mask[2]);
+       DIMCB_IoWrite(&g.dim2->MDWE3, mask[3]);
+
+       DIMCB_IoWrite(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr);
+
+       /* wait till transfer is completed */
+       while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1)
+               continue;
+
+       DIMCB_IoWrite(&g.dim2->MCTL, 0);   /* clear transfer complete */
+}
+
+static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
+{
+       u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+
+       dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static inline void dim2_clear_ctr(u32 ctr_addr)
+{
+       u32 const value[4] = { 0, 0, 0, 0 };
+
+       dim2_write_ctr(ctr_addr, value);
+}
+
+static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
+                              bool read_not_write, bool sync_mfe)
+{
+       u16 const cat =
+               (read_not_write << CAT_RNW_BIT) |
+               (ch_type << CAT_CT_SHIFT) |
+               (ch_addr << CAT_CL_SHIFT) |
+               (sync_mfe << CAT_MFE_BIT) |
+               (false << CAT_MT_BIT) |
+               (true << CAT_CE_BIT);
+       u8 const ctr_addr = cat_base + ch_addr / 8;
+       u8 const idx = (ch_addr % 8) / 2;
+       u8 const shift = (ch_addr % 2) * 16;
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 value[4] = { 0, 0, 0, 0 };
+
+       mask[idx] = (u32)0xFFFF << shift;
+       value[idx] = cat << shift;
+       dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_clear_cat(u8 cat_base, u8 ch_addr)
+{
+       u8 const ctr_addr = cat_base + ch_addr / 8;
+       u8 const idx = (ch_addr % 8) / 2;
+       u8 const shift = (ch_addr % 2) * 16;
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 value[4] = { 0, 0, 0, 0 };
+
+       mask[idx] = (u32)0xFFFF << shift;
+       dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size,
+                              u16 packet_length)
+{
+       u32 cdt[4] = { 0, 0, 0, 0 };
+
+       if (packet_length)
+               cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT);
+
+       cdt[3] =
+               ((hw_buffer_size - 1) << CDT3_BD_SHIFT) |
+               (dbr_address << CDT3_BA_SHIFT);
+       dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static void dim2_clear_cdt(u8 ch_addr)
+{
+       u32 cdt[4] = { 0, 0, 0, 0 };
+
+       dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static void dim2_configure_adt(u8 ch_addr)
+{
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       adt[0] =
+               (true << ADT0_CE_BIT) |
+               (true << ADT0_LE_BIT) |
+               (0 << ADT0_PG_BIT);
+
+       dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_clear_adt(u8 ch_addr)
+{
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr,
+                                 u16 buffer_size)
+{
+       u8 const shift = idx * 16;
+
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       mask[1] =
+               bit_mask(ADT1_PS_BIT + shift) |
+               bit_mask(ADT1_RDY_BIT + shift) |
+               (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+       adt[1] =
+               (true << (ADT1_PS_BIT + shift)) |
+               (true << (ADT1_RDY_BIT + shift)) |
+               ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+       mask[idx + 2] = 0xFFFFFFFF;
+       adt[idx + 2] = buf_addr;
+
+       dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
+                                u16 buffer_size)
+{
+       u8 const shift = idx * 16;
+
+       u32 mask[4] = { 0, 0, 0, 0 };
+       u32 adt[4] = { 0, 0, 0, 0 };
+
+       mask[1] =
+               bit_mask(ADT1_RDY_BIT + shift) |
+               (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+       adt[1] =
+               (true << (ADT1_RDY_BIT + shift)) |
+               ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+       mask[idx + 2] = 0xFFFFFFFF;
+       adt[idx + 2] = buf_addr;
+
+       dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+
+static void dim2_clear_ctram(void)
+{
+       u32 ctr_addr;
+
+       for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++)
+               dim2_clear_ctr(ctr_addr);
+}
+
+static void dim2_configure_channel(
+       u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
+       u16 packet_length, bool sync_mfe)
+{
+       dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
+       dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0, sync_mfe);
+
+       dim2_configure_adt(ch_addr);
+       dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe);
+
+       /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
+       DIMCB_IoWrite(&g.dim2->ACMR0,
+                     DIMCB_IoRead(&g.dim2->ACMR0) | bit_mask(ch_addr));
+}
+
+static void dim2_clear_channel(u8 ch_addr)
+{
+       /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
+       DIMCB_IoWrite(&g.dim2->ACMR0,
+                     DIMCB_IoRead(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
+
+       dim2_clear_cat(AHB_CAT, ch_addr);
+       dim2_clear_adt(ch_addr);
+
+       dim2_clear_cat(MLB_CAT, ch_addr);
+       dim2_clear_cdt(ch_addr);
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel state helpers */
+
+static void state_init(struct int_ch_state *state)
+{
+       state->request_counter = 0;
+       state->service_counter = 0;
+
+       state->idx1 = 0;
+       state->idx2 = 0;
+       state->level = 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* macro helper functions */
+
+static inline bool check_channel_address(u32 ch_address)
+{
+       return ch_address > 0 && (ch_address % 2) == 0 &&
+              (ch_address / 2) <= (u32)CAT_CL_MASK;
+}
+
+static inline bool check_packet_length(u32 packet_length)
+{
+       u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR;
+
+       if (packet_length <= 0)
+               return false; /* too small */
+
+       if (packet_length > max_size)
+               return false; /* too big */
+
+       if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK)
+               return false; /* too big */
+
+       return true;
+}
+
+static inline bool check_bytes_per_frame(u32 bytes_per_frame)
+{
+       u16 const max_size = ((u16)CDT3_BD_MASK + 1u) / SYNC_DBR_FACTOR;
+
+       if (bytes_per_frame <= 0)
+               return false; /* too small */
+
+       if (bytes_per_frame > max_size)
+               return false; /* too big */
+
+       return true;
+}
+
+static inline u16 norm_ctrl_async_buffer_size(u16 buf_size)
+{
+       u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u;
+
+       if (buf_size > max_size)
+               return max_size;
+
+       return buf_size;
+}
+
+static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
+{
+       u16 n;
+       u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+
+       if (buf_size > max_size)
+               buf_size = max_size;
+
+       n = buf_size / packet_length;
+
+       if (n < 2u)
+               return 0; /* too small buffer for given packet_length */
+
+       return packet_length * n;
+}
+
+static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
+{
+       u16 n;
+       u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+       u32 const unit = bytes_per_frame * (u16)FRAMES_PER_SUBBUFF;
+
+       if (buf_size > max_size)
+               buf_size = max_size;
+
+       n = buf_size / unit;
+
+       if (n < 1u)
+               return 0; /* too small buffer for given bytes_per_frame */
+
+       return unit * n;
+}
+
+static void dim2_cleanup(void)
+{
+       /* disable MediaLB */
+       DIMCB_IoWrite(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
+
+       dim2_clear_ctram();
+
+       /* disable mlb_int interrupt */
+       DIMCB_IoWrite(&g.dim2->MIEN, 0);
+
+       /* clear status for all dma channels */
+       DIMCB_IoWrite(&g.dim2->ACSR0, 0xFFFFFFFF);
+       DIMCB_IoWrite(&g.dim2->ACSR1, 0xFFFFFFFF);
+
+       /* mask interrupts for all channels */
+       DIMCB_IoWrite(&g.dim2->ACMR0, 0);
+       DIMCB_IoWrite(&g.dim2->ACMR1, 0);
+}
+
+static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
+{
+       dim2_cleanup();
+
+       /* configure and enable MediaLB */
+       DIMCB_IoWrite(&g.dim2->MLBC0,
+                     enable_6pin << MLBC0_MLBPEN_BIT |
+                     mlb_clock << MLBC0_MLBCLK_SHIFT |
+                     MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT |
+                     true << MLBC0_MLBEN_BIT);
+
+       /* activate all HBI channels */
+       DIMCB_IoWrite(&g.dim2->HCMR0, 0xFFFFFFFF);
+       DIMCB_IoWrite(&g.dim2->HCMR1, 0xFFFFFFFF);
+
+       /* enable HBI */
+       DIMCB_IoWrite(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
+
+       /* configure DMA */
+       DIMCB_IoWrite(&g.dim2->ACTL,
+                     ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
+                     true << ACTL_SCE_BIT);
+
+#if 0
+       DIMCB_IoWrite(&g.dim2->MIEN,
+                     bit_mask(MIEN_CTX_BREAK_BIT) |
+                     bit_mask(MIEN_CTX_PE_BIT) |
+                     bit_mask(MIEN_CTX_DONE_BIT) |
+                     bit_mask(MIEN_CRX_BREAK_BIT) |
+                     bit_mask(MIEN_CRX_PE_BIT) |
+                     bit_mask(MIEN_CRX_DONE_BIT) |
+                     bit_mask(MIEN_ATX_BREAK_BIT) |
+                     bit_mask(MIEN_ATX_PE_BIT) |
+                     bit_mask(MIEN_ATX_DONE_BIT) |
+                     bit_mask(MIEN_ARX_BREAK_BIT) |
+                     bit_mask(MIEN_ARX_PE_BIT) |
+                     bit_mask(MIEN_ARX_DONE_BIT));
+#endif
+}
+
+static bool dim2_is_mlb_locked(void)
+{
+       u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
+       u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
+                         bit_mask(MLBC1_LOCKERR_BIT);
+       u32 const c1 = DIMCB_IoRead(&g.dim2->MLBC1);
+       u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
+
+       DIMCB_IoWrite(&g.dim2->MLBC1, c1 & nda_mask);
+       return (DIMCB_IoRead(&g.dim2->MLBC1) & mask1) == 0 &&
+              (DIMCB_IoRead(&g.dim2->MLBC0) & mask0) != 0;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* channel help routines */
+
+static inline bool service_channel(u8 ch_addr, u8 idx)
+{
+       u8 const shift = idx * 16;
+       u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1);
+
+       if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0)
+               return false;
+
+       {
+               u32 mask[4] = { 0, 0, 0, 0 };
+               u32 adt_w[4] = { 0, 0, 0, 0 };
+
+               mask[1] =
+                       bit_mask(ADT1_DNE_BIT + shift) |
+                       bit_mask(ADT1_ERR_BIT + shift) |
+                       bit_mask(ADT1_RDY_BIT + shift);
+               dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w);
+       }
+
+       /* clear channel status bit */
+       DIMCB_IoWrite(&g.dim2->ACSR0, bit_mask(ch_addr));
+
+       return true;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* channel init routines */
+
+static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length)
+{
+       state_init(&ch->state);
+
+       ch->addr = ch_addr;
+
+       ch->packet_length = packet_length;
+       ch->bytes_per_frame = 0;
+       ch->done_sw_buffers_number = 0;
+}
+
+static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame)
+{
+       state_init(&ch->state);
+
+       ch->addr = ch_addr;
+
+       ch->packet_length = 0;
+       ch->bytes_per_frame = bytes_per_frame;
+       ch->done_sw_buffers_number = 0;
+}
+
+static void channel_init(struct dim_channel *ch, u8 ch_addr)
+{
+       state_init(&ch->state);
+
+       ch->addr = ch_addr;
+
+       ch->packet_length = 0;
+       ch->bytes_per_frame = 0;
+       ch->done_sw_buffers_number = 0;
+}
+
+/* returns true if channel interrupt state is cleared */
+static bool channel_service_interrupt(struct dim_channel *ch)
+{
+       struct int_ch_state *const state = &ch->state;
+
+       if (!service_channel(ch->addr, state->idx2))
+               return false;
+
+       state->idx2 ^= 1;
+       state->request_counter++;
+       return true;
+}
+
+static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size)
+{
+       struct int_ch_state *const state = &ch->state;
+
+       if (buf_size <= 0)
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size");
+
+       if (ch->packet_length == 0 && ch->bytes_per_frame == 0 &&
+           buf_size != norm_ctrl_async_buffer_size(buf_size))
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+                                   "Bad control/async buffer size");
+
+       if (ch->packet_length &&
+           buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length))
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+                                   "Bad isochronous buffer size");
+
+       if (ch->bytes_per_frame &&
+           buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame))
+               return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+                                   "Bad synchronous buffer size");
+
+       if (state->level >= 2u)
+               return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow");
+
+       ++state->level;
+
+       if (ch->packet_length || ch->bytes_per_frame)
+               dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size);
+       else
+               dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr, buf_size);
+       state->idx1 ^= 1;
+
+       return true;
+}
+
+static u8 channel_service(struct dim_channel *ch)
+{
+       struct int_ch_state *const state = &ch->state;
+
+       if (state->service_counter != state->request_counter) {
+               state->service_counter++;
+               if (state->level == 0)
+                       return DIM_ERR_UNDERFLOW;
+
+               --state->level;
+               ch->done_sw_buffers_number++;
+       }
+
+       return DIM_NO_ERROR;
+}
+
+static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
+{
+       if (buffers_number > ch->done_sw_buffers_number)
+               return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow");
+
+       ch->done_sw_buffers_number -= buffers_number;
+       return true;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* API */
+
+u8 DIM_Startup(void *dim_base_address, u32 mlb_clock)
+{
+       g.dim_is_initialized = false;
+
+       if (!dim_base_address)
+               return DIM_INIT_ERR_DIM_ADDR;
+
+       /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */
+       /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */
+       if (mlb_clock >= 8)
+               return DIM_INIT_ERR_MLB_CLOCK;
+
+       g.dim2 = dim_base_address;
+       g.dbr_map[0] = g.dbr_map[1] = 0;
+
+       dim2_initialize(mlb_clock >= 3, mlb_clock);
+
+       g.dim_is_initialized = true;
+
+       return DIM_NO_ERROR;
+}
+
+void DIM_Shutdown(void)
+{
+       g.dim_is_initialized = false;
+       dim2_cleanup();
+}
+
+bool DIM_GetLockState(void)
+{
+       return dim2_is_mlb_locked();
+}
+
+static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
+                         u16 ch_address, u16 hw_buffer_size)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (!check_channel_address(ch_address))
+               return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+       ch->dbr_size = hw_buffer_size;
+       ch->dbr_addr = alloc_dbr(ch->dbr_size);
+       if (ch->dbr_addr >= DBR_SIZE)
+               return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+       channel_init(ch, ch_address / 2);
+
+       dim2_configure_channel(ch->addr, type, is_tx,
+                              ch->dbr_addr, ch->dbr_size, 0, false);
+
+       return DIM_NO_ERROR;
+}
+
+u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size)
+{
+       return norm_ctrl_async_buffer_size(buf_size);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for isochronous data type
+ * conform to given packet length and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length)
+{
+       if (!check_packet_length(packet_length))
+               return 0;
+
+       return norm_isoc_buffer_size(buf_size, packet_length);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for synchronous data type
+ * conform to given bytes per frame and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame)
+{
+       if (!check_bytes_per_frame(bytes_per_frame))
+               return 0;
+
+       return norm_sync_buffer_size(buf_size, bytes_per_frame);
+}
+
+u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                  u16 max_buffer_size)
+{
+       return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
+                              max_buffer_size * 2);
+}
+
+u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                u16 max_buffer_size)
+{
+       return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
+                              max_buffer_size * 2);
+}
+
+u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+               u16 packet_length)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (!check_channel_address(ch_address))
+               return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+       if (!check_packet_length(packet_length))
+               return DIM_ERR_BAD_CONFIG;
+
+       ch->dbr_size = packet_length * ISOC_DBR_FACTOR;
+       ch->dbr_addr = alloc_dbr(ch->dbr_size);
+       if (ch->dbr_addr >= DBR_SIZE)
+               return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+       isoc_init(ch, ch_address / 2, packet_length);
+
+       dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
+                              ch->dbr_size, packet_length, false);
+
+       return DIM_NO_ERROR;
+}
+
+u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+               u16 bytes_per_frame)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       if (!check_channel_address(ch_address))
+               return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+       if (!check_bytes_per_frame(bytes_per_frame))
+               return DIM_ERR_BAD_CONFIG;
+
+       ch->dbr_size = bytes_per_frame * SYNC_DBR_FACTOR;
+       ch->dbr_addr = alloc_dbr(ch->dbr_size);
+       if (ch->dbr_addr >= DBR_SIZE)
+               return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+       sync_init(ch, ch_address / 2, bytes_per_frame);
+
+       dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
+                              ch->dbr_addr, ch->dbr_size, 0, true);
+
+       return DIM_NO_ERROR;
+}
+
+u8 DIM_DestroyChannel(struct dim_channel *ch)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       dim2_clear_channel(ch->addr);
+       if (ch->dbr_addr < DBR_SIZE)
+               free_dbr(ch->dbr_addr, ch->dbr_size);
+       ch->dbr_addr = DBR_SIZE;
+
+       return DIM_NO_ERROR;
+}
+
+void DIM_ServiceIrq(struct dim_channel *const *channels)
+{
+       bool state_changed;
+
+       if (!g.dim_is_initialized) {
+               dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+                            "DIM is not initialized");
+               return;
+       }
+
+       if (!channels) {
+               dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels");
+               return;
+       }
+
+       /*
+        * Use while-loop and a flag to make sure the age is changed back at least once,
+        * otherwise the interrupt may never come if CPU generates interrupt on changing age.
+        *
+        * This cycle runs not more than number of channels, because service_interrupts
+        * routine doesn't start the channel again.
+        */
+       do {
+               struct dim_channel *const *ch = channels;
+
+               state_changed = false;
+
+               while (*ch) {
+                       state_changed |= channel_service_interrupt(*ch);
+                       ++ch;
+               }
+       } while (state_changed);
+
+       /* clear pending Interrupts */
+       DIMCB_IoWrite(&g.dim2->MS0, 0);
+       DIMCB_IoWrite(&g.dim2->MS1, 0);
+}
+
+u8 DIM_ServiceChannel(struct dim_channel *ch)
+{
+       if (!g.dim_is_initialized || !ch)
+               return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+       return channel_service(ch);
+}
+
+struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
+               struct dim_ch_state_t *state_ptr)
+{
+       if (!ch || !state_ptr)
+               return NULL;
+
+       state_ptr->ready = ch->state.level < 2;
+       state_ptr->done_buffers = ch->done_sw_buffers_number;
+
+       return state_ptr;
+}
+
+bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size)
+{
+       if (!ch)
+               return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel");
+
+       return channel_start(ch, buffer_addr, buffer_size);
+}
+
+bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number)
+{
+       if (!ch)
+               return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel");
+
+       return channel_detach_buffers(ch, buffers_number);
+}
+
+u32 DIM_ReadRegister(u8 register_index)
+{
+       return DIMCB_IoRead((u32 *)g.dim2 + register_index);
+}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h
new file mode 100644 (file)
index 0000000..8929af9
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * dim2_hal.h - DIM2 HAL interface
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef _DIM2_HAL_H
+#define _DIM2_HAL_H
+
+#include <linux/types.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The values below are specified in the hardware specification.
+ * So, they should not be changed until the hardware specification changes.
+ */
+enum mlb_clk_speed {
+       CLK_256FS = 0,
+       CLK_512FS = 1,
+       CLK_1024FS = 2,
+       CLK_2048FS = 3,
+       CLK_3072FS = 4,
+       CLK_4096FS = 5,
+       CLK_6144FS = 6,
+       CLK_8192FS = 7,
+};
+
+struct dim_ch_state_t {
+       bool ready; /* Shows readiness to enqueue next buffer */
+       u16 done_buffers; /* Number of completed buffers */
+};
+
+typedef int atomic_counter_t;
+
+struct int_ch_state {
+       /* changed only in interrupt context */
+       volatile atomic_counter_t request_counter;
+
+       /* changed only in task context */
+       volatile atomic_counter_t service_counter;
+
+       u8 idx1;
+       u8 idx2;
+       u8 level; /* [0..2], buffering level */
+};
+
+struct dim_channel {
+       struct int_ch_state state;
+       u8 addr;
+       u16 dbr_addr;
+       u16 dbr_size;
+       u16 packet_length; /*< Isochronous packet length in bytes. */
+       u16 bytes_per_frame; /*< Synchronous bytes per frame. */
+       u16 done_sw_buffers_number; /*< Done software buffers number. */
+};
+
+
+u8 DIM_Startup(void *dim_base_address, u32 mlb_clock);
+
+void DIM_Shutdown(void);
+
+bool DIM_GetLockState(void);
+
+u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size);
+
+u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length);
+
+u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame);
+
+u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                  u16 max_buffer_size);
+
+u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+                u16 max_buffer_size);
+
+u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+               u16 packet_length);
+
+u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+               u16 bytes_per_frame);
+
+u8 DIM_DestroyChannel(struct dim_channel *ch);
+
+void DIM_ServiceIrq(struct dim_channel *const *channels);
+
+u8 DIM_ServiceChannel(struct dim_channel *ch);
+
+struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
+               struct dim_ch_state_t *dim_ch_state_ptr);
+
+bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr,
+                      u16 buffer_size);
+
+bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number);
+
+u32 DIM_ReadRegister(u8 register_index);
+
+
+u32 DIMCB_IoRead(u32 *ptr32);
+
+void DIMCB_IoWrite(u32 *ptr32, u32 value);
+
+void DIMCB_OnError(u8 error_id, const char *error_message);
+
+void DIMCB_OnFail(const char *filename, int linenum);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DIM2_HAL_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
new file mode 100644 (file)
index 0000000..6a5a3a2
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+
+#include <mostcore.h>
+#include <networking.h>
+#include "dim2_hal.h"
+#include "dim2_hdm.h"
+#include "dim2_errors.h"
+#include "dim2_sysfs.h"
+
+#define DMA_CHANNELS (32 - 1)  /* channel 0 is a system channel */
+
+#define MAX_BUFFERS_PACKET      32
+#define MAX_BUFFERS_STREAMING   32
+#define MAX_BUF_SIZE_PACKET     2048
+#define MAX_BUF_SIZE_STREAMING  (8*1024)
+
+/* command line parameter to select clock speed */
+static char *clock_speed;
+module_param(clock_speed, charp, 0);
+MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed");
+
+/*
+ * #############################################################################
+ *
+ * The define below activates an utility function used by HAL-simu
+ * for calling DIM interrupt handler.
+ * It is used only for TEST PURPOSE and shall be commented before release.
+ *
+ * #############################################################################
+ */
+/* #define ENABLE_HDM_TEST */
+
+static DEFINE_SPINLOCK(dim_lock);
+
+static void dim2_tasklet_fn(unsigned long data);
+static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0);
+
+/**
+ * struct hdm_channel - private structure to keep channel specific data
+ * @is_initialized: identifier to know whether the channel is initialized
+ * @ch: HAL specific channel data
+ * @pending_list: list to keep MBO's before starting transfer
+ * @started_list: list to keep MBO's after starting transfer
+ * @direction: channel direction (TX or RX)
+ * @data_type: channel data type
+ */
+struct hdm_channel {
+       char name[sizeof "caNNN"];
+       bool is_initialized;
+       struct dim_channel ch;
+       struct list_head pending_list;  /* before DIM_EnqueueBuffer() */
+       struct list_head started_list;  /* after DIM_EnqueueBuffer() */
+       enum most_channel_direction direction;
+       enum most_channel_data_type data_type;
+};
+
+/**
+ * struct dim2_hdm - private structure to keep interface specific data
+ * @hch: an array of channel specific data
+ * @most_iface: most interface structure
+ * @capabilities: an array of channel capability data
+ * @io_base: I/O register base address
+ * @irq_ahb0: dim2 AHB0 irq number
+ * @clk_speed: user selectable (through command line parameter) clock speed
+ * @netinfo_task: thread to deliver network status
+ * @netinfo_waitq: waitq for the thread to sleep
+ * @deliver_netinfo: to identify whether network status received
+ * @mac_addrs: INIC mac address
+ * @link_state: network link state
+ * @atx_idx: index of async tx channel
+ */
+struct dim2_hdm {
+       struct hdm_channel hch[DMA_CHANNELS];
+       struct most_channel_capability capabilities[DMA_CHANNELS];
+       struct most_interface most_iface;
+       char name[16 + sizeof "dim2-"];
+       void *io_base;
+       unsigned int irq_ahb0;
+       int clk_speed;
+       struct task_struct *netinfo_task;
+       wait_queue_head_t netinfo_waitq;
+       int deliver_netinfo;
+       unsigned char mac_addrs[6];
+       unsigned char link_state;
+       int atx_idx;
+       struct medialb_bus bus;
+};
+
+#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
+
+/* Macro to identify a network status message */
+#define PACKET_IS_NET_INFO(p)  \
+       (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \
+        ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A))
+
+#if defined(ENABLE_HDM_TEST)
+static struct dim2_hdm *test_dev;
+#endif
+
+bool dim2_sysfs_get_state_cb(void)
+{
+       bool state;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       state = DIM_GetLockState();
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       return state;
+}
+
+/**
+ * DIMCB_IoRead - callback from HAL to read an I/O register
+ * @ptr32: register address
+ */
+u32 DIMCB_IoRead(u32 *ptr32)
+{
+       return __raw_readl(ptr32);
+}
+
+/**
+ * DIMCB_IoWrite - callback from HAL to write value to an I/O register
+ * @ptr32: register address
+ * @value: value to write
+ */
+void DIMCB_IoWrite(u32 *ptr32, u32 value)
+{
+       __raw_writel(value, ptr32);
+}
+
+/**
+ * DIMCB_OnError - callback from HAL to report miscommunication between
+ * HDM and HAL
+ * @error_id: Error ID
+ * @error_message: Error message. Some text in a free format
+ */
+void DIMCB_OnError(u8 error_id, const char *error_message)
+{
+       pr_err("DIMCB_OnError: error_id - %d, error_message - %s\n", error_id,
+              error_message);
+}
+
+/**
+ * DIMCB_OnFail - callback from HAL to report unrecoverable errors
+ * @filename: Source file where the error happened
+ * @linenum: Line number of the file where the error happened
+ */
+void DIMCB_OnFail(const char *filename, int linenum)
+{
+       pr_err("DIMCB_OnFail: file - %s, line no. - %d\n", filename, linenum);
+}
+
+/**
+ * startup_dim - initialize the dim2 interface
+ * @pdev: platform device
+ *
+ * Get the value of command line parameter "clock_speed" if given or use the
+ * default value, enable the clock and PLL, and initialize the dim2 interface.
+ */
+static int startup_dim(struct platform_device *pdev)
+{
+       struct dim2_hdm *dev = platform_get_drvdata(pdev);
+       struct dim2_platform_data *pdata = pdev->dev.platform_data;
+       u8 hal_ret;
+
+       dev->clk_speed = -1;
+
+       if (clock_speed) {
+               if (!strcmp(clock_speed, "256fs"))
+                       dev->clk_speed = CLK_256FS;
+               else if (!strcmp(clock_speed, "512fs"))
+                       dev->clk_speed = CLK_512FS;
+               else if (!strcmp(clock_speed, "1024fs"))
+                       dev->clk_speed = CLK_1024FS;
+               else if (!strcmp(clock_speed, "2048fs"))
+                       dev->clk_speed = CLK_2048FS;
+               else if (!strcmp(clock_speed, "3072fs"))
+                       dev->clk_speed = CLK_3072FS;
+               else if (!strcmp(clock_speed, "4096fs"))
+                       dev->clk_speed = CLK_4096FS;
+               else if (!strcmp(clock_speed, "6144fs"))
+                       dev->clk_speed = CLK_6144FS;
+               else if (!strcmp(clock_speed, "8192fs"))
+                       dev->clk_speed = CLK_8192FS;
+       }
+
+       if (dev->clk_speed == -1) {
+               pr_info("Bad or missing clock speed parameter,"
+                       " using default value: 3072fs\n");
+               dev->clk_speed = CLK_3072FS;
+       } else
+               pr_info("Selected clock speed: %s\n", clock_speed);
+
+       if (pdata && pdata->init) {
+               int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
+
+               if (ret)
+                       return ret;
+       }
+
+       hal_ret = DIM_Startup(dev->io_base, dev->clk_speed);
+       if (hal_ret != DIM_NO_ERROR) {
+               pr_err("DIM_Startup failed: %d\n", hal_ret);
+               if (pdata && pdata->destroy)
+                       pdata->destroy(pdata);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ * try_start_dim_transfer - try to transfer a buffer on a channel
+ * @hdm_ch: channel specific data
+ *
+ * Transfer a buffer from pending_list if the channel is ready
+ */
+static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
+{
+       u16 buf_size;
+       struct list_head *head = &hdm_ch->pending_list;
+       struct mbo *mbo;
+       unsigned long flags;
+       struct dim_ch_state_t st;
+
+       BUG_ON(hdm_ch == 0);
+       BUG_ON(!hdm_ch->is_initialized);
+
+       spin_lock_irqsave(&dim_lock, flags);
+       if (list_empty(head)) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return -EAGAIN;
+       }
+
+       if (!DIM_GetChannelState(&hdm_ch->ch, &st)->ready) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return -EAGAIN;
+       }
+
+       mbo = list_entry(head->next, struct mbo, list);
+       buf_size = mbo->buffer_length;
+
+       BUG_ON(mbo->bus_address == 0);
+       if (!DIM_EnqueueBuffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
+               list_del(head->next);
+               spin_unlock_irqrestore(&dim_lock, flags);
+               mbo->processed_length = 0;
+               mbo->status = MBO_E_INVAL;
+               mbo->complete(mbo);
+               return -EFAULT;
+       }
+
+       list_move_tail(head->next, &hdm_ch->started_list);
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       return 0;
+}
+
+/**
+ * deliver_netinfo_thread - thread to deliver network status to mostcore
+ * @data: private data
+ *
+ * Wait for network status and deliver it to mostcore once it is received
+ */
+static int deliver_netinfo_thread(void *data)
+{
+       struct dim2_hdm *dev = (struct dim2_hdm *)data;
+
+       while (!kthread_should_stop()) {
+               wait_event_interruptible(dev->netinfo_waitq,
+                                        dev->deliver_netinfo ||
+                                        kthread_should_stop());
+
+               if (dev->deliver_netinfo) {
+                       dev->deliver_netinfo--;
+                       most_deliver_netinfo(&dev->most_iface, dev->link_state,
+                                            dev->mac_addrs);
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * retrieve_netinfo - retrieve network status from received buffer
+ * @dev: private data
+ * @mbo: received MBO
+ *
+ * Parse the message in buffer and get node address, link state, MAC address.
+ * Wake up a thread to deliver this status to mostcore
+ */
+static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo)
+{
+       u8 *data = mbo->virt_address;
+       u8 *mac = dev->mac_addrs;
+
+       pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]);
+       dev->link_state = data[18];
+       pr_info("NIState: %d\n", dev->link_state);
+       memcpy(mac, data + 19, 6);
+       pr_info("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+       dev->deliver_netinfo++;
+       wake_up_interruptible(&dev->netinfo_waitq);
+}
+
+/**
+ * service_done_flag - handle completed buffers
+ * @dev: private data
+ * @ch_idx: channel index
+ *
+ * Return back the completed buffers to mostcore, using completion callback
+ */
+static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
+{
+       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+       struct dim_ch_state_t st;
+       struct list_head *head;
+       struct mbo *mbo;
+       int done_buffers;
+       unsigned long flags;
+       u8 *data;
+
+       BUG_ON(hdm_ch == 0);
+       BUG_ON(!hdm_ch->is_initialized);
+
+       spin_lock_irqsave(&dim_lock, flags);
+
+       done_buffers = DIM_GetChannelState(&hdm_ch->ch, &st)->done_buffers;
+       if (!done_buffers) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return;
+       }
+
+       if (!DIM_DetachBuffers(&hdm_ch->ch, done_buffers)) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       head = &hdm_ch->started_list;
+
+       while (done_buffers) {
+               spin_lock_irqsave(&dim_lock, flags);
+               if (list_empty(head)) {
+                       spin_unlock_irqrestore(&dim_lock, flags);
+                       pr_crit("hard error: started_mbo list is empty "
+                               "whereas DIM2 has sent buffers\n");
+                       break;
+               }
+
+               mbo = list_entry(head->next, struct mbo, list);
+               list_del(head->next);
+               spin_unlock_irqrestore(&dim_lock, flags);
+
+               data = mbo->virt_address;
+
+               if (hdm_ch->data_type == MOST_CH_ASYNC &&
+                   hdm_ch->direction == MOST_CH_RX &&
+                   PACKET_IS_NET_INFO(data)) {
+
+                       retrieve_netinfo(dev, mbo);
+
+                       spin_lock_irqsave(&dim_lock, flags);
+                       list_add_tail(&mbo->list, &hdm_ch->pending_list);
+                       spin_unlock_irqrestore(&dim_lock, flags);
+               } else {
+                       if (hdm_ch->data_type == MOST_CH_CONTROL ||
+                           hdm_ch->data_type == MOST_CH_ASYNC) {
+
+                               u32 const data_size =
+                                       (u32)data[0] * 256 + data[1] + 2;
+
+                               mbo->processed_length =
+                                       min(data_size, (u32)mbo->buffer_length);
+                       } else {
+                               mbo->processed_length = mbo->buffer_length;
+                       }
+                       mbo->status = MBO_SUCCESS;
+                       mbo->complete(mbo);
+               }
+
+               done_buffers--;
+       }
+}
+
+static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
+               struct dim_channel **buffer)
+{
+       int idx = 0;
+       int ch_idx;
+
+       for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+               if (dev->hch[ch_idx].is_initialized)
+                       buffer[idx++] = &dev->hch[ch_idx].ch;
+       }
+       buffer[idx++] = 0;
+
+       return buffer;
+}
+
+/**
+ * dim2_tasklet_fn - tasklet function
+ * @data: private data
+ *
+ * Service each initialized channel, if needed
+ */
+static void dim2_tasklet_fn(unsigned long data)
+{
+       struct dim2_hdm *dev = (struct dim2_hdm *)data;
+       unsigned long flags;
+       int ch_idx;
+
+       for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+               if (!dev->hch[ch_idx].is_initialized)
+                       continue;
+
+               spin_lock_irqsave(&dim_lock, flags);
+               DIM_ServiceChannel(&(dev->hch[ch_idx].ch));
+               spin_unlock_irqrestore(&dim_lock, flags);
+
+               service_done_flag(dev, ch_idx);
+               while (!try_start_dim_transfer(dev->hch + ch_idx))
+                       continue;
+       }
+}
+
+/**
+ * dim2_ahb_isr - interrupt service routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Acknowledge the interrupt and schedule a tasklet to service channels.
+ * Return IRQ_HANDLED.
+ */
+static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
+{
+       struct dim2_hdm *dev = (struct dim2_hdm *)_dev;
+       struct dim_channel *buffer[DMA_CHANNELS + 1];
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       DIM_ServiceIrq(get_active_channels(dev, buffer));
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+#if !defined(ENABLE_HDM_TEST)
+       dim2_tasklet.data = (unsigned long)dev;
+       tasklet_schedule(&dim2_tasklet);
+#else
+       dim2_tasklet_fn((unsigned long)dev);
+#endif
+       return IRQ_HANDLED;
+}
+
+#if defined(ENABLE_HDM_TEST)
+
+/*
+ * Utility function used by HAL-simu for calling DIM interrupt handler.
+ * It is used only for TEST PURPOSE.
+ */
+void raise_dim_interrupt(void)
+{
+       (void)dim2_ahb_isr(0, test_dev);
+}
+#endif
+
+/**
+ * complete_all_mbos - complete MBO's in a list
+ * @head: list head
+ *
+ * Delete all the entries in list and return back MBO's to mostcore using
+ * completion call back.
+ */
+static void complete_all_mbos(struct list_head *head)
+{
+       unsigned long flags;
+       struct mbo *mbo;
+
+       for (;;) {
+               spin_lock_irqsave(&dim_lock, flags);
+               if (list_empty(head)) {
+                       spin_unlock_irqrestore(&dim_lock, flags);
+                       break;
+               }
+
+               mbo = list_entry(head->next, struct mbo, list);
+               list_del(head->next);
+               spin_unlock_irqrestore(&dim_lock, flags);
+
+               mbo->processed_length = 0;
+               mbo->status = MBO_E_CLOSE;
+               mbo->complete(mbo);
+       }
+}
+
+/**
+ * configure_channel - initialize a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Receives configuration information from mostcore and initialize
+ * the corresponding channel. Return 0 on success, negative on failure.
+ */
+static int configure_channel(struct most_interface *most_iface, int ch_idx,
+                            struct most_channel_config *ccfg)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       bool const is_tx = ccfg->direction == MOST_CH_TX;
+       u16 const sub_size = ccfg->subbuffer_size;
+       u16 const buf_size = ccfg->buffer_size;
+       u16 new_size;
+       unsigned long flags;
+       u8 hal_ret;
+       int const ch_addr = ch_idx * 2 + 2;
+       struct hdm_channel *const hdm_ch = dev->hch + ch_idx;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+       if (hdm_ch->is_initialized)
+               return -EPERM;
+
+       switch (ccfg->data_type) {
+       case MOST_CH_CONTROL:
+               new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
+               if (new_size == 0) {
+                       pr_err("%s: too small buffer size\n", hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = DIM_InitControl(&hdm_ch->ch, is_tx, ch_addr, buf_size);
+               break;
+       case MOST_CH_ASYNC:
+               new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
+               if (new_size == 0) {
+                       pr_err("%s: too small buffer size\n", hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = DIM_InitAsync(&hdm_ch->ch, is_tx, ch_addr, buf_size);
+               break;
+       case MOST_CH_ISOC_AVP:
+               new_size = DIM_NormIsocBufferSize(buf_size, sub_size);
+               if (new_size == 0) {
+                       pr_err("%s: invalid sub-buffer size or "
+                              "too small buffer size\n", hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = DIM_InitIsoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+               break;
+       case MOST_CH_SYNC:
+               new_size = DIM_NormSyncBufferSize(buf_size, sub_size);
+               if (new_size == 0) {
+                       pr_err("%s: invalid sub-buffer size or "
+                              "too small buffer size\n", hdm_ch->name);
+                       return -EINVAL;
+               }
+               ccfg->buffer_size = new_size;
+               if (new_size != buf_size)
+                       pr_warn("%s: fixed buffer size (%d -> %d)\n",
+                               hdm_ch->name, buf_size, new_size);
+               spin_lock_irqsave(&dim_lock, flags);
+               hal_ret = DIM_InitSync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+               break;
+       default:
+               pr_err("%s: configure failed, bad channel type: %d\n",
+                      hdm_ch->name, ccfg->data_type);
+               return -EINVAL;
+       }
+
+       if (hal_ret != DIM_NO_ERROR) {
+               spin_unlock_irqrestore(&dim_lock, flags);
+               pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n",
+                      hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx);
+               return -ENODEV;
+       }
+
+       hdm_ch->data_type = ccfg->data_type;
+       hdm_ch->direction = ccfg->direction;
+       hdm_ch->is_initialized = true;
+
+       if (hdm_ch->data_type == MOST_CH_ASYNC &&
+           hdm_ch->direction == MOST_CH_TX &&
+           dev->atx_idx < 0)
+               dev->atx_idx = ch_idx;
+
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       return 0;
+}
+
+/**
+ * enqueue - enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Push the buffer into pending_list and try to transfer one buffer from
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int enqueue(struct most_interface *most_iface, int ch_idx,
+                  struct mbo *mbo)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+       unsigned long flags;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+       if (!hdm_ch->is_initialized)
+               return -EPERM;
+
+       if (mbo->bus_address == 0)
+               return -EFAULT;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       list_add_tail(&mbo->list, &hdm_ch->pending_list);
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       (void)try_start_dim_transfer(hdm_ch);
+
+       return 0;
+}
+
+/**
+ * request_netinfo - triggers retrieving of network info
+ * @iface: pointer to the interface
+ * @channel_id: corresponding channel ID
+ *
+ * Send a command to INIC which triggers retrieving of network info by means of
+ * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
+ */
+static void request_netinfo(struct most_interface *most_iface, int ch_idx)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       struct mbo *mbo;
+       u8 *data;
+
+       if (dev->atx_idx < 0) {
+               pr_err("Async Tx Not initialized\n");
+               return;
+       }
+
+       mbo = most_get_mbo(&dev->most_iface, dev->atx_idx);
+       if (!mbo)
+               return;
+
+       mbo->buffer_length = 5;
+
+       data = mbo->virt_address;
+
+       data[0] = 0x00; /* PML High byte */
+       data[1] = 0x03; /* PML Low byte */
+       data[2] = 0x02; /* PMHL */
+       data[3] = 0x08; /* FPH */
+       data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */
+
+       most_submit_mbo(mbo);
+}
+
+/**
+ * poison_channel - poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Destroy a channel and complete all the buffers in both started_list &
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int poison_channel(struct most_interface *most_iface, int ch_idx)
+{
+       struct dim2_hdm *dev = iface_to_hdm(most_iface);
+       struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+       unsigned long flags;
+       u8 hal_ret;
+       int ret = 0;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+       if (!hdm_ch->is_initialized)
+               return -EPERM;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       hal_ret = DIM_DestroyChannel(&hdm_ch->ch);
+       hdm_ch->is_initialized = false;
+       if (ch_idx == dev->atx_idx)
+               dev->atx_idx = -1;
+       spin_unlock_irqrestore(&dim_lock, flags);
+       if (hal_ret != DIM_NO_ERROR) {
+               pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
+               ret = -EFAULT;
+       }
+
+       complete_all_mbos(&hdm_ch->started_list);
+       complete_all_mbos(&hdm_ch->pending_list);
+
+       return ret;
+}
+
+/*
+ * dim2_probe - dim2 probe handler
+ * @pdev: platform device structure
+ *
+ * Register the dim2 interface with mostcore and initialize it.
+ * Return 0 on success, negative on failure.
+ */
+static int dim2_probe(struct platform_device *pdev)
+{
+       struct dim2_hdm *dev;
+       struct resource *res;
+       int ret, i;
+       struct kobject *kobj;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->atx_idx = -1;
+
+       platform_set_drvdata(pdev, dev);
+#if defined(ENABLE_HDM_TEST)
+       test_dev = dev;
+#else
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               pr_err("no memory region defined\n");
+               ret = -ENOENT;
+               goto err_free_dev;
+       }
+
+       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+               pr_err("failed to request mem region\n");
+               ret = -EBUSY;
+               goto err_free_dev;
+       }
+
+       dev->io_base = ioremap(res->start, resource_size(res));
+       if (!dev->io_base) {
+               pr_err("failed to ioremap\n");
+               ret = -ENOMEM;
+               goto err_release_mem;
+       }
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               pr_err("failed to get irq\n");
+               goto err_unmap_io;
+       }
+       dev->irq_ahb0 = ret;
+
+       ret = request_irq(dev->irq_ahb0, dim2_ahb_isr, 0, "mlb_ahb0", dev);
+       if (ret) {
+               pr_err("failed to request IRQ: %d, err: %d\n", dev->irq_ahb0, ret);
+               goto err_unmap_io;
+       }
+#endif
+       init_waitqueue_head(&dev->netinfo_waitq);
+       dev->deliver_netinfo = 0;
+       dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev,
+                                       "dim2_netinfo");
+       if (IS_ERR(dev->netinfo_task)) {
+               ret = PTR_ERR(dev->netinfo_task);
+               goto err_free_irq;
+       }
+
+       for (i = 0; i < DMA_CHANNELS; i++) {
+               struct most_channel_capability *cap = dev->capabilities + i;
+               struct hdm_channel *hdm_ch = dev->hch + i;
+
+               INIT_LIST_HEAD(&hdm_ch->pending_list);
+               INIT_LIST_HEAD(&hdm_ch->started_list);
+               hdm_ch->is_initialized = false;
+               snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2);
+
+               cap->name_suffix = hdm_ch->name;
+               cap->direction = MOST_CH_RX | MOST_CH_TX;
+               cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+                                MOST_CH_ISOC_AVP | MOST_CH_SYNC;
+               cap->num_buffers_packet = MAX_BUFFERS_PACKET;
+               cap->buffer_size_packet = MAX_BUF_SIZE_PACKET;
+               cap->num_buffers_streaming = MAX_BUFFERS_STREAMING;
+               cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING;
+       }
+
+       {
+               const char *fmt;
+
+               if (sizeof(res->start) == sizeof(long long))
+                       fmt = "dim2-%016llx";
+               else if (sizeof(res->start) == sizeof(long))
+                       fmt = "dim2-%016lx";
+               else
+                       fmt = "dim2-%016x";
+
+               snprintf(dev->name, sizeof(dev->name), fmt, res->start);
+       }
+
+       dev->most_iface.interface = ITYPE_MEDIALB_DIM2;
+       dev->most_iface.description = dev->name;
+       dev->most_iface.num_channels = DMA_CHANNELS;
+       dev->most_iface.channel_vector = dev->capabilities;
+       dev->most_iface.configure = configure_channel;
+       dev->most_iface.enqueue = enqueue;
+       dev->most_iface.poison_channel = poison_channel;
+       dev->most_iface.request_netinfo = request_netinfo;
+
+       kobj = most_register_interface(&dev->most_iface);
+       if (IS_ERR(kobj)) {
+               ret = PTR_ERR(kobj);
+               pr_err("failed to register MOST interface\n");
+               goto err_stop_thread;
+       }
+
+       ret = dim2_sysfs_probe(&dev->bus, kobj);
+       if (ret)
+               goto err_unreg_iface;
+
+       ret = startup_dim(pdev);
+       if (ret) {
+               pr_err("failed to initialize DIM2\n");
+               goto err_destroy_bus;
+       }
+
+       return 0;
+
+err_destroy_bus:
+       dim2_sysfs_destroy(&dev->bus);
+err_unreg_iface:
+       most_deregister_interface(&dev->most_iface);
+err_stop_thread:
+       kthread_stop(dev->netinfo_task);
+err_free_irq:
+#if !defined(ENABLE_HDM_TEST)
+       free_irq(dev->irq_ahb0, dev);
+err_unmap_io:
+       iounmap(dev->io_base);
+err_release_mem:
+       release_mem_region(res->start, resource_size(res));
+err_free_dev:
+#endif
+       kfree(dev);
+
+       return ret;
+}
+
+/**
+ * dim2_remove - dim2 remove handler
+ * @pdev: platform device structure
+ *
+ * Unregister the interface from mostcore
+ */
+static int dim2_remove(struct platform_device *pdev)
+{
+       struct dim2_hdm *dev = platform_get_drvdata(pdev);
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct dim2_platform_data *pdata = pdev->dev.platform_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dim_lock, flags);
+       DIM_Shutdown();
+       spin_unlock_irqrestore(&dim_lock, flags);
+
+       if (pdata && pdata->destroy)
+               pdata->destroy(pdata);
+
+       dim2_sysfs_destroy(&dev->bus);
+       most_deregister_interface(&dev->most_iface);
+       kthread_stop(dev->netinfo_task);
+#if !defined(ENABLE_HDM_TEST)
+       free_irq(dev->irq_ahb0, dev);
+       iounmap(dev->io_base);
+       release_mem_region(res->start, resource_size(res));
+#endif
+       kfree(dev);
+       platform_set_drvdata(pdev, NULL);
+
+       /*
+        * break link to local platform_device_id struct
+        * to prevent crash by unload platform device module
+        */
+       pdev->id_entry = 0;
+
+       return 0;
+}
+
+static struct platform_device_id dim2_id[] = {
+       { "medialb_dim2" },
+       { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(platform, dim2_id);
+
+static struct platform_driver dim2_driver = {
+       .probe = dim2_probe,
+       .remove = dim2_remove,
+       .id_table = dim2_id,
+       .driver = {
+               .name = "hdm_dim2",
+               .owner = THIS_MODULE,
+       },
+};
+
+/**
+ * dim2_hdm_init - Driver Registration Routine
+ */
+static int __init dim2_hdm_init(void)
+{
+       pr_info("dim2_hdm_init()\n");
+       return platform_driver_register(&dim2_driver);
+}
+
+/**
+ * dim2_hdm_exit - Driver Cleanup Routine
+ **/
+static void __exit dim2_hdm_exit(void)
+{
+       pr_info("dim2_hdm_exit()\n");
+       platform_driver_unregister(&dim2_driver);
+}
+
+module_init(dim2_hdm_init);
+module_exit(dim2_hdm_exit);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h
new file mode 100644 (file)
index 0000000..6e68832
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * dim2_hdm.h - MediaLB DIM2 HDM Header
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef DIM2_HDM_H
+#define        DIM2_HDM_H
+
+struct device;
+
+/* platform dependent data for dim2 interface */
+struct dim2_platform_data {
+       int (*init)(struct dim2_platform_data *pd, void *io_base, int clk_speed);
+       void (*destroy)(struct dim2_platform_data *pd);
+       void *priv;
+};
+
+#endif /* DIM2_HDM_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
new file mode 100644 (file)
index 0000000..476f66f
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * dim2_reg.h - Definitions for registers of DIM2
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef DIM2_OS62420_H
+#define        DIM2_OS62420_H
+
+#include <linux/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct dim2_regs {
+       /* 0x00 */ u32 MLBC0;
+       /* 0x01 */ u32 rsvd0[1];
+       /* 0x02 */ u32 MLBPC0;
+       /* 0x03 */ u32 MS0;
+       /* 0x04 */ u32 rsvd1[1];
+       /* 0x05 */ u32 MS1;
+       /* 0x06 */ u32 rsvd2[2];
+       /* 0x08 */ u32 MSS;
+       /* 0x09 */ u32 MSD;
+       /* 0x0A */ u32 rsvd3[1];
+       /* 0x0B */ u32 MIEN;
+       /* 0x0C */ u32 rsvd4[1];
+       /* 0x0D */ u32 MLBPC2;
+       /* 0x0E */ u32 MLBPC1;
+       /* 0x0F */ u32 MLBC1;
+       /* 0x10 */ u32 rsvd5[0x10];
+       /* 0x20 */ u32 HCTL;
+       /* 0x21 */ u32 rsvd6[1];
+       /* 0x22 */ u32 HCMR0;
+       /* 0x23 */ u32 HCMR1;
+       /* 0x24 */ u32 HCER0;
+       /* 0x25 */ u32 HCER1;
+       /* 0x26 */ u32 HCBR0;
+       /* 0x27 */ u32 HCBR1;
+       /* 0x28 */ u32 rsvd7[8];
+       /* 0x30 */ u32 MDAT0;
+       /* 0x31 */ u32 MDAT1;
+       /* 0x32 */ u32 MDAT2;
+       /* 0x33 */ u32 MDAT3;
+       /* 0x34 */ u32 MDWE0;
+       /* 0x35 */ u32 MDWE1;
+       /* 0x36 */ u32 MDWE2;
+       /* 0x37 */ u32 MDWE3;
+       /* 0x38 */ u32 MCTL;
+       /* 0x39 */ u32 MADR;
+       /* 0x3A */ u32 rsvd8[0xB6];
+       /* 0xF0 */ u32 ACTL;
+       /* 0xF1 */ u32 rsvd9[3];
+       /* 0xF4 */ u32 ACSR0;
+       /* 0xF5 */ u32 ACSR1;
+       /* 0xF6 */ u32 ACMR0;
+       /* 0xF7 */ u32 ACMR1;
+};
+
+
+#define DIM2_MASK(n)  (~((~(u32)0)<<(n)))
+
+enum {
+       MLBC0_MLBLK_BIT = 7,
+
+       MLBC0_MLBPEN_BIT = 5,
+
+       MLBC0_MLBCLK_SHIFT = 2,
+       MLBC0_MLBCLK_VAL_256FS = 0,
+       MLBC0_MLBCLK_VAL_512FS = 1,
+       MLBC0_MLBCLK_VAL_1024FS = 2,
+       MLBC0_MLBCLK_VAL_2048FS = 3,
+
+       MLBC0_FCNT_SHIFT = 15,
+       MLBC0_FCNT_MASK = 7,
+       MLBC0_FCNT_VAL_1FPSB = 0,
+       MLBC0_FCNT_VAL_2FPSB = 1,
+       MLBC0_FCNT_VAL_4FPSB = 2,
+       MLBC0_FCNT_VAL_8FPSB = 3,
+       MLBC0_FCNT_VAL_16FPSB = 4,
+       MLBC0_FCNT_VAL_32FPSB = 5,
+       MLBC0_FCNT_VAL_64FPSB = 6,
+
+       MLBC0_MLBEN_BIT = 0,
+
+       MIEN_CTX_BREAK_BIT = 29,
+       MIEN_CTX_PE_BIT = 28,
+       MIEN_CTX_DONE_BIT = 27,
+
+       MIEN_CRX_BREAK_BIT = 26,
+       MIEN_CRX_PE_BIT = 25,
+       MIEN_CRX_DONE_BIT = 24,
+
+       MIEN_ATX_BREAK_BIT = 22,
+       MIEN_ATX_PE_BIT = 21,
+       MIEN_ATX_DONE_BIT = 20,
+
+       MIEN_ARX_BREAK_BIT = 19,
+       MIEN_ARX_PE_BIT = 18,
+       MIEN_ARX_DONE_BIT = 17,
+
+       MIEN_SYNC_PE_BIT = 16,
+
+       MIEN_ISOC_BUFO_BIT = 1,
+       MIEN_ISOC_PE_BIT = 0,
+
+       MLBC1_NDA_SHIFT = 8,
+       MLBC1_NDA_MASK = 0xFF,
+
+       MLBC1_CLKMERR_BIT = 7,
+       MLBC1_LOCKERR_BIT = 6,
+
+       ACTL_DMA_MODE_BIT = 2,
+       ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
+       ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
+       ACTL_SCE_BIT = 0,
+
+       HCTL_EN_BIT = 15
+};
+
+enum {
+       CDT1_BS_ISOC_SHIFT = 0,
+       CDT1_BS_ISOC_MASK = DIM2_MASK(9),
+
+       CDT3_BD_SHIFT = 0,
+       CDT3_BD_MASK = DIM2_MASK(12),
+       CDT3_BD_ISOC_MASK = DIM2_MASK(13),
+       CDT3_BA_SHIFT = 16,
+
+       ADT0_CE_BIT = 15,
+       ADT0_LE_BIT = 14,
+       ADT0_PG_BIT = 13,
+
+       ADT1_RDY_BIT = 15,
+       ADT1_DNE_BIT = 14,
+       ADT1_ERR_BIT = 13,
+       ADT1_PS_BIT = 12,
+       ADT1_MEP_BIT = 11,
+       ADT1_BD_SHIFT = 0,
+       ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
+       ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
+
+       CAT_MFE_BIT = 14,
+
+       CAT_MT_BIT = 13,
+
+       CAT_RNW_BIT = 12,
+
+       CAT_CE_BIT = 11,
+
+       CAT_CT_SHIFT = 8,
+       CAT_CT_VAL_SYNC = 0,
+       CAT_CT_VAL_CONTROL = 1,
+       CAT_CT_VAL_ASYNC = 2,
+       CAT_CT_VAL_ISOC = 3,
+
+       CAT_CL_SHIFT = 0,
+       CAT_CL_MASK = DIM2_MASK(6)
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DIM2_OS62420_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
new file mode 100644 (file)
index 0000000..8e331a2
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * dim2_sysfs.c - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include "dim2_sysfs.h"
+
+struct bus_attr {
+       struct attribute attr;
+       ssize_t (*show)(struct medialb_bus *bus, char *buf);
+       ssize_t (*store)(struct medialb_bus *bus, const char *buf, size_t count);
+};
+
+static ssize_t state_show(struct medialb_bus *bus, char *buf)
+{
+       bool state = dim2_sysfs_get_state_cb();
+
+       return sprintf(buf, "%s\n", state ? "locked" : "");
+}
+
+static struct bus_attr state_attr = __ATTR_RO(state);
+
+static struct attribute *bus_default_attrs[] = {
+       &state_attr.attr,
+       NULL,
+};
+
+static struct attribute_group bus_attr_group = {
+       .attrs = bus_default_attrs,
+};
+
+static void bus_kobj_release(struct kobject *kobj)
+{
+}
+
+static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
+                                 char *buf)
+{
+       struct medialb_bus *bus =
+               container_of(kobj, struct medialb_bus, kobj_group);
+       struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
+
+       if (!xattr->show)
+               return -EIO;
+
+       return xattr->show(bus, buf);
+}
+
+static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
+                                  const char *buf, size_t count)
+{
+       ssize_t ret;
+       struct medialb_bus *bus =
+               container_of(kobj, struct medialb_bus, kobj_group);
+       struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
+
+       if (!xattr->store)
+               return -EIO;
+
+       ret = xattr->store(bus, buf, count);
+       return ret;
+}
+
+static struct sysfs_ops const bus_kobj_sysfs_ops = {
+       .show = bus_kobj_attr_show,
+       .store = bus_kobj_attr_store,
+};
+
+static struct kobj_type bus_ktype = {
+       .release = bus_kobj_release,
+       .sysfs_ops = &bus_kobj_sysfs_ops,
+};
+
+int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
+{
+       int err;
+
+       kobject_init(&bus->kobj_group, &bus_ktype);
+       err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
+       if (err) {
+               pr_err("kobject_add() failed: %d\n", err);
+               goto err_kobject_add;
+       }
+
+       err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
+       if (err) {
+               pr_err("sysfs_create_group() failed: %d\n", err);
+               goto err_create_group;
+       }
+
+       return 0;
+
+err_create_group:
+       kobject_put(&bus->kobj_group);
+
+err_kobject_add:
+       return err;
+}
+
+void dim2_sysfs_destroy(struct medialb_bus *bus)
+{
+       kobject_put(&bus->kobj_group);
+}
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
new file mode 100644 (file)
index 0000000..e719691
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * dim2_sysfs.h - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#ifndef DIM2_SYSFS_H
+#define        DIM2_SYSFS_H
+
+
+#include <linux/kobject.h>
+
+
+struct medialb_bus {
+       struct kobject kobj_group;
+};
+
+struct dim2_hdm;
+
+int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
+void dim2_sysfs_destroy(struct medialb_bus *bus);
+
+/*
+ * callback,
+ * must deliver MediaLB state as true if locked or false if unlocked
+ */
+bool dim2_sysfs_get_state_cb(void);
+
+
+#endif /* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/hdm-i2c/Kconfig
new file mode 100644 (file)
index 0000000..6fd7983
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# MOST I2C configuration
+#
+
+config HDM_I2C
+       tristate "I2C HDM"
+       depends on I2C
+       ---help---
+         Say Y here if you want to connect via I2C to network tranceiver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hdm_i2c.
diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile
new file mode 100644 (file)
index 0000000..03a4a59
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_HDM_I2C) += hdm_i2c.o
+
+ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
new file mode 100644 (file)
index 0000000..029ded3
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * hdm_i2c.c - Hardware Dependent Module for I2C Interface
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include <mostcore.h>
+
+enum { CH_RX, CH_TX, NUM_CHANNELS };
+
+#define MAX_BUFFERS_CONTROL 32
+#define MAX_BUF_SIZE_CONTROL 256
+
+/**
+ * list_first_mbo - get the first mbo from a list
+ * @ptr:       the list head to take the mbo from.
+ */
+#define list_first_mbo(ptr) \
+       list_first_entry(ptr, struct mbo, list)
+
+
+/* IRQ / Polling option */
+static bool polling_req;
+module_param(polling_req, bool, S_IRUGO);
+MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
+
+/* Polling Rate */
+static int scan_rate = 100;
+module_param(scan_rate, int, 0644);
+MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100");
+
+struct hdm_i2c {
+       bool is_open[NUM_CHANNELS];
+       bool polling_mode;
+       struct most_interface most_iface;
+       struct most_channel_capability capabilities[NUM_CHANNELS];
+       struct i2c_client *client;
+       struct rx {
+               struct delayed_work dwork;
+               wait_queue_head_t waitq;
+               struct list_head list;
+               struct mutex list_mutex;
+       } rx;
+       char name[64];
+};
+
+#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface)
+
+/**
+ * configure_channel - called from MOST core to configure a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Receives configuration information from MOST core and initialize the
+ * corresponding channel.
+ */
+static int configure_channel(struct most_interface *most_iface,
+                            int ch_idx,
+                            struct most_channel_config *channel_config)
+{
+       struct hdm_i2c *dev = to_hdm(most_iface);
+
+       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+       BUG_ON(dev->is_open[ch_idx]);
+
+       if (channel_config->data_type != MOST_CH_CONTROL) {
+               pr_err("bad data type for channel %d\n", ch_idx);
+               return -EPERM;
+       }
+
+       if (channel_config->direction != dev->capabilities[ch_idx].direction) {
+               pr_err("bad direction for channel %d\n", ch_idx);
+               return -EPERM;
+       }
+
+       if (channel_config->direction == MOST_CH_RX) {
+               if (dev->polling_mode)
+                       schedule_delayed_work(&dev->rx.dwork,
+                                             msecs_to_jiffies(MSEC_PER_SEC / 4));
+       }
+       dev->is_open[ch_idx] = true;
+
+       return 0;
+}
+
+/**
+ * enqueue - called from MOST core to enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Transmit the data over I2C if it is a "write" request or push the buffer into
+ * list if it is an "read" request
+ */
+static int enqueue(struct most_interface *most_iface,
+                  int ch_idx, struct mbo *mbo)
+{
+       struct hdm_i2c *dev = to_hdm(most_iface);
+       int ret;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+       BUG_ON(!dev->is_open[ch_idx]);
+
+       if (ch_idx == CH_RX) {
+               /* RX */
+               mutex_lock(&dev->rx.list_mutex);
+               list_add_tail(&mbo->list, &dev->rx.list);
+               mutex_unlock(&dev->rx.list_mutex);
+               wake_up_interruptible(&dev->rx.waitq);
+       } else {
+               /* TX */
+               ret = i2c_master_send(dev->client, mbo->virt_address,
+                                     mbo->buffer_length);
+               if (ret <= 0) {
+                       mbo->processed_length = 0;
+                       mbo->status = MBO_E_INVAL;
+               } else {
+                       mbo->processed_length = mbo->buffer_length;
+                       mbo->status = MBO_SUCCESS;
+               }
+               mbo->complete(mbo);
+       }
+
+       return 0;
+}
+
+/**
+ * poison_channel - called from MOST core to poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * If channel direction is RX, complete the buffers in list with
+ * status MBO_E_CLOSE
+ */
+static int poison_channel(struct most_interface *most_iface,
+                         int ch_idx)
+{
+       struct hdm_i2c *dev = to_hdm(most_iface);
+       struct mbo *mbo;
+
+       BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+       BUG_ON(!dev->is_open[ch_idx]);
+
+       dev->is_open[ch_idx] = false;
+
+       if (ch_idx == CH_RX) {
+               mutex_lock(&dev->rx.list_mutex);
+               while (!list_empty(&dev->rx.list)) {
+                       mbo = list_first_mbo(&dev->rx.list);
+                       list_del(&mbo->list);
+                       mutex_unlock(&dev->rx.list_mutex);
+
+                       mbo->processed_length = 0;
+                       mbo->status = MBO_E_CLOSE;
+                       mbo->complete(mbo);
+
+                       mutex_lock(&dev->rx.list_mutex);
+               }
+               mutex_unlock(&dev->rx.list_mutex);
+               wake_up_interruptible(&dev->rx.waitq);
+       }
+
+       return 0;
+}
+
+static void request_netinfo(struct most_interface *most_iface,
+                           int ch_idx)
+{
+       pr_info("request_netinfo()\n");
+}
+
+static void do_rx_work(struct hdm_i2c *dev)
+{
+       struct mbo *mbo;
+       unsigned char msg[MAX_BUF_SIZE_CONTROL];
+       int ret, ch_idx = CH_RX;
+       uint16_t pml, data_size;
+
+       /* Read PML (2 bytes) */
+       ret = i2c_master_recv(dev->client, msg, 2);
+       if (ret <= 0) {
+               pr_err("Failed to receive PML\n");
+               return;
+       }
+
+       pml = (msg[0] << 8) | msg[1];
+       if (!pml)
+               return;
+
+       data_size = pml + 2;
+
+       /* Read the whole message, including PML */
+       ret = i2c_master_recv(dev->client, msg, data_size);
+       if (ret <= 0) {
+               pr_err("Failed to receive a Port Message\n");
+               return;
+       }
+
+       for (;;) {
+               /* Conditions to wait for: poisoned channel or free buffer
+                  available for reading  */
+               if (wait_event_interruptible(dev->rx.waitq,
+                                            !dev->is_open[ch_idx] ||
+                                            !list_empty(&dev->rx.list))) {
+                       pr_err("wait_event_interruptible() failed\n");
+                       return;
+               }
+
+               if (!dev->is_open[ch_idx])
+                       return;
+
+               mutex_lock(&dev->rx.list_mutex);
+
+               /* list may be empty if poison or remove is called */
+               if (!list_empty(&dev->rx.list))
+                       break;
+
+               mutex_unlock(&dev->rx.list_mutex);
+       }
+
+       mbo = list_first_mbo(&dev->rx.list);
+       list_del(&mbo->list);
+       mutex_unlock(&dev->rx.list_mutex);
+
+       mbo->processed_length = min(data_size, mbo->buffer_length);
+       memcpy(mbo->virt_address, msg, mbo->processed_length);
+       mbo->status = MBO_SUCCESS;
+       mbo->complete(mbo);
+}
+
+/**
+ * pending_rx_work - Read pending messages through I2C
+ * @work: definition of this work item
+ *
+ * Invoked by the Interrupt Service Routine, most_irq_handler()
+ */
+static void pending_rx_work(struct work_struct *work)
+{
+       struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work);
+
+       do_rx_work(dev);
+
+       if (dev->polling_mode) {
+               if (dev->is_open[CH_RX])
+                       schedule_delayed_work(&dev->rx.dwork,
+                                             msecs_to_jiffies(MSEC_PER_SEC
+                                                              / scan_rate));
+       } else
+               enable_irq(dev->client->irq);
+}
+
+/*
+ * most_irq_handler - Interrupt Service Routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Schedules a delayed work
+ *
+ * By default the interrupt line behavior is Active Low. Once an interrupt is
+ * generated by the device, until driver clears the interrupt (by reading
+ * the PMP message), device keeps the interrupt line in low state. Since i2c
+ * read is done in work queue, the interrupt line must be disabled temporarily
+ * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue,
+ * after reading the message.
+ *
+ * Note: If we use the interrupt line in Falling edge mode, there is a
+ * possibility to miss interrupts when ISR is getting executed.
+ *
+ */
+static irqreturn_t most_irq_handler(int irq, void *_dev)
+{
+       struct hdm_i2c *dev = _dev;
+
+       disable_irq_nosync(irq);
+
+       schedule_delayed_work(&dev->rx.dwork, 0);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * i2c_probe - i2c probe handler
+ * @client: i2c client device structure
+ * @id: i2c client device id
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Register the i2c client device as a MOST interface
+ */
+static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       struct hdm_i2c *dev;
+       int ret, i;
+       struct kobject *kobj;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       /* ID format: i2c-<bus>-<address> */
+       snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x",
+                client->adapter->nr, client->addr);
+
+       for (i = 0; i < NUM_CHANNELS; i++) {
+               dev->is_open[i] = false;
+               dev->capabilities[i].data_type = MOST_CH_CONTROL;
+               dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL;
+               dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL;
+       }
+       dev->capabilities[CH_RX].direction = MOST_CH_RX;
+       dev->capabilities[CH_RX].name_suffix = "rx";
+       dev->capabilities[CH_TX].direction = MOST_CH_TX;
+       dev->capabilities[CH_TX].name_suffix = "tx";
+
+       dev->most_iface.interface = ITYPE_I2C;
+       dev->most_iface.description = dev->name;
+       dev->most_iface.num_channels = NUM_CHANNELS;
+       dev->most_iface.channel_vector = dev->capabilities;
+       dev->most_iface.configure = configure_channel;
+       dev->most_iface.enqueue = enqueue;
+       dev->most_iface.poison_channel = poison_channel;
+       dev->most_iface.request_netinfo = request_netinfo;
+
+       INIT_LIST_HEAD(&dev->rx.list);
+       mutex_init(&dev->rx.list_mutex);
+       init_waitqueue_head(&dev->rx.waitq);
+
+       INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work);
+
+       dev->client = client;
+       i2c_set_clientdata(client, dev);
+
+       kobj = most_register_interface(&dev->most_iface);
+       if (IS_ERR(kobj)) {
+               pr_err("Failed to register i2c as a MOST interface\n");
+               kfree(dev);
+               return PTR_ERR(kobj);
+       }
+
+       dev->polling_mode = polling_req || client->irq <= 0;
+       if (!dev->polling_mode) {
+               pr_info("Requesting IRQ: %d\n", client->irq);
+               ret = request_irq(client->irq, most_irq_handler, IRQF_SHARED,
+                                 client->name, dev);
+               if (ret) {
+                       pr_info("IRQ request failed: %d, "
+                               "falling back to polling\n", ret);
+                       dev->polling_mode = true;
+               }
+       }
+
+       if (dev->polling_mode)
+               pr_info("Using polling at rate: %d times/sec\n", scan_rate);
+
+       return 0;
+}
+
+/*
+ * i2c_remove - i2c remove handler
+ * @client: i2c client device structure
+ *
+ * Return 0 on success.
+ *
+ * Unregister the i2c client device as a MOST interface
+ */
+static int i2c_remove(struct i2c_client *client)
+{
+       struct hdm_i2c *dev = i2c_get_clientdata(client);
+       int i;
+
+       if (!dev->polling_mode)
+               free_irq(client->irq, dev);
+
+       most_deregister_interface(&dev->most_iface);
+
+       for (i = 0 ; i < NUM_CHANNELS; i++)
+               if (dev->is_open[i])
+                       poison_channel(&dev->most_iface, i);
+       cancel_delayed_work_sync(&dev->rx.dwork);
+       kfree(dev);
+
+       return 0;
+}
+
+static const struct i2c_device_id i2c_id[] = {
+       { "most_i2c", 0 },
+       { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(i2c, i2c_id);
+
+static struct i2c_driver i2c_driver = {
+       .driver = {
+               .name = "hdm_i2c",
+               .owner = THIS_MODULE,
+       },
+       .probe = i2c_probe,
+       .remove = i2c_remove,
+       .id_table = i2c_id,
+};
+
+/**
+ * hdm_i2c_init - Driver Registration Routine
+ */
+static int __init hdm_i2c_init(void)
+{
+       pr_info("hdm_i2c_init()\n");
+
+       return i2c_add_driver(&i2c_driver);
+}
+
+/**
+ * hdm_i2c_exit - Driver Cleanup Routine
+ **/
+static void __exit hdm_i2c_exit(void)
+{
+       i2c_del_driver(&i2c_driver);
+       pr_info("hdm_i2c_exit()\n");
+}
+
+module_init(hdm_i2c_init);
+module_exit(hdm_i2c_exit);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("I2C Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig
new file mode 100644 (file)
index 0000000..a482c3f
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# MOST USB configuration
+#
+
+config HDM_USB
+       tristate "USB HDM"
+       depends on USB
+       select AIM_NETWORK
+       ---help---
+         Say Y here if you want to connect via USB to network tranceiver.
+         This device driver depends on the networking AIM.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hdm_usb.
diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile
new file mode 100644 (file)
index 0000000..6bbacb4
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_HDM_USB) += hdm_usb.o
+
+ccflags-y += -Idrivers/staging/most/mostcore/
+ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
new file mode 100644 (file)
index 0000000..305303f
--- /dev/null
@@ -0,0 +1,1454 @@
+/*
+ * hdm_usb.c - Hardware dependent module for USB
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include "mostcore.h"
+#include "networking.h"
+
+#define USB_MTU                        512
+#define NO_ISOCHRONOUS_URB     0
+#define AV_PACKETS_PER_XACT    2
+#define BUF_CHAIN_SIZE         0xFFFF
+#define MAX_NUM_ENDPOINTS      30
+#define MAX_SUFFIX_LEN         10
+#define MAX_STRING_LEN         80
+#define MAX_BUF_SIZE           0xFFFF
+#define CEILING(x, y)          (((x) + (y) - 1) / (y))
+
+#define USB_VENDOR_ID_SMSC     0x0424  /* VID: SMSC */
+#define USB_DEV_ID_BRDG                0xC001  /* PID: USB Bridge */
+#define USB_DEV_ID_INIC                0xCF18  /* PID: USB INIC */
+#define HW_RESYNC              0x0000
+/* DRCI Addresses */
+#define DRCI_REG_NI_STATE      0x0100
+#define DRCI_REG_PACKET_BW     0x0101
+#define DRCI_REG_NODE_ADDR     0x0102
+#define DRCI_REG_NODE_POS      0x0103
+#define DRCI_REG_MEP_FILTER    0x0140
+#define DRCI_REG_HASH_TBL0     0x0141
+#define DRCI_REG_HASH_TBL1     0x0142
+#define DRCI_REG_HASH_TBL2     0x0143
+#define DRCI_REG_HASH_TBL3     0x0144
+#define DRCI_REG_HW_ADDR_HI    0x0145
+#define DRCI_REG_HW_ADDR_MI    0x0146
+#define DRCI_REG_HW_ADDR_LO    0x0147
+#define DRCI_READ_REQ          0xA0
+#define DRCI_WRITE_REQ         0xA1
+
+/**
+ * struct buf_anchor - used to create a list of pending URBs
+ * @urb: pointer to USB request block
+ * @clear_work_obj:
+ * @list: linked list
+ * @urb_completion:
+ */
+struct buf_anchor {
+       struct urb *urb;
+       struct work_struct clear_work_obj;
+       struct list_head list;
+       struct completion urb_compl;
+};
+#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj)
+
+/**
+ * struct most_dci_obj - Direct Communication Interface
+ * @kobj:position in sysfs
+ * @usb_device: pointer to the usb device
+ */
+struct most_dci_obj {
+       struct kobject kobj;
+       struct usb_device *usb_device;
+};
+#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
+
+/**
+ * struct most_dev - holds all usb interface specific stuff
+ * @parent: parent object in sysfs
+ * @usb_device: pointer to usb device
+ * @iface: hardware interface
+ * @cap: channel capabilities
+ * @conf: channel configuration
+ * @dci: direct communication interface of hardware
+ * @hw_addr: MAC address of hardware
+ * @ep_address: endpoint address table
+ * @link_stat: link status of hardware
+ * @description: device description
+ * @suffix: suffix for channel name
+ * @anchor_list_lock: locks list access
+ * @padding_active: indicates channel uses padding
+ * @is_channel_healthy: health status table of each channel
+ * @anchor_list: list of anchored items
+ * @io_mutex: synchronize I/O with disconnect
+ * @link_stat_timer: timer for link status reports
+ * @poll_work_obj: work for polling link status
+ */
+struct most_dev {
+       struct kobject *parent;
+       struct usb_device *usb_device;
+       struct most_interface iface;
+       struct most_channel_capability *cap;
+       struct most_channel_config *conf;
+       struct most_dci_obj *dci;
+       u8 hw_addr[6];
+       u8 *ep_address;
+       u16 link_stat;
+       char description[MAX_STRING_LEN];
+       char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
+       spinlock_t anchor_list_lock[MAX_NUM_ENDPOINTS];
+       bool padding_active[MAX_NUM_ENDPOINTS];
+       bool is_channel_healthy[MAX_NUM_ENDPOINTS];
+       struct list_head *anchor_list;
+       struct mutex io_mutex;
+       struct timer_list link_stat_timer;
+       struct work_struct poll_work_obj;
+};
+#define to_mdev(d) container_of(d, struct most_dev, iface)
+#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
+
+static struct workqueue_struct *schedule_usb_work;
+static void wq_clear_halt(struct work_struct *wq_obj);
+static void wq_netinfo(struct work_struct *wq_obj);
+
+/**
+ * trigger_resync_vr - Vendor request to trigger HW re-sync mechanism
+ * @dev: usb device
+ *
+ */
+static void trigger_resync_vr(struct usb_device *dev)
+{
+       int retval;
+       u8 request_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+       int *data = kzalloc(sizeof(*data), GFP_KERNEL);
+
+       if (!data)
+               goto error;
+       *data = HW_RESYNC;
+       retval = usb_control_msg(dev,
+                                usb_sndctrlpipe(dev, 0),
+                                0,
+                                request_type,
+                                0,
+                                0,
+                                data,
+                                0,
+                                5 * HZ);
+       kfree(data);
+       if (retval >= 0)
+               return;
+error:
+       dev_err(&dev->dev, "Vendor request \"stall\" failed\n");
+}
+
+/**
+ * drci_rd_reg - read a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @buf: buffer to store data
+ *
+ * This is reads data from INIC's direct register communication interface
+ */
+static inline int drci_rd_reg(struct usb_device *dev, u16 reg, void *buf)
+{
+       return usb_control_msg(dev,
+                              usb_rcvctrlpipe(dev, 0),
+                              DRCI_READ_REQ,
+                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              0x0000,
+                              reg,
+                              buf,
+                              2,
+                              5 * HZ);
+}
+
+/**
+ * drci_wr_reg - write a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @data: data to write
+ *
+ * This is writes data to INIC's direct register communication interface
+ */
+static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
+{
+       return usb_control_msg(dev,
+                              usb_sndctrlpipe(dev, 0),
+                              DRCI_WRITE_REQ,
+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              data,
+                              reg,
+                              NULL,
+                              0,
+                              5 * HZ);
+}
+
+/**
+ * free_anchored_buffers - free device's anchored items
+ * @mdev: the device
+ * @channel: channel ID
+ */
+static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel)
+{
+       struct mbo *mbo;
+       struct buf_anchor *anchor, *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+       list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], list) {
+               struct urb *urb = anchor->urb;
+
+               spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+               if (likely(urb)) {
+                       mbo = urb->context;
+                       if (!irqs_disabled()) {
+                               usb_kill_urb(urb);
+                       } else {
+                               usb_unlink_urb(urb);
+                               wait_for_completion(&anchor->urb_compl);
+                       }
+                       if ((mbo) && (mbo->complete)) {
+                               mbo->status = MBO_E_CLOSE;
+                               mbo->processed_length = 0;
+                               mbo->complete(mbo);
+                       }
+                       usb_free_urb(urb);
+               }
+               spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+               list_del(&anchor->list);
+               kfree(anchor);
+       }
+       spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+}
+
+/**
+ * get_stream_frame_size - calculate frame size of current configuration
+ * @cfg: channel configuration
+ */
+static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
+{
+       unsigned int frame_size = 0;
+       unsigned int sub_size = cfg->subbuffer_size;
+
+       if (!sub_size) {
+               pr_warn("Misconfig: Subbuffer size zero.\n");
+               return frame_size;
+       }
+       switch (cfg->data_type) {
+       case MOST_CH_ISOC_AVP:
+               frame_size = AV_PACKETS_PER_XACT * sub_size;
+               break;
+       case MOST_CH_SYNC:
+               if (cfg->packets_per_xact == 0) {
+                       pr_warn("Misconfig: Packets per XACT zero\n");
+                       frame_size = 0;
+               } else if (cfg->packets_per_xact == 0xFF)
+                       frame_size = (USB_MTU / sub_size) * sub_size;
+               else
+                       frame_size = cfg->packets_per_xact * sub_size;
+               break;
+       default:
+               pr_warn("Query frame size of non-streaming channel\n");
+               break;
+       }
+       return frame_size;
+}
+
+/**
+ * hdm_poison_channel - mark buffers of this channel as invalid
+ * @iface: pointer to the interface
+ * @channel: channel ID
+ *
+ * This unlinks all URBs submitted to the HCD,
+ * calls the associated completion function of the core and removes
+ * them from the list.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int hdm_poison_channel(struct most_interface *iface, int channel)
+{
+       struct most_dev *mdev;
+
+       mdev = to_mdev(iface);
+       if (unlikely(!iface)) {
+               dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n");
+               return -EIO;
+       }
+       if (unlikely((channel < 0) || (channel >= iface->num_channels))) {
+               dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
+               return -ECHRNG;
+       }
+
+       mdev->is_channel_healthy[channel] = false;
+
+       mutex_lock(&mdev->io_mutex);
+       free_anchored_buffers(mdev, channel);
+       if (mdev->padding_active[channel] == true)
+               mdev->padding_active[channel] = false;
+
+       if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
+               del_timer_sync(&mdev->link_stat_timer);
+               cancel_work_sync(&mdev->poll_work_obj);
+       }
+       mutex_unlock(&mdev->io_mutex);
+       return 0;
+}
+
+/**
+ * hdm_add_padding - add padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This inserts the INIC hardware specific padding bytes into a streaming
+ * channel's buffer
+ */
+static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
+{
+       struct most_channel_config *conf = &mdev->conf[channel];
+       unsigned int j, num_frames, frame_size;
+       u16 rd_addr, wr_addr;
+
+       frame_size = get_stream_frame_size(conf);
+       if (!frame_size)
+               return -EIO;
+       num_frames = mbo->buffer_length / frame_size;
+
+       if (num_frames < 1) {
+               dev_err(&mdev->usb_device->dev,
+                       "Missed minimal transfer unit.\n");
+               return -EIO;
+       }
+
+       for (j = 1; j < num_frames; j++) {
+               wr_addr = (num_frames - j) * USB_MTU;
+               rd_addr = (num_frames - j) * frame_size;
+               memmove(mbo->virt_address + wr_addr,
+                       mbo->virt_address + rd_addr,
+                       frame_size);
+       }
+       mbo->buffer_length = num_frames * USB_MTU;
+       return 0;
+}
+
+/**
+ * hdm_remove_padding - remove padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This takes the INIC hardware specific padding bytes off a streaming
+ * channel's buffer.
+ */
+static int hdm_remove_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
+{
+       unsigned int j, num_frames, frame_size;
+       struct most_channel_config *const conf = &mdev->conf[channel];
+
+       frame_size = get_stream_frame_size(conf);
+       if (!frame_size)
+               return -EIO;
+       num_frames = mbo->processed_length / USB_MTU;
+
+       for (j = 1; j < num_frames; j++)
+               memmove(mbo->virt_address + frame_size * j,
+                       mbo->virt_address + USB_MTU * j,
+                       frame_size);
+
+       mbo->processed_length = frame_size * num_frames;
+       return 0;
+}
+
+/**
+ * hdm_write_completion - completion function for submitted Tx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before, it is immediately freed. On any other error the MBO
+ * transfer flag is set. On success it frees allocated resources and calls
+ * the completion function.
+ *
+ * Context: interrupt!
+ */
+static void hdm_write_completion(struct urb *urb)
+{
+       struct mbo *mbo;
+       struct buf_anchor *anchor;
+       struct most_dev *mdev;
+       struct device *dev;
+       unsigned int channel;
+       unsigned long flags;
+
+       mbo = urb->context;
+       anchor = mbo->priv;
+       mdev = to_mdev(mbo->ifp);
+       channel = mbo->hdm_channel_id;
+       dev = &mdev->usb_device->dev;
+
+       if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) ||
+           (mdev->is_channel_healthy[channel] == false)) {
+               complete(&anchor->urb_compl);
+               return;
+       }
+
+       if (unlikely(urb->status && !(urb->status == -ENOENT ||
+                                     urb->status == -ECONNRESET ||
+                                     urb->status == -ESHUTDOWN))) {
+               mbo->processed_length = 0;
+               switch (urb->status) {
+               case -EPIPE:
+                       dev_warn(dev, "Broken OUT pipe detected\n");
+                       most_stop_enqueue(&mdev->iface, channel);
+                       mbo->status = MBO_E_INVAL;
+                       usb_unlink_urb(urb);
+                       INIT_WORK(&anchor->clear_work_obj, wq_clear_halt);
+                       queue_work(schedule_usb_work, &anchor->clear_work_obj);
+                       return;
+               case -ENODEV:
+               case -EPROTO:
+                       mbo->status = MBO_E_CLOSE;
+                       break;
+               default:
+                       mbo->status = MBO_E_INVAL;
+                       break;
+               }
+       } else {
+               mbo->status = MBO_SUCCESS;
+               mbo->processed_length = urb->actual_length;
+       }
+
+       spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+       list_del(&anchor->list);
+       spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+       kfree(anchor);
+
+       if (likely(mbo->complete))
+               mbo->complete(mbo);
+       usb_free_urb(urb);
+}
+
+/**
+ * hdm_read_completion - completion funciton for submitted Rx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before it is immediately freed. On any other error the MBO transfer
+ * flag is set. On success it frees allocated resources, removes
+ * padding bytes -if necessary- and calls the completion function.
+ *
+ * Context: interrupt!
+ *
+ * **************************************************************************
+ *                   Error codes returned by in urb->status
+ *                   or in iso_frame_desc[n].status (for ISO)
+ * *************************************************************************
+ *
+ * USB device drivers may only test urb status values in completion handlers.
+ * This is because otherwise there would be a race between HCDs updating
+ * these values on one CPU, and device drivers testing them on another CPU.
+ *
+ * A transfer's actual_length may be positive even when an error has been
+ * reported.  That's because transfers often involve several packets, so that
+ * one or more packets could finish before an error stops further endpoint I/O.
+ *
+ * For isochronous URBs, the urb status value is non-zero only if the URB is
+ * unlinked, the device is removed, the host controller is disabled or the total
+ * transferred length is less than the requested length and the URB_SHORT_NOT_OK
+ * flag is set.  Completion handlers for isochronous URBs should only see
+ * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
+ * Individual frame descriptor status fields may report more status codes.
+ *
+ *
+ * 0                   Transfer completed successfully
+ *
+ * -ENOENT             URB was synchronously unlinked by usb_unlink_urb
+ *
+ * -EINPROGRESS                URB still pending, no results yet
+ *                     (That is, if drivers see this it's a bug.)
+ *
+ * -EPROTO (*, **)     a) bitstuff error
+ *                     b) no response packet received within the
+ *                        prescribed bus turn-around time
+ *                     c) unknown USB error
+ *
+ * -EILSEQ (*, **)     a) CRC mismatch
+ *                     b) no response packet received within the
+ *                        prescribed bus turn-around time
+ *                     c) unknown USB error
+ *
+ *                     Note that often the controller hardware does not
+ *                     distinguish among cases a), b), and c), so a
+ *                     driver cannot tell whether there was a protocol
+ *                     error, a failure to respond (often caused by
+ *                     device disconnect), or some other fault.
+ *
+ * -ETIME (**)         No response packet received within the prescribed
+ *                     bus turn-around time.  This error may instead be
+ *                     reported as -EPROTO or -EILSEQ.
+ *
+ * -ETIMEDOUT          Synchronous USB message functions use this code
+ *                     to indicate timeout expired before the transfer
+ *                     completed, and no other error was reported by HC.
+ *
+ * -EPIPE (**)         Endpoint stalled.  For non-control endpoints,
+ *                     reset this status with usb_clear_halt().
+ *
+ * -ECOMM              During an IN transfer, the host controller
+ *                     received data from an endpoint faster than it
+ *                     could be written to system memory
+ *
+ * -ENOSR              During an OUT transfer, the host controller
+ *                     could not retrieve data from system memory fast
+ *                     enough to keep up with the USB data rate
+ *
+ * -EOVERFLOW (*)      The amount of data returned by the endpoint was
+ *                     greater than either the max packet size of the
+ *                     endpoint or the remaining buffer size.  "Babble".
+ *
+ * -EREMOTEIO          The data read from the endpoint did not fill the
+ *                     specified buffer, and URB_SHORT_NOT_OK was set in
+ *                     urb->transfer_flags.
+ *
+ * -ENODEV             Device was removed.  Often preceded by a burst of
+ *                     other errors, since the hub driver doesn't detect
+ *                     device removal events immediately.
+ *
+ * -EXDEV              ISO transfer only partially completed
+ *                     (only set in iso_frame_desc[n].status, not urb->status)
+ *
+ * -EINVAL             ISO madness, if this happens: Log off and go home
+ *
+ * -ECONNRESET         URB was asynchronously unlinked by usb_unlink_urb
+ *
+ * -ESHUTDOWN          The device or host controller has been disabled due
+ *                     to some problem that could not be worked around,
+ *                     such as a physical disconnect.
+ *
+ *
+ * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
+ * hardware problems such as bad devices (including firmware) or cables.
+ *
+ * (**) This is also one of several codes that different kinds of host
+ * controller use to indicate a transfer has failed because of device
+ * disconnect.  In the interval before the hub driver starts disconnect
+ * processing, devices may receive such fault reports for every request.
+ *
+ * See <https://www.kernel.org/doc/Documentation/usb/error-codes.txt>
+ */
+static void hdm_read_completion(struct urb *urb)
+{
+       struct mbo *mbo;
+       struct buf_anchor *anchor;
+       struct most_dev *mdev;
+       struct device *dev;
+       unsigned long flags;
+       unsigned int channel;
+       struct most_channel_config *conf;
+
+       mbo = urb->context;
+       anchor = mbo->priv;
+       mdev = to_mdev(mbo->ifp);
+       channel = mbo->hdm_channel_id;
+       dev = &mdev->usb_device->dev;
+
+       if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) ||
+           (mdev->is_channel_healthy[channel] == false)) {
+               complete(&anchor->urb_compl);
+               return;
+       }
+
+       conf = &mdev->conf[channel];
+
+       if (unlikely(urb->status && !(urb->status == -ENOENT ||
+                                     urb->status == -ECONNRESET ||
+                                     urb->status == -ESHUTDOWN))) {
+               mbo->processed_length = 0;
+               switch (urb->status) {
+               case -EPIPE:
+                       dev_warn(dev, "Broken IN pipe detected\n");
+                       mbo->status = MBO_E_INVAL;
+                       usb_unlink_urb(urb);
+                       INIT_WORK(&anchor->clear_work_obj, wq_clear_halt);
+                       queue_work(schedule_usb_work, &anchor->clear_work_obj);
+                       return;
+               case -ENODEV:
+               case -EPROTO:
+                       mbo->status = MBO_E_CLOSE;
+                       break;
+               case -EOVERFLOW:
+                       dev_warn(dev, "Babble on IN pipe detected\n");
+               default:
+                       mbo->status = MBO_E_INVAL;
+                       break;
+               }
+       } else {
+               mbo->processed_length = urb->actual_length;
+               if (mdev->padding_active[channel] == false) {
+                       mbo->status = MBO_SUCCESS;
+               } else {
+                       if (hdm_remove_padding(mdev, channel, mbo)) {
+                               mbo->processed_length = 0;
+                               mbo->status = MBO_E_INVAL;
+                       } else {
+                               mbo->status = MBO_SUCCESS;
+                       }
+               }
+       }
+       spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+       list_del(&anchor->list);
+       spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+       kfree(anchor);
+
+       if (likely(mbo->complete))
+               mbo->complete(mbo);
+       usb_free_urb(urb);
+}
+
+/**
+ * hdm_enqueue - receive a buffer to be used for data transfer
+ * @iface: interface to enqueue to
+ * @channel: ID of the channel
+ * @mbo: pointer to the buffer object
+ *
+ * This allocates a new URB and fills it according to the channel
+ * that is being used for transmission of data. Before the URB is
+ * submitted it is stored in the private anchor list.
+ *
+ * Returns 0 on success. On any error the URB is freed and a error code
+ * is returned.
+ *
+ * Context: Could in _some_ cases be interrupt!
+ */
+static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo)
+{
+       struct most_dev *mdev;
+       struct buf_anchor *anchor;
+       struct most_channel_config *conf;
+       struct device *dev;
+       int retval = 0;
+       struct urb *urb;
+       unsigned long flags;
+       unsigned long length;
+       void *virt_address;
+
+       if (unlikely(!iface || !mbo))
+               return -EIO;
+       if (unlikely(iface->num_channels <= channel) || (channel < 0))
+               return -ECHRNG;
+
+       mdev = to_mdev(iface);
+       conf = &mdev->conf[channel];
+       dev = &mdev->usb_device->dev;
+
+       if (!mdev->usb_device)
+               return -ENODEV;
+
+       urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(dev, "Failed to allocate URB\n");
+               return -ENOMEM;
+       }
+
+       anchor = kzalloc(sizeof(*anchor), GFP_ATOMIC);
+       if (!anchor) {
+               retval = -ENOMEM;
+               goto _error;
+       }
+
+       anchor->urb = urb;
+       init_completion(&anchor->urb_compl);
+       mbo->priv = anchor;
+
+       spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+       list_add_tail(&anchor->list, &mdev->anchor_list[channel]);
+       spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+
+       if ((mdev->padding_active[channel] == true) &&
+           (conf->direction & MOST_CH_TX))
+               if (hdm_add_padding(mdev, channel, mbo)) {
+                       retval = -EIO;
+                       goto _error_1;
+               }
+
+       urb->transfer_dma = mbo->bus_address;
+       virt_address = mbo->virt_address;
+       length = mbo->buffer_length;
+
+       if (conf->direction & MOST_CH_TX) {
+               usb_fill_bulk_urb(urb, mdev->usb_device,
+                                 usb_sndbulkpipe(mdev->usb_device,
+                                                 mdev->ep_address[channel]),
+                                 virt_address,
+                                 length,
+                                 hdm_write_completion,
+                                 mbo);
+               if (conf->data_type != MOST_CH_ISOC_AVP)
+                       urb->transfer_flags |= URB_ZERO_PACKET;
+       } else {
+               usb_fill_bulk_urb(urb, mdev->usb_device,
+                                 usb_rcvbulkpipe(mdev->usb_device,
+                                                 mdev->ep_address[channel]),
+                                 virt_address,
+                                 length,
+                                 hdm_read_completion,
+                                 mbo);
+       }
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       retval = usb_submit_urb(urb, GFP_KERNEL);
+       if (retval) {
+               dev_err(dev, "URB submit failed with error %d.\n", retval);
+               goto _error_1;
+       }
+       return 0;
+
+_error_1:
+       spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+       list_del(&anchor->list);
+       spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+       kfree(anchor);
+_error:
+       usb_free_urb(urb);
+       return retval;
+}
+
+/**
+ * hdm_configure_channel - receive channel configuration from core
+ * @iface: interface
+ * @channel: channel ID
+ * @conf: structure that holds the configuration information
+ */
+static int hdm_configure_channel(struct most_interface *iface, int channel,
+                                struct most_channel_config *conf)
+{
+       unsigned int num_frames;
+       unsigned int frame_size;
+       unsigned int temp_size;
+       unsigned int tail_space;
+       struct most_dev *mdev;
+       struct device *dev;
+
+       mdev = to_mdev(iface);
+       mdev->is_channel_healthy[channel] = true;
+       dev = &mdev->usb_device->dev;
+
+       if (unlikely(!iface || !conf)) {
+               dev_err(dev, "Bad interface or config pointer.\n");
+               return -EINVAL;
+       }
+       if (unlikely((channel < 0) || (channel >= iface->num_channels))) {
+               dev_err(dev, "Channel ID out of range.\n");
+               return -EINVAL;
+       }
+       if ((!conf->num_buffers) || (!conf->buffer_size)) {
+               dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
+               return -EINVAL;
+       }
+
+       if (!(conf->data_type == MOST_CH_SYNC) &&
+           !((conf->data_type == MOST_CH_ISOC_AVP) &&
+             (conf->packets_per_xact != 0xFF))) {
+               mdev->padding_active[channel] = false;
+               goto exit;
+       }
+
+       mdev->padding_active[channel] = true;
+       temp_size = conf->buffer_size;
+
+       if ((conf->data_type != MOST_CH_SYNC) &&
+           (conf->data_type != MOST_CH_ISOC_AVP)) {
+               dev_warn(dev, "Unsupported data type\n");
+               return -EINVAL;
+       }
+
+       frame_size = get_stream_frame_size(conf);
+       if ((frame_size == 0) || (frame_size > USB_MTU)) {
+               dev_warn(dev, "Misconfig: frame size wrong\n");
+               return -EINVAL;
+       }
+
+       if (conf->buffer_size % frame_size) {
+               u16 tmp_val;
+
+               tmp_val = conf->buffer_size / frame_size;
+               conf->buffer_size = tmp_val * frame_size;
+               dev_notice(dev,
+                          "Channel %d - rouding buffer size to %d bytes, "
+                          "channel config says %d bytes\n",
+                          channel,
+                          conf->buffer_size,
+                          temp_size);
+       }
+
+       num_frames = conf->buffer_size / frame_size;
+       tail_space = num_frames * (USB_MTU - frame_size);
+       temp_size += tail_space;
+
+       /* calculate extra length to comply w/ HW padding */
+       conf->extra_len = (CEILING(temp_size, USB_MTU) * USB_MTU)
+                         - conf->buffer_size;
+exit:
+       mdev->conf[channel] = *conf;
+       return 0;
+}
+
+/**
+ * hdm_update_netinfo - retrieve latest networking information
+ * @mdev: device interface
+ *
+ * This triggers the USB vendor requests to read the hardware address and
+ * the current link status of the attached device.
+ */
+static int hdm_update_netinfo(struct most_dev *mdev)
+{
+       struct device *dev = &mdev->usb_device->dev;
+       int i;
+       u16 link;
+       u8 addr[6];
+
+       if (!is_valid_ether_addr(mdev->hw_addr)) {
+               if (0 > drci_rd_reg(mdev->usb_device,
+                                   DRCI_REG_HW_ADDR_HI, addr)) {
+                       dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n");
+                       return -1;
+               }
+               if (0 > drci_rd_reg(mdev->usb_device,
+                                   DRCI_REG_HW_ADDR_MI, addr + 2)) {
+                       dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n");
+                       return -1;
+               }
+               if (0 > drci_rd_reg(mdev->usb_device,
+                                   DRCI_REG_HW_ADDR_LO, addr + 4)) {
+                       dev_err(dev, "Vendor request \"hw_addr_low\" failed\n");
+                       return -1;
+               }
+               mutex_lock(&mdev->io_mutex);
+               for (i = 0; i < 6; i++)
+                       mdev->hw_addr[i] = addr[i];
+               mutex_unlock(&mdev->io_mutex);
+
+       }
+       if (0 > drci_rd_reg(mdev->usb_device, DRCI_REG_NI_STATE, &link)) {
+               dev_err(dev, "Vendor request \"link status\" failed\n");
+               return -1;
+       }
+       le16_to_cpus(&link);
+       mutex_lock(&mdev->io_mutex);
+       mdev->link_stat = link;
+       mutex_unlock(&mdev->io_mutex);
+       return 0;
+}
+
+/**
+ * hdm_request_netinfo - request network information
+ * @iface: pointer to interface
+ * @channel: channel ID
+ *
+ * This is used as trigger to set up the link status timer that
+ * polls for the NI state of the INIC every 2 seconds.
+ *
+ */
+static void hdm_request_netinfo(struct most_interface *iface, int channel)
+{
+       struct most_dev *mdev;
+
+       BUG_ON(!iface);
+       mdev = to_mdev(iface);
+       mdev->link_stat_timer.expires = jiffies + HZ;
+       mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
+}
+
+/**
+ * link_stat_timer_handler - add work to link_stat work queue
+ * @data: pointer to USB device instance
+ *
+ * The handler runs in interrupt context. That's why we need to defer the
+ * tasks to a work queue.
+ */
+static void link_stat_timer_handler(unsigned long data)
+{
+       struct most_dev *mdev = (struct most_dev *)data;
+
+       queue_work(schedule_usb_work, &mdev->poll_work_obj);
+       mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+       add_timer(&mdev->link_stat_timer);
+}
+
+/**
+ * wq_netinfo - work queue function
+ * @wq_obj: object that holds data for our deferred work to do
+ *
+ * This retrieves the network interface status of the USB INIC
+ * and compares it with the current status. If the status has
+ * changed, it updates the status of the core.
+ */
+static void wq_netinfo(struct work_struct *wq_obj)
+{
+       struct most_dev *mdev;
+       int i, prev_link_stat;
+       u8 prev_hw_addr[6];
+
+       mdev = to_mdev_from_work(wq_obj);
+       prev_link_stat = mdev->link_stat;
+
+       for (i = 0; i < 6; i++)
+               prev_hw_addr[i] = mdev->hw_addr[i];
+
+       if (0 > hdm_update_netinfo(mdev))
+               return;
+       if ((prev_link_stat != mdev->link_stat) ||
+           (prev_hw_addr[0] != mdev->hw_addr[0]) ||
+           (prev_hw_addr[1] != mdev->hw_addr[1]) ||
+           (prev_hw_addr[2] != mdev->hw_addr[2]) ||
+           (prev_hw_addr[3] != mdev->hw_addr[3]) ||
+           (prev_hw_addr[4] != mdev->hw_addr[4]) ||
+           (prev_hw_addr[5] != mdev->hw_addr[5]))
+               most_deliver_netinfo(&mdev->iface, mdev->link_stat,
+                                    &mdev->hw_addr[0]);
+}
+
+/**
+ * wq_clear_halt - work queue function
+ * @wq_obj: work_struct object to execute
+ *
+ * This sends a clear_halt to the given USB pipe.
+ */
+static void wq_clear_halt(struct work_struct *wq_obj)
+{
+       struct buf_anchor *anchor;
+       struct most_dev *mdev;
+       struct mbo *mbo;
+       struct urb *urb;
+       unsigned int channel;
+       unsigned long flags;
+
+       anchor = to_buf_anchor(wq_obj);
+       urb = anchor->urb;
+       mbo = urb->context;
+       mdev = to_mdev(mbo->ifp);
+       channel = mbo->hdm_channel_id;
+
+       if (usb_clear_halt(urb->dev, urb->pipe))
+               dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
+
+       usb_free_urb(urb);
+       spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+       list_del(&anchor->list);
+       spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+
+       if (likely(mbo->complete))
+               mbo->complete(mbo);
+       if (mdev->conf[channel].direction & MOST_CH_TX)
+               most_resume_enqueue(&mdev->iface, channel);
+
+       kfree(anchor);
+}
+
+/**
+ * hdm_usb_fops - file operation table for USB driver
+ */
+static const struct file_operations hdm_usb_fops = {
+       .owner = THIS_MODULE,
+};
+
+/**
+ * usb_device_id - ID table for HCD device probing
+ */
+static struct usb_device_id usbid[] = {
+       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
+       { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_INIC), },
+       { } /* Terminating entry */
+};
+
+#define MOST_DCI_RO_ATTR(_name) \
+       struct most_dci_attribute most_dci_attr_##_name = \
+               __ATTR(_name, S_IRUGO, show_value, NULL)
+
+#define MOST_DCI_ATTR(_name) \
+       struct most_dci_attribute most_dci_attr_##_name = \
+               __ATTR(_name, S_IRUGO | S_IWUSR, show_value, store_value)
+
+/**
+ * struct most_dci_attribute - to access the attributes of a dci object
+ * @attr: attributes of a dci object
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_dci_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct most_dci_obj *d,
+                       struct most_dci_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct most_dci_obj *d,
+                        struct most_dci_attribute *attr,
+                        const char *buf,
+                        size_t count);
+};
+#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
+
+
+/**
+ * dci_attr_show - show function for dci object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
+                            char *buf)
+{
+       struct most_dci_attribute *dci_attr = to_dci_attr(attr);
+       struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+       if (!dci_attr->show)
+               return -EIO;
+
+       return dci_attr->show(dci_obj, dci_attr, buf);
+}
+
+/**
+ * dci_attr_store - store function for dci object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t dci_attr_store(struct kobject *kobj,
+                             struct attribute *attr,
+                             const char *buf,
+                             size_t len)
+{
+       struct most_dci_attribute *dci_attr = to_dci_attr(attr);
+       struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+       if (!dci_attr->store)
+               return -EIO;
+
+       return dci_attr->store(dci_obj, dci_attr, buf, len);
+}
+
+static const struct sysfs_ops most_dci_sysfs_ops = {
+       .show = dci_attr_show,
+       .store = dci_attr_store,
+};
+
+/**
+ * most_dci_release - release function for dci object
+ * @kobj: pointer to kobject
+ *
+ * This frees the memory allocated for the dci object
+ */
+static void most_dci_release(struct kobject *kobj)
+{
+       struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+       kfree(dci_obj);
+}
+
+static ssize_t show_value(struct most_dci_obj *dci_obj,
+                         struct most_dci_attribute *attr, char *buf)
+{
+       u16 tmp_val;
+       u16 reg_addr;
+       int err;
+
+       if (!strcmp(attr->attr.name, "ni_state"))
+               reg_addr = DRCI_REG_NI_STATE;
+       else if (!strcmp(attr->attr.name, "packet_bandwidth"))
+               reg_addr = DRCI_REG_PACKET_BW;
+       else if (!strcmp(attr->attr.name, "node_address"))
+               reg_addr = DRCI_REG_NODE_ADDR;
+       else if (!strcmp(attr->attr.name, "node_position"))
+               reg_addr = DRCI_REG_NODE_POS;
+       else if (!strcmp(attr->attr.name, "mep_filter"))
+               reg_addr = DRCI_REG_MEP_FILTER;
+       else if (!strcmp(attr->attr.name, "mep_hash0"))
+               reg_addr = DRCI_REG_HASH_TBL0;
+       else if (!strcmp(attr->attr.name, "mep_hash1"))
+               reg_addr = DRCI_REG_HASH_TBL1;
+       else if (!strcmp(attr->attr.name, "mep_hash2"))
+               reg_addr = DRCI_REG_HASH_TBL2;
+       else if (!strcmp(attr->attr.name, "mep_hash3"))
+               reg_addr = DRCI_REG_HASH_TBL3;
+       else if (!strcmp(attr->attr.name, "mep_eui48_hi"))
+               reg_addr = DRCI_REG_HW_ADDR_HI;
+       else if (!strcmp(attr->attr.name, "mep_eui48_mi"))
+               reg_addr = DRCI_REG_HW_ADDR_MI;
+       else if (!strcmp(attr->attr.name, "mep_eui48_lo"))
+               reg_addr = DRCI_REG_HW_ADDR_LO;
+       else
+               return -EIO;
+
+       err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val);
+       if (err < 0)
+               return err;
+
+       return snprintf(buf, PAGE_SIZE, "%04x\n", le16_to_cpu(tmp_val));
+}
+
+static ssize_t store_value(struct most_dci_obj *dci_obj,
+                          struct most_dci_attribute *attr,
+                          const char *buf, size_t count)
+{
+       u16 v16;
+       u16 reg_addr;
+       int err;
+
+       if (!strcmp(attr->attr.name, "mep_filter"))
+               reg_addr = DRCI_REG_MEP_FILTER;
+       else if (!strcmp(attr->attr.name, "mep_hash0"))
+               reg_addr = DRCI_REG_HASH_TBL0;
+       else if (!strcmp(attr->attr.name, "mep_hash1"))
+               reg_addr = DRCI_REG_HASH_TBL1;
+       else if (!strcmp(attr->attr.name, "mep_hash2"))
+               reg_addr = DRCI_REG_HASH_TBL2;
+       else if (!strcmp(attr->attr.name, "mep_hash3"))
+               reg_addr = DRCI_REG_HASH_TBL3;
+       else if (!strcmp(attr->attr.name, "mep_eui48_hi"))
+               reg_addr = DRCI_REG_HW_ADDR_HI;
+       else if (!strcmp(attr->attr.name, "mep_eui48_mi"))
+               reg_addr = DRCI_REG_HW_ADDR_MI;
+       else if (!strcmp(attr->attr.name, "mep_eui48_lo"))
+               reg_addr = DRCI_REG_HW_ADDR_LO;
+       else
+               return -EIO;
+
+       err = kstrtou16(buf, 16, &v16);
+       if (err)
+               return err;
+
+       err = drci_wr_reg(dci_obj->usb_device, reg_addr, cpu_to_le16(v16));
+       if (err < 0)
+               return err;
+
+       return count;
+}
+
+static MOST_DCI_RO_ATTR(ni_state);
+static MOST_DCI_RO_ATTR(packet_bandwidth);
+static MOST_DCI_RO_ATTR(node_address);
+static MOST_DCI_RO_ATTR(node_position);
+static MOST_DCI_ATTR(mep_filter);
+static MOST_DCI_ATTR(mep_hash0);
+static MOST_DCI_ATTR(mep_hash1);
+static MOST_DCI_ATTR(mep_hash2);
+static MOST_DCI_ATTR(mep_hash3);
+static MOST_DCI_ATTR(mep_eui48_hi);
+static MOST_DCI_ATTR(mep_eui48_mi);
+static MOST_DCI_ATTR(mep_eui48_lo);
+
+/**
+ * most_dci_def_attrs - array of default attribute files of the dci object
+ */
+static struct attribute *most_dci_def_attrs[] = {
+       &most_dci_attr_ni_state.attr,
+       &most_dci_attr_packet_bandwidth.attr,
+       &most_dci_attr_node_address.attr,
+       &most_dci_attr_node_position.attr,
+       &most_dci_attr_mep_filter.attr,
+       &most_dci_attr_mep_hash0.attr,
+       &most_dci_attr_mep_hash1.attr,
+       &most_dci_attr_mep_hash2.attr,
+       &most_dci_attr_mep_hash3.attr,
+       &most_dci_attr_mep_eui48_hi.attr,
+       &most_dci_attr_mep_eui48_mi.attr,
+       &most_dci_attr_mep_eui48_lo.attr,
+       NULL,
+};
+
+/**
+ * DCI ktype
+ */
+static struct kobj_type most_dci_ktype = {
+       .sysfs_ops = &most_dci_sysfs_ops,
+       .release = most_dci_release,
+       .default_attrs = most_dci_def_attrs,
+};
+
+/**
+ * create_most_dci_obj - allocates a dci object
+ * @parent: parent kobject
+ *
+ * This creates a dci object and registers it with sysfs.
+ * Returns a pointer to the object or NULL when something went wrong.
+ */
+static struct
+most_dci_obj *create_most_dci_obj(struct kobject *parent)
+{
+       struct most_dci_obj *most_dci;
+       int retval;
+
+       most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
+       if (!most_dci)
+               return NULL;
+
+       retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
+                                     "dci");
+       if (retval) {
+               kobject_put(&most_dci->kobj);
+               return NULL;
+       }
+       return most_dci;
+}
+
+/**
+ * destroy_most_dci_obj - DCI object release function
+ * @p: pointer to dci object
+ */
+static void destroy_most_dci_obj(struct most_dci_obj *p)
+{
+       kobject_put(&p->kobj);
+}
+
+/**
+ * hdm_probe - probe function of USB device driver
+ * @interface: Interface of the attached USB device
+ * @id: Pointer to the USB ID table.
+ *
+ * This allocates and initializes the device instance, adds the new
+ * entry to the internal list, scans the USB descriptors and registers
+ * the interface with the core.
+ * Additionally, the DCI objects are created and the hardware is sync'd.
+ *
+ * Return 0 on success. In case of an error a negative number is returned.
+ */
+static int
+hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+       unsigned int i;
+       unsigned int num_endpoints;
+       struct most_channel_capability *tmp_cap;
+       struct most_dev *mdev;
+       struct usb_device *usb_dev;
+       struct device *dev;
+       struct usb_host_interface *usb_iface_desc;
+       struct usb_endpoint_descriptor *ep_desc;
+       int ret = 0;
+
+       usb_iface_desc = interface->cur_altsetting;
+       usb_dev = interface_to_usbdev(interface);
+       dev = &usb_dev->dev;
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               goto exit_ENOMEM;
+
+       usb_set_intfdata(interface, mdev);
+       num_endpoints = usb_iface_desc->desc.bNumEndpoints;
+       mutex_init(&mdev->io_mutex);
+       INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
+       init_timer(&mdev->link_stat_timer);
+
+       mdev->usb_device = usb_dev;
+       mdev->link_stat_timer.function = link_stat_timer_handler;
+       mdev->link_stat_timer.data = (unsigned long)mdev;
+       mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+
+       mdev->iface.mod = hdm_usb_fops.owner;
+       mdev->iface.interface = ITYPE_USB;
+       mdev->iface.configure = hdm_configure_channel;
+       mdev->iface.request_netinfo = hdm_request_netinfo;
+       mdev->iface.enqueue = hdm_enqueue;
+       mdev->iface.poison_channel = hdm_poison_channel;
+       mdev->iface.description = mdev->description;
+       mdev->iface.num_channels = num_endpoints;
+
+       snprintf(mdev->description, sizeof(mdev->description),
+                "usb_device %d-%s:%d.%d",
+                usb_dev->bus->busnum,
+                usb_dev->devpath,
+                usb_dev->config->desc.bConfigurationValue,
+                usb_iface_desc->desc.bInterfaceNumber);
+
+       mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
+       if (!mdev->conf)
+               goto exit_free;
+
+       mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
+       if (!mdev->cap)
+               goto exit_free1;
+
+       mdev->iface.channel_vector = mdev->cap;
+       mdev->iface.priv = NULL;
+
+       mdev->ep_address =
+               kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
+       if (!mdev->ep_address)
+               goto exit_free2;
+
+       mdev->anchor_list =
+               kcalloc(num_endpoints, sizeof(*mdev->anchor_list), GFP_KERNEL);
+       if (!mdev->anchor_list)
+               goto exit_free3;
+
+       tmp_cap = mdev->cap;
+       for (i = 0; i < num_endpoints; i++) {
+               ep_desc = &usb_iface_desc->endpoint[i].desc;
+               mdev->ep_address[i] = ep_desc->bEndpointAddress;
+               mdev->padding_active[i] = false;
+               mdev->is_channel_healthy[i] = true;
+
+               snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
+                        mdev->ep_address[i]);
+
+               tmp_cap->name_suffix = &mdev->suffix[i][0];
+               tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
+               tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
+               tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
+               tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
+               tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+                                    MOST_CH_ISOC_AVP | MOST_CH_SYNC;
+               if (ep_desc->bEndpointAddress & USB_DIR_IN)
+                       tmp_cap->direction = MOST_CH_RX;
+               else
+                       tmp_cap->direction = MOST_CH_TX;
+               tmp_cap++;
+               INIT_LIST_HEAD(&mdev->anchor_list[i]);
+               spin_lock_init(&mdev->anchor_list_lock[i]);
+       }
+       dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
+                  le16_to_cpu(usb_dev->descriptor.idVendor),
+                  le16_to_cpu(usb_dev->descriptor.idProduct),
+                  usb_dev->bus->busnum,
+                  usb_dev->devnum);
+
+       dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
+                  usb_dev->bus->busnum,
+                  usb_dev->devpath,
+                  usb_dev->config->desc.bConfigurationValue,
+                  usb_iface_desc->desc.bInterfaceNumber);
+
+       mdev->parent = most_register_interface(&mdev->iface);
+       if (IS_ERR(mdev->parent)) {
+               ret = PTR_ERR(mdev->parent);
+               goto exit_free4;
+       }
+
+       mutex_lock(&mdev->io_mutex);
+       if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC) {
+               /* this increments the reference count of the instance
+                * object of the core
+                */
+               mdev->dci = create_most_dci_obj(mdev->parent);
+               if (!mdev->dci) {
+                       mutex_unlock(&mdev->io_mutex);
+                       most_deregister_interface(&mdev->iface);
+                       ret = -ENOMEM;
+                       goto exit_free4;
+               }
+
+               kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
+               mdev->dci->usb_device = mdev->usb_device;
+               trigger_resync_vr(usb_dev);
+       }
+       mutex_unlock(&mdev->io_mutex);
+       return 0;
+
+exit_free4:
+       kfree(mdev->anchor_list);
+exit_free3:
+       kfree(mdev->ep_address);
+exit_free2:
+       kfree(mdev->cap);
+exit_free1:
+       kfree(mdev->conf);
+exit_free:
+       kfree(mdev);
+exit_ENOMEM:
+       if (ret == 0 || ret == -ENOMEM) {
+               ret = -ENOMEM;
+               dev_err(dev, "out of memory\n");
+       }
+       return ret;
+}
+
+/**
+ * hdm_disconnect - disconnect function of USB device driver
+ * @interface: Interface of the attached USB device
+ *
+ * This deregisters the interface with the core, removes the kernel timer
+ * and frees resources.
+ *
+ * Context: hub kernel thread
+ */
+static void hdm_disconnect(struct usb_interface *interface)
+{
+       struct most_dev *mdev;
+
+       mdev = usb_get_intfdata(interface);
+       mutex_lock(&mdev->io_mutex);
+       usb_set_intfdata(interface, NULL);
+       mdev->usb_device = NULL;
+       mutex_unlock(&mdev->io_mutex);
+
+       del_timer_sync(&mdev->link_stat_timer);
+       cancel_work_sync(&mdev->poll_work_obj);
+
+       destroy_most_dci_obj(mdev->dci);
+       most_deregister_interface(&mdev->iface);
+
+       kfree(mdev->anchor_list);
+       kfree(mdev->cap);
+       kfree(mdev->conf);
+       kfree(mdev->ep_address);
+       kfree(mdev);
+}
+
+static struct usb_driver hdm_usb = {
+       .name = "hdm_usb",
+       .id_table = usbid,
+       .probe = hdm_probe,
+       .disconnect = hdm_disconnect,
+};
+
+static int __init hdm_usb_init(void)
+{
+       pr_info("hdm_usb_init()\n");
+       if (usb_register(&hdm_usb)) {
+               pr_err("could not register hdm_usb driver\n");
+               return -EIO;
+       }
+       schedule_usb_work = create_workqueue("hdmu_work");
+       if (schedule_usb_work == NULL) {
+               pr_err("could not create workqueue\n");
+               usb_deregister(&hdm_usb);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void __exit hdm_usb_exit(void)
+{
+       pr_info("hdm_usb_exit()\n");
+       destroy_workqueue(schedule_usb_work);
+       usb_deregister(&hdm_usb);
+}
+
+module_init(hdm_usb_init);
+module_exit(hdm_usb_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("HDM_4_USB");
diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig
new file mode 100644 (file)
index 0000000..38abf1b
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# MOSTCore configuration
+#
+
+config MOSTCORE
+       tristate "MOST Core"
+
+       ---help---
+         Say Y here if you want to enable MOST support.
+         This device driver needs at least an additional AIM and HDM to work.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mostcore.
diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile
new file mode 100644 (file)
index 0000000..a078f01
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MOSTCORE) += mostcore.o
+
+mostcore-objs := core.o
diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c
new file mode 100644 (file)
index 0000000..7bb16db
--- /dev/null
@@ -0,0 +1,1932 @@
+/*
+ * core.c - Implementation of core module of MOST Linux driver stack
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/sysfs.h>
+#include <linux/kthread.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include "mostcore.h"
+
+#define MAX_CHANNELS   64
+#define STRING_SIZE    80
+
+static struct class *most_class;
+static struct device *class_glue_dir;
+static struct ida mdev_id;
+static int modref;
+
+struct most_c_obj {
+       struct kobject kobj;
+       struct completion cleanup;
+       atomic_t mbo_ref;
+       atomic_t mbo_nq_level;
+       uint16_t channel_id;
+       bool is_poisoned;
+       bool is_started;
+       int is_starving;
+       struct most_interface *iface;
+       struct most_inst_obj *inst;
+       struct most_channel_config cfg;
+       bool keep_mbo;
+       bool enqueue_halt;
+       struct list_head fifo;
+       spinlock_t fifo_lock;
+       struct list_head halt_fifo;
+       struct list_head list;
+       struct most_aim *first_aim;
+       struct most_aim *second_aim;
+       struct list_head trash_fifo;
+       struct task_struct *hdm_enqueue_task;
+       struct mutex stop_task_mutex;
+       wait_queue_head_t hdm_fifo_wq;
+};
+#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
+
+struct most_inst_obj {
+       int dev_id;
+       atomic_t tainted;
+       struct most_interface *iface;
+       struct list_head channel_list;
+       struct most_c_obj *channel[MAX_CHANNELS];
+       struct kobject kobj;
+       struct list_head list;
+};
+#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
+
+/**
+ * list_pop_mbo - retrieves the first MBO of the list and removes it
+ * @ptr: the list head to grab the MBO from.
+ */
+#define list_pop_mbo(ptr)                                              \
+({                                                                     \
+       struct mbo *_mbo = list_first_entry(ptr, struct mbo, list);     \
+       list_del(&_mbo->list);                                          \
+       _mbo;                                                           \
+})
+
+static struct mutex deregister_mutex;
+
+/*                  ___             ___
+ *                  ___C H A N N E L___
+ */
+
+/**
+ * struct most_c_attr - to access the attributes of a channel object
+ * @attr: attributes of a channel
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_c_attr {
+       struct attribute attr;
+       ssize_t (*show)(struct most_c_obj *d,
+                       struct most_c_attr *attr,
+                       char *buf);
+       ssize_t (*store)(struct most_c_obj *d,
+                        struct most_c_attr *attr,
+                        const char *buf,
+                        size_t count);
+};
+#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
+
+#define MOST_CHNL_ATTR(_name, _mode, _show, _store) \
+               struct most_c_attr most_chnl_attr_##_name = \
+               __ATTR(_name, _mode, _show, _store)
+
+/**
+ * channel_attr_show - show function of channel object
+ * @kobj: pointer to its kobject
+ * @attr: pointer to its attributes
+ * @buf: buffer
+ */
+static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
+                                char *buf)
+{
+       struct most_c_attr *channel_attr = to_channel_attr(attr);
+       struct most_c_obj *c_obj = to_c_obj(kobj);
+
+       if (!channel_attr->show)
+               return -EIO;
+
+       return channel_attr->show(c_obj, channel_attr, buf);
+}
+
+/**
+ * channel_attr_store - store function of channel object
+ * @kobj: pointer to its kobject
+ * @attr: pointer to its attributes
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t channel_attr_store(struct kobject *kobj,
+                                 struct attribute *attr,
+                                 const char *buf,
+                                 size_t len)
+{
+       struct most_c_attr *channel_attr = to_channel_attr(attr);
+       struct most_c_obj *c_obj = to_c_obj(kobj);
+
+       if (!channel_attr->store)
+               return -EIO;
+       return channel_attr->store(c_obj, channel_attr, buf, len);
+}
+
+static const struct sysfs_ops most_channel_sysfs_ops = {
+       .show = channel_attr_show,
+       .store = channel_attr_store,
+};
+
+/**
+ * most_free_mbo_coherent - free an MBO and its coherent buffer
+ * @mbo: buffer to be released
+ *
+ */
+static void most_free_mbo_coherent(struct mbo *mbo)
+{
+       struct most_c_obj *c = mbo->context;
+       u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+       dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
+                         mbo->bus_address);
+       kfree(mbo);
+       if (atomic_sub_and_test(1, &c->mbo_ref))
+               complete(&c->cleanup);
+}
+
+/**
+ * flush_channel_fifos - clear the channel fifos
+ * @c: pointer to channel object
+ */
+static void flush_channel_fifos(struct most_c_obj *c)
+{
+       unsigned long flags, hf_flags;
+       struct mbo *mbo, *tmp;
+
+       if (list_empty(&c->fifo) && list_empty(&c->halt_fifo))
+               return;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
+               list_del(&mbo->list);
+               spin_unlock_irqrestore(&c->fifo_lock, flags);
+               if (likely(mbo))
+                       most_free_mbo_coherent(mbo);
+               spin_lock_irqsave(&c->fifo_lock, flags);
+       }
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+       spin_lock_irqsave(&c->fifo_lock, hf_flags);
+       list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
+               list_del(&mbo->list);
+               spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+               if (likely(mbo))
+                       most_free_mbo_coherent(mbo);
+               spin_lock_irqsave(&c->fifo_lock, hf_flags);
+       }
+       spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+
+       if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo))))
+               pr_info("WARN: fifo | trash fifo not empty\n");
+}
+
+/**
+ * flush_trash_fifo - clear the trash fifo
+ * @c: pointer to channel object
+ */
+static int flush_trash_fifo(struct most_c_obj *c)
+{
+       struct mbo *mbo, *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) {
+               list_del(&mbo->list);
+               spin_unlock_irqrestore(&c->fifo_lock, flags);
+               most_free_mbo_coherent(mbo);
+               spin_lock_irqsave(&c->fifo_lock, flags);
+       }
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       return 0;
+}
+
+/**
+ * most_channel_release - release function of channel object
+ * @kobj: pointer to channel's kobject
+ */
+static void most_channel_release(struct kobject *kobj)
+{
+       struct most_c_obj *c = to_c_obj(kobj);
+
+       kfree(c);
+}
+
+static ssize_t show_available_directions(struct most_c_obj *c,
+               struct most_c_attr *attr,
+               char *buf)
+{
+       unsigned int i = c->channel_id;
+
+       strcpy(buf, "");
+       if (c->iface->channel_vector[i].direction & MOST_CH_RX)
+               strcat(buf, "dir_rx ");
+       if (c->iface->channel_vector[i].direction & MOST_CH_TX)
+               strcat(buf, "dir_tx ");
+       strcat(buf, "\n");
+       return strlen(buf) + 1;
+}
+
+static ssize_t show_available_datatypes(struct most_c_obj *c,
+                                       struct most_c_attr *attr,
+                                       char *buf)
+{
+       unsigned int i = c->channel_id;
+
+       strcpy(buf, "");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL)
+               strcat(buf, "control ");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC)
+               strcat(buf, "async ");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC)
+               strcat(buf, "sync ");
+       if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP)
+               strcat(buf, "isoc_avp ");
+       strcat(buf, "\n");
+       return strlen(buf) + 1;
+}
+
+static
+ssize_t show_number_of_packet_buffers(struct most_c_obj *c,
+                                     struct most_c_attr *attr,
+                                     char *buf)
+{
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].num_buffers_packet);
+}
+
+static
+ssize_t show_number_of_stream_buffers(struct most_c_obj *c,
+                                     struct most_c_attr *attr,
+                                     char *buf)
+{
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].num_buffers_streaming);
+}
+
+static
+ssize_t show_size_of_packet_buffer(struct most_c_obj *c,
+                                  struct most_c_attr *attr,
+                                  char *buf)
+{
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].buffer_size_packet);
+}
+
+static
+ssize_t show_size_of_stream_buffer(struct most_c_obj *c,
+                                  struct most_c_attr *attr,
+                                  char *buf)
+{
+       unsigned int i = c->channel_id;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       c->iface->channel_vector[i].buffer_size_streaming);
+}
+
+static ssize_t show_channel_starving(struct most_c_obj *c,
+                                    struct most_c_attr *attr,
+                                    char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
+}
+
+
+#define create_show_channel_attribute(val) \
+       static MOST_CHNL_ATTR(val, S_IRUGO, show_##val, NULL)
+
+create_show_channel_attribute(available_directions);
+create_show_channel_attribute(available_datatypes);
+create_show_channel_attribute(number_of_packet_buffers);
+create_show_channel_attribute(number_of_stream_buffers);
+create_show_channel_attribute(size_of_stream_buffer);
+create_show_channel_attribute(size_of_packet_buffer);
+create_show_channel_attribute(channel_starving);
+
+static ssize_t show_set_number_of_buffers(struct most_c_obj *c,
+                                         struct most_c_attr *attr,
+                                         char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
+}
+
+static ssize_t store_set_number_of_buffers(struct most_c_obj *c,
+                                          struct most_c_attr *attr,
+                                          const char *buf,
+                                          size_t count)
+{
+       int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+static ssize_t show_set_buffer_size(struct most_c_obj *c,
+                                   struct most_c_attr *attr,
+                                   char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
+}
+
+static ssize_t store_set_buffer_size(struct most_c_obj *c,
+                                    struct most_c_attr *attr,
+                                    const char *buf,
+                                    size_t count)
+{
+       int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+static ssize_t show_set_direction(struct most_c_obj *c,
+                                 struct most_c_attr *attr,
+                                 char *buf)
+{
+       if (c->cfg.direction & MOST_CH_TX)
+               return snprintf(buf, PAGE_SIZE, "dir_tx\n");
+       else if (c->cfg.direction & MOST_CH_RX)
+               return snprintf(buf, PAGE_SIZE, "dir_rx\n");
+       return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t store_set_direction(struct most_c_obj *c,
+                                  struct most_c_attr *attr,
+                                  const char *buf,
+                                  size_t count)
+{
+       if (!strcmp(buf, "dir_rx\n"))
+               c->cfg.direction = MOST_CH_RX;
+       else if (!strcmp(buf, "dir_tx\n"))
+               c->cfg.direction = MOST_CH_TX;
+       else {
+               pr_info("WARN: invalid attribute settings\n");
+               return -EINVAL;
+       }
+       return count;
+}
+
+static ssize_t show_set_datatype(struct most_c_obj *c,
+                                struct most_c_attr *attr,
+                                char *buf)
+{
+       if (c->cfg.data_type & MOST_CH_CONTROL)
+               return snprintf(buf, PAGE_SIZE, "control\n");
+       else if (c->cfg.data_type & MOST_CH_ASYNC)
+               return snprintf(buf, PAGE_SIZE, "async\n");
+       else if (c->cfg.data_type & MOST_CH_SYNC)
+               return snprintf(buf, PAGE_SIZE, "sync\n");
+       else if (c->cfg.data_type & MOST_CH_ISOC_AVP)
+               return snprintf(buf, PAGE_SIZE, "isoc_avp\n");
+       return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t store_set_datatype(struct most_c_obj *c,
+                                 struct most_c_attr *attr,
+                                 const char *buf,
+                                 size_t count)
+{
+       if (!strcmp(buf, "control\n"))
+               c->cfg.data_type = MOST_CH_CONTROL;
+       else if (!strcmp(buf, "async\n"))
+               c->cfg.data_type = MOST_CH_ASYNC;
+       else if (!strcmp(buf, "sync\n"))
+               c->cfg.data_type = MOST_CH_SYNC;
+       else if (!strcmp(buf, "isoc_avp\n"))
+               c->cfg.data_type = MOST_CH_ISOC_AVP;
+       else {
+               pr_info("WARN: invalid attribute settings\n");
+               return -EINVAL;
+       }
+       return count;
+}
+
+static ssize_t show_set_subbuffer_size(struct most_c_obj *c,
+                                      struct most_c_attr *attr,
+                                      char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
+}
+
+static ssize_t store_set_subbuffer_size(struct most_c_obj *c,
+                                       struct most_c_attr *attr,
+                                       const char *buf,
+                                       size_t count)
+{
+       int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+static ssize_t show_set_packets_per_xact(struct most_c_obj *c,
+                                        struct most_c_attr *attr,
+                                        char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
+}
+
+static ssize_t store_set_packets_per_xact(struct most_c_obj *c,
+                                         struct most_c_attr *attr,
+                                         const char *buf,
+                                         size_t count)
+{
+       int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
+
+       if (ret)
+               return ret;
+       return count;
+}
+
+#define create_channel_attribute(value) \
+       static MOST_CHNL_ATTR(value, S_IRUGO | S_IWUSR, \
+                             show_##value, \
+                             store_##value)
+
+create_channel_attribute(set_buffer_size);
+create_channel_attribute(set_number_of_buffers);
+create_channel_attribute(set_direction);
+create_channel_attribute(set_datatype);
+create_channel_attribute(set_subbuffer_size);
+create_channel_attribute(set_packets_per_xact);
+
+
+/**
+ * most_channel_def_attrs - array of default attributes of channel object
+ */
+static struct attribute *most_channel_def_attrs[] = {
+       &most_chnl_attr_available_directions.attr,
+       &most_chnl_attr_available_datatypes.attr,
+       &most_chnl_attr_number_of_packet_buffers.attr,
+       &most_chnl_attr_number_of_stream_buffers.attr,
+       &most_chnl_attr_size_of_packet_buffer.attr,
+       &most_chnl_attr_size_of_stream_buffer.attr,
+       &most_chnl_attr_set_number_of_buffers.attr,
+       &most_chnl_attr_set_buffer_size.attr,
+       &most_chnl_attr_set_direction.attr,
+       &most_chnl_attr_set_datatype.attr,
+       &most_chnl_attr_set_subbuffer_size.attr,
+       &most_chnl_attr_set_packets_per_xact.attr,
+       &most_chnl_attr_channel_starving.attr,
+       NULL,
+};
+
+static struct kobj_type most_channel_ktype = {
+       .sysfs_ops = &most_channel_sysfs_ops,
+       .release = most_channel_release,
+       .default_attrs = most_channel_def_attrs,
+};
+
+static struct kset *most_channel_kset;
+
+/**
+ * create_most_c_obj - allocates a channel object
+ * @name: name of the channel object
+ * @parent: parent kobject
+ *
+ * This create a channel object and registers it with sysfs.
+ * Returns a pointer to the object or NULL when something went wrong.
+ */
+static struct most_c_obj *
+create_most_c_obj(const char *name, struct kobject *parent)
+{
+       struct most_c_obj *c;
+       int retval;
+
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c)
+               return NULL;
+       c->kobj.kset = most_channel_kset;
+       retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent,
+                                     "%s", name);
+       if (retval) {
+               kobject_put(&c->kobj);
+               return NULL;
+       }
+       kobject_uevent(&c->kobj, KOBJ_ADD);
+       return c;
+}
+
+/**
+ * destroy_most_c_obj - channel release function
+ * @c: pointer to channel object
+ *
+ * This decrements the reference counter of the channel object.
+ * If the reference count turns zero, its release function is called.
+ */
+static void destroy_most_c_obj(struct most_c_obj *c)
+{
+       if (c->first_aim)
+               c->first_aim->disconnect_channel(c->iface, c->channel_id);
+       if (c->second_aim)
+               c->second_aim->disconnect_channel(c->iface, c->channel_id);
+       c->first_aim = NULL;
+       c->second_aim = NULL;
+
+       mutex_lock(&deregister_mutex);
+       flush_trash_fifo(c);
+       flush_channel_fifos(c);
+       mutex_unlock(&deregister_mutex);
+       kobject_put(&c->kobj);
+}
+
+/*                  ___               ___
+ *                  ___I N S T A N C E___
+ */
+#define MOST_INST_ATTR(_name, _mode, _show, _store) \
+               struct most_inst_attribute most_inst_attr_##_name = \
+               __ATTR(_name, _mode, _show, _store)
+
+static struct list_head instance_list;
+
+/**
+ * struct most_inst_attribute - to access the attributes of instance object
+ * @attr: attributes of an instance
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_inst_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct most_inst_obj *d,
+                       struct most_inst_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct most_inst_obj *d,
+                        struct most_inst_attribute *attr,
+                        const char *buf,
+                        size_t count);
+};
+#define to_instance_attr(a) \
+       container_of(a, struct most_inst_attribute, attr)
+
+/**
+ * instance_attr_show - show function for an instance object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t instance_attr_show(struct kobject *kobj,
+                                 struct attribute *attr,
+                                 char *buf)
+{
+       struct most_inst_attribute *instance_attr;
+       struct most_inst_obj *instance_obj;
+
+       instance_attr = to_instance_attr(attr);
+       instance_obj = to_inst_obj(kobj);
+
+       if (!instance_attr->show)
+               return -EIO;
+
+       return instance_attr->show(instance_obj, instance_attr, buf);
+}
+
+/**
+ * instance_attr_store - store function for an instance object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t instance_attr_store(struct kobject *kobj,
+                                  struct attribute *attr,
+                                  const char *buf,
+                                  size_t len)
+{
+       struct most_inst_attribute *instance_attr;
+       struct most_inst_obj *instance_obj;
+
+       instance_attr = to_instance_attr(attr);
+       instance_obj = to_inst_obj(kobj);
+
+       if (!instance_attr->store)
+               return -EIO;
+
+       return instance_attr->store(instance_obj, instance_attr, buf, len);
+}
+
+static const struct sysfs_ops most_inst_sysfs_ops = {
+       .show = instance_attr_show,
+       .store = instance_attr_store,
+};
+
+/**
+ * most_inst_release - release function for instance object
+ * @kobj: pointer to instance's kobject
+ *
+ * This frees the allocated memory for the instance object
+ */
+static void most_inst_release(struct kobject *kobj)
+{
+       struct most_inst_obj *inst = to_inst_obj(kobj);
+
+       kfree(inst);
+}
+
+static ssize_t show_description(struct most_inst_obj *instance_obj,
+                               struct most_inst_attribute *attr,
+                               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       instance_obj->iface->description);
+}
+
+static ssize_t show_interface(struct most_inst_obj *instance_obj,
+                             struct most_inst_attribute *attr,
+                             char *buf)
+{
+       switch (instance_obj->iface->interface) {
+       case ITYPE_LOOPBACK:
+               return snprintf(buf, PAGE_SIZE, "loopback\n");
+       case ITYPE_I2C:
+               return snprintf(buf, PAGE_SIZE, "i2c\n");
+       case ITYPE_I2S:
+               return snprintf(buf, PAGE_SIZE, "i2s\n");
+       case ITYPE_TSI:
+               return snprintf(buf, PAGE_SIZE, "tsi\n");
+       case ITYPE_HBI:
+               return snprintf(buf, PAGE_SIZE, "hbi\n");
+       case ITYPE_MEDIALB_DIM:
+               return snprintf(buf, PAGE_SIZE, "mlb_dim\n");
+       case ITYPE_MEDIALB_DIM2:
+               return snprintf(buf, PAGE_SIZE, "mlb_dim2\n");
+       case ITYPE_USB:
+               return snprintf(buf, PAGE_SIZE, "usb\n");
+       case ITYPE_PCIE:
+               return snprintf(buf, PAGE_SIZE, "pcie\n");
+       }
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+#define create_inst_attribute(value) \
+       static MOST_INST_ATTR(value, S_IRUGO, show_##value, NULL)
+
+create_inst_attribute(description);
+create_inst_attribute(interface);
+
+static struct attribute *most_inst_def_attrs[] = {
+       &most_inst_attr_description.attr,
+       &most_inst_attr_interface.attr,
+       NULL,
+};
+
+static struct kobj_type most_inst_ktype = {
+       .sysfs_ops = &most_inst_sysfs_ops,
+       .release = most_inst_release,
+       .default_attrs = most_inst_def_attrs,
+};
+
+static struct kset *most_inst_kset;
+
+
+/**
+ * create_most_inst_obj - creates an instance object
+ * @name: name of the object to be created
+ *
+ * This allocates memory for an instance structure, assigns the proper kset
+ * and registers it with sysfs.
+ *
+ * Returns a pointer to the instance object or NULL when something went wrong.
+ */
+static struct most_inst_obj *create_most_inst_obj(const char *name)
+{
+       struct most_inst_obj *inst;
+       int retval;
+
+       inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+       if (!inst)
+               return NULL;
+       inst->kobj.kset = most_inst_kset;
+       retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL,
+                                     "%s", name);
+       if (retval) {
+               kobject_put(&inst->kobj);
+               return NULL;
+       }
+       kobject_uevent(&inst->kobj, KOBJ_ADD);
+       return inst;
+}
+
+/**
+ * destroy_most_inst_obj - MOST instance release function
+ * @inst: pointer to the instance object
+ *
+ * This decrements the reference counter of the instance object.
+ * If the reference count turns zero, its release function is called
+ */
+static void destroy_most_inst_obj(struct most_inst_obj *inst)
+{
+       struct most_c_obj *c, *tmp;
+
+       /* need to destroy channels first, since
+        * each channel incremented the
+        * reference count of the inst->kobj
+        */
+       list_for_each_entry_safe(c, tmp, &inst->channel_list, list) {
+               destroy_most_c_obj(c);
+       }
+       kobject_put(&inst->kobj);
+}
+
+/*                  ___     ___
+ *                  ___A I M___
+ */
+struct most_aim_obj {
+       struct kobject kobj;
+       struct list_head list;
+       struct most_aim *driver;
+       char add_link[STRING_SIZE];
+       char remove_link[STRING_SIZE];
+};
+#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
+
+static struct list_head aim_list;
+
+
+/**
+ * struct most_aim_attribute - to access the attributes of AIM object
+ * @attr: attributes of an AIM
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_aim_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct most_aim_obj *d,
+                       struct most_aim_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct most_aim_obj *d,
+                        struct most_aim_attribute *attr,
+                        const char *buf,
+                        size_t count);
+};
+#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
+
+/**
+ * aim_attr_show - show function of an AIM object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t aim_attr_show(struct kobject *kobj,
+                            struct attribute *attr,
+                            char *buf)
+{
+       struct most_aim_attribute *aim_attr;
+       struct most_aim_obj *aim_obj;
+
+       aim_attr = to_aim_attr(attr);
+       aim_obj = to_aim_obj(kobj);
+
+       if (!aim_attr->show)
+               return -EIO;
+
+       return aim_attr->show(aim_obj, aim_attr, buf);
+}
+
+/**
+ * aim_attr_store - store function of an AIM object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t aim_attr_store(struct kobject *kobj,
+                             struct attribute *attr,
+                             const char *buf,
+                             size_t len)
+{
+       struct most_aim_attribute *aim_attr;
+       struct most_aim_obj *aim_obj;
+
+       aim_attr = to_aim_attr(attr);
+       aim_obj = to_aim_obj(kobj);
+
+       if (!aim_attr->store)
+               return -EIO;
+       return aim_attr->store(aim_obj, aim_attr, buf, len);
+}
+
+static const struct sysfs_ops most_aim_sysfs_ops = {
+       .show = aim_attr_show,
+       .store = aim_attr_store,
+};
+
+/**
+ * most_aim_release - AIM release function
+ * @kobj: pointer to AIM's kobject
+ */
+static void most_aim_release(struct kobject *kobj)
+{
+       struct most_aim_obj *aim_obj = to_aim_obj(kobj);
+
+       kfree(aim_obj);
+}
+
+static ssize_t show_add_link(struct most_aim_obj *aim_obj,
+                            struct most_aim_attribute *attr,
+                            char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->add_link);
+}
+
+/**
+ * split_string - parses and changes string in the buffer buf and
+ * splits it into two mandatory and one optional substrings.
+ *
+ * @buf: complete string from attribute 'add_channel'
+ * @a: address of pointer to 1st substring (=instance name)
+ * @b: address of pointer to 2nd substring (=channel name)
+ * @c: optional address of pointer to 3rd substring (=user defined name)
+ *
+ * Examples:
+ *
+ * Input: "mdev0:ch0@ep_81:my_channel\n" or
+ *        "mdev0:ch0@ep_81:my_channel"
+ *
+ * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> "my_channel"
+ *
+ * Input: "mdev0:ch0@ep_81\n"
+ * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> ""
+ *
+ * Input: "mdev0:ch0@ep_81"
+ * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c == NULL
+ */
+static int split_string(char *buf, char **a, char **b, char **c)
+{
+       *a = strsep(&buf, ":");
+       if (!*a)
+               return -EIO;
+
+       *b = strsep(&buf, ":\n");
+       if (!*b)
+               return -EIO;
+
+       if (c)
+               *c = strsep(&buf, ":\n");
+
+       return 0;
+}
+
+/**
+ * get_channel_by_name - get pointer to channel object
+ * @mdev: name of the device instance
+ * @mdev_ch: name of the respective channel
+ *
+ * This retrieves the pointer to a channel object.
+ */
+static struct
+most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
+{
+       struct most_c_obj *c, *tmp;
+       struct most_inst_obj *i, *i_tmp;
+       int found = 0;
+
+       list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+               if (!strcmp(kobject_name(&i->kobj), mdev)) {
+                       found++;
+                       break;
+               }
+       }
+       if (unlikely(!found))
+               return ERR_PTR(-EIO);
+
+       list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
+               if (!strcmp(kobject_name(&c->kobj), mdev_ch)) {
+                       found++;
+                       break;
+               }
+       }
+       if (unlikely(2 > found))
+               return ERR_PTR(-EIO);
+       return c;
+}
+
+/**
+ * store_add_link - store() function for add_link attribute
+ * @aim_obj: pointer to AIM object
+ * @attr: its attributes
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * This parses the string given by buf and splits it into
+ * three substrings. Note: third substring is optional. In case a cdev
+ * AIM is loaded the optional 3rd substring will make up the name of
+ * device node in the /dev directory. If omitted, the device node will
+ * inherit the channel's name within sysfs.
+ *
+ * Searches for a pair of device and channel and probes the AIM
+ *
+ * Example:
+ * (1) echo -n -e "mdev0:ch0@ep_81:my_rxchannel\n" >add_link
+ * (2) echo -n -e "mdev0:ch0@ep_81\n" >add_link
+ *
+ * (1) would create the device node /dev/my_rxchannel
+ * (2) would create the device node /dev/mdev0-ch0@ep_81
+ */
+static ssize_t store_add_link(struct most_aim_obj *aim_obj,
+                             struct most_aim_attribute *attr,
+                             const char *buf,
+                             size_t len)
+{
+       struct most_c_obj *c;
+       struct most_aim **aim_ptr;
+       char buffer[STRING_SIZE];
+       char *mdev;
+       char *mdev_ch;
+       char *mdev_devnod;
+       char devnod_buf[STRING_SIZE];
+       int ret;
+       size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+       strlcpy(buffer, buf, max_len);
+       strlcpy(aim_obj->add_link, buf, max_len);
+
+       ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod);
+       if (ret)
+               return ret;
+
+       if (!mdev_devnod || *mdev_devnod == 0) {
+               snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch);
+               mdev_devnod = devnod_buf;
+       }
+
+       c = get_channel_by_name(mdev, mdev_ch);
+       if (IS_ERR(c))
+               return -ENODEV;
+
+       if (!c->first_aim)
+               aim_ptr = &c->first_aim;
+       else if (!c->second_aim)
+               aim_ptr = &c->second_aim;
+       else
+               return -ENOSPC;
+
+       ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
+                                            &c->cfg, &c->kobj, mdev_devnod);
+       if (ret)
+               return ret;
+       *aim_ptr = aim_obj->driver;
+       return len;
+}
+
+static struct most_aim_attribute most_aim_attr_add_link =
+       __ATTR(add_link, S_IRUGO | S_IWUSR, show_add_link, store_add_link);
+
+static ssize_t show_remove_link(struct most_aim_obj *aim_obj,
+                               struct most_aim_attribute *attr,
+                               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->remove_link);
+}
+
+/**
+ * store_remove_link - store function for remove_link attribute
+ * @aim_obj: pointer to AIM object
+ * @attr: its attributes
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * Example:
+ * echo -n -e "mdev0:ch0@ep_81\n" >remove_link
+ */
+static ssize_t store_remove_link(struct most_aim_obj *aim_obj,
+                                struct most_aim_attribute *attr,
+                                const char *buf,
+                                size_t len)
+{
+       struct most_c_obj *c;
+       char buffer[STRING_SIZE];
+       char *mdev;
+       char *mdev_ch;
+       int ret;
+       size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+       strlcpy(buffer, buf, max_len);
+       strlcpy(aim_obj->remove_link, buf, max_len);
+       ret = split_string(buffer, &mdev, &mdev_ch, NULL);
+       if (ret)
+               return ret;
+
+       c = get_channel_by_name(mdev, mdev_ch);
+       if (IS_ERR(c))
+               return -ENODEV;
+
+       if (c->first_aim == aim_obj->driver)
+               c->first_aim = NULL;
+       if (c->second_aim == aim_obj->driver)
+               c->second_aim = NULL;
+       if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
+               return -EIO;
+       return len;
+}
+
+static struct most_aim_attribute most_aim_attr_remove_link =
+       __ATTR(remove_link, S_IRUGO | S_IWUSR, show_remove_link, store_remove_link);
+
+static struct attribute *most_aim_def_attrs[] = {
+       &most_aim_attr_add_link.attr,
+       &most_aim_attr_remove_link.attr,
+       NULL,
+};
+
+static struct kobj_type most_aim_ktype = {
+       .sysfs_ops = &most_aim_sysfs_ops,
+       .release = most_aim_release,
+       .default_attrs = most_aim_def_attrs,
+};
+
+static struct kset *most_aim_kset;
+
+/**
+ * create_most_aim_obj - creates an AIM object
+ * @name: name of the AIM
+ *
+ * This creates an AIM object assigns the proper kset and registers
+ * it with sysfs.
+ * Returns a pointer to the object or NULL if something went wrong.
+ */
+static struct most_aim_obj *create_most_aim_obj(const char *name)
+{
+       struct most_aim_obj *most_aim;
+       int retval;
+
+       most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL);
+       if (!most_aim)
+               return NULL;
+       most_aim->kobj.kset = most_aim_kset;
+       retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype,
+                                     NULL, "%s", name);
+       if (retval) {
+               kobject_put(&most_aim->kobj);
+               return NULL;
+       }
+       kobject_uevent(&most_aim->kobj, KOBJ_ADD);
+       return most_aim;
+}
+
+/**
+ * destroy_most_aim_obj - AIM release function
+ * @p: pointer to AIM object
+ *
+ * This decrements the reference counter of the AIM object. If the
+ * reference count turns zero, its release function will be called.
+ */
+static void destroy_most_aim_obj(struct most_aim_obj *p)
+{
+       kobject_put(&p->kobj);
+}
+
+
+/*                  ___       ___
+ *                  ___C O R E___
+ */
+
+/**
+ * Instantiation of the MOST bus
+ */
+static struct bus_type most_bus = {
+       .name = "most",
+};
+
+/**
+ * Instantiation of the core driver
+ */
+static struct device_driver mostcore = {
+       .name = "mostcore",
+       .bus = &most_bus,
+};
+
+static inline void trash_mbo(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_c_obj *c = mbo->context;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_add(&mbo->list, &c->trash_fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+}
+
+static struct mbo *get_hdm_mbo(struct most_c_obj *c)
+{
+       unsigned long flags;
+       struct mbo *mbo;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       if (c->enqueue_halt || list_empty(&c->halt_fifo))
+               mbo = NULL;
+       else
+               mbo = list_pop_mbo(&c->halt_fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       return mbo;
+}
+
+static void nq_hdm_mbo(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_c_obj *c = mbo->context;
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_add_tail(&mbo->list, &c->halt_fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       wake_up_interruptible(&c->hdm_fifo_wq);
+}
+
+static int hdm_enqueue_thread(void *data)
+{
+       struct most_c_obj *c = data;
+       struct mbo *mbo;
+       typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
+
+       while (likely(!kthread_should_stop())) {
+               wait_event_interruptible(c->hdm_fifo_wq,
+                                        (mbo = get_hdm_mbo(c))
+                                        || kthread_should_stop());
+
+               if (unlikely(!mbo))
+                       continue;
+
+               if (c->cfg.direction == MOST_CH_RX)
+                       mbo->buffer_length = c->cfg.buffer_size;
+
+               if (unlikely(enqueue(mbo->ifp, mbo->hdm_channel_id, mbo))) {
+                       pr_err("hdm enqueue failed\n");
+                       nq_hdm_mbo(mbo);
+                       c->hdm_enqueue_task = NULL;
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
+{
+       struct task_struct *task =
+               kthread_run(&hdm_enqueue_thread, c, "hdm_fifo_%d", channel_id);
+
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+
+       c->hdm_enqueue_task = task;
+       return 0;
+}
+
+/**
+ * arm_mbo - recycle MBO for further usage
+ * @mbo: buffer object
+ *
+ * This puts an MBO back to the list to have it ready for up coming
+ * tx transactions.
+ *
+ * In case the MBO belongs to a channel that recently has been
+ * poisoned, the MBO is scheduled to be trashed.
+ * Calls the completion handler of an attached AIM.
+ */
+static void arm_mbo(struct mbo *mbo)
+{
+       unsigned long flags;
+       struct most_c_obj *c;
+
+       BUG_ON((!mbo) || (!mbo->context));
+       c = mbo->context;
+
+       if (c->is_poisoned) {
+               trash_mbo(mbo);
+               return;
+       }
+
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       list_add_tail(&mbo->list, &c->fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+       if (c->second_aim && c->second_aim->tx_completion)
+               c->second_aim->tx_completion(c->iface, c->channel_id);
+       if (c->first_aim && c->first_aim->tx_completion)
+               c->first_aim->tx_completion(c->iface, c->channel_id);
+}
+
+/**
+ * arm_mbo_chain - helper function that arms an MBO chain for the HDM
+ * @c: pointer to interface channel
+ * @dir: direction of the channel
+ * @compl: pointer to completion function
+ *
+ * This allocates buffer objects including the containing DMA coherent
+ * buffer and puts them in the fifo.
+ * Buffers of Rx channels are put in the kthread fifo, hence immediately
+ * submitted to the HDM.
+ *
+ * Returns the number of allocated and enqueued MBOs.
+ */
+static int arm_mbo_chain(struct most_c_obj *c, int dir,
+                        void (*compl)(struct mbo *))
+{
+       unsigned int i;
+       int retval;
+       struct mbo *mbo;
+       u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+       atomic_set(&c->mbo_nq_level, 0);
+
+       for (i = 0; i < c->cfg.num_buffers; i++) {
+               mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
+               if (!mbo) {
+                       pr_info("WARN: Allocation of MBO failed.\n");
+                       retval = i;
+                       goto _exit;
+               }
+               mbo->context = c;
+               mbo->ifp = c->iface;
+               mbo->hdm_channel_id = c->channel_id;
+               mbo->virt_address = dma_alloc_coherent(NULL,
+                                                      coherent_buf_size,
+                                                      &mbo->bus_address,
+                                                      GFP_KERNEL);
+               if (!mbo->virt_address) {
+                       pr_info("WARN: No DMA coherent buffer.\n");
+                       retval = i;
+                       goto _error1;
+               }
+               mbo->complete = compl;
+               if (dir == MOST_CH_RX) {
+                       nq_hdm_mbo(mbo);
+                       atomic_inc(&c->mbo_nq_level);
+               } else {
+                       arm_mbo(mbo);
+               }
+       }
+       return i;
+
+_error1:
+       kfree(mbo);
+_exit:
+       return retval;
+}
+
+/**
+ * most_submit_mbo - submits an MBO to fifo
+ * @mbo: pointer to the MBO
+ *
+ */
+int most_submit_mbo(struct mbo *mbo)
+{
+       struct most_c_obj *c;
+       struct most_inst_obj *i;
+
+       if (unlikely((!mbo) || (!mbo->context))) {
+               pr_err("Bad MBO or missing channel reference\n");
+               return -EINVAL;
+       }
+       c = mbo->context;
+       i = c->inst;
+
+       if (unlikely(atomic_read(&i->tainted)))
+               return -ENODEV;
+
+       nq_hdm_mbo(mbo);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_submit_mbo);
+
+/**
+ * most_write_completion - write completion handler
+ * @mbo: pointer to MBO
+ *
+ * This recycles the MBO for further usage. In case the channel has been
+ * poisoned, the MBO is scheduled to be trashed.
+ */
+static void most_write_completion(struct mbo *mbo)
+{
+       struct most_c_obj *c;
+
+       BUG_ON((!mbo) || (!mbo->context));
+
+       c = mbo->context;
+       if (mbo->status == MBO_E_INVAL)
+               pr_info("WARN: Tx MBO status: invalid\n");
+       if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE)))
+               trash_mbo(mbo);
+       else
+               arm_mbo(mbo);
+}
+
+/**
+ * get_channel_by_iface - get pointer to channel object
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This retrieves a pointer to a channel of the given interface and channel ID.
+ */
+static struct
+most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
+{
+       struct most_inst_obj *i;
+
+       if (unlikely(!iface)) {
+               pr_err("Bad interface\n");
+               return NULL;
+       }
+       if (unlikely((id < 0) || (id >= iface->num_channels))) {
+               pr_err("Channel index (%d) out of range\n", id);
+               return NULL;
+       }
+       i = iface->priv;
+       if (unlikely(!i)) {
+               pr_err("interface is not registered\n");
+               return NULL;
+       }
+       return i->channel[id];
+}
+
+/**
+ * most_get_mbo - get pointer to an MBO of pool
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This attempts to get a free buffer out of the channel fifo.
+ * Returns a pointer to MBO on success or NULL otherwise.
+ */
+struct mbo *most_get_mbo(struct most_interface *iface, int id)
+{
+       struct mbo *mbo;
+       struct most_c_obj *c;
+       unsigned long flags;
+
+       c = get_channel_by_iface(iface, id);
+       if (unlikely(!c))
+               return NULL;
+       spin_lock_irqsave(&c->fifo_lock, flags);
+       if (list_empty(&c->fifo)) {
+               spin_unlock_irqrestore(&c->fifo_lock, flags);
+               return NULL;
+       }
+       mbo = list_pop_mbo(&c->fifo);
+       spin_unlock_irqrestore(&c->fifo_lock, flags);
+       mbo->buffer_length = c->cfg.buffer_size;
+       return mbo;
+}
+EXPORT_SYMBOL_GPL(most_get_mbo);
+
+
+/**
+ * most_put_mbo - return buffer to pool
+ * @mbo: buffer object
+ */
+void most_put_mbo(struct mbo *mbo)
+{
+       struct most_c_obj *c;
+       struct most_inst_obj *i;
+
+       c = mbo->context;
+       i = c->inst;
+
+       if (unlikely(atomic_read(&i->tainted))) {
+               mbo->status = MBO_E_CLOSE;
+               trash_mbo(mbo);
+               return;
+       }
+       if (c->cfg.direction == MOST_CH_TX) {
+               arm_mbo(mbo);
+               return;
+       }
+       nq_hdm_mbo(mbo);
+       atomic_inc(&c->mbo_nq_level);
+}
+EXPORT_SYMBOL_GPL(most_put_mbo);
+
+/**
+ * most_read_completion - read completion handler
+ * @mbo: pointer to MBO
+ *
+ * This function is called by the HDM when data has been received from the
+ * hardware and copied to the buffer of the MBO.
+ *
+ * In case the channel has been poisoned it puts the buffer in the trash queue.
+ * Otherwise, it passes the buffer to an AIM for further processing.
+ */
+static void most_read_completion(struct mbo *mbo)
+{
+       struct most_c_obj *c;
+
+       c = mbo->context;
+       if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE)))
+               goto release_mbo;
+
+       if (mbo->status == MBO_E_INVAL) {
+               nq_hdm_mbo(mbo);
+               atomic_inc(&c->mbo_nq_level);
+               return;
+       }
+
+       if (atomic_sub_and_test(1, &c->mbo_nq_level)) {
+               pr_info("WARN: rx device out of buffers\n");
+               c->is_starving = 1;
+       }
+
+       if (c->first_aim && c->first_aim->rx_completion &&
+           c->first_aim->rx_completion(mbo) == 0)
+               return;
+       if (c->second_aim && c->second_aim->rx_completion &&
+           c->second_aim->rx_completion(mbo) == 0)
+               return;
+       pr_info("WARN: no driver linked with this channel\n");
+       mbo->status = MBO_E_CLOSE;
+release_mbo:
+       trash_mbo(mbo);
+}
+
+/**
+ * most_start_channel - prepares a channel for communication
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This prepares the channel for usage. Cross-checks whether the
+ * channel's been properly configured.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+int most_start_channel(struct most_interface *iface, int id)
+{
+       int num_buffer;
+       int ret;
+       struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+       if (unlikely(!c))
+               return -EINVAL;
+
+       if (c->is_started)
+               return -EBUSY;
+
+       if (!try_module_get(iface->mod)) {
+               pr_info("failed to acquire HDM lock\n");
+               return -ENOLCK;
+       }
+       modref++;
+
+       c->cfg.extra_len = 0;
+       if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
+               pr_info("channel configuration failed. Go check settings...\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       init_waitqueue_head(&c->hdm_fifo_wq);
+
+       if (c->cfg.direction == MOST_CH_RX)
+               num_buffer = arm_mbo_chain(c, c->cfg.direction,
+                                          most_read_completion);
+       else
+               num_buffer = arm_mbo_chain(c, c->cfg.direction,
+                                          most_write_completion);
+       if (unlikely(0 == num_buffer)) {
+               pr_info("failed to allocate memory\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       ret = run_enqueue_thread(c, id);
+       if (ret)
+               goto error;
+
+       c->is_started = true;
+       c->is_starving = 0;
+       atomic_set(&c->mbo_ref, num_buffer);
+       return 0;
+error:
+       if (iface->mod)
+               module_put(iface->mod);
+       modref--;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(most_start_channel);
+
+/**
+ * most_stop_channel - stops a running channel
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ */
+int most_stop_channel(struct most_interface *iface, int id)
+{
+       struct most_c_obj *c;
+
+       if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
+               pr_err("Bad interface or index out of range\n");
+               return -EINVAL;
+       }
+       c = get_channel_by_iface(iface, id);
+       if (unlikely(!c))
+               return -EINVAL;
+
+       if (!c->is_started)
+               return 0;
+
+       /* FIXME: we need to know calling AIM to reset only one link */
+       c->first_aim = NULL;
+       c->second_aim = NULL;
+       /* do not go into recursion calling aim->disconnect_channel */
+
+       mutex_lock(&c->stop_task_mutex);
+       if (c->hdm_enqueue_task)
+               kthread_stop(c->hdm_enqueue_task);
+       c->hdm_enqueue_task = NULL;
+       mutex_unlock(&c->stop_task_mutex);
+
+       mutex_lock(&deregister_mutex);
+       if (atomic_read(&c->inst->tainted)) {
+               mutex_unlock(&deregister_mutex);
+               return -ENODEV;
+       }
+       mutex_unlock(&deregister_mutex);
+
+       if (iface->mod && modref) {
+               module_put(iface->mod);
+               modref--;
+       }
+
+       c->is_poisoned = true;
+       if (c->iface->poison_channel(c->iface, c->channel_id)) {
+               pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
+                      c->iface->description);
+               return -EAGAIN;
+       }
+       flush_trash_fifo(c);
+       flush_channel_fifos(c);
+
+#ifdef CMPL_INTERRUPTIBLE
+       if (wait_for_completion_interruptible(&c->cleanup)) {
+               pr_info("Interrupted while clean up ch %d\n", c->channel_id);
+               return -EINTR;
+       }
+#else
+       wait_for_completion(&c->cleanup);
+#endif
+       c->is_poisoned = false;
+       c->is_started = false;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_stop_channel);
+
+/**
+ * most_register_aim - registers an AIM (driver) with the core
+ * @aim: instance of AIM to be registered
+ */
+int most_register_aim(struct most_aim *aim)
+{
+       struct most_aim_obj *aim_obj;
+
+       if (!aim) {
+               pr_err("Bad driver\n");
+               return -EINVAL;
+       }
+       aim_obj = create_most_aim_obj(aim->name);
+       if (!aim_obj) {
+               pr_info("failed to alloc driver object\n");
+               return -ENOMEM;
+       }
+       aim_obj->driver = aim;
+       aim->context = aim_obj;
+       pr_info("registered new application interfacing module %s\n",
+               aim->name);
+       list_add_tail(&aim_obj->list, &aim_list);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_register_aim);
+
+/**
+ * most_deregister_aim - deregisters an AIM (driver) with the core
+ * @aim: AIM to be removed
+ */
+int most_deregister_aim(struct most_aim *aim)
+{
+       struct most_aim_obj *aim_obj;
+       struct most_c_obj *c, *tmp;
+       struct most_inst_obj *i, *i_tmp;
+
+       if (!aim) {
+               pr_err("Bad driver\n");
+               return -EINVAL;
+       }
+
+       aim_obj = aim->context;
+       if (!aim_obj) {
+               pr_info("driver not registered.\n");
+               return -EINVAL;
+       }
+       list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+               list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
+                       if (c->first_aim == aim || c->second_aim == aim)
+                               aim->disconnect_channel(
+                                       c->iface, c->channel_id);
+                       if (c->first_aim == aim)
+                               c->first_aim = NULL;
+                       if (c->second_aim == aim)
+                               c->second_aim = NULL;
+               }
+       }
+       list_del(&aim_obj->list);
+       destroy_most_aim_obj(aim_obj);
+       pr_info("deregistering application interfacing module %s\n", aim->name);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(most_deregister_aim);
+
+/**
+ * most_register_interface - registers an interface with core
+ * @iface: pointer to the instance of the interface description.
+ *
+ * Allocates and initializes a new interface instance and all of its channels.
+ * Returns a pointer to kobject or an error pointer.
+ */
+struct kobject *most_register_interface(struct most_interface *iface)
+{
+       unsigned int i;
+       int id;
+       char name[STRING_SIZE];
+       char channel_name[STRING_SIZE];
+       struct most_c_obj *c;
+       struct most_inst_obj *inst;
+
+       if (!iface || !iface->enqueue || !iface->configure ||
+           !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
+               pr_err("Bad interface or channel overflow\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
+       if (id < 0) {
+               pr_info("Failed to alloc mdev ID\n");
+               return ERR_PTR(id);
+       }
+       snprintf(name, STRING_SIZE, "mdev%d", id);
+
+       inst = create_most_inst_obj(name);
+       if (!inst) {
+               pr_info("Failed to allocate interface instance\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       iface->priv = inst;
+       INIT_LIST_HEAD(&inst->channel_list);
+       inst->iface = iface;
+       inst->dev_id = id;
+       atomic_set(&inst->tainted, 0);
+       list_add_tail(&inst->list, &instance_list);
+
+       for (i = 0; i < iface->num_channels; i++) {
+               const char *name_suffix = iface->channel_vector[i].name_suffix;
+
+               if (!name_suffix)
+                       snprintf(channel_name, STRING_SIZE, "ch%d", i);
+               else if (name_suffix[0] == '@')
+                       snprintf(channel_name, STRING_SIZE, "ch%d%s", i,
+                                name_suffix);
+               else
+                       snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
+
+               /* this increments the reference count of this instance */
+               c = create_most_c_obj(channel_name, &inst->kobj);
+               if (!c)
+                       goto free_instance;
+               inst->channel[i] = c;
+               c->is_starving = 0;
+               c->iface = iface;
+               c->inst = inst;
+               c->channel_id = i;
+               c->keep_mbo = false;
+               c->enqueue_halt = false;
+               c->is_poisoned = false;
+               c->is_started = false;
+               c->cfg.direction = 0;
+               c->cfg.data_type = 0;
+               c->cfg.num_buffers = 0;
+               c->cfg.buffer_size = 0;
+               c->cfg.subbuffer_size = 0;
+               c->cfg.packets_per_xact = 0;
+               spin_lock_init(&c->fifo_lock);
+               INIT_LIST_HEAD(&c->fifo);
+               INIT_LIST_HEAD(&c->trash_fifo);
+               INIT_LIST_HEAD(&c->halt_fifo);
+               init_completion(&c->cleanup);
+               atomic_set(&c->mbo_ref, 0);
+               mutex_init(&c->stop_task_mutex);
+               list_add_tail(&c->list, &inst->channel_list);
+       }
+       pr_info("registered new MOST device mdev%d (%s)\n",
+               inst->dev_id, iface->description);
+       return &inst->kobj;
+
+free_instance:
+       pr_info("Failed allocate channel(s)\n");
+       list_del(&inst->list);
+       destroy_most_inst_obj(inst);
+       return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(most_register_interface);
+
+/**
+ * most_deregister_interface - deregisters an interface with core
+ * @iface: pointer to the interface instance description.
+ *
+ * Before removing an interface instance from the list, all running
+ * channels are stopped and poisoned.
+ */
+void most_deregister_interface(struct most_interface *iface)
+{
+       struct most_inst_obj *i = iface->priv;
+       struct most_c_obj *c;
+
+       mutex_lock(&deregister_mutex);
+       if (unlikely(!i)) {
+               pr_info("Bad Interface\n");
+               mutex_unlock(&deregister_mutex);
+               return;
+       }
+       pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
+               iface->description);
+
+       atomic_set(&i->tainted, 1);
+       mutex_unlock(&deregister_mutex);
+
+       while (modref) {
+               if (iface->mod && modref)
+                       module_put(iface->mod);
+               modref--;
+       }
+
+       list_for_each_entry(c, &i->channel_list, list) {
+               if (!c->is_started)
+                       continue;
+
+               mutex_lock(&c->stop_task_mutex);
+               if (c->hdm_enqueue_task)
+                       kthread_stop(c->hdm_enqueue_task);
+               c->hdm_enqueue_task = NULL;
+               mutex_unlock(&c->stop_task_mutex);
+
+               if (iface->poison_channel(iface, c->channel_id))
+                       pr_err("Can't poison channel %d\n", c->channel_id);
+       }
+       ida_simple_remove(&mdev_id, i->dev_id);
+       list_del(&i->list);
+       destroy_most_inst_obj(i);
+}
+EXPORT_SYMBOL_GPL(most_deregister_interface);
+
+/**
+ * most_stop_enqueue - prevents core from enqueueing MBOs
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This is called by an HDM that _cannot_ attend to its duties and
+ * is imminent to get run over by the core. The core is not going to
+ * enqueue any further packets unless the flagging HDM calls
+ * most_resume enqueue().
+ */
+void most_stop_enqueue(struct most_interface *iface, int id)
+{
+       struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+       if (likely(c))
+               c->enqueue_halt = true;
+}
+EXPORT_SYMBOL_GPL(most_stop_enqueue);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * sitting in the wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int id)
+{
+       struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+       if (unlikely(!c))
+               return;
+       c->enqueue_halt = false;
+
+       wake_up_interruptible(&c->hdm_fifo_wq);
+}
+EXPORT_SYMBOL_GPL(most_resume_enqueue);
+
+static int __init most_init(void)
+{
+       pr_info("init()\n");
+       INIT_LIST_HEAD(&instance_list);
+       INIT_LIST_HEAD(&aim_list);
+       mutex_init(&deregister_mutex);
+       ida_init(&mdev_id);
+
+       if (bus_register(&most_bus)) {
+               pr_info("Cannot register most bus\n");
+               goto exit;
+       }
+
+       most_class = class_create(THIS_MODULE, "most");
+       if (IS_ERR(most_class)) {
+               pr_info("No udev support.\n");
+               goto exit_bus;
+       }
+       if (driver_register(&mostcore)) {
+               pr_info("Cannot register core driver\n");
+               goto exit_class;
+       }
+
+       class_glue_dir =
+               device_create(most_class, NULL, 0, NULL, "mostcore");
+       if (!class_glue_dir)
+               goto exit_driver;
+
+       most_aim_kset =
+               kset_create_and_add("aims", NULL, &class_glue_dir->kobj);
+       if (!most_aim_kset)
+               goto exit_class_container;
+
+       most_inst_kset =
+               kset_create_and_add("devices", NULL, &class_glue_dir->kobj);
+       if (!most_inst_kset)
+               goto exit_driver_kset;
+
+       return 0;
+
+exit_driver_kset:
+       kset_unregister(most_aim_kset);
+exit_class_container:
+       device_destroy(most_class, 0);
+exit_driver:
+       driver_unregister(&mostcore);
+exit_class:
+       class_destroy(most_class);
+exit_bus:
+       bus_unregister(&most_bus);
+exit:
+       return -ENOMEM;
+}
+
+static void __exit most_exit(void)
+{
+       struct most_inst_obj *i, *i_tmp;
+       struct most_aim_obj *d, *d_tmp;
+
+       pr_info("exit core module\n");
+       list_for_each_entry_safe(d, d_tmp, &aim_list, list) {
+               destroy_most_aim_obj(d);
+       }
+
+       list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+               list_del(&i->list);
+               destroy_most_inst_obj(i);
+       }
+       kset_unregister(most_inst_kset);
+       kset_unregister(most_aim_kset);
+       device_destroy(most_class, 0);
+       driver_unregister(&mostcore);
+       class_destroy(most_class);
+       bus_unregister(&most_bus);
+       ida_destroy(&mdev_id);
+}
+
+module_init(most_init);
+module_exit(most_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Core module of stacked MOST Linux driver");
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
new file mode 100644 (file)
index 0000000..299c7d5
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * mostcore.h - Interface between MostCore,
+ *   Hardware Dependent Module (HDM) and Application Interface Module (AIM).
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * 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.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/*
+ * Authors:
+ *   Andrey Shvetsov <andrey.shvetsov@k2l.de>
+ *   Christian Gromm <christian.gromm@microchip.com>
+ *   Sebastian Graf
+ */
+
+#ifndef __MOST_CORE_H__
+#define __MOST_CORE_H__
+
+#include <linux/types.h>
+
+struct kobject;
+struct module;
+
+/**
+ * Interface type
+ */
+enum most_interface_type {
+       ITYPE_LOOPBACK = 1,
+       ITYPE_I2C,
+       ITYPE_I2S,
+       ITYPE_TSI,
+       ITYPE_HBI,
+       ITYPE_MEDIALB_DIM,
+       ITYPE_MEDIALB_DIM2,
+       ITYPE_USB,
+       ITYPE_PCIE
+};
+
+/**
+ * Channel direction.
+ */
+enum most_channel_direction {
+       MOST_CH_RX = 1 << 0,
+       MOST_CH_TX = 1 << 1,
+};
+
+/**
+ * Channel data type.
+ */
+enum most_channel_data_type {
+       MOST_CH_CONTROL = 1 << 0,
+       MOST_CH_ASYNC = 1 << 1,
+       MOST_CH_ISOC_AVP = 1 << 2,
+       MOST_CH_SYNC = 1 << 5,
+};
+
+
+enum mbo_status_flags {
+       /* MBO was processed successfully (data was send or received )*/
+       MBO_SUCCESS = 0,
+       /* The MBO contains wrong or missing information.  */
+       MBO_E_INVAL,
+       /* MBO was completed as HDM Channel will be closed */
+       MBO_E_CLOSE,
+};
+
+/**
+ * struct most_channel_capability - Channel capability
+ * @direction: Supported channel directions.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_direction. Zero is allowed value and means
+ * "channel may not be used".
+ * @data_type: Supported channel data types.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_data_type. Zero is allowed value and means
+ * "channel may not be used".
+ * @num_buffer_packet: Maximum number of buffers supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @buffer_size_packet: Maximum buffer size supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @num_buffer_streaming: Maximum number of buffers supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @buffer_size_streaming: Maximum buffer size supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @name_suffix: Optional suffix providean by an HDM that is attached to the
+ * regular channel name.
+ *
+ * Describes the capabilities of a MostCore channel like supported Data Types
+ * and directions. This information is provided by an HDM for the MostCore.
+ *
+ * The Core creates read only sysfs attribute files in
+ * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the
+ * following attributes:
+ *     -available_directions
+ *     -available_datatypes
+ *     -number_of_packet_buffers
+ *     -number_of_stream_buffers
+ *     -size_of_packet_buffer
+ *     -size_of_stream_buffer
+ * where content of each file is a string with all supported properties of this
+ * very channel attribute.
+ */
+struct most_channel_capability {
+       u16 direction;
+       u16 data_type;
+       u16 num_buffers_packet;
+       u16 buffer_size_packet;
+       u16 num_buffers_streaming;
+       u16 buffer_size_streaming;
+       char *name_suffix;
+};
+
+/**
+ * struct most_channel_config - stores channel configuration
+ * @direction: direction of the channel
+ * @data_type: data type travelling over this channel
+ * @num_buffers: number of buffers
+ * @buffer_size: size of a buffer for AIM.
+ * Buffer size may be cutted down by HDM in a configure callback
+ * to match to a given interface and channel type.
+ * @extra_len: additional buffer space for internal HDM purposes like padding.
+ * May be set by HDM in a configure callback if needed.
+ * @subbuffer_size: size of a subbuffer
+ * @packets_per_xact: number of MOST frames that are packet inside one USB
+ *                   packet. This is USB specific
+ *
+ * Describes the configuration for a MostCore channel. This information is
+ * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
+ * parameter of the "configure" function call.
+ */
+struct most_channel_config {
+       enum most_channel_direction direction;
+       enum most_channel_data_type data_type;
+       u16 num_buffers;
+       u16 buffer_size;
+       u16 extra_len;
+       u16 subbuffer_size;
+       u16 packets_per_xact;
+};
+
+/*
+ * struct mbo - MOST Buffer Object.
+ * @context: context for core completion handler
+ * @priv: private data for HDM
+ *
+ *     public: documented fields that are used for the communications
+ *     between MostCore and HDMs
+ *
+ * @list: list head for use by the mbo's current owner
+ * @ifp: (in) associated interface instance
+ * @hdm_channel_id: (in) HDM channel instance
+ * @virt_address: (in) kernel virtual address of the buffer
+ * @bus_address: (in) bus address of the buffer
+ * @buffer_length: (in) buffer payload length
+ * @processed_length: (out) processed length
+ * @status: (out) transfer status
+ * @complete: (in) completion routine
+ *
+ * The MostCore allocates and initializes the MBO.
+ *
+ * The HDM receives MBO for transfer from MostCore with the call to enqueue().
+ * The HDM copies the data to- or from the buffer depending on configured
+ * channel direction, set "processed_length" and "status" and completes
+ * the transfer procedure by calling the completion routine.
+ *
+ * At the end the MostCore deallocates the MBO or recycles it for further
+ * transfers for the same or different HDM.
+ *
+ * Directions of usage:
+ * The core driver should never access any MBO fields (even if marked
+ * as "public") while the MBO is owned by an HDM. The ownership starts with
+ * the call of enqueue() and ends with the call of its complete() routine.
+ *
+ *                                     II.
+ * Every HDM attached to the core driver _must_ ensure that it returns any MBO
+ * it owns (due to a previous call to enqueue() by the core driver) before it
+ * de-registers an interface or gets unloaded from the kernel. If this direction
+ * is violated memory leaks will occur, since the core driver does _not_ track
+ * MBOs it is currently not in control of.
+ *
+ */
+struct mbo {
+       void *context;
+       void *priv;
+       struct list_head list;
+       struct most_interface *ifp;
+       u16 hdm_channel_id;
+       void *virt_address;
+       dma_addr_t bus_address;
+       u16 buffer_length;
+       u16 processed_length;
+       enum mbo_status_flags status;
+       void (*complete)(struct mbo *);
+};
+
+/**
+ * Interface instance description.
+ *
+ * Describes one instance of an interface like Medusa PCIe or Vantage USB.
+ * This structure is allocated and initialized in the HDM. MostCore may not
+ * modify this structure.
+ *
+ * @interface Interface type. \sa most_interface_type.
+ * @description PRELIMINARY.
+ *   Unique description of the device instance from point of view of the
+ *   interface in free text form (ASCII).
+ *   It may be a hexadecimal presentation of the memory address for the MediaLB
+ *   IP or USB device ID with USB properties for USB interface, etc.
+ * @num_channels Number of channels and size of the channel_vector.
+ * @channel_vector Properties of the channels.
+ *   Array index represents channel ID by the driver.
+ * @configure Callback to change data type for the channel of the
+ *   interface instance. May be zero if the instance of the interface is not
+ *   configurable. Parameter channel_config describes direction and data
+ *   type for the channel, configured by the higher level. The content of
+ * @enqueue Delivers MBO to the HDM for processing.
+ *   After HDM completes Rx- or Tx- operation the processed MBO shall
+ *   be returned back to the MostCore using completion routine.
+ *   The reason to get the MBO delivered from the MostCore after the channel
+ *   is poisoned is the re-opening of the channel by the application.
+ *   In this case the HDM shall hold MBOs and service the channel as usual.
+ *   The HDM must be able to hold at least one MBO for each channel.
+ *   The callback returns a negative value on error, otherwise 0.
+ * @poison_channel Informs HDM about closing the channel. The HDM shall
+ *   cancel all transfers and synchronously or asynchronously return
+ *   all enqueued for this channel MBOs using the completion routine.
+ *   The callback returns a negative value on error, otherwise 0.
+ * @request_netinfo: triggers retrieving of network info from the HDM by
+ *   means of "Message exchange over MDP/MEP"
+ * @priv Private field used by mostcore to store context information.
+ */
+struct most_interface {
+       struct module *mod;
+       enum most_interface_type interface;
+       const char *description;
+       int num_channels;
+       struct most_channel_capability *channel_vector;
+       int (*configure)(struct most_interface *iface, int channel_idx,
+                        struct most_channel_config *channel_config);
+       int (*enqueue)(struct most_interface *iface, int channel_idx,
+                      struct mbo *mbo);
+       int (*poison_channel)(struct most_interface *iface, int channel_idx);
+       void (*request_netinfo)(struct most_interface *iface, int channel_idx);
+       void *priv;
+};
+
+/**
+ * struct most_aim - identifies MOST device driver to mostcore
+ * @name: Driver name
+ * @probe_channel: function for core to notify driver about channel connection
+ * @disconnect_channel: notification that a certain channel isn't available anymore
+ * @rx_completion: completion handler for received packets
+ * @tx_completion: completion handler for transmitted packets
+ * @context: context pointer to be used by mostcore
+ */
+struct most_aim {
+       const char *name;
+       int (*probe_channel)(struct most_interface *iface, int channel_idx,
+                            struct most_channel_config *cfg,
+                            struct kobject *parent, char *name);
+       int (*disconnect_channel)(struct most_interface *iface,
+                                 int channel_idx);
+       int (*rx_completion)(struct mbo *mbo);
+       int (*tx_completion)(struct most_interface *iface, int channel_idx);
+       void *context;
+};
+
+/**
+ * most_register_interface - Registers instance of the interface.
+ * @iface: Pointer to the interface instance description.
+ *
+ * Returns a pointer to the kobject of the generated instance.
+ *
+ * Note: HDM has to ensure that any reference held on the kobj is
+ * released before deregistering the interface.
+ */
+struct kobject *most_register_interface(struct most_interface *iface);
+
+/**
+ * Deregisters instance of the interface.
+ * @intf_instance Pointer to the interface instance description.
+ */
+void most_deregister_interface(struct most_interface *iface);
+int most_submit_mbo(struct mbo *mbo);
+
+/**
+ * most_stop_enqueue - prevents core from enqueing MBOs
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ */
+void most_stop_enqueue(struct most_interface *iface, int channel_idx);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * in wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int channel_idx);
+int most_register_aim(struct most_aim *aim);
+int most_deregister_aim(struct most_aim *aim);
+struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx);
+void most_put_mbo(struct mbo *mbo);
+int most_start_channel(struct most_interface *iface, int channel_idx);
+int most_stop_channel(struct most_interface *iface, int channel_idx);
+
+
+#endif /* MOST_CORE_H_ */
index 7285c64bac240099743f4427d9aa50e9a4dd77c4..ad30ce4206ef404241ab3a5a4f12994036f11321 100644 (file)
@@ -948,7 +948,6 @@ static const struct of_device_id spinand_dt[] = {
 static struct spi_driver spinand_driver = {
        .driver = {
                .name           = "mt29f",
-               .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
                .of_match_table = spinand_dt,
        },
index 7f2c24dc51b425a34d8cdeb1760d23818bf4a299..6c8e413b5b632d005d3693a985f9bf2e71a943dc 100644 (file)
@@ -101,7 +101,7 @@ struct spinand_cmd {
        u8              *rx_buf;        /* Rx buf */
 };
 
-extern int spinand_mtd(struct mtd_info *mtd);
-extern void spinand_mtd_release(struct mtd_info *mtd);
+int spinand_mtd(struct mtd_info *mtd);
+void spinand_mtd_release(struct mtd_info *mtd);
 
 #endif /* __LINUX_MTD_SPI_NAND_H */
index 77c3c3522afa2036e595ae35978105ca99be00db..e914147d737976701f1c87dda632c325e39ff103 100644 (file)
@@ -163,7 +163,7 @@ static void xls_gmac_init(void)
        switch (nlm_prom_info.board_major_version) {
        case 12:
                /* first block RGMII or XAUI, use RGMII */
-               ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII,
+               ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII;
                ndata0.tx_stnid[0] = FMN_STNID_GMAC0_TX0;
                ndata0.phy_addr[0] = 0;
 
index 13e03f0a0a4670804c677287c4c50059a43db777..2f65ec5a615cdf16ab84df59e7033285f9291c21 100644 (file)
@@ -1102,4 +1102,4 @@ struct xlr_net_priv {
        u64 *class_3_spill;
 };
 
-extern void xlr_set_gmac_speed(struct xlr_net_priv *priv);
+void xlr_set_gmac_speed(struct xlr_net_priv *priv);
index e271375053faa01729e1a91f096a4491e148dba0..2ec9de906ca326856cd6adc105e969bec2bb8504 100644 (file)
@@ -165,19 +165,18 @@ struct nvec_chip {
        int state;
 };
 
-extern int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
-                            short size);
+int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
+                    short size);
 
-extern struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
-                                       const unsigned char *data, short size);
+struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
+                                const unsigned char *data, short size);
 
-extern int nvec_register_notifier(struct nvec_chip *nvec,
-                                 struct notifier_block *nb,
-                                 unsigned int events);
+int nvec_register_notifier(struct nvec_chip *nvec,
+                          struct notifier_block *nb,
+                          unsigned int events);
 
-extern int nvec_unregister_notifier(struct nvec_chip *dev,
-                                   struct notifier_block *nb);
+int nvec_unregister_notifier(struct nvec_chip *dev, struct notifier_block *nb);
 
-extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
+void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
 
 #endif
index a530b55f27d89d34a407ededa5d975991212f3d0..5ed8483fc24d178215fd66d72c846987fc268005 100644 (file)
@@ -25,7 +25,7 @@
 
 extern const struct ethtool_ops cvm_oct_ethtool_ops;
 
-extern void octeon_mdiobus_force_mod_depencency(void);
+void octeon_mdiobus_force_mod_depencency(void);
 
 int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int cvm_oct_phy_setup_device(struct net_device *dev);
index beb7aac9c289077fb75af9a10eaf0375b8bb51ba..51dcb611702f1fd1f274e989a57dd14fda85982e 100644 (file)
@@ -118,9 +118,10 @@ static void cvm_oct_rgmii_poll(struct net_device *dev)
        }
 
        /* Since the 10Mbps preamble workaround is allowed we need to enable
-          preamble checking, FCS stripping, and clear error bits on
-          every speed change. If errors occur during 10Mbps operation
-          the above code will change this stuff */
+        * preamble checking, FCS stripping, and clear error bits on
+        * every speed change. If errors occur during 10Mbps operation
+        * the above code will change this stuff
+        */
        cvm_oct_set_hw_preamble(priv, true);
 
        if (priv->phydev == NULL) {
index 7c1c1b052b7d172a7ec7eb8fedc11a96af3f92c0..e2df041ca82d4e9f7c978c62f7ae9ea4a9c1bf8d 100644 (file)
@@ -396,10 +396,12 @@ dont_put_skbuff_in_hw:
 
        /* Check if we can use the hardware checksumming */
        if ((skb->protocol == htons(ETH_P_IP)) &&
-           (ip_hdr(skb)->version == 4) && (ip_hdr(skb)->ihl == 5) &&
-           ((ip_hdr(skb)->frag_off == 0) || (ip_hdr(skb)->frag_off == htons(1 << 14)))
-           && ((ip_hdr(skb)->protocol == IPPROTO_TCP)
-               || (ip_hdr(skb)->protocol == IPPROTO_UDP))) {
+           (ip_hdr(skb)->version == 4) &&
+           (ip_hdr(skb)->ihl == 5) &&
+           ((ip_hdr(skb)->frag_off == 0) ||
+            (ip_hdr(skb)->frag_off == htons(1 << 14))) &&
+           ((ip_hdr(skb)->protocol == IPPROTO_TCP) ||
+            (ip_hdr(skb)->protocol == IPPROTO_UDP))) {
                /* Use hardware checksum calc */
                pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1;
        }
index f9dba23a375914fc3fe4807f901860300e9bfc64..0718b35f7335758794d8e65b44796543f275da3c 100644 (file)
@@ -157,6 +157,7 @@ static void cvm_oct_configure_common_hw(void)
 #ifdef __LITTLE_ENDIAN
        {
                union cvmx_ipd_ctl_status ipd_ctl_status;
+
                ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
                ipd_ctl_status.s.pkt_lend = 1;
                ipd_ctl_status.s.wqe_lend = 1;
index e9d3e9a7e8a78b5a830c8418451196918e65cef6..a242c700bc537ad3c8b4df4478dc56b2f8114973 100644 (file)
@@ -53,20 +53,20 @@ struct octeon_ethernet {
 
 int cvm_oct_free_work(void *work_queue_entry);
 
-extern int cvm_oct_rgmii_init(struct net_device *dev);
-extern void cvm_oct_rgmii_uninit(struct net_device *dev);
-extern int cvm_oct_rgmii_open(struct net_device *dev);
+int cvm_oct_rgmii_init(struct net_device *dev);
+void cvm_oct_rgmii_uninit(struct net_device *dev);
+int cvm_oct_rgmii_open(struct net_device *dev);
 
-extern int cvm_oct_sgmii_init(struct net_device *dev);
-extern int cvm_oct_sgmii_open(struct net_device *dev);
+int cvm_oct_sgmii_init(struct net_device *dev);
+int cvm_oct_sgmii_open(struct net_device *dev);
 
-extern int cvm_oct_spi_init(struct net_device *dev);
-extern void cvm_oct_spi_uninit(struct net_device *dev);
-extern int cvm_oct_xaui_init(struct net_device *dev);
-extern int cvm_oct_xaui_open(struct net_device *dev);
+int cvm_oct_spi_init(struct net_device *dev);
+void cvm_oct_spi_uninit(struct net_device *dev);
+int cvm_oct_xaui_init(struct net_device *dev);
+int cvm_oct_xaui_open(struct net_device *dev);
 
-extern int cvm_oct_common_init(struct net_device *dev);
-extern void cvm_oct_common_uninit(struct net_device *dev);
+int cvm_oct_common_init(struct net_device *dev);
+void cvm_oct_common_uninit(struct net_device *dev);
 void cvm_oct_adjust_link(struct net_device *dev);
 int cvm_oct_common_stop(struct net_device *dev);
 int cvm_oct_common_open(struct net_device *dev,
index aec98958f795bf56f1c77985887ce53e6eeafb15..d06e19db1b80c242a97c7ba71a4cb5dec745e37c 100644 (file)
@@ -98,7 +98,7 @@ struct dcon_platform_data {
 
 #include <linux/interrupt.h>
 
-extern irqreturn_t dcon_interrupt(int irq, void *id);
+irqreturn_t dcon_interrupt(int irq, void *id);
 
 #ifdef CONFIG_FB_OLPC_DCON_1
 extern struct dcon_platform_data dcon_pdata_xo_1;
diff --git a/drivers/staging/ozwpan/Kconfig b/drivers/staging/ozwpan/Kconfig
deleted file mode 100644 (file)
index 7904cae..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-config USB_WPAN_HCD
-       tristate "USB over WiFi Host Controller"
-       depends on USB && NET
-       help
-         A driver for USB Host Controllers that are compatible with
-         Ozmo Devices USB over WiFi technology.
-
-         To compile this driver a module, choose M here: the module
-         will be called "ozwpan".
diff --git a/drivers/staging/ozwpan/Makefile b/drivers/staging/ozwpan/Makefile
deleted file mode 100644 (file)
index 29529c1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# -----------------------------------------------------------------------------
-# Copyright (c) 2011 Ozmo Inc
-# Released under the GNU General Public License Version 2 (GPLv2).
-# -----------------------------------------------------------------------------
-
-obj-$(CONFIG_USB_WPAN_HCD) += ozwpan.o
-ozwpan-y := \
-       ozmain.o \
-       ozpd.o \
-       ozusbsvc.o \
-       ozusbsvc1.o \
-       ozhcd.o \
-       ozeltbuf.o \
-       ozproto.o \
-       ozcdev.o \
-       ozurbparanoia.o
diff --git a/drivers/staging/ozwpan/README b/drivers/staging/ozwpan/README
deleted file mode 100644 (file)
index 7c055ec..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-OZWPAN USB Host Controller Driver
----------------------------------
-This driver is a USB HCD driver that does not have an associated a physical
-device but instead uses Wi-Fi to communicate with the wireless peripheral.
-The USB requests are converted into a layer 2 network protocol and transmitted
-on the network using an ethertype (0x892e) regestered to Ozmo Device Inc.
-This driver is compatible with existing wireless devices that use Ozmo Devices
-technology.
-
-To operate the driver must be bound to a suitable network interface. This can
-be done when the module is loaded (specifying the name of the network interface
-as a parameter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after
-loading using an ioctl call. See the ozappif.h file and the ioctls
-OZ_IOCTL_ADD_BINDING and OZ_IOCTL_REMOVE_BINDING.
-
-The devices connect to the host use Wi-Fi Direct so a network card that supports
-Wi-Fi direct is required. A recent version (0.8.x or later) version of the
-wpa_supplicant can be used to setup the network interface to create a persistent
-autonomous group (for older pre-WFD peripherals) or put in a listen state to
-allow group negotiation to occur for more recent devices that support WFD.
-
-The protocol used over the network does not directly mimic the USB bus
-transactions as this would be rather busy and inefficient. Instead the chapter 9
-requests are converted into a request/response pair of messages. (See
-ozprotocol.h for data structures used in the protocol).
diff --git a/drivers/staging/ozwpan/TODO b/drivers/staging/ozwpan/TODO
deleted file mode 100644 (file)
index f32c1c0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-TODO:
-       - Convert event tracing code to in-kernel tracing infrastructure
-       - Check for remaining ioctl & check if that can be converted into
-         sysfs entries
-       - Convert debug prints to appropriate dev_debug or something better
-       - Modify Kconfig to add CONFIG option for enabling/disabling event
-         tracing.
-       - check USB HCD implementation is complete and correct.
-       - code review by USB developer community.
-       - testing with as many devices as possible.
-
-Please send any patches for this driver to
-Shigekatsu Tateno <shigekatsu.tateno@atmel.com>
-and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
diff --git a/drivers/staging/ozwpan/ozappif.h b/drivers/staging/ozwpan/ozappif.h
deleted file mode 100644 (file)
index ea1b271..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZAPPIF_H
-#define _OZAPPIF_H
-
-#define OZ_IOCTL_MAGIC 0xf4
-
-struct oz_mac_addr {
-       __u8 a[6];
-};
-
-#define OZ_MAX_PDS     8
-
-struct oz_pd_list {
-       __u32 count;
-       struct oz_mac_addr addr[OZ_MAX_PDS];
-};
-
-#define OZ_MAX_BINDING_LEN     32
-
-struct oz_binding_info {
-       char name[OZ_MAX_BINDING_LEN];
-};
-
-#define OZ_IOCTL_GET_PD_LIST   _IOR(OZ_IOCTL_MAGIC, 0, struct oz_pd_list)
-#define OZ_IOCTL_SET_ACTIVE_PD _IOW(OZ_IOCTL_MAGIC, 1, struct oz_mac_addr)
-#define OZ_IOCTL_GET_ACTIVE_PD _IOR(OZ_IOCTL_MAGIC, 2, struct oz_mac_addr)
-#define OZ_IOCTL_ADD_BINDING   _IOW(OZ_IOCTL_MAGIC, 3, struct oz_binding_info)
-#define OZ_IOCTL_REMOVE_BINDING        _IOW(OZ_IOCTL_MAGIC, 4, struct oz_binding_info)
-#define OZ_IOCTL_MAX           5
-
-
-#endif /* _OZAPPIF_H */
diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
deleted file mode 100644 (file)
index da0e1fd..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozappif.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozcdev.h"
-
-#define OZ_RD_BUF_SZ   256
-struct oz_cdev {
-       dev_t devnum;
-       struct cdev cdev;
-       wait_queue_head_t rdq;
-       spinlock_t lock;
-       u8 active_addr[ETH_ALEN];
-       struct oz_pd *active_pd;
-};
-
-/* Per PD context for the serial service stored in the PD. */
-struct oz_serial_ctx {
-       atomic_t ref_count;
-       u8 tx_seq_num;
-       u8 rx_seq_num;
-       u8 rd_buf[OZ_RD_BUF_SZ];
-       int rd_in;
-       int rd_out;
-};
-
-static struct oz_cdev g_cdev;
-static struct class *g_oz_class;
-
-/*
- * Context: process and softirq
- */
-static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd)
-{
-       struct oz_serial_ctx *ctx;
-
-       spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-       ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL];
-       if (ctx)
-               atomic_inc(&ctx->ref_count);
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-       return ctx;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
-{
-       if (atomic_dec_and_test(&ctx->ref_count)) {
-               oz_dbg(ON, "Dealloc serial context\n");
-               kfree(ctx);
-       }
-}
-
-/*
- * Context: process
- */
-static int oz_cdev_open(struct inode *inode, struct file *filp)
-{
-       struct oz_cdev *dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
-
-       oz_dbg(ON, "major = %d minor = %d\n", imajor(inode), iminor(inode));
-
-       filp->private_data = dev;
-       return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_cdev_release(struct inode *inode, struct file *filp)
-{
-       return 0;
-}
-
-/*
- * Context: process
- */
-static ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count,
-               loff_t *fpos)
-{
-       int n;
-       int ix;
-
-       struct oz_pd *pd;
-       struct oz_serial_ctx *ctx;
-
-       spin_lock_bh(&g_cdev.lock);
-       pd = g_cdev.active_pd;
-       if (pd)
-               oz_pd_get(pd);
-       spin_unlock_bh(&g_cdev.lock);
-       if (pd == NULL)
-               return -1;
-       ctx = oz_cdev_claim_ctx(pd);
-       if (ctx == NULL)
-               goto out2;
-       n = ctx->rd_in - ctx->rd_out;
-       if (n < 0)
-               n += OZ_RD_BUF_SZ;
-       if (count > n)
-               count = n;
-       ix = ctx->rd_out;
-       n = OZ_RD_BUF_SZ - ix;
-       if (n > count)
-               n = count;
-       if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
-               count = 0;
-               goto out1;
-       }
-       ix += n;
-       if (ix == OZ_RD_BUF_SZ)
-               ix = 0;
-       if (n < count) {
-               if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) {
-                       count = 0;
-                       goto out1;
-               }
-               ix = count-n;
-       }
-       ctx->rd_out = ix;
-out1:
-       oz_cdev_release_ctx(ctx);
-out2:
-       oz_pd_put(pd);
-       return count;
-}
-
-/*
- * Context: process
- */
-static ssize_t oz_cdev_write(struct file *filp, const char __user *buf,
-               size_t count, loff_t *fpos)
-{
-       struct oz_pd *pd;
-       struct oz_elt_buf *eb;
-       struct oz_elt_info *ei;
-       struct oz_elt *elt;
-       struct oz_app_hdr *app_hdr;
-       struct oz_serial_ctx *ctx;
-
-       if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr))
-               return -EINVAL;
-
-       spin_lock_bh(&g_cdev.lock);
-       pd = g_cdev.active_pd;
-       if (pd)
-               oz_pd_get(pd);
-       spin_unlock_bh(&g_cdev.lock);
-       if (pd == NULL)
-               return -ENXIO;
-       if (!(pd->state & OZ_PD_S_CONNECTED))
-               return -EAGAIN;
-       eb = &pd->elt_buff;
-       ei = oz_elt_info_alloc(eb);
-       if (ei == NULL) {
-               count = 0;
-               goto out;
-       }
-       elt = (struct oz_elt *)ei->data;
-       app_hdr = (struct oz_app_hdr *)(elt+1);
-       elt->length = sizeof(struct oz_app_hdr) + count;
-       elt->type = OZ_ELT_APP_DATA;
-       ei->app_id = OZ_APPID_SERIAL;
-       ei->length = elt->length + sizeof(struct oz_elt);
-       app_hdr->app_id = OZ_APPID_SERIAL;
-       if (copy_from_user(app_hdr+1, buf, count))
-               goto out;
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-       ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL];
-       if (ctx) {
-               app_hdr->elt_seq_num = ctx->tx_seq_num++;
-               if (ctx->tx_seq_num == 0)
-                       ctx->tx_seq_num = 1;
-               spin_lock(&eb->lock);
-               if (oz_queue_elt_info(eb, 0, 0, ei) == 0)
-                       ei = NULL;
-               spin_unlock(&eb->lock);
-       }
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-out:
-       if (ei) {
-               count = 0;
-               spin_lock_bh(&eb->lock);
-               oz_elt_info_free(eb, ei);
-               spin_unlock_bh(&eb->lock);
-       }
-       oz_pd_put(pd);
-       return count;
-}
-
-/*
- * Context: process
- */
-static int oz_set_active_pd(const u8 *addr)
-{
-       int rc = 0;
-       struct oz_pd *pd;
-       struct oz_pd *old_pd;
-
-       pd = oz_pd_find(addr);
-       if (pd) {
-               spin_lock_bh(&g_cdev.lock);
-               ether_addr_copy(g_cdev.active_addr, addr);
-               old_pd = g_cdev.active_pd;
-               g_cdev.active_pd = pd;
-               spin_unlock_bh(&g_cdev.lock);
-               if (old_pd)
-                       oz_pd_put(old_pd);
-       } else {
-               if (is_zero_ether_addr(addr)) {
-                       spin_lock_bh(&g_cdev.lock);
-                       pd = g_cdev.active_pd;
-                       g_cdev.active_pd = NULL;
-                       memset(g_cdev.active_addr, 0,
-                               sizeof(g_cdev.active_addr));
-                       spin_unlock_bh(&g_cdev.lock);
-                       if (pd)
-                               oz_pd_put(pd);
-               } else {
-                       rc = -1;
-               }
-       }
-       return rc;
-}
-
-/*
- * Context: process
- */
-static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
-                         unsigned long arg)
-{
-       int rc = 0;
-
-       if (_IOC_TYPE(cmd) != OZ_IOCTL_MAGIC)
-               return -ENOTTY;
-       if (_IOC_NR(cmd) > OZ_IOCTL_MAX)
-               return -ENOTTY;
-       if (_IOC_DIR(cmd) & _IOC_READ)
-               rc = !access_ok(VERIFY_WRITE, (void __user *)arg,
-                       _IOC_SIZE(cmd));
-       else if (_IOC_DIR(cmd) & _IOC_WRITE)
-               rc = !access_ok(VERIFY_READ, (void __user *)arg,
-                       _IOC_SIZE(cmd));
-       if (rc)
-               return -EFAULT;
-       switch (cmd) {
-       case OZ_IOCTL_GET_PD_LIST: {
-                       struct oz_pd_list list;
-
-                       oz_dbg(ON, "OZ_IOCTL_GET_PD_LIST\n");
-                       memset(&list, 0, sizeof(list));
-                       list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS);
-                       if (copy_to_user((void __user *)arg, &list,
-                               sizeof(list)))
-                               return -EFAULT;
-               }
-               break;
-       case OZ_IOCTL_SET_ACTIVE_PD: {
-                       u8 addr[ETH_ALEN];
-
-                       oz_dbg(ON, "OZ_IOCTL_SET_ACTIVE_PD\n");
-                       if (copy_from_user(addr, (void __user *)arg, ETH_ALEN))
-                               return -EFAULT;
-                       rc = oz_set_active_pd(addr);
-               }
-               break;
-       case OZ_IOCTL_GET_ACTIVE_PD: {
-                       u8 addr[ETH_ALEN];
-
-                       oz_dbg(ON, "OZ_IOCTL_GET_ACTIVE_PD\n");
-                       spin_lock_bh(&g_cdev.lock);
-                       ether_addr_copy(addr, g_cdev.active_addr);
-                       spin_unlock_bh(&g_cdev.lock);
-                       if (copy_to_user((void __user *)arg, addr, ETH_ALEN))
-                               return -EFAULT;
-               }
-               break;
-       case OZ_IOCTL_ADD_BINDING:
-       case OZ_IOCTL_REMOVE_BINDING: {
-                       struct oz_binding_info b;
-
-                       if (copy_from_user(&b, (void __user *)arg,
-                               sizeof(struct oz_binding_info))) {
-                               return -EFAULT;
-                       }
-                       /* Make sure name is null terminated. */
-                       b.name[OZ_MAX_BINDING_LEN-1] = 0;
-                       if (cmd == OZ_IOCTL_ADD_BINDING)
-                               oz_binding_add(b.name);
-                       else
-                               oz_binding_remove(b.name);
-               }
-               break;
-       }
-       return rc;
-}
-
-/*
- * Context: process
- */
-static unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
-{
-       unsigned int ret = 0;
-       struct oz_cdev *dev = filp->private_data;
-
-       oz_dbg(ON, "Poll called wait = %p\n", wait);
-       spin_lock_bh(&dev->lock);
-       if (dev->active_pd) {
-               struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd);
-
-               if (ctx) {
-                       if (ctx->rd_in != ctx->rd_out)
-                               ret |= POLLIN | POLLRDNORM;
-                       oz_cdev_release_ctx(ctx);
-               }
-       }
-       spin_unlock_bh(&dev->lock);
-       if (wait)
-               poll_wait(filp, &dev->rdq, wait);
-       return ret;
-}
-
-/*
- */
-static const struct file_operations oz_fops = {
-       .owner =        THIS_MODULE,
-       .open =         oz_cdev_open,
-       .release =      oz_cdev_release,
-       .read =         oz_cdev_read,
-       .write =        oz_cdev_write,
-       .unlocked_ioctl = oz_cdev_ioctl,
-       .poll =         oz_cdev_poll
-};
-
-/*
- * Context: process
- */
-int oz_cdev_register(void)
-{
-       int err;
-       struct device *dev;
-
-       memset(&g_cdev, 0, sizeof(g_cdev));
-       err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan");
-       if (err < 0)
-               return err;
-       oz_dbg(ON, "Alloc dev number %d:%d\n",
-              MAJOR(g_cdev.devnum), MINOR(g_cdev.devnum));
-       cdev_init(&g_cdev.cdev, &oz_fops);
-       g_cdev.cdev.owner = THIS_MODULE;
-       spin_lock_init(&g_cdev.lock);
-       init_waitqueue_head(&g_cdev.rdq);
-       err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1);
-       if (err < 0) {
-               oz_dbg(ON, "Failed to add cdev\n");
-               goto unregister;
-       }
-       g_oz_class = class_create(THIS_MODULE, "ozmo_wpan");
-       if (IS_ERR(g_oz_class)) {
-               oz_dbg(ON, "Failed to register ozmo_wpan class\n");
-               err = PTR_ERR(g_oz_class);
-               goto delete;
-       }
-       dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan");
-       if (IS_ERR(dev)) {
-               oz_dbg(ON, "Failed to create sysfs entry for cdev\n");
-               err = PTR_ERR(dev);
-               goto delete;
-       }
-       return 0;
-
-delete:
-       cdev_del(&g_cdev.cdev);
-unregister:
-       unregister_chrdev_region(g_cdev.devnum, 1);
-       return err;
-}
-
-/*
- * Context: process
- */
-int oz_cdev_deregister(void)
-{
-       cdev_del(&g_cdev.cdev);
-       unregister_chrdev_region(g_cdev.devnum, 1);
-       if (g_oz_class) {
-               device_destroy(g_oz_class, g_cdev.devnum);
-               class_destroy(g_oz_class);
-       }
-       return 0;
-}
-
-/*
- * Context: process
- */
-int oz_cdev_init(void)
-{
-       oz_app_enable(OZ_APPID_SERIAL, 1);
-       return 0;
-}
-
-/*
- * Context: process
- */
-void oz_cdev_term(void)
-{
-       oz_app_enable(OZ_APPID_SERIAL, 0);
-}
-
-/*
- * Context: softirq-serialized
- */
-int oz_cdev_start(struct oz_pd *pd, int resume)
-{
-       struct oz_serial_ctx *ctx;
-       struct oz_serial_ctx *old_ctx;
-
-       if (resume) {
-               oz_dbg(ON, "Serial service resumed\n");
-               return 0;
-       }
-       ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC);
-       if (ctx == NULL)
-               return -ENOMEM;
-       atomic_set(&ctx->ref_count, 1);
-       ctx->tx_seq_num = 1;
-       spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-       old_ctx = pd->app_ctx[OZ_APPID_SERIAL];
-       if (old_ctx) {
-               spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-               kfree(ctx);
-       } else {
-               pd->app_ctx[OZ_APPID_SERIAL] = ctx;
-               spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-       }
-       spin_lock(&g_cdev.lock);
-       if ((g_cdev.active_pd == NULL) &&
-               ether_addr_equal(pd->mac_addr, g_cdev.active_addr)) {
-               oz_pd_get(pd);
-               g_cdev.active_pd = pd;
-               oz_dbg(ON, "Active PD arrived\n");
-       }
-       spin_unlock(&g_cdev.lock);
-       oz_dbg(ON, "Serial service started\n");
-       return 0;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_cdev_stop(struct oz_pd *pd, int pause)
-{
-       struct oz_serial_ctx *ctx;
-
-       if (pause) {
-               oz_dbg(ON, "Serial service paused\n");
-               return;
-       }
-       spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-       ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL];
-       pd->app_ctx[OZ_APPID_SERIAL] = NULL;
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
-       if (ctx)
-               oz_cdev_release_ctx(ctx);
-       spin_lock(&g_cdev.lock);
-       if (pd == g_cdev.active_pd)
-               g_cdev.active_pd = NULL;
-       else
-               pd = NULL;
-       spin_unlock(&g_cdev.lock);
-       if (pd) {
-               oz_pd_put(pd);
-               oz_dbg(ON, "Active PD departed\n");
-       }
-       oz_dbg(ON, "Serial service stopped\n");
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
-{
-       struct oz_serial_ctx *ctx;
-       struct oz_app_hdr *app_hdr;
-       u8 *data;
-       int len;
-       int space;
-       int copy_sz;
-       int ix;
-
-       ctx = oz_cdev_claim_ctx(pd);
-       if (ctx == NULL) {
-               oz_dbg(ON, "Cannot claim serial context\n");
-               return;
-       }
-
-       app_hdr = (struct oz_app_hdr *)(elt+1);
-       /* If sequence number is non-zero then check it is not a duplicate.
-        */
-       if (app_hdr->elt_seq_num != 0) {
-               if (((ctx->rx_seq_num - app_hdr->elt_seq_num) & 0x80) == 0) {
-                       /* Reject duplicate element. */
-                       oz_dbg(ON, "Duplicate element:%02x %02x\n",
-                              app_hdr->elt_seq_num, ctx->rx_seq_num);
-                       goto out;
-               }
-       }
-       ctx->rx_seq_num = app_hdr->elt_seq_num;
-       len = elt->length - sizeof(struct oz_app_hdr);
-       data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr);
-       if (len <= 0)
-               goto out;
-       space = ctx->rd_out - ctx->rd_in - 1;
-       if (space < 0)
-               space += OZ_RD_BUF_SZ;
-       if (len > space) {
-               oz_dbg(ON, "Not enough space:%d %d\n", len, space);
-               len = space;
-       }
-       ix = ctx->rd_in;
-       copy_sz = OZ_RD_BUF_SZ - ix;
-       if (copy_sz > len)
-               copy_sz = len;
-       memcpy(&ctx->rd_buf[ix], data, copy_sz);
-       len -= copy_sz;
-       ix += copy_sz;
-       if (ix == OZ_RD_BUF_SZ)
-               ix = 0;
-       if (len) {
-               memcpy(ctx->rd_buf, data+copy_sz, len);
-               ix = len;
-       }
-       ctx->rd_in = ix;
-       wake_up(&g_cdev.rdq);
-out:
-       oz_cdev_release_ctx(ctx);
-}
diff --git a/drivers/staging/ozwpan/ozcdev.h b/drivers/staging/ozwpan/ozcdev.h
deleted file mode 100644 (file)
index dd11935..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZCDEV_H
-#define _OZCDEV_H
-
-int oz_cdev_register(void);
-int oz_cdev_deregister(void);
-int oz_cdev_init(void);
-void oz_cdev_term(void);
-int oz_cdev_start(struct oz_pd *pd, int resume);
-void oz_cdev_stop(struct oz_pd *pd, int pause);
-void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt);
-
-#endif /* _OZCDEV_H */
diff --git a/drivers/staging/ozwpan/ozdbg.h b/drivers/staging/ozwpan/ozdbg.h
deleted file mode 100644 (file)
index b86a2b7..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-
-#ifndef _OZDBG_H
-#define _OZDBG_H
-
-#define OZ_WANT_DBG 0
-#define OZ_WANT_VERBOSE_DBG 1
-
-#define OZ_DBG_ON              0x0
-#define OZ_DBG_STREAM          0x1
-#define OZ_DBG_URB             0x2
-#define OZ_DBG_CTRL_DETAIL     0x4
-#define OZ_DBG_HUB             0x8
-#define OZ_DBG_RX_FRAMES       0x10
-#define OZ_DBG_TX_FRAMES       0x20
-
-#define OZ_DEFAULT_DBG_MASK                    \
-       (                                       \
-       /* OZ_DBG_STREAM | */                   \
-       /* OZ_DBG_URB | */                      \
-       /* OZ_DBG_CTRL_DETAIL | */              \
-       OZ_DBG_HUB |                            \
-       /* OZ_DBG_RX_FRAMES | */                \
-       /* OZ_DBG_TX_FRAMES | */                \
-       0)
-
-extern unsigned int oz_dbg_mask;
-
-#define oz_want_dbg(mask)                                              \
-       ((OZ_WANT_DBG && (OZ_DBG_##mask == OZ_DBG_ON)) ||               \
-        (OZ_WANT_VERBOSE_DBG && (OZ_DBG_##mask & oz_dbg_mask)))
-
-#define oz_dbg(mask, fmt, ...)                                         \
-do {                                                                   \
-       if (oz_want_dbg(mask))                                          \
-               pr_debug(fmt, ##__VA_ARGS__);                           \
-} while (0)
-
-#define oz_cdev_dbg(cdev, mask, fmt, ...)                              \
-do {                                                                   \
-       if (oz_want_dbg(mask))                                          \
-               netdev_dbg((cdev)->dev, fmt, ##__VA_ARGS__);            \
-} while (0)
-
-#define oz_pd_dbg(pd, mask, fmt, ...)                                  \
-do {                                                                   \
-       if (oz_want_dbg(mask))                                          \
-               pr_debug(fmt, ##__VA_ARGS__);                           \
-} while (0)
-
-#endif /* _OZDBG_H */
diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c
deleted file mode 100644 (file)
index 01b25da..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-
-/*
- * Context: softirq-serialized
- */
-void oz_elt_buf_init(struct oz_elt_buf *buf)
-{
-       memset(buf, 0, sizeof(struct oz_elt_buf));
-       INIT_LIST_HEAD(&buf->stream_list);
-       INIT_LIST_HEAD(&buf->order_list);
-       INIT_LIST_HEAD(&buf->isoc_list);
-       spin_lock_init(&buf->lock);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_elt_buf_term(struct oz_elt_buf *buf)
-{
-       struct oz_elt_info *ei, *n;
-
-       list_for_each_entry_safe(ei, n, &buf->isoc_list, link_order)
-               kfree(ei);
-       list_for_each_entry_safe(ei, n, &buf->order_list, link_order)
-               kfree(ei);
-}
-
-/*
- * Context: softirq or process
- */
-struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf)
-{
-       struct oz_elt_info *ei;
-
-       ei = kmem_cache_zalloc(oz_elt_info_cache, GFP_ATOMIC);
-       if (ei) {
-               INIT_LIST_HEAD(&ei->link);
-               INIT_LIST_HEAD(&ei->link_order);
-       }
-       return ei;
-}
-
-/*
- * Precondition: oz_elt_buf.lock must be held.
- * Context: softirq or process
- */
-void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei)
-{
-       if (ei)
-               kmem_cache_free(oz_elt_info_cache, ei);
-}
-
-/*------------------------------------------------------------------------------
- * Context: softirq
- */
-void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list)
-{
-       struct oz_elt_info *ei, *n;
-
-       spin_lock_bh(&buf->lock);
-       list_for_each_entry_safe(ei, n, list->next, link)
-               oz_elt_info_free(buf, ei);
-       spin_unlock_bh(&buf->lock);
-}
-
-int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count)
-{
-       struct oz_elt_stream *st;
-
-       oz_dbg(ON, "%s: (0x%x)\n", __func__, id);
-
-       st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC);
-       if (st == NULL)
-               return -ENOMEM;
-       atomic_set(&st->ref_count, 1);
-       st->id = id;
-       st->max_buf_count = max_buf_count;
-       INIT_LIST_HEAD(&st->elt_list);
-       spin_lock_bh(&buf->lock);
-       list_add_tail(&st->link, &buf->stream_list);
-       spin_unlock_bh(&buf->lock);
-       return 0;
-}
-
-int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
-{
-       struct list_head *e, *n;
-       struct oz_elt_stream *st = NULL;
-
-       oz_dbg(ON, "%s: (0x%x)\n", __func__, id);
-       spin_lock_bh(&buf->lock);
-       list_for_each(e, &buf->stream_list) {
-               st = list_entry(e, struct oz_elt_stream, link);
-               if (st->id == id) {
-                       list_del(e);
-                       break;
-               }
-               st = NULL;
-       }
-       if (!st) {
-               spin_unlock_bh(&buf->lock);
-               return -1;
-       }
-       list_for_each_safe(e, n, &st->elt_list) {
-               struct oz_elt_info *ei =
-                       list_entry(e, struct oz_elt_info, link);
-               list_del_init(&ei->link);
-               list_del_init(&ei->link_order);
-               st->buf_count -= ei->length;
-               oz_dbg(STREAM, "Stream down: %d %d %d\n",
-                      st->buf_count, ei->length, atomic_read(&st->ref_count));
-               oz_elt_stream_put(st);
-               oz_elt_info_free(buf, ei);
-       }
-       spin_unlock_bh(&buf->lock);
-       oz_elt_stream_put(st);
-       return 0;
-}
-
-void oz_elt_stream_get(struct oz_elt_stream *st)
-{
-       atomic_inc(&st->ref_count);
-}
-
-void oz_elt_stream_put(struct oz_elt_stream *st)
-{
-       if (atomic_dec_and_test(&st->ref_count)) {
-               oz_dbg(ON, "Stream destroyed\n");
-               kfree(st);
-       }
-}
-
-/*
- * Precondition: Element buffer lock must be held.
- * If this function fails the caller is responsible for deallocating the elt
- * info structure.
- */
-int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
-       struct oz_elt_info *ei)
-{
-       struct oz_elt_stream *st = NULL;
-       struct list_head *e;
-
-       if (id) {
-               list_for_each(e, &buf->stream_list) {
-                       st = list_entry(e, struct oz_elt_stream, link);
-                       if (st->id == id)
-                               break;
-               }
-               if (e == &buf->stream_list) {
-                       /* Stream specified but stream not known so fail.
-                        * Caller deallocates element info. */
-                       return -1;
-               }
-       }
-       if (st) {
-               /* If this is an ISOC fixed element that needs a frame number
-                * then insert that now. Earlier we stored the unit count in
-                * this field.
-                */
-               struct oz_isoc_fixed *body = (struct oz_isoc_fixed *)
-                       &ei->data[sizeof(struct oz_elt)];
-               if ((body->app_id == OZ_APPID_USB) && (body->type
-                       == OZ_USB_ENDPOINT_DATA) &&
-                       (body->format == OZ_DATA_F_ISOC_FIXED)) {
-                       u8 unit_count = body->frame_number;
-
-                       body->frame_number = st->frame_number;
-                       st->frame_number += unit_count;
-               }
-               /* Claim stream and update accounts */
-               oz_elt_stream_get(st);
-               ei->stream = st;
-               st->buf_count += ei->length;
-               /* Add to list in stream. */
-               list_add_tail(&ei->link, &st->elt_list);
-               oz_dbg(STREAM, "Stream up: %d %d\n", st->buf_count, ei->length);
-               /* Check if we have too much buffered for this stream. If so
-                * start dropping elements until we are back in bounds.
-                */
-               while ((st->buf_count > st->max_buf_count) &&
-                       !list_empty(&st->elt_list)) {
-                       struct oz_elt_info *ei2 =
-                               list_first_entry(&st->elt_list,
-                                       struct oz_elt_info, link);
-                       list_del_init(&ei2->link);
-                       list_del_init(&ei2->link_order);
-                       st->buf_count -= ei2->length;
-                       oz_elt_info_free(buf, ei2);
-                       oz_elt_stream_put(st);
-               }
-       }
-       list_add_tail(&ei->link_order, isoc ?
-               &buf->isoc_list : &buf->order_list);
-       return 0;
-}
-
-int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
-               unsigned max_len, struct list_head *list)
-{
-       int count = 0;
-       struct list_head *el;
-       struct oz_elt_info *ei, *n;
-
-       spin_lock_bh(&buf->lock);
-       if (isoc)
-               el = &buf->isoc_list;
-       else
-               el = &buf->order_list;
-
-       list_for_each_entry_safe(ei, n, el, link_order) {
-               if ((*len + ei->length) <= max_len) {
-                       struct oz_app_hdr *app_hdr = (struct oz_app_hdr *)
-                               &ei->data[sizeof(struct oz_elt)];
-                       app_hdr->elt_seq_num = buf->tx_seq_num[ei->app_id]++;
-                       if (buf->tx_seq_num[ei->app_id] == 0)
-                               buf->tx_seq_num[ei->app_id] = 1;
-                       *len += ei->length;
-                       list_del(&ei->link);
-                       list_del(&ei->link_order);
-                       if (ei->stream) {
-                               ei->stream->buf_count -= ei->length;
-                               oz_dbg(STREAM, "Stream down: %d %d\n",
-                                      ei->stream->buf_count, ei->length);
-                               oz_elt_stream_put(ei->stream);
-                               ei->stream = NULL;
-                       }
-                       INIT_LIST_HEAD(&ei->link_order);
-                       list_add_tail(&ei->link, list);
-                       count++;
-               } else {
-                       break;
-               }
-       }
-       spin_unlock_bh(&buf->lock);
-       return count;
-}
-
-int oz_are_elts_available(struct oz_elt_buf *buf)
-{
-       return !list_empty(&buf->order_list);
-}
diff --git a/drivers/staging/ozwpan/ozeltbuf.h b/drivers/staging/ozwpan/ozeltbuf.h
deleted file mode 100644 (file)
index f09f5fe..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZELTBUF_H
-#define _OZELTBUF_H
-
-#include "ozprotocol.h"
-
-/*-----------------------------------------------------------------------------
- */
-struct oz_pd;
-typedef void (*oz_elt_callback_t)(struct oz_pd *pd, long context);
-
-struct oz_elt_stream {
-       struct list_head link;
-       struct list_head elt_list;
-       atomic_t ref_count;
-       unsigned buf_count;
-       unsigned max_buf_count;
-       u8 frame_number;
-       u8 id;
-};
-
-#define OZ_MAX_ELT_PAYLOAD     255
-struct oz_elt_info {
-       struct list_head link;
-       struct list_head link_order;
-       u8 flags;
-       u8 app_id;
-       oz_elt_callback_t callback;
-       long context;
-       struct oz_elt_stream *stream;
-       u8 data[sizeof(struct oz_elt) + OZ_MAX_ELT_PAYLOAD];
-       int length;
-};
-/* Flags values */
-#define OZ_EI_F_MARKED         0x1
-
-struct oz_elt_buf {
-       spinlock_t lock;
-       struct list_head stream_list;
-       struct list_head order_list;
-       struct list_head isoc_list;
-       u8 tx_seq_num[OZ_NB_APPS];
-};
-
-void oz_elt_buf_init(struct oz_elt_buf *buf);
-void oz_elt_buf_term(struct oz_elt_buf *buf);
-struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf);
-void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei);
-void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list);
-int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count);
-int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id);
-void oz_elt_stream_get(struct oz_elt_stream *st);
-void oz_elt_stream_put(struct oz_elt_stream *st);
-int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
-               struct oz_elt_info *ei);
-int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
-               unsigned max_len, struct list_head *list);
-int oz_are_elts_available(struct oz_elt_buf *buf);
-
-#endif /* _OZELTBUF_H */
-
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
deleted file mode 100644 (file)
index 784b5ec..0000000
+++ /dev/null
@@ -1,2301 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- *
- * This file provides the implementation of a USB host controller device that
- * does not have any associated hardware. Instead the virtual device is
- * connected to the WiFi network and emulates the operation of a USB hcd by
- * receiving and sending network frames.
- * Note:
- * We take great pains to reduce the amount of code where interrupts need to be
- * disabled and in this respect we are different from standard HCD's. In
- * particular we don't want in_irq() code bleeding over to the protocol side of
- * the driver.
- * The troublesome functions are the urb enqueue and dequeue functions both of
- * which can be called in_irq(). So for these functions we put the urbs into a
- * queue and request a tasklet to process them. This means that a spinlock with
- * interrupts disabled must be held for insertion and removal but most code is
- * is in tasklet or soft irq context. The lock that protects this list is called
- * the tasklet lock and serves the purpose of the 'HCD lock' which must be held
- * when calling the following functions.
- *   usb_hcd_link_urb_to_ep()
- *   usb_hcd_unlink_urb_from_ep()
- *   usb_hcd_flush_endpoint()
- *   usb_hcd_check_unlink_urb()
- * -----------------------------------------------------------------------------
- */
-#include <linux/platform_device.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include "linux/usb/hcd.h"
-#include <asm/unaligned.h>
-#include "ozdbg.h"
-#include "ozusbif.h"
-#include "ozurbparanoia.h"
-#include "ozhcd.h"
-
-/*
- * Number of units of buffering to capture for an isochronous IN endpoint before
- * allowing data to be indicated up.
- */
-#define OZ_IN_BUFFERING_UNITS  100
-
-/* Name of our platform device.
- */
-#define OZ_PLAT_DEV_NAME       "ozwpan"
-
-/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec)
- */
-#define EP0_TIMEOUT_COUNTER 13
-
-/* Debounce time HCD driver should wait before unregistering.
- */
-#define OZ_HUB_DEBOUNCE_TIMEOUT 1500
-
-/*
- * Used to link urbs together and also store some status information for each
- * urb.
- * A cache of these are kept in a pool to reduce number of calls to kmalloc.
- */
-struct oz_urb_link {
-       struct list_head link;
-       struct urb *urb;
-       struct oz_port *port;
-       u8 req_id;
-       u8 ep_num;
-       unsigned submit_counter;
-};
-
-static struct kmem_cache *oz_urb_link_cache;
-
-/* Holds state information about a USB endpoint.
- */
-#define OZ_EP_BUFFER_SIZE_ISOC  (1024 * 24)
-#define OZ_EP_BUFFER_SIZE_INT   512
-struct oz_endpoint {
-       struct list_head urb_list;      /* List of oz_urb_link items. */
-       struct list_head link;          /* For isoc ep, links in to isoc
-                                          lists of oz_port. */
-       struct timespec timestamp;
-       int credit;
-       int credit_ceiling;
-       u8 ep_num;
-       u8 attrib;
-       u8 *buffer;
-       int buffer_size;
-       int in_ix;
-       int out_ix;
-       int buffered_units;
-       unsigned flags;
-       int start_frame;
-};
-
-/* Bits in the flags field. */
-#define OZ_F_EP_BUFFERING      0x1
-#define OZ_F_EP_HAVE_STREAM    0x2
-
-/* Holds state information about a USB interface.
- */
-struct oz_interface {
-       unsigned ep_mask;
-       u8 alt;
-};
-
-/* Holds state information about an hcd port.
- */
-#define OZ_NB_ENDPOINTS        16
-struct oz_port {
-       unsigned flags;
-       unsigned status;
-       void *hpd;
-       struct oz_hcd *ozhcd;
-       spinlock_t port_lock;
-       u8 bus_addr;
-       u8 next_req_id;
-       u8 config_num;
-       int num_iface;
-       struct oz_interface *iface;
-       struct oz_endpoint *out_ep[OZ_NB_ENDPOINTS];
-       struct oz_endpoint *in_ep[OZ_NB_ENDPOINTS];
-       struct list_head isoc_out_ep;
-       struct list_head isoc_in_ep;
-};
-
-#define OZ_PORT_F_PRESENT      0x1
-#define OZ_PORT_F_CHANGED      0x2
-#define OZ_PORT_F_DYING                0x4
-
-/* Data structure in the private context area of struct usb_hcd.
- */
-#define OZ_NB_PORTS    8
-struct oz_hcd {
-       spinlock_t hcd_lock;
-       struct list_head urb_pending_list;
-       struct list_head urb_cancel_list;
-       struct list_head orphanage;
-       int conn_port; /* Port that is currently connecting, -1 if none.*/
-       struct oz_port ports[OZ_NB_PORTS];
-       uint flags;
-       struct usb_hcd *hcd;
-};
-
-/* Bits in flags field.
- */
-#define OZ_HDC_F_SUSPENDED     0x1
-
-/*
- * Static function prototypes.
- */
-static int oz_hcd_start(struct usb_hcd *hcd);
-static void oz_hcd_stop(struct usb_hcd *hcd);
-static void oz_hcd_shutdown(struct usb_hcd *hcd);
-static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
-                               gfp_t mem_flags);
-static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
-static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
-                               struct usb_host_endpoint *ep);
-static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
-                               struct usb_host_endpoint *ep);
-static int oz_hcd_get_frame_number(struct usb_hcd *hcd);
-static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf);
-static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
-                               u16 windex, char *buf, u16 wlength);
-static int oz_hcd_bus_suspend(struct usb_hcd *hcd);
-static int oz_hcd_bus_resume(struct usb_hcd *hcd);
-static int oz_plat_probe(struct platform_device *dev);
-static int oz_plat_remove(struct platform_device *dev);
-static void oz_plat_shutdown(struct platform_device *dev);
-static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg);
-static int oz_plat_resume(struct platform_device *dev);
-static void oz_urb_process_tasklet(unsigned long unused);
-static int oz_build_endpoints_for_config(struct usb_hcd *hcd,
-               struct oz_port *port, struct usb_host_config *config,
-               gfp_t mem_flags);
-static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
-                               struct oz_port *port);
-static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
-                       struct oz_port *port,
-                       struct usb_host_interface *intf, gfp_t mem_flags);
-static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd,
-                       struct oz_port *port, int if_ix);
-static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
-               gfp_t mem_flags);
-static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
-               struct urb *urb);
-static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status);
-
-/*
- * Static external variables.
- */
-static struct platform_device *g_plat_dev;
-static struct oz_hcd *g_ozhcd;
-static DEFINE_SPINLOCK(g_hcdlock);     /* Guards g_ozhcd. */
-static const char g_hcd_name[] = "Ozmo WPAN";
-static DEFINE_SPINLOCK(g_tasklet_lock);
-static struct tasklet_struct g_urb_process_tasklet;
-static struct tasklet_struct g_urb_cancel_tasklet;
-static atomic_t g_pending_urbs = ATOMIC_INIT(0);
-static atomic_t g_usb_frame_number = ATOMIC_INIT(0);
-static const struct hc_driver g_oz_hc_drv = {
-       .description =          g_hcd_name,
-       .product_desc =         "Ozmo Devices WPAN",
-       .hcd_priv_size =        sizeof(struct oz_hcd),
-       .flags =                HCD_USB11,
-       .start =                oz_hcd_start,
-       .stop =                 oz_hcd_stop,
-       .shutdown =             oz_hcd_shutdown,
-       .urb_enqueue =          oz_hcd_urb_enqueue,
-       .urb_dequeue =          oz_hcd_urb_dequeue,
-       .endpoint_disable =     oz_hcd_endpoint_disable,
-       .endpoint_reset =       oz_hcd_endpoint_reset,
-       .get_frame_number =     oz_hcd_get_frame_number,
-       .hub_status_data =      oz_hcd_hub_status_data,
-       .hub_control =          oz_hcd_hub_control,
-       .bus_suspend =          oz_hcd_bus_suspend,
-       .bus_resume =           oz_hcd_bus_resume,
-};
-
-static struct platform_driver g_oz_plat_drv = {
-       .probe = oz_plat_probe,
-       .remove = oz_plat_remove,
-       .shutdown = oz_plat_shutdown,
-       .suspend = oz_plat_suspend,
-       .resume = oz_plat_resume,
-       .driver = {
-               .name = OZ_PLAT_DEV_NAME,
-       },
-};
-
-/*
- * Gets our private context area (which is of type struct oz_hcd) from the
- * usb_hcd structure.
- * Context: any
- */
-static inline struct oz_hcd *oz_hcd_private(struct usb_hcd *hcd)
-{
-       return (struct oz_hcd *)hcd->hcd_priv;
-}
-
-/*
- * Searches list of ports to find the index of the one with a specified  USB
- * bus address. If none of the ports has the bus address then the connection
- * port is returned, if there is one or -1 otherwise.
- * Context: any
- */
-static int oz_get_port_from_addr(struct oz_hcd *ozhcd, u8 bus_addr)
-{
-       int i;
-
-       for (i = 0; i < OZ_NB_PORTS; i++) {
-               if (ozhcd->ports[i].bus_addr == bus_addr)
-                       return i;
-       }
-       return ozhcd->conn_port;
-}
-
-/*
- * Context: any
- */
-static struct oz_urb_link *oz_alloc_urb_link(void)
-{
-       return kmem_cache_alloc(oz_urb_link_cache, GFP_ATOMIC);
-}
-
-/*
- * Context: any
- */
-static void oz_free_urb_link(struct oz_urb_link *urbl)
-{
-       if (!urbl)
-               return;
-
-       kmem_cache_free(oz_urb_link_cache, urbl);
-}
-
-/*
- * Allocates endpoint structure and optionally a buffer. If a buffer is
- * allocated it immediately follows the endpoint structure.
- * Context: softirq
- */
-static struct oz_endpoint *oz_ep_alloc(int buffer_size, gfp_t mem_flags)
-{
-       struct oz_endpoint *ep;
-
-       ep = kzalloc(sizeof(struct oz_endpoint)+buffer_size, mem_flags);
-       if (!ep)
-               return NULL;
-
-       INIT_LIST_HEAD(&ep->urb_list);
-       INIT_LIST_HEAD(&ep->link);
-       ep->credit = -1;
-       if (buffer_size) {
-               ep->buffer_size = buffer_size;
-               ep->buffer = (u8 *)(ep+1);
-       }
-
-       return ep;
-}
-
-/*
- * Pre-condition: Must be called with g_tasklet_lock held and interrupts
- * disabled.
- * Context: softirq or process
- */
-static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd,
-               struct urb *urb)
-{
-       struct oz_urb_link *urbl;
-
-       list_for_each_entry(urbl, &ozhcd->urb_cancel_list, link) {
-               if (urb == urbl->urb) {
-                       list_del_init(&urbl->link);
-                       return urbl;
-               }
-       }
-       return NULL;
-}
-
-/*
- * This is called when we have finished processing an urb. It unlinks it from
- * the ep and returns it to the core.
- * Context: softirq or process
- */
-static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
-               int status)
-{
-       struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       unsigned long irq_state;
-       struct oz_urb_link *cancel_urbl;
-
-       spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       usb_hcd_unlink_urb_from_ep(hcd, urb);
-       /* Clear hcpriv which will prevent it being put in the cancel list
-        * in the event that an attempt is made to cancel it.
-        */
-       urb->hcpriv = NULL;
-       /* Walk the cancel list in case the urb is already sitting there.
-        * Since we process the cancel list in a tasklet rather than in
-        * the dequeue function this could happen.
-        */
-       cancel_urbl = oz_uncancel_urb(ozhcd, urb);
-       /* Note: we release lock but do not enable local irqs.
-        * It appears that usb_hcd_giveback_urb() expects irqs to be disabled,
-        * or at least other host controllers disable interrupts at this point
-        * so we do the same. We must, however, release the lock otherwise a
-        * deadlock will occur if an urb is submitted to our driver in the urb
-        * completion function. Because we disable interrupts it is possible
-        * that the urb_enqueue function can be called with them disabled.
-        */
-       spin_unlock(&g_tasklet_lock);
-       if (oz_forget_urb(urb)) {
-               oz_dbg(ON, "ERROR Unknown URB %p\n", urb);
-       } else {
-               atomic_dec(&g_pending_urbs);
-               usb_hcd_giveback_urb(hcd, urb, status);
-       }
-       spin_lock(&g_tasklet_lock);
-       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-       oz_free_urb_link(cancel_urbl);
-}
-
-/*
- * Deallocates an endpoint including deallocating any associated stream and
- * returning any queued urbs to the core.
- * Context: softirq
- */
-static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
-{
-       if (port) {
-               LIST_HEAD(list);
-               struct oz_hcd *ozhcd = port->ozhcd;
-
-               if (ep->flags & OZ_F_EP_HAVE_STREAM)
-                       oz_usb_stream_delete(port->hpd, ep->ep_num);
-               /* Transfer URBs to the orphanage while we hold the lock. */
-               spin_lock_bh(&ozhcd->hcd_lock);
-               /* Note: this works even if ep->urb_list is empty.*/
-               list_replace_init(&ep->urb_list, &list);
-               /* Put the URBs in the orphanage. */
-               list_splice_tail(&list, &ozhcd->orphanage);
-               spin_unlock_bh(&ozhcd->hcd_lock);
-       }
-       oz_dbg(ON, "Freeing endpoint memory\n");
-       kfree(ep);
-}
-
-/*
- * Context: softirq
- */
-static void oz_complete_buffered_urb(struct oz_port *port,
-                       struct oz_endpoint *ep,
-                       struct urb *urb)
-{
-       int data_len, available_space, copy_len;
-
-       data_len = ep->buffer[ep->out_ix];
-       if (data_len <= urb->transfer_buffer_length)
-               available_space = data_len;
-       else
-               available_space = urb->transfer_buffer_length;
-
-       if (++ep->out_ix == ep->buffer_size)
-               ep->out_ix = 0;
-       copy_len = ep->buffer_size - ep->out_ix;
-       if (copy_len >= available_space)
-               copy_len = available_space;
-       memcpy(urb->transfer_buffer, &ep->buffer[ep->out_ix], copy_len);
-
-       if (copy_len < available_space) {
-               memcpy((urb->transfer_buffer + copy_len), ep->buffer,
-                                               (available_space - copy_len));
-               ep->out_ix = available_space - copy_len;
-       } else {
-               ep->out_ix += copy_len;
-       }
-       urb->actual_length = available_space;
-       if (ep->out_ix == ep->buffer_size)
-               ep->out_ix = 0;
-
-       ep->buffered_units--;
-       oz_dbg(ON, "Trying to give back buffered frame of size=%d\n",
-              available_space);
-       oz_complete_urb(port->ozhcd->hcd, urb, 0);
-}
-
-/*
- * Context: softirq
- */
-static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
-                       struct urb *urb, u8 req_id)
-{
-       struct oz_urb_link *urbl;
-       struct oz_endpoint *ep = NULL;
-       int err = 0;
-
-       if (ep_addr >= OZ_NB_ENDPOINTS) {
-               oz_dbg(ON, "%s: Invalid endpoint number\n", __func__);
-               return -EINVAL;
-       }
-       urbl = oz_alloc_urb_link();
-       if (!urbl)
-               return -ENOMEM;
-       urbl->submit_counter = 0;
-       urbl->urb = urb;
-       urbl->req_id = req_id;
-       urbl->ep_num = ep_addr;
-       /* Hold lock while we insert the URB into the list within the
-        * endpoint structure.
-        */
-       spin_lock_bh(&port->ozhcd->hcd_lock);
-       /* If the urb has been unlinked while out of any list then
-        * complete it now.
-        */
-       if (urb->unlinked) {
-               spin_unlock_bh(&port->ozhcd->hcd_lock);
-               oz_dbg(ON, "urb %p unlinked so complete immediately\n", urb);
-               oz_complete_urb(port->ozhcd->hcd, urb, 0);
-               oz_free_urb_link(urbl);
-               return 0;
-       }
-
-       if (in_dir)
-               ep = port->in_ep[ep_addr];
-       else
-               ep = port->out_ep[ep_addr];
-       if (!ep) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       /*For interrupt endpoint check for buffered data
-       * & complete urb
-       */
-       if (((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
-                                                && ep->buffered_units > 0) {
-               oz_free_urb_link(urbl);
-               spin_unlock_bh(&port->ozhcd->hcd_lock);
-               oz_complete_buffered_urb(port, ep, urb);
-               return 0;
-       }
-
-       if (port->hpd) {
-               list_add_tail(&urbl->link, &ep->urb_list);
-               if (!in_dir && ep_addr && (ep->credit < 0)) {
-                       getrawmonotonic(&ep->timestamp);
-                       ep->credit = 0;
-               }
-       } else {
-               err = -EPIPE;
-       }
-out:
-       spin_unlock_bh(&port->ozhcd->hcd_lock);
-       if (err)
-               oz_free_urb_link(urbl);
-       return err;
-}
-
-/*
- * Removes an urb from the queue in the endpoint.
- * Returns 0 if it is found and -EIDRM otherwise.
- * Context: softirq
- */
-static int oz_dequeue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
-                       struct urb *urb)
-{
-       struct oz_urb_link *urbl = NULL;
-       struct oz_endpoint *ep;
-
-       spin_lock_bh(&port->ozhcd->hcd_lock);
-       if (in_dir)
-               ep = port->in_ep[ep_addr];
-       else
-               ep = port->out_ep[ep_addr];
-       if (ep) {
-               struct list_head *e;
-
-               list_for_each(e, &ep->urb_list) {
-                       urbl = list_entry(e, struct oz_urb_link, link);
-                       if (urbl->urb == urb) {
-                               list_del_init(e);
-                               break;
-                       }
-                       urbl = NULL;
-               }
-       }
-       spin_unlock_bh(&port->ozhcd->hcd_lock);
-       oz_free_urb_link(urbl);
-       return urbl ? 0 : -EIDRM;
-}
-
-/*
- * Finds an urb given its request id.
- * Context: softirq
- */
-static struct urb *oz_find_urb_by_id(struct oz_port *port, int ep_ix,
-               u8 req_id)
-{
-       struct oz_hcd *ozhcd = port->ozhcd;
-       struct urb *urb = NULL;
-       struct oz_urb_link *urbl;
-       struct oz_endpoint *ep;
-
-       spin_lock_bh(&ozhcd->hcd_lock);
-       ep = port->out_ep[ep_ix];
-       if (ep) {
-               struct list_head *e;
-
-               list_for_each(e, &ep->urb_list) {
-                       urbl = list_entry(e, struct oz_urb_link, link);
-                       if (urbl->req_id == req_id) {
-                               urb = urbl->urb;
-                               list_del_init(e);
-                               break;
-                       }
-               }
-       }
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       /* If urb is non-zero then we we must have an urb link to delete.
-        */
-       if (urb)
-               oz_free_urb_link(urbl);
-       return urb;
-}
-
-/*
- * Pre-condition: Port lock must be held.
- * Context: softirq
- */
-static void oz_acquire_port(struct oz_port *port, void *hpd)
-{
-       INIT_LIST_HEAD(&port->isoc_out_ep);
-       INIT_LIST_HEAD(&port->isoc_in_ep);
-       port->flags |= OZ_PORT_F_PRESENT | OZ_PORT_F_CHANGED;
-       port->status |= USB_PORT_STAT_CONNECTION |
-                       (USB_PORT_STAT_C_CONNECTION << 16);
-       oz_usb_get(hpd);
-       port->hpd = hpd;
-}
-
-/*
- * Context: softirq
- */
-static struct oz_hcd *oz_hcd_claim(void)
-{
-       struct oz_hcd *ozhcd;
-
-       spin_lock_bh(&g_hcdlock);
-       ozhcd = g_ozhcd;
-       if (ozhcd)
-               usb_get_hcd(ozhcd->hcd);
-       spin_unlock_bh(&g_hcdlock);
-       return ozhcd;
-}
-
-/*
- * Context: softirq
- */
-static inline void oz_hcd_put(struct oz_hcd *ozhcd)
-{
-       if (ozhcd)
-               usb_put_hcd(ozhcd->hcd);
-}
-
-/*
- * This is called by the protocol handler to notify that a PD has arrived.
- * We allocate a port to associate with the PD and create a structure for
- * endpoint 0. This port is made the connection port.
- * In the event that one of the other port is already a connection port then
- * we fail.
- * TODO We should be able to do better than fail and should be able remember
- * that this port needs configuring and make it the connection port once the
- * current connection port has been assigned an address. Collisions here are
- * probably very rare indeed.
- * Context: softirq
- */
-struct oz_port *oz_hcd_pd_arrived(void *hpd)
-{
-       int i;
-       struct oz_port *hport;
-       struct oz_hcd *ozhcd;
-       struct oz_endpoint *ep;
-
-       ozhcd = oz_hcd_claim();
-       if (!ozhcd)
-               return NULL;
-       /* Allocate an endpoint object in advance (before holding hcd lock) to
-        * use for out endpoint 0.
-        */
-       ep = oz_ep_alloc(0, GFP_ATOMIC);
-       if (!ep)
-               goto err_put;
-
-       spin_lock_bh(&ozhcd->hcd_lock);
-       if (ozhcd->conn_port >= 0)
-               goto err_unlock;
-
-       for (i = 0; i < OZ_NB_PORTS; i++) {
-               struct oz_port *port = &ozhcd->ports[i];
-
-               spin_lock(&port->port_lock);
-               if (!(port->flags & (OZ_PORT_F_PRESENT | OZ_PORT_F_CHANGED))) {
-                       oz_acquire_port(port, hpd);
-                       spin_unlock(&port->port_lock);
-                       break;
-               }
-               spin_unlock(&port->port_lock);
-       }
-       if (i == OZ_NB_PORTS)
-               goto err_unlock;
-
-       ozhcd->conn_port = i;
-       hport = &ozhcd->ports[i];
-       hport->out_ep[0] = ep;
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       if (ozhcd->flags & OZ_HDC_F_SUSPENDED)
-               usb_hcd_resume_root_hub(ozhcd->hcd);
-       usb_hcd_poll_rh_status(ozhcd->hcd);
-       oz_hcd_put(ozhcd);
-
-       return hport;
-
-err_unlock:
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       oz_ep_free(NULL, ep);
-err_put:
-       oz_hcd_put(ozhcd);
-       return NULL;
-}
-
-/*
- * This is called by the protocol handler to notify that the PD has gone away.
- * We need to deallocate all resources and then request that the root hub is
- * polled. We release the reference we hold on the PD.
- * Context: softirq
- */
-void oz_hcd_pd_departed(struct oz_port *port)
-{
-       struct oz_hcd *ozhcd;
-       void *hpd;
-       struct oz_endpoint *ep = NULL;
-
-       if (port == NULL) {
-               oz_dbg(ON, "%s: port = 0\n", __func__);
-               return;
-       }
-       ozhcd = port->ozhcd;
-       if (ozhcd == NULL)
-               return;
-       /* Check if this is the connection port - if so clear it.
-        */
-       spin_lock_bh(&ozhcd->hcd_lock);
-       if ((ozhcd->conn_port >= 0) &&
-               (port == &ozhcd->ports[ozhcd->conn_port])) {
-               oz_dbg(ON, "Clearing conn_port\n");
-               ozhcd->conn_port = -1;
-       }
-       spin_lock(&port->port_lock);
-       port->flags |= OZ_PORT_F_DYING;
-       spin_unlock(&port->port_lock);
-       spin_unlock_bh(&ozhcd->hcd_lock);
-
-       oz_clean_endpoints_for_config(ozhcd->hcd, port);
-       spin_lock_bh(&port->port_lock);
-       hpd = port->hpd;
-       port->hpd = NULL;
-       port->bus_addr = 0xff;
-       port->config_num = 0;
-       port->flags &= ~(OZ_PORT_F_PRESENT | OZ_PORT_F_DYING);
-       port->flags |= OZ_PORT_F_CHANGED;
-       port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE);
-       port->status |= (USB_PORT_STAT_C_CONNECTION << 16);
-       /* If there is an endpont 0 then clear the pointer while we hold
-        * the spinlock be we deallocate it after releasing the lock.
-        */
-       if (port->out_ep[0]) {
-               ep = port->out_ep[0];
-               port->out_ep[0] = NULL;
-       }
-       spin_unlock_bh(&port->port_lock);
-       if (ep)
-               oz_ep_free(port, ep);
-       usb_hcd_poll_rh_status(ozhcd->hcd);
-       oz_usb_put(hpd);
-}
-
-/*
- * Context: softirq
- */
-void oz_hcd_pd_reset(void *hpd, void *hport)
-{
-       /* Cleanup the current configuration and report reset to the core.
-        */
-       struct oz_port *port = hport;
-       struct oz_hcd *ozhcd = port->ozhcd;
-
-       oz_dbg(ON, "PD Reset\n");
-       spin_lock_bh(&port->port_lock);
-       port->flags |= OZ_PORT_F_CHANGED;
-       port->status |= USB_PORT_STAT_RESET;
-       port->status |= (USB_PORT_STAT_C_RESET << 16);
-       spin_unlock_bh(&port->port_lock);
-       oz_clean_endpoints_for_config(ozhcd->hcd, port);
-       usb_hcd_poll_rh_status(ozhcd->hcd);
-}
-
-/*
- * Context: softirq
- */
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, const u8 *desc,
-                       u8 length, u16 offset, u16 total_size)
-{
-       struct oz_port *port = hport;
-       struct urb *urb;
-       int err = 0;
-
-       oz_dbg(ON, "oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n",
-              length, offset, total_size);
-       urb = oz_find_urb_by_id(port, 0, req_id);
-       if (!urb)
-               return;
-       if (status == 0) {
-               unsigned int copy_len;
-               unsigned int required_size = urb->transfer_buffer_length;
-
-               if (required_size > total_size)
-                       required_size = total_size;
-               copy_len = required_size-offset;
-               if (length <= copy_len)
-                       copy_len = length;
-               memcpy(urb->transfer_buffer+offset, desc, copy_len);
-               offset += copy_len;
-               if (offset < required_size) {
-                       struct usb_ctrlrequest *setup =
-                               (struct usb_ctrlrequest *)urb->setup_packet;
-                       unsigned wvalue = le16_to_cpu(setup->wValue);
-
-                       if (oz_enqueue_ep_urb(port, 0, 0, urb, req_id))
-                               err = -ENOMEM;
-                       else if (oz_usb_get_desc_req(port->hpd, req_id,
-                                       setup->bRequestType, (u8)(wvalue>>8),
-                                       (u8)wvalue, setup->wIndex, offset,
-                                       required_size-offset)) {
-                               oz_dequeue_ep_urb(port, 0, 0, urb);
-                               err = -ENOMEM;
-                       }
-                       if (err == 0)
-                               return;
-               }
-       }
-       urb->actual_length = total_size;
-       oz_complete_urb(port->ozhcd->hcd, urb, 0);
-}
-
-/*
- * Context: softirq
- */
-static void oz_display_conf_type(u8 t)
-{
-       switch (t) {
-       case USB_REQ_GET_STATUS:
-               oz_dbg(ON, "USB_REQ_GET_STATUS - cnf\n");
-               break;
-       case USB_REQ_CLEAR_FEATURE:
-               oz_dbg(ON, "USB_REQ_CLEAR_FEATURE - cnf\n");
-               break;
-       case USB_REQ_SET_FEATURE:
-               oz_dbg(ON, "USB_REQ_SET_FEATURE - cnf\n");
-               break;
-       case USB_REQ_SET_ADDRESS:
-               oz_dbg(ON, "USB_REQ_SET_ADDRESS - cnf\n");
-               break;
-       case USB_REQ_GET_DESCRIPTOR:
-               oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
-               break;
-       case USB_REQ_SET_DESCRIPTOR:
-               oz_dbg(ON, "USB_REQ_SET_DESCRIPTOR - cnf\n");
-               break;
-       case USB_REQ_GET_CONFIGURATION:
-               oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - cnf\n");
-               break;
-       case USB_REQ_SET_CONFIGURATION:
-               oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - cnf\n");
-               break;
-       case USB_REQ_GET_INTERFACE:
-               oz_dbg(ON, "USB_REQ_GET_INTERFACE - cnf\n");
-               break;
-       case USB_REQ_SET_INTERFACE:
-               oz_dbg(ON, "USB_REQ_SET_INTERFACE - cnf\n");
-               break;
-       case USB_REQ_SYNCH_FRAME:
-               oz_dbg(ON, "USB_REQ_SYNCH_FRAME - cnf\n");
-               break;
-       }
-}
-
-/*
- * Context: softirq
- */
-static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb,
-               u8 rcode, u8 config_num)
-{
-       int rc = 0;
-       struct usb_hcd *hcd = port->ozhcd->hcd;
-
-       if (rcode == 0) {
-               port->config_num = config_num;
-               oz_clean_endpoints_for_config(hcd, port);
-               if (oz_build_endpoints_for_config(hcd, port,
-                       &urb->dev->config[port->config_num-1], GFP_ATOMIC)) {
-                       rc = -ENOMEM;
-               }
-       } else {
-               rc = -ENOMEM;
-       }
-       oz_complete_urb(hcd, urb, rc);
-}
-
-/*
- * Context: softirq
- */
-static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb,
-               u8 rcode, u8 if_num, u8 alt)
-{
-       struct usb_hcd *hcd = port->ozhcd->hcd;
-       int rc = 0;
-
-       if ((rcode == 0) && (port->config_num > 0)) {
-               struct usb_host_config *config;
-               struct usb_host_interface *intf;
-
-               oz_dbg(ON, "Set interface %d alt %d\n", if_num, alt);
-               oz_clean_endpoints_for_interface(hcd, port, if_num);
-               config = &urb->dev->config[port->config_num-1];
-               intf = &config->intf_cache[if_num]->altsetting[alt];
-               if (oz_build_endpoints_for_interface(hcd, port, intf,
-                       GFP_ATOMIC))
-                       rc = -ENOMEM;
-               else
-                       port->iface[if_num].alt = alt;
-       } else {
-               rc = -ENOMEM;
-       }
-       oz_complete_urb(hcd, urb, rc);
-}
-
-/*
- * Context: softirq
- */
-void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
-       int data_len)
-{
-       struct oz_port *port = hport;
-       struct urb *urb;
-       struct usb_ctrlrequest *setup;
-       struct usb_hcd *hcd = port->ozhcd->hcd;
-       unsigned windex;
-       unsigned wvalue;
-
-       oz_dbg(ON, "oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len);
-       urb = oz_find_urb_by_id(port, 0, req_id);
-       if (!urb) {
-               oz_dbg(ON, "URB not found\n");
-               return;
-       }
-       setup = (struct usb_ctrlrequest *)urb->setup_packet;
-       windex = le16_to_cpu(setup->wIndex);
-       wvalue = le16_to_cpu(setup->wValue);
-       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               /* Standard requests */
-               oz_display_conf_type(setup->bRequest);
-               switch (setup->bRequest) {
-               case USB_REQ_SET_CONFIGURATION:
-                       oz_hcd_complete_set_config(port, urb, rcode,
-                               (u8)wvalue);
-                       break;
-               case USB_REQ_SET_INTERFACE:
-                       oz_hcd_complete_set_interface(port, urb, rcode,
-                               (u8)windex, (u8)wvalue);
-                       break;
-               default:
-                       oz_complete_urb(hcd, urb, 0);
-               }
-
-       } else {
-               int copy_len;
-
-               oz_dbg(ON, "VENDOR-CLASS - cnf\n");
-               if (data_len) {
-                       if (data_len <= urb->transfer_buffer_length)
-                               copy_len = data_len;
-                       else
-                               copy_len = urb->transfer_buffer_length;
-                       memcpy(urb->transfer_buffer, data, copy_len);
-                       urb->actual_length = copy_len;
-               }
-               oz_complete_urb(hcd, urb, 0);
-       }
-}
-
-/*
- * Context: softirq-serialized
- */
-static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data,
-                             int data_len)
-{
-       int space;
-       int copy_len;
-
-       if (!ep->buffer)
-               return -1;
-       space = ep->out_ix-ep->in_ix-1;
-       if (space < 0)
-               space += ep->buffer_size;
-       if (space < (data_len+1)) {
-               oz_dbg(ON, "Buffer full\n");
-               return -1;
-       }
-       ep->buffer[ep->in_ix] = (u8)data_len;
-       if (++ep->in_ix == ep->buffer_size)
-               ep->in_ix = 0;
-       copy_len = ep->buffer_size - ep->in_ix;
-       if (copy_len > data_len)
-               copy_len = data_len;
-       memcpy(&ep->buffer[ep->in_ix], data, copy_len);
-
-       if (copy_len < data_len) {
-               memcpy(ep->buffer, data+copy_len, data_len-copy_len);
-               ep->in_ix = data_len-copy_len;
-       } else {
-               ep->in_ix += copy_len;
-       }
-       if (ep->in_ix == ep->buffer_size)
-               ep->in_ix = 0;
-       ep->buffered_units++;
-       return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len)
-{
-       struct oz_port *port = (struct oz_port *)hport;
-       struct oz_endpoint *ep;
-       struct oz_hcd *ozhcd = port->ozhcd;
-
-       spin_lock_bh(&ozhcd->hcd_lock);
-       ep = port->in_ep[endpoint & USB_ENDPOINT_NUMBER_MASK];
-       if (ep == NULL)
-               goto done;
-       switch (ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) {
-       case USB_ENDPOINT_XFER_INT:
-       case USB_ENDPOINT_XFER_BULK:
-               if (!list_empty(&ep->urb_list)) {
-                       struct oz_urb_link *urbl =
-                               list_first_entry(&ep->urb_list,
-                                       struct oz_urb_link, link);
-                       struct urb *urb;
-                       int copy_len;
-
-                       list_del_init(&urbl->link);
-                       spin_unlock_bh(&ozhcd->hcd_lock);
-                       urb = urbl->urb;
-                       oz_free_urb_link(urbl);
-                       if (data_len <= urb->transfer_buffer_length)
-                               copy_len = data_len;
-                       else
-                               copy_len = urb->transfer_buffer_length;
-                       memcpy(urb->transfer_buffer, data, copy_len);
-                       urb->actual_length = copy_len;
-                       oz_complete_urb(port->ozhcd->hcd, urb, 0);
-                       return;
-               }
-               oz_dbg(ON, "buffering frame as URB is not available\n");
-               oz_hcd_buffer_data(ep, data, data_len);
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               oz_hcd_buffer_data(ep, data, data_len);
-               break;
-       }
-done:
-       spin_unlock_bh(&ozhcd->hcd_lock);
-}
-
-/*
- * Context: unknown
- */
-static inline int oz_usb_get_frame_number(void)
-{
-       return atomic_inc_return(&g_usb_frame_number);
-}
-
-/*
- * Context: softirq
- */
-int oz_hcd_heartbeat(void *hport)
-{
-       int rc = 0;
-       struct oz_port *port = hport;
-       struct oz_hcd *ozhcd = port->ozhcd;
-       struct oz_urb_link *urbl, *n;
-       LIST_HEAD(xfr_list);
-       struct urb *urb;
-       struct oz_endpoint *ep;
-       struct timespec ts, delta;
-
-       getrawmonotonic(&ts);
-       /* Check the OUT isoc endpoints to see if any URB data can be sent.
-        */
-       spin_lock_bh(&ozhcd->hcd_lock);
-       list_for_each_entry(ep, &port->isoc_out_ep, link) {
-               if (ep->credit < 0)
-                       continue;
-               delta = timespec_sub(ts, ep->timestamp);
-               ep->credit += div_u64(timespec_to_ns(&delta), NSEC_PER_MSEC);
-               if (ep->credit > ep->credit_ceiling)
-                       ep->credit = ep->credit_ceiling;
-               ep->timestamp = ts;
-               while (ep->credit && !list_empty(&ep->urb_list)) {
-                       urbl = list_first_entry(&ep->urb_list,
-                               struct oz_urb_link, link);
-                       urb = urbl->urb;
-                       if ((ep->credit + 1) < urb->number_of_packets)
-                               break;
-                       ep->credit -= urb->number_of_packets;
-                       if (ep->credit < 0)
-                               ep->credit = 0;
-                       list_move_tail(&urbl->link, &xfr_list);
-               }
-       }
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       /* Send to PD and complete URBs.
-        */
-       list_for_each_entry_safe(urbl, n, &xfr_list, link) {
-               urb = urbl->urb;
-               list_del_init(&urbl->link);
-               urb->error_count = 0;
-               urb->start_frame = oz_usb_get_frame_number();
-               oz_usb_send_isoc(port->hpd, urbl->ep_num, urb);
-               oz_free_urb_link(urbl);
-               oz_complete_urb(port->ozhcd->hcd, urb, 0);
-       }
-       /* Check the IN isoc endpoints to see if any URBs can be completed.
-        */
-       spin_lock_bh(&ozhcd->hcd_lock);
-       list_for_each_entry(ep, &port->isoc_in_ep, link) {
-               if (ep->flags & OZ_F_EP_BUFFERING) {
-                       if (ep->buffered_units >= OZ_IN_BUFFERING_UNITS) {
-                               ep->flags &= ~OZ_F_EP_BUFFERING;
-                               ep->credit = 0;
-                               ep->timestamp = ts;
-                               ep->start_frame = 0;
-                       }
-                       continue;
-               }
-               delta = timespec_sub(ts, ep->timestamp);
-               ep->credit += div_u64(timespec_to_ns(&delta), NSEC_PER_MSEC);
-               ep->timestamp = ts;
-               list_for_each_entry_safe(urbl, n, &ep->urb_list, link) {
-                       struct urb *urb = urbl->urb;
-                       int len = 0;
-                       int copy_len;
-                       int i;
-
-                       if (ep->credit  < urb->number_of_packets)
-                               break;
-                       if (ep->buffered_units < urb->number_of_packets)
-                               break;
-                       urb->actual_length = 0;
-                       for (i = 0; i < urb->number_of_packets; i++) {
-                               len = ep->buffer[ep->out_ix];
-                               if (++ep->out_ix == ep->buffer_size)
-                                       ep->out_ix = 0;
-                               copy_len = ep->buffer_size - ep->out_ix;
-                               if (copy_len > len)
-                                       copy_len = len;
-                               memcpy(urb->transfer_buffer,
-                                       &ep->buffer[ep->out_ix], copy_len);
-                               if (copy_len < len) {
-                                       memcpy(urb->transfer_buffer+copy_len,
-                                               ep->buffer, len-copy_len);
-                                       ep->out_ix = len-copy_len;
-                               } else
-                                       ep->out_ix += copy_len;
-                               if (ep->out_ix == ep->buffer_size)
-                                       ep->out_ix = 0;
-                               urb->iso_frame_desc[i].offset =
-                                       urb->actual_length;
-                               urb->actual_length += len;
-                               urb->iso_frame_desc[i].actual_length = len;
-                               urb->iso_frame_desc[i].status = 0;
-                       }
-                       ep->buffered_units -= urb->number_of_packets;
-                       urb->error_count = 0;
-                       urb->start_frame = ep->start_frame;
-                       ep->start_frame += urb->number_of_packets;
-                       list_move_tail(&urbl->link, &xfr_list);
-                       ep->credit -= urb->number_of_packets;
-               }
-       }
-       if (!list_empty(&port->isoc_out_ep) || !list_empty(&port->isoc_in_ep))
-               rc = 1;
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       /* Complete the filled URBs.
-        */
-       list_for_each_entry_safe(urbl, n, &xfr_list, link) {
-               urb = urbl->urb;
-               list_del_init(&urbl->link);
-               oz_free_urb_link(urbl);
-               oz_complete_urb(port->ozhcd->hcd, urb, 0);
-       }
-       /* Check if there are any ep0 requests that have timed out.
-        * If so resent to PD.
-        */
-       ep = port->out_ep[0];
-       if (ep) {
-               spin_lock_bh(&ozhcd->hcd_lock);
-               list_for_each_entry_safe(urbl, n, &ep->urb_list, link) {
-                       if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) {
-                               oz_dbg(ON, "Request 0x%p timeout\n", urbl->urb);
-                               list_move_tail(&urbl->link, &xfr_list);
-                               urbl->submit_counter = 0;
-                       } else {
-                               urbl->submit_counter++;
-                       }
-               }
-               if (!list_empty(&ep->urb_list))
-                       rc = 1;
-               spin_unlock_bh(&ozhcd->hcd_lock);
-               list_for_each_entry_safe(urbl, n, &xfr_list, link) {
-                       oz_dbg(ON, "Resending request to PD\n");
-                       oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC);
-                       oz_free_urb_link(urbl);
-               }
-       }
-       return rc;
-}
-
-/*
- * Context: softirq
- */
-static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
-               struct oz_port *port,
-               struct usb_host_interface *intf, gfp_t mem_flags)
-{
-       struct oz_hcd *ozhcd = port->ozhcd;
-       int i;
-       int if_ix = intf->desc.bInterfaceNumber;
-       int request_heartbeat = 0;
-
-       oz_dbg(ON, "interface[%d] = %p\n", if_ix, intf);
-       if (if_ix >= port->num_iface || port->iface == NULL)
-               return -ENOMEM;
-       for (i = 0; i < intf->desc.bNumEndpoints; i++) {
-               struct usb_host_endpoint *hep = &intf->endpoint[i];
-               u8 ep_addr = hep->desc.bEndpointAddress;
-               u8 ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
-               struct oz_endpoint *ep;
-               int buffer_size = 0;
-
-               oz_dbg(ON, "%d bEndpointAddress = %x\n", i, ep_addr);
-               if (ep_addr & USB_ENDPOINT_DIR_MASK) {
-                       switch (hep->desc.bmAttributes &
-                                               USB_ENDPOINT_XFERTYPE_MASK) {
-                       case USB_ENDPOINT_XFER_ISOC:
-                               buffer_size = OZ_EP_BUFFER_SIZE_ISOC;
-                               break;
-                       case USB_ENDPOINT_XFER_INT:
-                               buffer_size = OZ_EP_BUFFER_SIZE_INT;
-                               break;
-                       }
-               }
-
-               ep = oz_ep_alloc(buffer_size, mem_flags);
-               if (!ep) {
-                       oz_clean_endpoints_for_interface(hcd, port, if_ix);
-                       return -ENOMEM;
-               }
-               ep->attrib = hep->desc.bmAttributes;
-               ep->ep_num = ep_num;
-               if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
-                       == USB_ENDPOINT_XFER_ISOC) {
-                       oz_dbg(ON, "wMaxPacketSize = %d\n",
-                              usb_endpoint_maxp(&hep->desc));
-                       ep->credit_ceiling = 200;
-                       if (ep_addr & USB_ENDPOINT_DIR_MASK) {
-                               ep->flags |= OZ_F_EP_BUFFERING;
-                       } else {
-                               ep->flags |= OZ_F_EP_HAVE_STREAM;
-                               if (oz_usb_stream_create(port->hpd, ep_num))
-                                       ep->flags &= ~OZ_F_EP_HAVE_STREAM;
-                       }
-               }
-               spin_lock_bh(&ozhcd->hcd_lock);
-               if (ep_addr & USB_ENDPOINT_DIR_MASK) {
-                       port->in_ep[ep_num] = ep;
-                       port->iface[if_ix].ep_mask |=
-                               (1<<(ep_num+OZ_NB_ENDPOINTS));
-                       if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
-                                == USB_ENDPOINT_XFER_ISOC) {
-                               list_add_tail(&ep->link, &port->isoc_in_ep);
-                               request_heartbeat = 1;
-                       }
-               } else {
-                       port->out_ep[ep_num] = ep;
-                       port->iface[if_ix].ep_mask |= (1<<ep_num);
-                       if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
-                               == USB_ENDPOINT_XFER_ISOC) {
-                               list_add_tail(&ep->link, &port->isoc_out_ep);
-                               request_heartbeat = 1;
-                       }
-               }
-               spin_unlock_bh(&ozhcd->hcd_lock);
-               if (request_heartbeat && port->hpd)
-                       oz_usb_request_heartbeat(port->hpd);
-       }
-       return 0;
-}
-
-/*
- * Context: softirq
- */
-static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd,
-                       struct oz_port *port, int if_ix)
-{
-       struct oz_hcd *ozhcd = port->ozhcd;
-       unsigned mask;
-       int i;
-       LIST_HEAD(ep_list);
-       struct oz_endpoint *ep, *n;
-
-       oz_dbg(ON, "Deleting endpoints for interface %d\n", if_ix);
-       if (if_ix >= port->num_iface)
-               return;
-       spin_lock_bh(&ozhcd->hcd_lock);
-       mask = port->iface[if_ix].ep_mask;
-       port->iface[if_ix].ep_mask = 0;
-       for (i = 0; i < OZ_NB_ENDPOINTS; i++) {
-               struct list_head *e;
-               /* Gather OUT endpoints.
-                */
-               if ((mask & (1<<i)) && port->out_ep[i]) {
-                       e = &port->out_ep[i]->link;
-                       port->out_ep[i] = NULL;
-                       /* Remove from isoc list if present.
-                        */
-                       list_move_tail(e, &ep_list);
-               }
-               /* Gather IN endpoints.
-                */
-               if ((mask & (1<<(i+OZ_NB_ENDPOINTS))) && port->in_ep[i]) {
-                       e = &port->in_ep[i]->link;
-                       port->in_ep[i] = NULL;
-                       list_move_tail(e, &ep_list);
-               }
-       }
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       list_for_each_entry_safe(ep, n, &ep_list, link) {
-               list_del_init(&ep->link);
-               oz_ep_free(port, ep);
-       }
-}
-
-/*
- * Context: softirq
- */
-static int oz_build_endpoints_for_config(struct usb_hcd *hcd,
-               struct oz_port *port, struct usb_host_config *config,
-               gfp_t mem_flags)
-{
-       struct oz_hcd *ozhcd = port->ozhcd;
-       int i;
-       int num_iface = config->desc.bNumInterfaces;
-
-       if (num_iface) {
-               struct oz_interface *iface;
-
-               iface = kmalloc_array(num_iface, sizeof(struct oz_interface),
-                                       mem_flags | __GFP_ZERO);
-               if (!iface)
-                       return -ENOMEM;
-               spin_lock_bh(&ozhcd->hcd_lock);
-               port->iface = iface;
-               port->num_iface = num_iface;
-               spin_unlock_bh(&ozhcd->hcd_lock);
-       }
-       for (i = 0; i < num_iface; i++) {
-               struct usb_host_interface *intf =
-                       &config->intf_cache[i]->altsetting[0];
-               if (oz_build_endpoints_for_interface(hcd, port, intf,
-                       mem_flags))
-                       goto fail;
-       }
-       return 0;
-fail:
-       oz_clean_endpoints_for_config(hcd, port);
-       return -1;
-}
-
-/*
- * Context: softirq
- */
-static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
-                       struct oz_port *port)
-{
-       struct oz_hcd *ozhcd = port->ozhcd;
-       int i;
-
-       oz_dbg(ON, "Deleting endpoints for configuration\n");
-       for (i = 0; i < port->num_iface; i++)
-               oz_clean_endpoints_for_interface(hcd, port, i);
-       spin_lock_bh(&ozhcd->hcd_lock);
-       if (port->iface) {
-               oz_dbg(ON, "Freeing interfaces object\n");
-               kfree(port->iface);
-               port->iface = NULL;
-       }
-       port->num_iface = 0;
-       spin_unlock_bh(&ozhcd->hcd_lock);
-}
-
-/*
- * Context: tasklet
- */
-static void *oz_claim_hpd(struct oz_port *port)
-{
-       void *hpd;
-       struct oz_hcd *ozhcd = port->ozhcd;
-
-       spin_lock_bh(&ozhcd->hcd_lock);
-       hpd = port->hpd;
-       if (hpd)
-               oz_usb_get(hpd);
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       return hpd;
-}
-
-/*
- * Context: tasklet
- */
-static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
-               gfp_t mem_flags)
-{
-       struct usb_ctrlrequest *setup;
-       unsigned windex;
-       unsigned wvalue;
-       unsigned wlength;
-       void *hpd;
-       u8 req_id;
-       int rc = 0;
-       unsigned complete = 0;
-
-       int port_ix = -1;
-       struct oz_port *port = NULL;
-
-       oz_dbg(URB, "[%s]:(%p)\n", __func__, urb);
-       port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
-       if (port_ix < 0) {
-               rc = -EPIPE;
-               goto out;
-       }
-       port =  &ozhcd->ports[port_ix];
-       if (((port->flags & OZ_PORT_F_PRESENT) == 0)
-               || (port->flags & OZ_PORT_F_DYING)) {
-               oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n",
-                      port_ix, urb->dev->devnum);
-               rc = -EPIPE;
-               goto out;
-       }
-       /* Store port in private context data.
-        */
-       urb->hcpriv = port;
-       setup = (struct usb_ctrlrequest *)urb->setup_packet;
-       windex = le16_to_cpu(setup->wIndex);
-       wvalue = le16_to_cpu(setup->wValue);
-       wlength = le16_to_cpu(setup->wLength);
-       oz_dbg(CTRL_DETAIL, "bRequestType = %x\n", setup->bRequestType);
-       oz_dbg(CTRL_DETAIL, "bRequest = %x\n", setup->bRequest);
-       oz_dbg(CTRL_DETAIL, "wValue = %x\n", wvalue);
-       oz_dbg(CTRL_DETAIL, "wIndex = %x\n", windex);
-       oz_dbg(CTRL_DETAIL, "wLength = %x\n", wlength);
-
-       req_id = port->next_req_id++;
-       hpd = oz_claim_hpd(port);
-       if (hpd == NULL) {
-               oz_dbg(ON, "Cannot claim port\n");
-               rc = -EPIPE;
-               goto out;
-       }
-
-       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               /* Standard requests
-                */
-               switch (setup->bRequest) {
-               case USB_REQ_GET_DESCRIPTOR:
-                       oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - req\n");
-                       break;
-               case USB_REQ_SET_ADDRESS:
-                       oz_dbg(ON, "USB_REQ_SET_ADDRESS - req\n");
-                       oz_dbg(ON, "Port %d address is 0x%x\n",
-                              ozhcd->conn_port,
-                              (u8)le16_to_cpu(setup->wValue));
-                       spin_lock_bh(&ozhcd->hcd_lock);
-                       if (ozhcd->conn_port >= 0) {
-                               ozhcd->ports[ozhcd->conn_port].bus_addr =
-                                       (u8)le16_to_cpu(setup->wValue);
-                               oz_dbg(ON, "Clearing conn_port\n");
-                               ozhcd->conn_port = -1;
-                       }
-                       spin_unlock_bh(&ozhcd->hcd_lock);
-                       complete = 1;
-                       break;
-               case USB_REQ_SET_CONFIGURATION:
-                       oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - req\n");
-                       break;
-               case USB_REQ_GET_CONFIGURATION:
-                       /* We short circuit this case and reply directly since
-                        * we have the selected configuration number cached.
-                        */
-                       oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - reply now\n");
-                       if (urb->transfer_buffer_length >= 1) {
-                               urb->actual_length = 1;
-                               *((u8 *)urb->transfer_buffer) =
-                                       port->config_num;
-                               complete = 1;
-                       } else {
-                               rc = -EPIPE;
-                       }
-                       break;
-               case USB_REQ_GET_INTERFACE:
-                       /* We short circuit this case and reply directly since
-                        * we have the selected interface alternative cached.
-                        */
-                       oz_dbg(ON, "USB_REQ_GET_INTERFACE - reply now\n");
-                       if (urb->transfer_buffer_length >= 1) {
-                               urb->actual_length = 1;
-                               *((u8 *)urb->transfer_buffer) =
-                                       port->iface[(u8)windex].alt;
-                               oz_dbg(ON, "interface = %d alt = %d\n",
-                                      windex, port->iface[(u8)windex].alt);
-                               complete = 1;
-                       } else {
-                               rc = -EPIPE;
-                       }
-                       break;
-               case USB_REQ_SET_INTERFACE:
-                       oz_dbg(ON, "USB_REQ_SET_INTERFACE - req\n");
-                       break;
-               }
-       }
-       if (!rc && !complete) {
-               int data_len = 0;
-
-               if ((setup->bRequestType & USB_DIR_IN) == 0)
-                       data_len = wlength;
-               urb->actual_length = data_len;
-               if (oz_usb_control_req(port->hpd, req_id, setup,
-                               urb->transfer_buffer, data_len)) {
-                       rc = -ENOMEM;
-               } else {
-                       /* Note: we are queuing the request after we have
-                        * submitted it to be transmitted. If the request were
-                        * to complete before we queued it then it would not
-                        * be found in the queue. It seems impossible for
-                        * this to happen but if it did the request would
-                        * be resubmitted so the problem would hopefully
-                        * resolve itself. Putting the request into the
-                        * queue before it has been sent is worse since the
-                        * urb could be cancelled while we are using it
-                        * to build the request.
-                        */
-                       if (oz_enqueue_ep_urb(port, 0, 0, urb, req_id))
-                               rc = -ENOMEM;
-               }
-       }
-       oz_usb_put(hpd);
-out:
-       if (rc || complete) {
-               oz_dbg(ON, "Completing request locally\n");
-               oz_complete_urb(ozhcd->hcd, urb, rc);
-       } else {
-               oz_usb_request_heartbeat(port->hpd);
-       }
-}
-
-/*
- * Context: tasklet
- */
-static int oz_urb_process(struct oz_hcd *ozhcd, struct urb *urb)
-{
-       int rc = 0;
-       struct oz_port *port = urb->hcpriv;
-       u8 ep_addr;
-
-       /* When we are paranoid we keep a list of urbs which we check against
-        * before handing one back. This is just for debugging during
-        * development and should be turned off in the released driver.
-        */
-       oz_remember_urb(urb);
-       /* Check buffer is valid.
-        */
-       if (!urb->transfer_buffer && urb->transfer_buffer_length)
-               return -EINVAL;
-       /* Check if there is a device at the port - refuse if not.
-        */
-       if ((port->flags & OZ_PORT_F_PRESENT) == 0)
-               return -EPIPE;
-       ep_addr = usb_pipeendpoint(urb->pipe);
-       if (ep_addr) {
-               /* If the request is not for EP0 then queue it.
-                */
-               if (oz_enqueue_ep_urb(port, ep_addr, usb_pipein(urb->pipe),
-                       urb, 0))
-                       rc = -EPIPE;
-       } else {
-               oz_process_ep0_urb(ozhcd, urb, GFP_ATOMIC);
-       }
-       return rc;
-}
-
-/*
- * Context: tasklet
- */
-static void oz_urb_process_tasklet(unsigned long unused)
-{
-       unsigned long irq_state;
-       struct urb *urb;
-       struct oz_hcd *ozhcd = oz_hcd_claim();
-       struct oz_urb_link *urbl, *n;
-       int rc = 0;
-
-       if (ozhcd == NULL)
-               return;
-       /* This is called from a tasklet so is in softirq context but the urb
-        * list is filled from any context so we need to lock
-        * appropriately while removing urbs.
-        */
-       spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       list_for_each_entry_safe(urbl, n, &ozhcd->urb_pending_list, link) {
-               list_del_init(&urbl->link);
-               spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-               urb = urbl->urb;
-               oz_free_urb_link(urbl);
-               rc = oz_urb_process(ozhcd, urb);
-               if (rc)
-                       oz_complete_urb(ozhcd->hcd, urb, rc);
-               spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       }
-       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-       oz_hcd_put(ozhcd);
-}
-
-/*
- * This function searches for the urb in any of the lists it could be in.
- * If it is found it is removed from the list and completed. If the urb is
- * being processed then it won't be in a list so won't be found. However, the
- * call to usb_hcd_check_unlink_urb() will set the value of the unlinked field
- * to a non-zero value. When an attempt is made to put the urb back in a list
- * the unlinked field will be checked and the urb will then be completed.
- * Context: tasklet
- */
-static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
-{
-       struct oz_urb_link *urbl = NULL;
-       struct list_head *e;
-       struct oz_hcd *ozhcd;
-       unsigned long irq_state;
-       u8 ix;
-
-       if (port == NULL) {
-               oz_dbg(ON, "%s: ERROR: (%p) port is null\n", __func__, urb);
-               return;
-       }
-       ozhcd = port->ozhcd;
-       if (ozhcd == NULL) {
-               oz_dbg(ON, "%s; ERROR: (%p) ozhcd is null\n", __func__, urb);
-               return;
-       }
-
-       /* Look in the tasklet queue.
-        */
-       spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       list_for_each(e, &ozhcd->urb_cancel_list) {
-               urbl = list_entry(e, struct oz_urb_link, link);
-               if (urb == urbl->urb) {
-                       list_del_init(e);
-                       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-                       goto out2;
-               }
-       }
-       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-       urbl = NULL;
-
-       /* Look in the orphanage.
-        */
-       spin_lock_irqsave(&ozhcd->hcd_lock, irq_state);
-       list_for_each(e, &ozhcd->orphanage) {
-               urbl = list_entry(e, struct oz_urb_link, link);
-               if (urbl->urb == urb) {
-                       list_del(e);
-                       oz_dbg(ON, "Found urb in orphanage\n");
-                       goto out;
-               }
-       }
-       ix = (ep_num & 0xf);
-       urbl = NULL;
-       if ((ep_num & USB_DIR_IN) && ix)
-               urbl = oz_remove_urb(port->in_ep[ix], urb);
-       else
-               urbl = oz_remove_urb(port->out_ep[ix], urb);
-out:
-       spin_unlock_irqrestore(&ozhcd->hcd_lock, irq_state);
-out2:
-       if (urbl) {
-               urb->actual_length = 0;
-               oz_free_urb_link(urbl);
-               oz_complete_urb(ozhcd->hcd, urb, -EPIPE);
-       }
-}
-
-/*
- * Context: tasklet
- */
-static void oz_urb_cancel_tasklet(unsigned long unused)
-{
-       unsigned long irq_state;
-       struct urb *urb;
-       struct oz_urb_link *urbl, *n;
-       struct oz_hcd *ozhcd = oz_hcd_claim();
-
-       if (ozhcd == NULL)
-               return;
-       spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       list_for_each_entry_safe(urbl, n, &ozhcd->urb_cancel_list, link) {
-               list_del_init(&urbl->link);
-               spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-               urb = urbl->urb;
-               if (urb->unlinked)
-                       oz_urb_cancel(urbl->port, urbl->ep_num, urb);
-               oz_free_urb_link(urbl);
-               spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       }
-       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-       oz_hcd_put(ozhcd);
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
-{
-       if (ozhcd) {
-               struct oz_urb_link *urbl, *n;
-
-               list_for_each_entry_safe(urbl, n, &ozhcd->orphanage, link) {
-                       list_del(&urbl->link);
-                       oz_complete_urb(ozhcd->hcd, urbl->urb, status);
-                       oz_free_urb_link(urbl);
-               }
-       }
-}
-
-/*
- * Context: unknown
- */
-static int oz_hcd_start(struct usb_hcd *hcd)
-{
-       hcd->power_budget = 200;
-       hcd->state = HC_STATE_RUNNING;
-       hcd->uses_new_polling = 1;
-       return 0;
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_stop(struct usb_hcd *hcd)
-{
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_shutdown(struct usb_hcd *hcd)
-{
-}
-
-/*
- * Called to queue an urb for the device.
- * This function should return a non-zero error code if it fails the urb but
- * should not call usb_hcd_giveback_urb().
- * Context: any
- */
-static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
-                               gfp_t mem_flags)
-{
-       struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       int rc;
-       int port_ix;
-       struct oz_port *port;
-       unsigned long irq_state;
-       struct oz_urb_link *urbl;
-
-       oz_dbg(URB, "%s: (%p)\n",  __func__, urb);
-       if (unlikely(ozhcd == NULL)) {
-               oz_dbg(URB, "Refused urb(%p) not ozhcd\n", urb);
-               return -EPIPE;
-       }
-       if (unlikely(hcd->state != HC_STATE_RUNNING)) {
-               oz_dbg(URB, "Refused urb(%p) not running\n", urb);
-               return -EPIPE;
-       }
-       port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
-       if (port_ix < 0)
-               return -EPIPE;
-       port =  &ozhcd->ports[port_ix];
-       if (port == NULL)
-               return -EPIPE;
-       if (!(port->flags & OZ_PORT_F_PRESENT) ||
-                               (port->flags & OZ_PORT_F_CHANGED)) {
-               oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n",
-                      port_ix, urb->dev->devnum);
-               return -EPIPE;
-       }
-       urb->hcpriv = port;
-       /* Put request in queue for processing by tasklet.
-        */
-       urbl = oz_alloc_urb_link();
-       if (unlikely(urbl == NULL))
-               return -ENOMEM;
-       urbl->urb = urb;
-       spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       rc = usb_hcd_link_urb_to_ep(hcd, urb);
-       if (unlikely(rc)) {
-               spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-               oz_free_urb_link(urbl);
-               return rc;
-       }
-       list_add_tail(&urbl->link, &ozhcd->urb_pending_list);
-       spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-       tasklet_schedule(&g_urb_process_tasklet);
-       atomic_inc(&g_pending_urbs);
-       return 0;
-}
-
-/*
- * Context: tasklet
- */
-static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
-                               struct urb *urb)
-{
-       struct oz_urb_link *urbl;
-
-       if (unlikely(ep == NULL))
-               return NULL;
-
-       list_for_each_entry(urbl, &ep->urb_list, link) {
-               if (urbl->urb == urb) {
-                       list_del_init(&urbl->link);
-                       if (usb_pipeisoc(urb->pipe)) {
-                               ep->credit -= urb->number_of_packets;
-                               if (ep->credit < 0)
-                                       ep->credit = 0;
-                       }
-                       return urbl;
-               }
-       }
-       return NULL;
-}
-
-/*
- * Called to dequeue a previously submitted urb for the device.
- * Context: any
- */
-static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
-       struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       struct oz_urb_link *urbl;
-       int rc;
-       unsigned long irq_state;
-
-       oz_dbg(URB, "%s: (%p)\n",  __func__, urb);
-       urbl = oz_alloc_urb_link();
-       if (unlikely(urbl == NULL))
-               return -ENOMEM;
-       spin_lock_irqsave(&g_tasklet_lock, irq_state);
-       /* The following function checks the urb is still in the queue
-        * maintained by the core and that the unlinked field is zero.
-        * If both are true the function sets the unlinked field and returns
-        * zero. Otherwise it returns an error.
-        */
-       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
-       /* We have to check we haven't completed the urb or are about
-        * to complete it. When we do we set hcpriv to 0 so if this has
-        * already happened we don't put the urb in the cancel queue.
-        */
-       if ((rc == 0) && urb->hcpriv) {
-               urbl->urb = urb;
-               urbl->port = (struct oz_port *)urb->hcpriv;
-               urbl->ep_num = usb_pipeendpoint(urb->pipe);
-               if (usb_pipein(urb->pipe))
-                       urbl->ep_num |= USB_DIR_IN;
-               list_add_tail(&urbl->link, &ozhcd->urb_cancel_list);
-               spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-               tasklet_schedule(&g_urb_cancel_tasklet);
-       } else {
-               spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
-               oz_free_urb_link(urbl);
-       }
-       return rc;
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
-                               struct usb_host_endpoint *ep)
-{
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
-                               struct usb_host_endpoint *ep)
-{
-}
-
-/*
- * Context: unknown
- */
-static int oz_hcd_get_frame_number(struct usb_hcd *hcd)
-{
-       oz_dbg(ON, "oz_hcd_get_frame_number\n");
-       return oz_usb_get_frame_number();
-}
-
-/*
- * Context: softirq
- * This is called as a consquence of us calling usb_hcd_poll_rh_status() and we
- * always do that in softirq context.
- */
-static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
-{
-       struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       int i;
-
-       buf[0] = 0;
-       buf[1] = 0;
-
-       spin_lock_bh(&ozhcd->hcd_lock);
-       for (i = 0; i < OZ_NB_PORTS; i++) {
-               if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) {
-                       oz_dbg(HUB, "Port %d changed\n", i);
-                       ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED;
-                       if (i < 7)
-                               buf[0] |= 1 << (i + 1);
-                       else
-                               buf[1] |= 1 << (i - 7);
-               }
-       }
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       if (buf[0] != 0 || buf[1] != 0)
-               return 2;
-       return 0;
-}
-
-/*
- * Context: process
- */
-static void oz_get_hub_descriptor(struct usb_hcd *hcd,
-                               struct usb_hub_descriptor *desc)
-{
-       memset(desc, 0, sizeof(*desc));
-       desc->bDescriptorType = 0x29;
-       desc->bDescLength = 9;
-       desc->wHubCharacteristics = cpu_to_le16(0x0001);
-       desc->bNbrPorts = OZ_NB_PORTS;
-}
-
-/*
- * Context: process
- */
-static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
-{
-       struct oz_port *port;
-       u8 port_id = (u8)windex;
-       struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       unsigned set_bits = 0;
-       unsigned clear_bits = 0;
-
-       if ((port_id < 1) || (port_id > OZ_NB_PORTS))
-               return -EPIPE;
-       port = &ozhcd->ports[port_id-1];
-       switch (wvalue) {
-       case USB_PORT_FEAT_CONNECTION:
-               oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n");
-               break;
-       case USB_PORT_FEAT_ENABLE:
-               oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n");
-               break;
-       case USB_PORT_FEAT_SUSPEND:
-               oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n");
-               break;
-       case USB_PORT_FEAT_OVER_CURRENT:
-               oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
-               break;
-       case USB_PORT_FEAT_RESET:
-               oz_dbg(HUB, "USB_PORT_FEAT_RESET\n");
-               set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16);
-               clear_bits = USB_PORT_STAT_RESET;
-               ozhcd->ports[port_id-1].bus_addr = 0;
-               break;
-       case USB_PORT_FEAT_POWER:
-               oz_dbg(HUB, "USB_PORT_FEAT_POWER\n");
-               set_bits |= USB_PORT_STAT_POWER;
-               break;
-       case USB_PORT_FEAT_LOWSPEED:
-               oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n");
-               break;
-       case USB_PORT_FEAT_C_CONNECTION:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n");
-               break;
-       case USB_PORT_FEAT_C_ENABLE:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n");
-               break;
-       case USB_PORT_FEAT_C_SUSPEND:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n");
-               break;
-       case USB_PORT_FEAT_C_OVER_CURRENT:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
-               break;
-       case USB_PORT_FEAT_C_RESET:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n");
-               break;
-       case USB_PORT_FEAT_TEST:
-               oz_dbg(HUB, "USB_PORT_FEAT_TEST\n");
-               break;
-       case USB_PORT_FEAT_INDICATOR:
-               oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n");
-               break;
-       default:
-               oz_dbg(HUB, "Other %d\n", wvalue);
-               break;
-       }
-       if (set_bits || clear_bits) {
-               spin_lock_bh(&port->port_lock);
-               port->status &= ~clear_bits;
-               port->status |= set_bits;
-               spin_unlock_bh(&port->port_lock);
-       }
-       oz_dbg(HUB, "Port[%d] status = 0x%x\n", port_id, port->status);
-       return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
-{
-       struct oz_port *port;
-       u8 port_id = (u8)windex;
-       struct oz_hcd *ozhcd = oz_hcd_private(hcd);
-       unsigned clear_bits = 0;
-
-       if ((port_id < 1) || (port_id > OZ_NB_PORTS))
-               return -EPIPE;
-       port = &ozhcd->ports[port_id-1];
-       switch (wvalue) {
-       case USB_PORT_FEAT_CONNECTION:
-               oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n");
-               break;
-       case USB_PORT_FEAT_ENABLE:
-               oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n");
-               clear_bits = USB_PORT_STAT_ENABLE;
-               break;
-       case USB_PORT_FEAT_SUSPEND:
-               oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n");
-               break;
-       case USB_PORT_FEAT_OVER_CURRENT:
-               oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
-               break;
-       case USB_PORT_FEAT_RESET:
-               oz_dbg(HUB, "USB_PORT_FEAT_RESET\n");
-               break;
-       case USB_PORT_FEAT_POWER:
-               oz_dbg(HUB, "USB_PORT_FEAT_POWER\n");
-               clear_bits |= USB_PORT_STAT_POWER;
-               break;
-       case USB_PORT_FEAT_LOWSPEED:
-               oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n");
-               break;
-       case USB_PORT_FEAT_C_CONNECTION:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n");
-               clear_bits = USB_PORT_STAT_C_CONNECTION << 16;
-               break;
-       case USB_PORT_FEAT_C_ENABLE:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n");
-               clear_bits = USB_PORT_STAT_C_ENABLE << 16;
-               break;
-       case USB_PORT_FEAT_C_SUSPEND:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n");
-               break;
-       case USB_PORT_FEAT_C_OVER_CURRENT:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
-               break;
-       case USB_PORT_FEAT_C_RESET:
-               oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n");
-               clear_bits = USB_PORT_FEAT_C_RESET << 16;
-               break;
-       case USB_PORT_FEAT_TEST:
-               oz_dbg(HUB, "USB_PORT_FEAT_TEST\n");
-               break;
-       case USB_PORT_FEAT_INDICATOR:
-               oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n");
-               break;
-       default:
-               oz_dbg(HUB, "Other %d\n", wvalue);
-               break;
-       }
-       if (clear_bits) {
-               spin_lock_bh(&port->port_lock);
-               port->status &= ~clear_bits;
-               spin_unlock_bh(&port->port_lock);
-       }
-       oz_dbg(HUB, "Port[%d] status = 0x%x\n",
-              port_id, ozhcd->ports[port_id-1].status);
-       return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf)
-{
-       struct oz_hcd *ozhcd;
-       u32 status;
-
-       if ((windex < 1) || (windex > OZ_NB_PORTS))
-               return -EPIPE;
-       ozhcd = oz_hcd_private(hcd);
-       oz_dbg(HUB, "GetPortStatus windex = %d\n", windex);
-       status = ozhcd->ports[windex-1].status;
-       put_unaligned(cpu_to_le32(status), (__le32 *)buf);
-       oz_dbg(HUB, "Port[%d] status = %x\n", windex, status);
-       return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
-                               u16 windex, char *buf, u16 wlength)
-{
-       int err = 0;
-
-       switch (req_type) {
-       case ClearHubFeature:
-               oz_dbg(HUB, "ClearHubFeature: %d\n", req_type);
-               break;
-       case ClearPortFeature:
-               err = oz_clear_port_feature(hcd, wvalue, windex);
-               break;
-       case GetHubDescriptor:
-               oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf);
-               break;
-       case GetHubStatus:
-               oz_dbg(HUB, "GetHubStatus: req_type = 0x%x\n", req_type);
-               put_unaligned(cpu_to_le32(0), (__le32 *)buf);
-               break;
-       case GetPortStatus:
-               err = oz_get_port_status(hcd, windex, buf);
-               break;
-       case SetHubFeature:
-               oz_dbg(HUB, "SetHubFeature: %d\n", req_type);
-               break;
-       case SetPortFeature:
-               err = oz_set_port_feature(hcd, wvalue, windex);
-               break;
-       default:
-               oz_dbg(HUB, "Other: %d\n", req_type);
-               break;
-       }
-       return err;
-}
-
-/*
- * Context: process
- */
-static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
-{
-       struct oz_hcd *ozhcd;
-
-       ozhcd = oz_hcd_private(hcd);
-       spin_lock_bh(&ozhcd->hcd_lock);
-       hcd->state = HC_STATE_SUSPENDED;
-       ozhcd->flags |= OZ_HDC_F_SUSPENDED;
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_hcd_bus_resume(struct usb_hcd *hcd)
-{
-       struct oz_hcd *ozhcd;
-
-       ozhcd = oz_hcd_private(hcd);
-       spin_lock_bh(&ozhcd->hcd_lock);
-       ozhcd->flags &= ~OZ_HDC_F_SUSPENDED;
-       hcd->state = HC_STATE_RUNNING;
-       spin_unlock_bh(&ozhcd->hcd_lock);
-       return 0;
-}
-
-static void oz_plat_shutdown(struct platform_device *dev)
-{
-}
-
-/*
- * Context: process
- */
-static int oz_plat_probe(struct platform_device *dev)
-{
-       int i;
-       int err;
-       struct usb_hcd *hcd;
-       struct oz_hcd *ozhcd;
-
-       hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev));
-       if (hcd == NULL) {
-               oz_dbg(ON, "Failed to created hcd object OK\n");
-               return -ENOMEM;
-       }
-       ozhcd = oz_hcd_private(hcd);
-       memset(ozhcd, 0, sizeof(*ozhcd));
-       INIT_LIST_HEAD(&ozhcd->urb_pending_list);
-       INIT_LIST_HEAD(&ozhcd->urb_cancel_list);
-       INIT_LIST_HEAD(&ozhcd->orphanage);
-       ozhcd->hcd = hcd;
-       ozhcd->conn_port = -1;
-       spin_lock_init(&ozhcd->hcd_lock);
-       for (i = 0; i < OZ_NB_PORTS; i++) {
-               struct oz_port *port = &ozhcd->ports[i];
-
-               port->ozhcd = ozhcd;
-               port->flags = 0;
-               port->status = 0;
-               port->bus_addr = 0xff;
-               spin_lock_init(&port->port_lock);
-       }
-       err = usb_add_hcd(hcd, 0, 0);
-       if (err) {
-               oz_dbg(ON, "Failed to add hcd object OK\n");
-               usb_put_hcd(hcd);
-               return -1;
-       }
-       device_wakeup_enable(hcd->self.controller);
-
-       spin_lock_bh(&g_hcdlock);
-       g_ozhcd = ozhcd;
-       spin_unlock_bh(&g_hcdlock);
-       return 0;
-}
-
-/*
- * Context: unknown
- */
-static int oz_plat_remove(struct platform_device *dev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(dev);
-       struct oz_hcd *ozhcd;
-
-       if (hcd == NULL)
-               return -1;
-       ozhcd = oz_hcd_private(hcd);
-       spin_lock_bh(&g_hcdlock);
-       if (ozhcd == g_ozhcd)
-               g_ozhcd = NULL;
-       spin_unlock_bh(&g_hcdlock);
-       oz_dbg(ON, "Clearing orphanage\n");
-       oz_hcd_clear_orphanage(ozhcd, -EPIPE);
-       oz_dbg(ON, "Removing hcd\n");
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-       return 0;
-}
-
-/*
- * Context: unknown
- */
-static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return 0;
-}
-
-
-/*
- * Context: unknown
- */
-static int oz_plat_resume(struct platform_device *dev)
-{
-       return 0;
-}
-
-/*
- * Context: process
- */
-int oz_hcd_init(void)
-{
-       int err;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       oz_urb_link_cache = KMEM_CACHE(oz_urb_link, 0);
-       if (!oz_urb_link_cache)
-               return -ENOMEM;
-
-       tasklet_init(&g_urb_process_tasklet, oz_urb_process_tasklet, 0);
-       tasklet_init(&g_urb_cancel_tasklet, oz_urb_cancel_tasklet, 0);
-       err = platform_driver_register(&g_oz_plat_drv);
-       oz_dbg(ON, "platform_driver_register() returned %d\n", err);
-       if (err)
-               goto error;
-       g_plat_dev = platform_device_alloc(OZ_PLAT_DEV_NAME, -1);
-       if (g_plat_dev == NULL) {
-               err = -ENOMEM;
-               goto error1;
-       }
-       oz_dbg(ON, "platform_device_alloc() succeeded\n");
-       err = platform_device_add(g_plat_dev);
-       if (err)
-               goto error2;
-       oz_dbg(ON, "platform_device_add() succeeded\n");
-       return 0;
-error2:
-       platform_device_put(g_plat_dev);
-error1:
-       platform_driver_unregister(&g_oz_plat_drv);
-error:
-       tasklet_disable(&g_urb_process_tasklet);
-       tasklet_disable(&g_urb_cancel_tasklet);
-       oz_dbg(ON, "oz_hcd_init() failed %d\n", err);
-       return err;
-}
-
-/*
- * Context: process
- */
-void oz_hcd_term(void)
-{
-       msleep(OZ_HUB_DEBOUNCE_TIMEOUT);
-       tasklet_kill(&g_urb_process_tasklet);
-       tasklet_kill(&g_urb_cancel_tasklet);
-       platform_device_unregister(g_plat_dev);
-       platform_driver_unregister(&g_oz_plat_drv);
-       oz_dbg(ON, "Pending urbs:%d\n", atomic_read(&g_pending_urbs));
-       kmem_cache_destroy(oz_urb_link_cache);
-}
diff --git a/drivers/staging/ozwpan/ozhcd.h b/drivers/staging/ozwpan/ozhcd.h
deleted file mode 100644 (file)
index 55e97b1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-#ifndef _OZHCD_H
-#define _OZHCD_H
-
-int oz_hcd_init(void);
-void oz_hcd_term(void);
-struct oz_port *oz_hcd_pd_arrived(void *ctx);
-void oz_hcd_pd_departed(struct oz_port *hport);
-void oz_hcd_pd_reset(void *hpd, void *hport);
-
-#endif /* _OZHCD_H */
-
diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c
deleted file mode 100644 (file)
index 74ef348..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/errno.h>
-#include <linux/ieee80211.h>
-#include "ozdbg.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozcdev.h"
-
-unsigned int oz_dbg_mask = OZ_DEFAULT_DBG_MASK;
-
-/*
- * The name of the 802.11 mac device. Empty string is the default value but a
- * value can be supplied as a parameter to the module. An empty string means
- * bind to nothing. '*' means bind to all netcards - this includes non-802.11
- * netcards. Bindings can be added later using an IOCTL.
- */
-static char *g_net_dev = "";
-module_param(g_net_dev, charp, S_IRUGO);
-MODULE_PARM_DESC(g_net_dev, "The device(s) to bind to; "
-       "'*' means all, '' (empty string; default) means none.");
-
-/*
- * Context: process
- */
-static int __init ozwpan_init(void)
-{
-       int err;
-
-       err = oz_cdev_register();
-       if (err)
-               return err;
-       err = oz_protocol_init(g_net_dev);
-       if (err)
-               goto err_protocol;
-       oz_app_enable(OZ_APPID_USB, 1);
-       oz_apps_init();
-       return 0;
-
-err_protocol:
-       oz_cdev_deregister();
-       return err;
-}
-
-/*
- * Context: process
- */
-static void __exit ozwpan_exit(void)
-{
-       oz_protocol_term();
-       oz_apps_term();
-       oz_cdev_deregister();
-}
-
-module_init(ozwpan_init);
-module_exit(ozwpan_exit);
-
-MODULE_AUTHOR("Chris Kelly");
-MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.13");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
deleted file mode 100644 (file)
index 021d74a..0000000
+++ /dev/null
@@ -1,886 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/errno.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozcdev.h"
-#include "ozusbsvc.h"
-#include <asm/unaligned.h>
-#include <linux/uaccess.h>
-#include <net/psnap.h>
-
-static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd);
-static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f);
-static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f);
-static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f);
-static int oz_send_isoc_frame(struct oz_pd *pd);
-static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f);
-static void oz_isoc_stream_free(struct oz_isoc_stream *st);
-static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data);
-static void oz_isoc_destructor(struct sk_buff *skb);
-
-/*
- * Counts the uncompleted isoc frames submitted to netcard.
- */
-static atomic_t g_submitted_isoc = ATOMIC_INIT(0);
-
-/* Application handler functions.
- */
-static const struct oz_app_if g_app_if[OZ_NB_APPS] = {
-       [OZ_APPID_USB] = {
-               .init      = oz_usb_init,
-               .term      = oz_usb_term,
-               .start     = oz_usb_start,
-               .stop      = oz_usb_stop,
-               .rx        = oz_usb_rx,
-               .heartbeat = oz_usb_heartbeat,
-               .farewell  = oz_usb_farewell,
-       },
-       [OZ_APPID_SERIAL] = {
-               .init      = oz_cdev_init,
-               .term      = oz_cdev_term,
-               .start     = oz_cdev_start,
-               .stop      = oz_cdev_stop,
-               .rx        = oz_cdev_rx,
-       },
-};
-
-
-/*
- * Context: softirq or process
- */
-void oz_pd_set_state(struct oz_pd *pd, unsigned state)
-{
-       pd->state = state;
-       switch (state) {
-       case OZ_PD_S_IDLE:
-               oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n");
-               break;
-       case OZ_PD_S_CONNECTED:
-               oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n");
-               break;
-       case OZ_PD_S_STOPPED:
-               oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n");
-               break;
-       case OZ_PD_S_SLEEP:
-               oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n");
-               break;
-       }
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_get(struct oz_pd *pd)
-{
-       atomic_inc(&pd->ref_count);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_put(struct oz_pd *pd)
-{
-       if (atomic_dec_and_test(&pd->ref_count))
-               oz_pd_destroy(pd);
-}
-
-/*
- * Context: softirq-serialized
- */
-struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
-{
-       struct oz_pd *pd;
-       int i;
-
-       pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC);
-       if (!pd)
-               return NULL;
-
-       atomic_set(&pd->ref_count, 2);
-       for (i = 0; i < OZ_NB_APPS; i++)
-               spin_lock_init(&pd->app_lock[i]);
-       pd->last_rx_pkt_num = 0xffffffff;
-       oz_pd_set_state(pd, OZ_PD_S_IDLE);
-       pd->max_tx_size = OZ_MAX_TX_SIZE;
-       ether_addr_copy(pd->mac_addr, mac_addr);
-       oz_elt_buf_init(&pd->elt_buff);
-       spin_lock_init(&pd->tx_frame_lock);
-       INIT_LIST_HEAD(&pd->tx_queue);
-       INIT_LIST_HEAD(&pd->farewell_list);
-       pd->last_sent_frame = &pd->tx_queue;
-       spin_lock_init(&pd->stream_lock);
-       INIT_LIST_HEAD(&pd->stream_list);
-       tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler,
-                                               (unsigned long)pd);
-       tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler,
-                                               (unsigned long)pd);
-       hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       pd->heartbeat.function = oz_pd_heartbeat_event;
-       pd->timeout.function = oz_pd_timeout_event;
-
-       return pd;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_pd_free(struct work_struct *work)
-{
-       struct list_head *e, *n;
-       struct oz_pd *pd;
-
-       oz_pd_dbg(pd, ON, "Destroying PD\n");
-       pd = container_of(work, struct oz_pd, workitem);
-       /*Disable timer tasklets*/
-       tasklet_kill(&pd->heartbeat_tasklet);
-       tasklet_kill(&pd->timeout_tasklet);
-
-       /* Free streams, queued tx frames and farewells. */
-
-       list_for_each_safe(e, n, &pd->stream_list)
-               oz_isoc_stream_free(list_entry(e, struct oz_isoc_stream, link));
-
-       list_for_each_safe(e, n, &pd->tx_queue) {
-               struct oz_tx_frame *f = list_entry(e, struct oz_tx_frame, link);
-
-               if (f->skb != NULL)
-                       kfree_skb(f->skb);
-               oz_retire_frame(pd, f);
-       }
-
-       oz_elt_buf_term(&pd->elt_buff);
-
-       list_for_each_safe(e, n, &pd->farewell_list)
-               kfree(list_entry(e, struct oz_farewell, link));
-
-       if (pd->net_dev)
-               dev_put(pd->net_dev);
-       kfree(pd);
-}
-
-/*
- * Context: softirq or Process
- */
-void oz_pd_destroy(struct oz_pd *pd)
-{
-       if (hrtimer_active(&pd->timeout))
-               hrtimer_cancel(&pd->timeout);
-       if (hrtimer_active(&pd->heartbeat))
-               hrtimer_cancel(&pd->heartbeat);
-
-       INIT_WORK(&pd->workitem, oz_pd_free);
-       if (!schedule_work(&pd->workitem))
-               oz_pd_dbg(pd, ON, "failed to schedule workitem\n");
-}
-
-/*
- * Context: softirq-serialized
- */
-int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
-{
-       int i, rc = 0;
-
-       oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume);
-       for (i = 0; i < OZ_NB_APPS; i++) {
-               if (g_app_if[i].start && (apps & (1 << i))) {
-                       if (g_app_if[i].start(pd, resume)) {
-                               rc = -1;
-                               oz_pd_dbg(pd, ON,
-                                         "Unable to start service %d\n", i);
-                               break;
-                       }
-                       spin_lock_bh(&g_polling_lock);
-                       pd->total_apps |= (1 << i);
-                       if (resume)
-                               pd->paused_apps &= ~(1 << i);
-                       spin_unlock_bh(&g_polling_lock);
-               }
-       }
-       return rc;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
-{
-       int i;
-
-       oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause);
-       for (i = 0; i < OZ_NB_APPS; i++) {
-               if (g_app_if[i].stop && (apps & (1 << i))) {
-                       spin_lock_bh(&g_polling_lock);
-                       if (pause) {
-                               pd->paused_apps |=  (1 << i);
-                       } else {
-                               pd->total_apps  &= ~(1 << i);
-                               pd->paused_apps &= ~(1 << i);
-                       }
-                       spin_unlock_bh(&g_polling_lock);
-                       g_app_if[i].stop(pd, pause);
-               }
-       }
-}
-
-/*
- * Context: softirq
- */
-void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
-{
-       int i, more = 0;
-
-       for (i = 0; i < OZ_NB_APPS; i++) {
-               if (g_app_if[i].heartbeat && (apps & (1 << i))) {
-                       if (g_app_if[i].heartbeat(pd))
-                               more = 1;
-               }
-       }
-       if ((!more) && (hrtimer_active(&pd->heartbeat)))
-               hrtimer_cancel(&pd->heartbeat);
-       if (pd->mode & OZ_F_ISOC_ANYTIME) {
-               int count = 8;
-
-               while (count-- && (oz_send_isoc_frame(pd) >= 0))
-                       ;
-       }
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_stop(struct oz_pd *pd)
-{
-       u16 stop_apps;
-
-       oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state);
-       oz_pd_indicate_farewells(pd);
-       spin_lock_bh(&g_polling_lock);
-       stop_apps = pd->total_apps;
-       pd->total_apps = 0;
-       pd->paused_apps = 0;
-       spin_unlock_bh(&g_polling_lock);
-       oz_services_stop(pd, stop_apps, 0);
-       spin_lock_bh(&g_polling_lock);
-       oz_pd_set_state(pd, OZ_PD_S_STOPPED);
-       /* Remove from PD list.*/
-       list_del(&pd->link);
-       spin_unlock_bh(&g_polling_lock);
-       oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count));
-       oz_pd_put(pd);
-}
-
-/*
- * Context: softirq
- */
-int oz_pd_sleep(struct oz_pd *pd)
-{
-       int do_stop = 0;
-       u16 stop_apps;
-
-       spin_lock_bh(&g_polling_lock);
-       if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) {
-               spin_unlock_bh(&g_polling_lock);
-               return 0;
-       }
-       if (pd->keep_alive && pd->session_id)
-               oz_pd_set_state(pd, OZ_PD_S_SLEEP);
-       else
-               do_stop = 1;
-
-       stop_apps = pd->total_apps;
-       spin_unlock_bh(&g_polling_lock);
-       if (do_stop) {
-               oz_pd_stop(pd);
-       } else {
-               oz_services_stop(pd, stop_apps, 1);
-               oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive);
-       }
-       return do_stop;
-}
-
-/*
- * Context: softirq
- */
-static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd)
-{
-       struct oz_tx_frame *f;
-
-       f = kmem_cache_alloc(oz_tx_frame_cache, GFP_ATOMIC);
-       if (f) {
-               f->total_size = sizeof(struct oz_hdr);
-               INIT_LIST_HEAD(&f->link);
-               INIT_LIST_HEAD(&f->elt_list);
-       }
-       return f;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f)
-{
-       pd->nb_queued_isoc_frames--;
-       list_del_init(&f->link);
-
-       kmem_cache_free(oz_tx_frame_cache, f);
-
-       oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n",
-              pd->nb_queued_isoc_frames);
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f)
-{
-       kmem_cache_free(oz_tx_frame_cache, f);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_set_more_bit(struct sk_buff *skb)
-{
-       struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
-
-       oz_hdr->control |= OZ_F_MORE_DATA;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb)
-{
-       struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
-
-       oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
-}
-
-/*
- * Context: softirq
- */
-int oz_prepare_frame(struct oz_pd *pd, int empty)
-{
-       struct oz_tx_frame *f;
-
-       if ((pd->mode & OZ_MODE_MASK) != OZ_MODE_TRIGGERED)
-               return -1;
-       if (pd->nb_queued_frames >= OZ_MAX_QUEUED_FRAMES)
-               return -1;
-       if (!empty && !oz_are_elts_available(&pd->elt_buff))
-               return -1;
-       f = oz_tx_frame_alloc(pd);
-       if (f == NULL)
-               return -1;
-       f->skb = NULL;
-       f->hdr.control =
-               (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ACK_REQUESTED;
-       ++pd->last_tx_pkt_num;
-       put_unaligned(cpu_to_le32(pd->last_tx_pkt_num), &f->hdr.pkt_num);
-       if (empty == 0) {
-               oz_select_elts_for_tx(&pd->elt_buff, 0, &f->total_size,
-                       pd->max_tx_size, &f->elt_list);
-       }
-       spin_lock(&pd->tx_frame_lock);
-       list_add_tail(&f->link, &pd->tx_queue);
-       pd->nb_queued_frames++;
-       spin_unlock(&pd->tx_frame_lock);
-       return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f)
-{
-       struct sk_buff *skb;
-       struct net_device *dev = pd->net_dev;
-       struct oz_hdr *oz_hdr;
-       struct oz_elt *elt;
-       struct oz_elt_info *ei;
-
-       /* Allocate skb with enough space for the lower layers as well
-        * as the space we need.
-        */
-       skb = alloc_skb(f->total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
-       if (skb == NULL)
-               return NULL;
-       /* Reserve the head room for lower layers.
-        */
-       skb_reserve(skb, LL_RESERVED_SPACE(dev));
-       skb_reset_network_header(skb);
-       skb->dev = dev;
-       skb->protocol = htons(OZ_ETHERTYPE);
-       if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
-               dev->dev_addr, skb->len) < 0)
-               goto fail;
-       /* Push the tail to the end of the area we are going to copy to.
-        */
-       oz_hdr = (struct oz_hdr *)skb_put(skb, f->total_size);
-       f->hdr.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
-       memcpy(oz_hdr, &f->hdr, sizeof(struct oz_hdr));
-       /* Copy the elements into the frame body.
-        */
-       elt = (struct oz_elt *)(oz_hdr+1);
-       list_for_each_entry(ei, &f->elt_list, link) {
-               memcpy(elt, ei->data, ei->length);
-               elt = oz_next_elt(elt);
-       }
-       return skb;
-fail:
-       kfree_skb(skb);
-       return NULL;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f)
-{
-       struct oz_elt_info *ei, *n;
-
-       list_for_each_entry_safe(ei, n, &f->elt_list, link) {
-               list_del_init(&ei->link);
-               if (ei->callback)
-                       ei->callback(pd, ei->context);
-               spin_lock_bh(&pd->elt_buff.lock);
-               oz_elt_info_free(&pd->elt_buff, ei);
-               spin_unlock_bh(&pd->elt_buff.lock);
-       }
-       oz_tx_frame_free(pd, f);
-}
-
-/*
- * Context: softirq-serialized
- */
-static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data)
-{
-       struct sk_buff *skb;
-       struct oz_tx_frame *f;
-       struct list_head *e;
-
-       spin_lock(&pd->tx_frame_lock);
-       e = pd->last_sent_frame->next;
-       if (e == &pd->tx_queue) {
-               spin_unlock(&pd->tx_frame_lock);
-               return -1;
-       }
-       f = list_entry(e, struct oz_tx_frame, link);
-
-       if (f->skb != NULL) {
-               skb = f->skb;
-               oz_tx_isoc_free(pd, f);
-               spin_unlock(&pd->tx_frame_lock);
-               if (more_data)
-                       oz_set_more_bit(skb);
-               oz_set_last_pkt_nb(pd, skb);
-               if ((int)atomic_read(&g_submitted_isoc) <
-                                                       OZ_MAX_SUBMITTED_ISOC) {
-                       if (dev_queue_xmit(skb) < 0) {
-                               oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n");
-                               return -1;
-                       }
-                       atomic_inc(&g_submitted_isoc);
-                       oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n",
-                              pd->nb_queued_isoc_frames);
-                       return 0;
-               }
-               kfree_skb(skb);
-               oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n");
-               return -1;
-       }
-
-       pd->last_sent_frame = e;
-       skb = oz_build_frame(pd, f);
-       spin_unlock(&pd->tx_frame_lock);
-       if (!skb)
-               return -1;
-       if (more_data)
-               oz_set_more_bit(skb);
-       oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num);
-       if (dev_queue_xmit(skb) < 0)
-               return -1;
-
-       return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_send_queued_frames(struct oz_pd *pd, int backlog)
-{
-       while (oz_prepare_frame(pd, 0) >= 0)
-               backlog++;
-
-       switch (pd->mode & (OZ_F_ISOC_NO_ELTS | OZ_F_ISOC_ANYTIME)) {
-
-               case OZ_F_ISOC_NO_ELTS: {
-                       backlog += pd->nb_queued_isoc_frames;
-                       if (backlog <= 0)
-                               goto out;
-                       if (backlog > OZ_MAX_SUBMITTED_ISOC)
-                               backlog = OZ_MAX_SUBMITTED_ISOC;
-                       break;
-               }
-               case OZ_NO_ELTS_ANYTIME: {
-                       if ((backlog <= 0) && (pd->isoc_sent == 0))
-                               goto out;
-                       break;
-               }
-               default: {
-                       if (backlog <= 0)
-                               goto out;
-                       break;
-               }
-       }
-       while (backlog--) {
-               if (oz_send_next_queued_frame(pd, backlog) < 0)
-                       break;
-       }
-       return;
-
-out:   oz_prepare_frame(pd, 1);
-       oz_send_next_queued_frame(pd, 0);
-}
-
-/*
- * Context: softirq
- */
-static int oz_send_isoc_frame(struct oz_pd *pd)
-{
-       struct sk_buff *skb;
-       struct net_device *dev = pd->net_dev;
-       struct oz_hdr *oz_hdr;
-       struct oz_elt *elt;
-       struct oz_elt_info *ei;
-       LIST_HEAD(list);
-       int total_size = sizeof(struct oz_hdr);
-
-       oz_select_elts_for_tx(&pd->elt_buff, 1, &total_size,
-               pd->max_tx_size, &list);
-       if (list_empty(&list))
-               return 0;
-       skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
-       if (skb == NULL) {
-               oz_dbg(ON, "Cannot alloc skb\n");
-               oz_elt_info_free_chain(&pd->elt_buff, &list);
-               return -1;
-       }
-       skb_reserve(skb, LL_RESERVED_SPACE(dev));
-       skb_reset_network_header(skb);
-       skb->dev = dev;
-       skb->protocol = htons(OZ_ETHERTYPE);
-       if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
-               dev->dev_addr, skb->len) < 0) {
-               kfree_skb(skb);
-               return -1;
-       }
-       oz_hdr = (struct oz_hdr *)skb_put(skb, total_size);
-       oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC;
-       oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
-       elt = (struct oz_elt *)(oz_hdr+1);
-
-       list_for_each_entry(ei, &list, link) {
-               memcpy(elt, ei->data, ei->length);
-               elt = oz_next_elt(elt);
-       }
-       dev_queue_xmit(skb);
-       oz_elt_info_free_chain(&pd->elt_buff, &list);
-       return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn)
-{
-       struct oz_tx_frame *f, *tmp = NULL;
-       u8 diff;
-       u32 pkt_num;
-
-       LIST_HEAD(list);
-
-       spin_lock(&pd->tx_frame_lock);
-       list_for_each_entry(f, &pd->tx_queue, link) {
-               pkt_num = le32_to_cpu(get_unaligned(&f->hdr.pkt_num));
-               diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK;
-               if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0))
-                       break;
-               oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n",
-                      pkt_num, pd->nb_queued_frames);
-               tmp = f;
-               pd->nb_queued_frames--;
-       }
-       if (tmp)
-               list_cut_position(&list, &pd->tx_queue, &tmp->link);
-       pd->last_sent_frame = &pd->tx_queue;
-       spin_unlock(&pd->tx_frame_lock);
-
-       list_for_each_entry_safe(f, tmp, &list, link)
-               oz_retire_frame(pd, f);
-}
-
-/*
- * Precondition: stream_lock must be held.
- * Context: softirq
- */
-static struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num)
-{
-       struct oz_isoc_stream *st;
-
-       list_for_each_entry(st, &pd->stream_list, link) {
-               if (st->ep_num == ep_num)
-                       return st;
-       }
-       return NULL;
-}
-
-/*
- * Context: softirq
- */
-int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num)
-{
-       struct oz_isoc_stream *st;
-
-       st = kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC);
-       if (!st)
-               return -ENOMEM;
-       st->ep_num = ep_num;
-       spin_lock_bh(&pd->stream_lock);
-       if (!pd_stream_find(pd, ep_num)) {
-               list_add(&st->link, &pd->stream_list);
-               st = NULL;
-       }
-       spin_unlock_bh(&pd->stream_lock);
-       kfree(st);
-       return 0;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_isoc_stream_free(struct oz_isoc_stream *st)
-{
-       kfree_skb(st->skb);
-       kfree(st);
-}
-
-/*
- * Context: softirq
- */
-int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num)
-{
-       struct oz_isoc_stream *st;
-
-       spin_lock_bh(&pd->stream_lock);
-       st = pd_stream_find(pd, ep_num);
-       if (st)
-               list_del(&st->link);
-       spin_unlock_bh(&pd->stream_lock);
-       if (st)
-               oz_isoc_stream_free(st);
-       return 0;
-}
-
-/*
- * Context: any
- */
-static void oz_isoc_destructor(struct sk_buff *skb)
-{
-       atomic_dec(&g_submitted_isoc);
-}
-
-/*
- * Context: softirq
- */
-int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
-{
-       struct net_device *dev = pd->net_dev;
-       struct oz_isoc_stream *st;
-       u8 nb_units = 0;
-       struct sk_buff *skb = NULL;
-       struct oz_hdr *oz_hdr = NULL;
-       int size = 0;
-
-       spin_lock_bh(&pd->stream_lock);
-       st = pd_stream_find(pd, ep_num);
-       if (st) {
-               skb = st->skb;
-               st->skb = NULL;
-               nb_units = st->nb_units;
-               st->nb_units = 0;
-               oz_hdr = st->oz_hdr;
-               size = st->size;
-       }
-       spin_unlock_bh(&pd->stream_lock);
-       if (!st)
-               return 0;
-       if (!skb) {
-               /* Allocate enough space for max size frame. */
-               skb = alloc_skb(pd->max_tx_size + OZ_ALLOCATED_SPACE(dev),
-                               GFP_ATOMIC);
-               if (skb == NULL)
-                       return 0;
-               /* Reserve the head room for lower layers. */
-               skb_reserve(skb, LL_RESERVED_SPACE(dev));
-               skb_reset_network_header(skb);
-               skb->dev = dev;
-               skb->protocol = htons(OZ_ETHERTYPE);
-               /* For audio packet set priority to AC_VO */
-               skb->priority = 0x7;
-               size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large);
-               oz_hdr = (struct oz_hdr *)skb_put(skb, size);
-       }
-       memcpy(skb_put(skb, len), data, len);
-       size += len;
-       if (++nb_units < pd->ms_per_isoc) {
-               spin_lock_bh(&pd->stream_lock);
-               st->skb = skb;
-               st->nb_units = nb_units;
-               st->oz_hdr = oz_hdr;
-               st->size = size;
-               spin_unlock_bh(&pd->stream_lock);
-       } else {
-               struct oz_hdr oz;
-               struct oz_isoc_large iso;
-
-               spin_lock_bh(&pd->stream_lock);
-               iso.frame_number = st->frame_num;
-               st->frame_num += nb_units;
-               spin_unlock_bh(&pd->stream_lock);
-               oz.control =
-                       (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC;
-               oz.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
-               oz.pkt_num = 0;
-               iso.endpoint = ep_num;
-               iso.format = OZ_DATA_F_ISOC_LARGE;
-               iso.ms_data = nb_units;
-               memcpy(oz_hdr, &oz, sizeof(oz));
-               memcpy(oz_hdr+1, &iso, sizeof(iso));
-               if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
-                               dev->dev_addr, skb->len) < 0)
-                       goto out;
-
-               skb->destructor = oz_isoc_destructor;
-               /*Queue for Xmit if mode is not ANYTIME*/
-               if (!(pd->mode & OZ_F_ISOC_ANYTIME)) {
-                       struct oz_tx_frame *isoc_unit = NULL;
-                       int nb = pd->nb_queued_isoc_frames;
-
-                       if (nb >= pd->isoc_latency) {
-                               struct oz_tx_frame *f;
-
-                               oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n",
-                                      nb);
-                               spin_lock(&pd->tx_frame_lock);
-                               list_for_each_entry(f, &pd->tx_queue, link) {
-                                       if (f->skb != NULL) {
-                                               oz_tx_isoc_free(pd, f);
-                                               break;
-                                       }
-                               }
-                               spin_unlock(&pd->tx_frame_lock);
-                       }
-                       isoc_unit = oz_tx_frame_alloc(pd);
-                       if (isoc_unit == NULL)
-                               goto out;
-                       isoc_unit->hdr = oz;
-                       isoc_unit->skb = skb;
-                       spin_lock_bh(&pd->tx_frame_lock);
-                       list_add_tail(&isoc_unit->link, &pd->tx_queue);
-                       pd->nb_queued_isoc_frames++;
-                       spin_unlock_bh(&pd->tx_frame_lock);
-                       oz_dbg(TX_FRAMES,
-                              "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n",
-                              pd->nb_queued_isoc_frames, pd->nb_queued_frames);
-                       return 0;
-               }
-
-               /*In ANYTIME mode Xmit unit immediately*/
-               if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) {
-                       atomic_inc(&g_submitted_isoc);
-                       if (dev_queue_xmit(skb) < 0)
-                               return -1;
-                       return 0;
-               }
-
-out:   kfree_skb(skb);
-       return -1;
-
-       }
-       return 0;
-}
-
-/*
- * Context: process
- */
-void oz_apps_init(void)
-{
-       int i;
-
-       for (i = 0; i < OZ_NB_APPS; i++) {
-               if (g_app_if[i].init)
-                       g_app_if[i].init();
-       }
-}
-
-/*
- * Context: process
- */
-void oz_apps_term(void)
-{
-       int i;
-
-       /* Terminate all the apps. */
-       for (i = 0; i < OZ_NB_APPS; i++) {
-               if (g_app_if[i].term)
-                       g_app_if[i].term();
-       }
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt)
-{
-       if (app_id < OZ_NB_APPS && g_app_if[app_id].rx)
-               g_app_if[app_id].rx(pd, elt);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_indicate_farewells(struct oz_pd *pd)
-{
-       struct oz_farewell *f;
-       const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB];
-
-       while (1) {
-               spin_lock_bh(&g_polling_lock);
-               if (list_empty(&pd->farewell_list)) {
-                       spin_unlock_bh(&g_polling_lock);
-                       break;
-               }
-               f = list_first_entry(&pd->farewell_list,
-                               struct oz_farewell, link);
-               list_del(&f->link);
-               spin_unlock_bh(&g_polling_lock);
-               if (ai->farewell)
-                       ai->farewell(pd, f->ep_num, f->report, f->len);
-               kfree(f);
-       }
-}
diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h
deleted file mode 100644 (file)
index 212fab0..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZPD_H_
-#define _OZPD_H_
-
-#include <linux/interrupt.h>
-#include "ozeltbuf.h"
-
-/* PD state
- */
-#define OZ_PD_S_IDLE           0x1
-#define OZ_PD_S_CONNECTED      0x2
-#define OZ_PD_S_SLEEP          0x4
-#define OZ_PD_S_STOPPED                0x8
-
-/* Timer event types.
- */
-#define OZ_TIMER_TOUT          1
-#define OZ_TIMER_HEARTBEAT     2
-#define OZ_TIMER_STOP          3
-
-/*
- *External spinlock variable
- */
-extern spinlock_t g_polling_lock;
-
-/* Data structure that hold information on a frame for transmisson. This is
- * built when the frame is first transmitted and is used to rebuild the frame
- * if a re-transmission is required.
- */
-struct oz_tx_frame {
-       struct list_head link;
-       struct list_head elt_list;
-       struct oz_hdr hdr;
-       struct sk_buff *skb;
-       int total_size;
-};
-
-struct oz_isoc_stream {
-       struct list_head link;
-       u8 ep_num;
-       u8 frame_num;
-       u8 nb_units;
-       int size;
-       struct sk_buff *skb;
-       struct oz_hdr *oz_hdr;
-};
-
-struct oz_farewell {
-       struct list_head link;
-       u8 ep_num;
-       u8 index;
-       u8 len;
-       u8 report[0];
-};
-
-/* Data structure that holds information on a specific peripheral device (PD).
- */
-struct oz_pd {
-       struct list_head link;
-       atomic_t        ref_count;
-       u8              mac_addr[ETH_ALEN];
-       unsigned        state;
-       unsigned        state_flags;
-       unsigned        send_flags;
-       u16             total_apps;
-       u16             paused_apps;
-       u8              session_id;
-       u8              param_rsp_status;
-       u8              pd_info;
-       u8              isoc_sent;
-       u32             last_rx_pkt_num;
-       u32             last_tx_pkt_num;
-       struct timespec last_rx_timestamp;
-       u32             trigger_pkt_num;
-       unsigned long   pulse_time;
-       unsigned long   pulse_period;
-       unsigned long   presleep;
-       unsigned long   keep_alive;
-       struct oz_elt_buf elt_buff;
-       void            *app_ctx[OZ_NB_APPS];
-       spinlock_t      app_lock[OZ_NB_APPS];
-       int             max_tx_size;
-       u8              mode;
-       u8              ms_per_isoc;
-       unsigned        isoc_latency;
-       unsigned        max_stream_buffering;
-       int             nb_queued_frames;
-       int             nb_queued_isoc_frames;
-       spinlock_t      tx_frame_lock;
-       struct list_head *last_sent_frame;
-       struct list_head tx_queue;
-       struct list_head farewell_list;
-       spinlock_t      stream_lock;
-       struct list_head stream_list;
-       struct net_device *net_dev;
-       struct hrtimer  heartbeat;
-       struct hrtimer  timeout;
-       u8      timeout_type;
-       struct tasklet_struct   heartbeat_tasklet;
-       struct tasklet_struct   timeout_tasklet;
-       struct work_struct workitem;
-};
-
-#define OZ_MAX_QUEUED_FRAMES   4
-
-struct oz_pd *oz_pd_alloc(const u8 *mac_addr);
-void oz_pd_destroy(struct oz_pd *pd);
-void oz_pd_get(struct oz_pd *pd);
-void oz_pd_put(struct oz_pd *pd);
-void oz_pd_set_state(struct oz_pd *pd, unsigned state);
-void oz_pd_indicate_farewells(struct oz_pd *pd);
-int oz_pd_sleep(struct oz_pd *pd);
-void oz_pd_stop(struct oz_pd *pd);
-void oz_pd_heartbeat(struct oz_pd *pd, u16 apps);
-int oz_services_start(struct oz_pd *pd, u16 apps, int resume);
-void oz_services_stop(struct oz_pd *pd, u16 apps, int pause);
-int oz_prepare_frame(struct oz_pd *pd, int empty);
-void oz_send_queued_frames(struct oz_pd *pd, int backlog);
-void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn);
-int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num);
-int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num);
-int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len);
-void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt);
-void oz_apps_init(void);
-void oz_apps_term(void);
-
-extern struct kmem_cache *oz_elt_info_cache;
-extern struct kmem_cache *oz_tx_frame_cache;
-
-#endif /* Sentry */
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
deleted file mode 100644 (file)
index 1ba24a2..0000000
+++ /dev/null
@@ -1,813 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/errno.h>
-#include <linux/ieee80211.h>
-#include <linux/slab.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozusbsvc.h"
-
-#include "ozappif.h"
-#include <asm/unaligned.h>
-#include <linux/uaccess.h>
-#include <net/psnap.h>
-
-#define OZ_CF_CONN_SUCCESS     1
-#define OZ_CF_CONN_FAILURE     2
-
-#define OZ_DO_STOP             1
-#define OZ_DO_SLEEP            2
-
-struct oz_binding {
-       struct packet_type ptype;
-       char name[OZ_MAX_BINDING_LEN];
-       struct list_head link;
-};
-
-/*
- * External variable
- */
-
-DEFINE_SPINLOCK(g_polling_lock);
-/*
- * Static external variables.
- */
-static LIST_HEAD(g_pd_list);
-static LIST_HEAD(g_binding);
-static DEFINE_SPINLOCK(g_binding_lock);
-static struct sk_buff_head g_rx_queue;
-static u8 g_session_id;
-static u16 g_apps = 0x1;
-static int g_processing_rx;
-
-struct kmem_cache *oz_elt_info_cache;
-struct kmem_cache *oz_tx_frame_cache;
-
-/*
- * Context: softirq-serialized
- */
-static u8 oz_get_new_session_id(u8 exclude)
-{
-       if (++g_session_id == 0)
-               g_session_id = 1;
-       if (g_session_id == exclude) {
-               if (++g_session_id == 0)
-                       g_session_id = 1;
-       }
-       return g_session_id;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
-{
-       struct sk_buff *skb;
-       struct net_device *dev = pd->net_dev;
-       struct oz_hdr *oz_hdr;
-       struct oz_elt *elt;
-       struct oz_elt_connect_rsp *body;
-
-       int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) +
-                       sizeof(struct oz_elt_connect_rsp);
-       skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
-       if (skb == NULL)
-               return;
-       skb_reserve(skb, LL_RESERVED_SPACE(dev));
-       skb_reset_network_header(skb);
-       oz_hdr = (struct oz_hdr *)skb_put(skb, sz);
-       elt = (struct oz_elt *)(oz_hdr+1);
-       body = (struct oz_elt_connect_rsp *)(elt+1);
-       skb->dev = dev;
-       skb->protocol = htons(OZ_ETHERTYPE);
-       /* Fill in device header */
-       if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
-                       dev->dev_addr, skb->len) < 0) {
-               kfree_skb(skb);
-               return;
-       }
-       oz_hdr->control = OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT;
-       oz_hdr->last_pkt_num = 0;
-       put_unaligned(0, &oz_hdr->pkt_num);
-       elt->type = OZ_ELT_CONNECT_RSP;
-       elt->length = sizeof(struct oz_elt_connect_rsp);
-       memset(body, 0, sizeof(struct oz_elt_connect_rsp));
-       body->status = status;
-       if (status == 0) {
-               body->mode = pd->mode;
-               body->session_id = pd->session_id;
-               put_unaligned(cpu_to_le16(pd->total_apps), &body->apps);
-       }
-       oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status);
-       dev_queue_xmit(skb);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void pd_set_keepalive(struct oz_pd *pd, u8 kalive)
-{
-       unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK;
-
-       switch (kalive & OZ_KALIVE_TYPE_MASK) {
-       case OZ_KALIVE_SPECIAL:
-               pd->keep_alive = keep_alive * 1000*60*60*24*20;
-               break;
-       case OZ_KALIVE_SECS:
-               pd->keep_alive = keep_alive*1000;
-               break;
-       case OZ_KALIVE_MINS:
-               pd->keep_alive = keep_alive*1000*60;
-               break;
-       case OZ_KALIVE_HOURS:
-               pd->keep_alive = keep_alive*1000*60*60;
-               break;
-       default:
-               pd->keep_alive = 0;
-       }
-       oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer)
-{
-       if (presleep)
-               pd->presleep = presleep*100;
-       else
-               pd->presleep = OZ_PRESLEEP_TOUT;
-       if (start_timer) {
-               spin_unlock(&g_polling_lock);
-               oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
-               spin_lock(&g_polling_lock);
-       }
-       oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep);
-}
-
-/*
- * Context: softirq-serialized
- */
-static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
-                       const u8 *pd_addr, struct net_device *net_dev)
-{
-       struct oz_pd *pd;
-       struct oz_elt_connect_req *body =
-                       (struct oz_elt_connect_req *)(elt+1);
-       u8 rsp_status = OZ_STATUS_SUCCESS;
-       u8 stop_needed = 0;
-       u16 new_apps = g_apps;
-       struct net_device *old_net_dev = NULL;
-       struct oz_pd *free_pd = NULL;
-
-       if (cur_pd) {
-               pd = cur_pd;
-               spin_lock_bh(&g_polling_lock);
-       } else {
-               struct oz_pd *pd2 = NULL;
-               struct list_head *e;
-
-               pd = oz_pd_alloc(pd_addr);
-               if (pd == NULL)
-                       return NULL;
-               getnstimeofday(&pd->last_rx_timestamp);
-               spin_lock_bh(&g_polling_lock);
-               list_for_each(e, &g_pd_list) {
-                       pd2 = list_entry(e, struct oz_pd, link);
-                       if (ether_addr_equal(pd2->mac_addr, pd_addr)) {
-                               free_pd = pd;
-                               pd = pd2;
-                               break;
-                       }
-               }
-               if (pd != pd2)
-                       list_add_tail(&pd->link, &g_pd_list);
-       }
-       if (pd == NULL) {
-               spin_unlock_bh(&g_polling_lock);
-               return NULL;
-       }
-       if (pd->net_dev != net_dev) {
-               old_net_dev = pd->net_dev;
-               dev_hold(net_dev);
-               pd->net_dev = net_dev;
-       }
-       oz_dbg(ON, "Host vendor: %d\n", body->host_vendor);
-       pd->max_tx_size = OZ_MAX_TX_SIZE;
-       pd->mode = body->mode;
-       pd->pd_info = body->pd_info;
-       if (pd->mode & OZ_F_ISOC_NO_ELTS) {
-               pd->ms_per_isoc = body->ms_per_isoc;
-               if (!pd->ms_per_isoc)
-                       pd->ms_per_isoc = 4;
-
-               switch (body->ms_isoc_latency & OZ_LATENCY_MASK) {
-               case OZ_ONE_MS_LATENCY:
-                       pd->isoc_latency = (body->ms_isoc_latency &
-                                       ~OZ_LATENCY_MASK) / pd->ms_per_isoc;
-                       break;
-               case OZ_TEN_MS_LATENCY:
-                       pd->isoc_latency = ((body->ms_isoc_latency &
-                               ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc;
-                       break;
-               default:
-                       pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC;
-               }
-       }
-       if (body->max_len_div16)
-               pd->max_tx_size = ((u16)body->max_len_div16)<<4;
-       oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n",
-              pd->max_tx_size, pd->ms_per_isoc);
-       pd->max_stream_buffering = 3*1024;
-       pd->pulse_period = OZ_QUANTUM;
-       pd_set_presleep(pd, body->presleep, 0);
-       pd_set_keepalive(pd, body->keep_alive);
-
-       new_apps &= le16_to_cpu(get_unaligned(&body->apps));
-       if ((new_apps & 0x1) && (body->session_id)) {
-               if (pd->session_id) {
-                       if (pd->session_id != body->session_id) {
-                               rsp_status = OZ_STATUS_SESSION_MISMATCH;
-                               goto done;
-                       }
-               } else {
-                       new_apps &= ~0x1;  /* Resume not permitted */
-                       pd->session_id =
-                               oz_get_new_session_id(body->session_id);
-               }
-       } else {
-               if (pd->session_id && !body->session_id) {
-                       rsp_status = OZ_STATUS_SESSION_TEARDOWN;
-                       stop_needed = 1;
-               } else {
-                       new_apps &= ~0x1;  /* Resume not permitted */
-                       pd->session_id =
-                               oz_get_new_session_id(body->session_id);
-               }
-       }
-done:
-       if (rsp_status == OZ_STATUS_SUCCESS) {
-               u16 start_apps = new_apps & ~pd->total_apps & ~0x1;
-               u16 stop_apps = pd->total_apps & ~new_apps & ~0x1;
-               u16 resume_apps = new_apps & pd->paused_apps  & ~0x1;
-
-               spin_unlock_bh(&g_polling_lock);
-               oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
-               oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n",
-                      new_apps, pd->total_apps, pd->paused_apps);
-               if (start_apps) {
-                       if (oz_services_start(pd, start_apps, 0))
-                               rsp_status = OZ_STATUS_TOO_MANY_PDS;
-               }
-               if (resume_apps)
-                       if (oz_services_start(pd, resume_apps, 1))
-                               rsp_status = OZ_STATUS_TOO_MANY_PDS;
-               if (stop_apps)
-                       oz_services_stop(pd, stop_apps, 0);
-               oz_pd_request_heartbeat(pd);
-       } else {
-               spin_unlock_bh(&g_polling_lock);
-       }
-       oz_send_conn_rsp(pd, rsp_status);
-       if (rsp_status != OZ_STATUS_SUCCESS) {
-               if (stop_needed)
-                       oz_pd_stop(pd);
-               oz_pd_put(pd);
-               pd = NULL;
-       }
-       if (old_net_dev)
-               dev_put(old_net_dev);
-       if (free_pd)
-               oz_pd_destroy(free_pd);
-       return pd;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index,
-                       const u8 *report, u8 len)
-{
-       struct oz_farewell *f;
-       struct oz_farewell *f2;
-       int found = 0;
-
-       f = kmalloc(sizeof(struct oz_farewell) + len, GFP_ATOMIC);
-       if (!f)
-               return;
-       f->ep_num = ep_num;
-       f->index = index;
-       f->len = len;
-       memcpy(f->report, report, len);
-       oz_dbg(ON, "RX: Adding farewell report\n");
-       spin_lock(&g_polling_lock);
-       list_for_each_entry(f2, &pd->farewell_list, link) {
-               if ((f2->ep_num == ep_num) && (f2->index == index)) {
-                       found = 1;
-                       list_del(&f2->link);
-                       break;
-               }
-       }
-       list_add_tail(&f->link, &pd->farewell_list);
-       spin_unlock(&g_polling_lock);
-       if (found)
-               kfree(f2);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_rx_frame(struct sk_buff *skb)
-{
-       u8 *mac_hdr;
-       u8 *src_addr;
-       struct oz_elt *elt;
-       int length;
-       struct oz_pd *pd = NULL;
-       struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
-       struct timespec current_time;
-       int dup = 0;
-       u32 pkt_num;
-
-       oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n",
-              oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control);
-       mac_hdr = skb_mac_header(skb);
-       src_addr = &mac_hdr[ETH_ALEN];
-       length = skb->len;
-
-       /* Check the version field */
-       if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) {
-               oz_dbg(ON, "Incorrect protocol version: %d\n",
-                      oz_get_prot_ver(oz_hdr->control));
-               goto done;
-       }
-
-       pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num));
-
-       pd = oz_pd_find(src_addr);
-       if (pd) {
-               if (!(pd->state & OZ_PD_S_CONNECTED))
-                       oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
-               getnstimeofday(&current_time);
-               if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) ||
-                       (pd->presleep < MSEC_PER_SEC))  {
-                       oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
-                       pd->last_rx_timestamp = current_time;
-               }
-               if (pkt_num != pd->last_rx_pkt_num) {
-                       pd->last_rx_pkt_num = pkt_num;
-               } else {
-                       dup = 1;
-                       oz_dbg(ON, "Duplicate frame\n");
-               }
-       }
-
-       if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) {
-               oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n");
-               pd->last_sent_frame = &pd->tx_queue;
-               if (oz_hdr->control & OZ_F_ACK) {
-                       /* Retire completed frames */
-                       oz_retire_tx_frames(pd, oz_hdr->last_pkt_num);
-               }
-               if ((oz_hdr->control & OZ_F_ACK_REQUESTED) &&
-                               (pd->state == OZ_PD_S_CONNECTED)) {
-                       int backlog = pd->nb_queued_frames;
-
-                       pd->trigger_pkt_num = pkt_num;
-                       /* Send queued frames */
-                       oz_send_queued_frames(pd, backlog);
-               }
-       }
-
-       length -= sizeof(struct oz_hdr);
-       elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr));
-
-       while (length >= sizeof(struct oz_elt)) {
-               length -= sizeof(struct oz_elt) + elt->length;
-               if (length < 0)
-                       break;
-               switch (elt->type) {
-               case OZ_ELT_CONNECT_REQ:
-                       oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n");
-                       pd = oz_connect_req(pd, elt, src_addr, skb->dev);
-                       break;
-               case OZ_ELT_DISCONNECT:
-                       oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n");
-                       if (pd)
-                               oz_pd_sleep(pd);
-                       break;
-               case OZ_ELT_UPDATE_PARAM_REQ: {
-                               struct oz_elt_update_param *body =
-                                       (struct oz_elt_update_param *)(elt + 1);
-                               oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n");
-                               if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
-                                       spin_lock(&g_polling_lock);
-                                       pd_set_keepalive(pd, body->keepalive);
-                                       pd_set_presleep(pd, body->presleep, 1);
-                                       spin_unlock(&g_polling_lock);
-                               }
-                       }
-                       break;
-               case OZ_ELT_FAREWELL_REQ: {
-                               struct oz_elt_farewell *body =
-                                       (struct oz_elt_farewell *)(elt + 1);
-                               oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n");
-                               oz_add_farewell(pd, body->ep_num,
-                                       body->index, body->report,
-                                       elt->length + 1 - sizeof(*body));
-                       }
-                       break;
-               case OZ_ELT_APP_DATA:
-                       if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
-                               struct oz_app_hdr *app_hdr =
-                                       (struct oz_app_hdr *)(elt+1);
-                               if (dup)
-                                       break;
-                               oz_handle_app_elt(pd, app_hdr->app_id, elt);
-                       }
-                       break;
-               default:
-                       oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type);
-               }
-               elt = oz_next_elt(elt);
-       }
-done:
-       if (pd)
-               oz_pd_put(pd);
-       consume_skb(skb);
-}
-
-/*
- * Context: process
- */
-void oz_protocol_term(void)
-{
-       struct oz_binding *b, *t;
-
-       /* Walk the list of bindings and remove each one.
-        */
-       spin_lock_bh(&g_binding_lock);
-       list_for_each_entry_safe(b, t, &g_binding, link) {
-               list_del(&b->link);
-               spin_unlock_bh(&g_binding_lock);
-               dev_remove_pack(&b->ptype);
-               if (b->ptype.dev)
-                       dev_put(b->ptype.dev);
-               kfree(b);
-               spin_lock_bh(&g_binding_lock);
-       }
-       spin_unlock_bh(&g_binding_lock);
-       /* Walk the list of PDs and stop each one. This causes the PD to be
-        * removed from the list so we can just pull each one from the head
-        * of the list.
-        */
-       spin_lock_bh(&g_polling_lock);
-       while (!list_empty(&g_pd_list)) {
-               struct oz_pd *pd =
-                       list_first_entry(&g_pd_list, struct oz_pd, link);
-               oz_pd_get(pd);
-               spin_unlock_bh(&g_polling_lock);
-               oz_pd_stop(pd);
-               oz_pd_put(pd);
-               spin_lock_bh(&g_polling_lock);
-       }
-       spin_unlock_bh(&g_polling_lock);
-       oz_dbg(ON, "Protocol stopped\n");
-
-       kmem_cache_destroy(oz_tx_frame_cache);
-       kmem_cache_destroy(oz_elt_info_cache);
-}
-
-/*
- * Context: softirq
- */
-void oz_pd_heartbeat_handler(unsigned long data)
-{
-       struct oz_pd *pd = (struct oz_pd *)data;
-       u16 apps = 0;
-
-       spin_lock_bh(&g_polling_lock);
-       if (pd->state & OZ_PD_S_CONNECTED)
-               apps = pd->total_apps;
-       spin_unlock_bh(&g_polling_lock);
-       if (apps)
-               oz_pd_heartbeat(pd, apps);
-       oz_pd_put(pd);
-}
-
-/*
- * Context: softirq
- */
-void oz_pd_timeout_handler(unsigned long data)
-{
-       int type;
-       struct oz_pd *pd = (struct oz_pd *)data;
-
-       spin_lock_bh(&g_polling_lock);
-       type = pd->timeout_type;
-       spin_unlock_bh(&g_polling_lock);
-       switch (type) {
-       case OZ_TIMER_TOUT:
-               oz_pd_sleep(pd);
-               break;
-       case OZ_TIMER_STOP:
-               oz_pd_stop(pd);
-               break;
-       }
-       oz_pd_put(pd);
-}
-
-/*
- * Context: Interrupt
- */
-enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer)
-{
-       struct oz_pd *pd;
-
-       pd = container_of(timer, struct oz_pd, heartbeat);
-       hrtimer_forward_now(timer, ktime_set(pd->pulse_period /
-       MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC));
-       oz_pd_get(pd);
-       tasklet_schedule(&pd->heartbeat_tasklet);
-       return HRTIMER_RESTART;
-}
-
-/*
- * Context: Interrupt
- */
-enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer)
-{
-       struct oz_pd *pd;
-
-       pd = container_of(timer, struct oz_pd, timeout);
-       oz_pd_get(pd);
-       tasklet_schedule(&pd->timeout_tasklet);
-       return HRTIMER_NORESTART;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time)
-{
-       spin_lock_bh(&g_polling_lock);
-       switch (type) {
-       case OZ_TIMER_TOUT:
-       case OZ_TIMER_STOP:
-               if (hrtimer_active(&pd->timeout)) {
-                       hrtimer_set_expires(&pd->timeout, ktime_set(due_time /
-                       MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
-                                                       NSEC_PER_MSEC));
-                       hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL);
-               } else {
-                       hrtimer_start(&pd->timeout, ktime_set(due_time /
-                       MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
-                                       NSEC_PER_MSEC), HRTIMER_MODE_REL);
-               }
-               pd->timeout_type = type;
-               break;
-       case OZ_TIMER_HEARTBEAT:
-               if (!hrtimer_active(&pd->heartbeat))
-                       hrtimer_start(&pd->heartbeat, ktime_set(due_time /
-                       MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
-                                       NSEC_PER_MSEC), HRTIMER_MODE_REL);
-               break;
-       }
-       spin_unlock_bh(&g_polling_lock);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_request_heartbeat(struct oz_pd *pd)
-{
-       oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ?
-                                       pd->pulse_period : OZ_QUANTUM);
-}
-
-/*
- * Context: softirq or process
- */
-struct oz_pd *oz_pd_find(const u8 *mac_addr)
-{
-       struct oz_pd *pd;
-
-       spin_lock_bh(&g_polling_lock);
-       list_for_each_entry(pd, &g_pd_list, link) {
-               if (ether_addr_equal(pd->mac_addr, mac_addr)) {
-                       oz_pd_get(pd);
-                       spin_unlock_bh(&g_polling_lock);
-                       return pd;
-               }
-       }
-       spin_unlock_bh(&g_polling_lock);
-       return NULL;
-}
-
-/*
- * Context: process
- */
-void oz_app_enable(int app_id, int enable)
-{
-       if (app_id < OZ_NB_APPS) {
-               spin_lock_bh(&g_polling_lock);
-               if (enable)
-                       g_apps |= (1<<app_id);
-               else
-                       g_apps &= ~(1<<app_id);
-               spin_unlock_bh(&g_polling_lock);
-       }
-}
-
-/*
- * Context: softirq
- */
-static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev,
-               struct packet_type *pt, struct net_device *orig_dev)
-{
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (skb == NULL)
-               return 0;
-       spin_lock_bh(&g_rx_queue.lock);
-       if (g_processing_rx) {
-               /* We already hold the lock so use __ variant.
-                */
-               __skb_queue_head(&g_rx_queue, skb);
-               spin_unlock_bh(&g_rx_queue.lock);
-       } else {
-               g_processing_rx = 1;
-               do {
-
-                       spin_unlock_bh(&g_rx_queue.lock);
-                       oz_rx_frame(skb);
-                       spin_lock_bh(&g_rx_queue.lock);
-                       if (skb_queue_empty(&g_rx_queue)) {
-                               g_processing_rx = 0;
-                               spin_unlock_bh(&g_rx_queue.lock);
-                               break;
-                       }
-                       /* We already hold the lock so use __ variant.
-                        */
-                       skb = __skb_dequeue(&g_rx_queue);
-               } while (1);
-       }
-       return 0;
-}
-
-/*
- * Context: process
- */
-void oz_binding_add(const char *net_dev)
-{
-       struct oz_binding *binding;
-
-       binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL);
-       if (!binding)
-               return;
-
-       binding->ptype.type = htons(OZ_ETHERTYPE);
-       binding->ptype.func = oz_pkt_recv;
-       if (net_dev && *net_dev) {
-               memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
-               oz_dbg(ON, "Adding binding: %s\n", net_dev);
-               binding->ptype.dev = dev_get_by_name(&init_net, net_dev);
-               if (binding->ptype.dev == NULL) {
-                       oz_dbg(ON, "Netdev %s not found\n", net_dev);
-                       kfree(binding);
-                       return;
-               }
-       }
-       dev_add_pack(&binding->ptype);
-       spin_lock_bh(&g_binding_lock);
-       list_add_tail(&binding->link, &g_binding);
-       spin_unlock_bh(&g_binding_lock);
-}
-
-/*
- * Context: process
- */
-static void pd_stop_all_for_device(struct net_device *net_dev)
-{
-       LIST_HEAD(h);
-       struct oz_pd *pd;
-       struct oz_pd *n;
-
-       spin_lock_bh(&g_polling_lock);
-       list_for_each_entry_safe(pd, n, &g_pd_list, link) {
-               if (pd->net_dev == net_dev) {
-                       list_move(&pd->link, &h);
-                       oz_pd_get(pd);
-               }
-       }
-       spin_unlock_bh(&g_polling_lock);
-       while (!list_empty(&h)) {
-               pd = list_first_entry(&h, struct oz_pd, link);
-               oz_pd_stop(pd);
-               oz_pd_put(pd);
-       }
-}
-
-/*
- * Context: process
- */
-void oz_binding_remove(const char *net_dev)
-{
-       struct oz_binding *binding;
-       int found = 0;
-
-       oz_dbg(ON, "Removing binding: %s\n", net_dev);
-       spin_lock_bh(&g_binding_lock);
-       list_for_each_entry(binding, &g_binding, link) {
-               if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) {
-                       oz_dbg(ON, "Binding '%s' found\n", net_dev);
-                       found = 1;
-                       break;
-               }
-       }
-       spin_unlock_bh(&g_binding_lock);
-       if (found) {
-               dev_remove_pack(&binding->ptype);
-               if (binding->ptype.dev) {
-                       dev_put(binding->ptype.dev);
-                       pd_stop_all_for_device(binding->ptype.dev);
-               }
-               list_del(&binding->link);
-               kfree(binding);
-       }
-}
-
-/*
- * Context: process
- */
-static char *oz_get_next_device_name(char *s, char *dname, int max_size)
-{
-       while (*s == ',')
-               s++;
-       while (*s && (*s != ',') && max_size > 1) {
-               *dname++ = *s++;
-               max_size--;
-       }
-       *dname = 0;
-       return s;
-}
-
-/*
- * Context: process
- */
-int oz_protocol_init(char *devs)
-{
-       oz_elt_info_cache = KMEM_CACHE(oz_elt_info, 0);
-       if (!oz_elt_info_cache)
-               return -ENOMEM;
-
-       oz_tx_frame_cache = KMEM_CACHE(oz_tx_frame, 0);
-       if (!oz_tx_frame_cache) {
-               kmem_cache_destroy(oz_elt_info_cache);
-               return -ENOMEM;
-       }
-
-       skb_queue_head_init(&g_rx_queue);
-       if (devs[0] == '*') {
-               oz_binding_add(NULL);
-       } else {
-               char d[32];
-
-               while (*devs) {
-                       devs = oz_get_next_device_name(devs, d, sizeof(d));
-                       if (d[0])
-                               oz_binding_add(d);
-               }
-       }
-       return 0;
-}
-
-/*
- * Context: process
- */
-int oz_get_pd_list(struct oz_mac_addr *addr, int max_count)
-{
-       struct oz_pd *pd;
-       int count = 0;
-
-       spin_lock_bh(&g_polling_lock);
-       list_for_each_entry(pd, &g_pd_list, link) {
-               if (count >= max_count)
-                       break;
-               ether_addr_copy((u8 *)&addr[count++], pd->mac_addr);
-       }
-       spin_unlock_bh(&g_polling_lock);
-       return count;
-}
-
diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h
deleted file mode 100644 (file)
index 30c2db9..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZPROTO_H
-#define _OZPROTO_H
-
-#include <asm/byteorder.h>
-#include "ozdbg.h"
-#include "ozappif.h"
-
-#define OZ_ALLOCATED_SPACE(__x)        (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom)
-
-/* Quantum in MS */
-#define OZ_QUANTUM             8
-/* Default timeouts.
- */
-#define OZ_PRESLEEP_TOUT       11
-
-/* Maximun sizes of tx frames. */
-#define OZ_MAX_TX_SIZE         760
-
-/* Maximum number of uncompleted isoc frames that can be pending in network. */
-#define OZ_MAX_SUBMITTED_ISOC  16
-
-/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */
-#define OZ_MAX_TX_QUEUE_ISOC   32
-
-/* Application handler functions.
- */
-struct oz_app_if {
-       int  (*init)(void);
-       void (*term)(void);
-       int  (*start)(struct oz_pd *pd, int resume);
-       void (*stop)(struct oz_pd *pd, int pause);
-       void (*rx)(struct oz_pd *pd, struct oz_elt *elt);
-       int  (*heartbeat)(struct oz_pd *pd);
-       void (*farewell)(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len);
-};
-
-int oz_protocol_init(char *devs);
-void oz_protocol_term(void);
-int oz_get_pd_list(struct oz_mac_addr *addr, int max_count);
-void oz_app_enable(int app_id, int enable);
-struct oz_pd *oz_pd_find(const u8 *mac_addr);
-void oz_binding_add(const char *net_dev);
-void oz_binding_remove(const char *net_dev);
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
-void oz_timer_delete(struct oz_pd *pd, int type);
-void oz_pd_request_heartbeat(struct oz_pd *pd);
-void oz_pd_heartbeat_handler(unsigned long data);
-void oz_pd_timeout_handler(unsigned long data);
-enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
-enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer);
-int oz_get_pd_status_list(char *pd_list, int max_count);
-int oz_get_binding_list(char *buf, int max_if);
-
-extern struct kmem_cache *oz_elt_info_cache;
-extern struct kmem_cache *oz_tx_frame_cache;
-
-#endif /* _OZPROTO_H */
diff --git a/drivers/staging/ozwpan/ozprotocol.h b/drivers/staging/ozwpan/ozprotocol.h
deleted file mode 100644 (file)
index 4642072..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZPROTOCOL_H
-#define _OZPROTOCOL_H
-
-#define PACKED __packed
-
-#define OZ_ETHERTYPE 0x892e
-
-/* Status codes
- */
-#define OZ_STATUS_SUCCESS              0
-#define OZ_STATUS_INVALID_PARAM                1
-#define OZ_STATUS_TOO_MANY_PDS         2
-#define OZ_STATUS_NOT_ALLOWED          4
-#define OZ_STATUS_SESSION_MISMATCH     5
-#define OZ_STATUS_SESSION_TEARDOWN     6
-
-/* This is the generic element header.
-   Every element starts with this.
- */
-struct oz_elt {
-       u8 type;
-       u8 length;
-} PACKED;
-
-#define oz_next_elt(__elt)     \
-       (struct oz_elt *)((u8 *)((__elt) + 1) + (__elt)->length)
-
-/* Protocol element IDs.
- */
-#define OZ_ELT_CONNECT_REQ     0x06
-#define OZ_ELT_CONNECT_RSP     0x07
-#define OZ_ELT_DISCONNECT      0x08
-#define OZ_ELT_UPDATE_PARAM_REQ        0x11
-#define OZ_ELT_FAREWELL_REQ    0x12
-#define OZ_ELT_APP_DATA                0x31
-
-/* This is the Ozmo header which is the first Ozmo specific part
- * of a frame and comes after the MAC header.
- */
-struct oz_hdr {
-       u8      control;
-       u8      last_pkt_num;
-       u32     pkt_num;
-} PACKED;
-
-#define OZ_PROTOCOL_VERSION    0x1
-/* Bits in the control field. */
-#define OZ_VERSION_MASK                0xc
-#define OZ_VERSION_SHIFT       2
-#define OZ_F_ACK               0x10
-#define OZ_F_ISOC              0x20
-#define OZ_F_MORE_DATA         0x40
-#define OZ_F_ACK_REQUESTED     0x80
-
-#define oz_get_prot_ver(__x)   (((__x) & OZ_VERSION_MASK) >> OZ_VERSION_SHIFT)
-
-/* Used to select the bits of packet number to put in the last_pkt_num.
- */
-#define OZ_LAST_PN_MASK                0x00ff
-
-#define OZ_LAST_PN_HALF_CYCLE  127
-
-#define OZ_LATENCY_MASK                0xc0
-#define OZ_ONE_MS_LATENCY      0x40
-#define OZ_TEN_MS_LATENCY      0x80
-
-/* Connect request data structure.
- */
-struct oz_elt_connect_req {
-       u8      mode;
-       u8      resv1[16];
-       u8      pd_info;
-       u8      session_id;
-       u8      presleep;
-       u8      ms_isoc_latency;
-       u8      host_vendor;
-       u8      keep_alive;
-       u16     apps;
-       u8      max_len_div16;
-       u8      ms_per_isoc;
-       u8      resv3[2];
-} PACKED;
-
-/* mode field bits.
- */
-#define OZ_MODE_POLLED         0x0
-#define OZ_MODE_TRIGGERED      0x1
-#define OZ_MODE_MASK           0xf
-#define OZ_F_ISOC_NO_ELTS      0x40
-#define OZ_F_ISOC_ANYTIME      0x80
-#define OZ_NO_ELTS_ANYTIME     0xc0
-
-/* Keep alive field.
- */
-#define OZ_KALIVE_TYPE_MASK    0xc0
-#define OZ_KALIVE_VALUE_MASK   0x3f
-#define OZ_KALIVE_SPECIAL      0x00
-#define OZ_KALIVE_SECS         0x40
-#define OZ_KALIVE_MINS         0x80
-#define OZ_KALIVE_HOURS                0xc0
-
-/* Connect response data structure.
- */
-struct oz_elt_connect_rsp {
-       u8      mode;
-       u8      status;
-       u8      resv1[3];
-       u8      session_id;
-       u16     apps;
-       u32     resv2;
-} PACKED;
-
-struct oz_elt_farewell {
-       u8      ep_num;
-       u8      index;
-       u8      report[1];
-} PACKED;
-
-struct oz_elt_update_param {
-       u8      resv1[16];
-       u8      presleep;
-       u8      resv2;
-       u8      host_vendor;
-       u8      keepalive;
-} PACKED;
-
-/* Header common to all application elements.
- */
-struct oz_app_hdr {
-       u8      app_id;
-       u8      elt_seq_num;
-} PACKED;
-
-/* Values for app_id.
- */
-#define OZ_APPID_USB                           0x1
-#define OZ_APPID_SERIAL                                0x4
-#define OZ_APPID_MAX                           OZ_APPID_SERIAL
-#define OZ_NB_APPS                             (OZ_APPID_MAX+1)
-
-/* USB header common to all elements for the  USB application.
- * This header extends the oz_app_hdr and comes directly after
- * the element header in a USB application.
- */
-struct oz_usb_hdr {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-} PACKED;
-
-
-
-/* USB requests element subtypes (type field of hs_usb_hdr).
- */
-#define OZ_GET_DESC_REQ                        1
-#define OZ_GET_DESC_RSP                        2
-#define OZ_SET_CONFIG_REQ              3
-#define OZ_SET_CONFIG_RSP              4
-#define OZ_SET_INTERFACE_REQ           5
-#define OZ_SET_INTERFACE_RSP           6
-#define OZ_VENDOR_CLASS_REQ            7
-#define OZ_VENDOR_CLASS_RSP            8
-#define OZ_GET_STATUS_REQ              9
-#define OZ_GET_STATUS_RSP              10
-#define OZ_CLEAR_FEATURE_REQ           11
-#define OZ_CLEAR_FEATURE_RSP           12
-#define OZ_SET_FEATURE_REQ             13
-#define OZ_SET_FEATURE_RSP             14
-#define OZ_GET_CONFIGURATION_REQ       15
-#define OZ_GET_CONFIGURATION_RSP       16
-#define OZ_GET_INTERFACE_REQ           17
-#define OZ_GET_INTERFACE_RSP           18
-#define OZ_SYNCH_FRAME_REQ             19
-#define OZ_SYNCH_FRAME_RSP             20
-#define OZ_USB_ENDPOINT_DATA           23
-
-#define OZ_REQD_D2H                    0x80
-
-struct oz_get_desc_req {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u16     offset;
-       u16     size;
-       u8      req_type;
-       u8      desc_type;
-       __le16  w_index;
-       u8      index;
-} PACKED;
-
-/* Values for desc_type field.
-*/
-#define OZ_DESC_DEVICE                 0x01
-#define OZ_DESC_CONFIG                 0x02
-#define OZ_DESC_STRING                 0x03
-
-/* Values for req_type field.
- */
-#define OZ_RECP_MASK                   0x1F
-#define OZ_RECP_DEVICE                 0x00
-#define OZ_RECP_INTERFACE              0x01
-#define OZ_RECP_ENDPOINT               0x02
-
-#define OZ_REQT_MASK                   0x60
-#define OZ_REQT_STD                    0x00
-#define OZ_REQT_CLASS                  0x20
-#define OZ_REQT_VENDOR                 0x40
-
-struct oz_get_desc_rsp {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       __le16  offset;
-       __le16  total_size;
-       u8      rcode;
-       u8      data[1];
-} PACKED;
-
-struct oz_feature_req {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      recipient;
-       u8      index;
-       u16     feature;
-} PACKED;
-
-struct oz_feature_rsp {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      rcode;
-} PACKED;
-
-struct oz_set_config_req {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      index;
-} PACKED;
-
-struct oz_set_config_rsp {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      rcode;
-} PACKED;
-
-struct oz_set_interface_req {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      index;
-       u8      alternative;
-} PACKED;
-
-struct oz_set_interface_rsp {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      rcode;
-} PACKED;
-
-struct oz_get_interface_req {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      index;
-} PACKED;
-
-struct oz_get_interface_rsp {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      rcode;
-       u8      alternative;
-} PACKED;
-
-struct oz_vendor_class_req {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      req_type;
-       u8      request;
-       u16     value;
-       u16     index;
-       u8      data[1];
-} PACKED;
-
-struct oz_vendor_class_rsp {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      req_id;
-       u8      rcode;
-       u8      data[1];
-} PACKED;
-
-struct oz_data {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      endpoint;
-       u8      format;
-} PACKED;
-
-struct oz_isoc_fixed {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      endpoint;
-       u8      format;
-       u8      unit_size;
-       u8      frame_number;
-       u8      data[1];
-} PACKED;
-
-struct oz_multiple_fixed {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      endpoint;
-       u8      format;
-       u8      unit_size;
-       u8      data[1];
-} PACKED;
-
-struct oz_fragmented {
-       u8      app_id;
-       u8      elt_seq_num;
-       u8      type;
-       u8      endpoint;
-       u8      format;
-       u16     total_size;
-       u16     offset;
-       u8      data[1];
-} PACKED;
-
-/* Note: the following does not get packaged in an element in the same way
- * that other data formats are packaged. Instead the data is put in a frame
- * directly after the oz_header and is the only permitted data in such a
- * frame. The length of the data is directly determined from the frame size.
- */
-struct oz_isoc_large {
-       u8      endpoint;
-       u8      format;
-       u8      ms_data;
-       u8      frame_number;
-} PACKED;
-
-#define OZ_DATA_F_TYPE_MASK            0xF
-#define OZ_DATA_F_MULTIPLE_FIXED       0x1
-#define OZ_DATA_F_MULTIPLE_VAR         0x2
-#define OZ_DATA_F_ISOC_FIXED           0x3
-#define OZ_DATA_F_ISOC_VAR             0x4
-#define OZ_DATA_F_FRAGMENTED           0x5
-#define OZ_DATA_F_ISOC_LARGE           0x7
-
-#endif /* _OZPROTOCOL_H */
diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c
deleted file mode 100644 (file)
index cf6278a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include <linux/usb.h>
-#include "ozdbg.h"
-
-#ifdef WANT_URB_PARANOIA
-
-#include "ozurbparanoia.h"
-
-#define OZ_MAX_URBS    1000
-struct urb *g_urb_memory[OZ_MAX_URBS];
-int g_nb_urbs;
-DEFINE_SPINLOCK(g_urb_mem_lock);
-
-void oz_remember_urb(struct urb *urb)
-{
-       unsigned long irq_state;
-
-       spin_lock_irqsave(&g_urb_mem_lock, irq_state);
-       if (g_nb_urbs < OZ_MAX_URBS) {
-               g_urb_memory[g_nb_urbs++] = urb;
-               oz_dbg(ON, "urb up = %d %p\n", g_nb_urbs, urb);
-       } else {
-               oz_dbg(ON, "ERROR urb buffer full\n");
-       }
-       spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
-}
-
-/*
- */
-int oz_forget_urb(struct urb *urb)
-{
-       unsigned long irq_state;
-       int i;
-       int rc = -1;
-
-       spin_lock_irqsave(&g_urb_mem_lock, irq_state);
-       for (i = 0; i < g_nb_urbs; i++) {
-               if (g_urb_memory[i] == urb) {
-                       rc = 0;
-                       if (--g_nb_urbs > i)
-                               memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
-                                       (g_nb_urbs - i) * sizeof(struct urb *));
-                       oz_dbg(ON, "urb down = %d %p\n", g_nb_urbs, urb);
-               }
-       }
-       spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
-       return rc;
-}
-#endif /* #ifdef WANT_URB_PARANOIA */
-
diff --git a/drivers/staging/ozwpan/ozurbparanoia.h b/drivers/staging/ozwpan/ozurbparanoia.h
deleted file mode 100644 (file)
index 5080ea7..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _OZURBPARANOIA_H
-#define _OZURBPARANOIA_H
-/* -----------------------------------------------------------------------------
- * Released under the GNU General Public License Version 2 (GPLv2).
- * Copyright (c) 2011 Ozmo Inc
- * -----------------------------------------------------------------------------
- */
-
-#ifdef WANT_URB_PARANOIA
-void oz_remember_urb(struct urb *urb);
-int oz_forget_urb(struct urb *urb);
-#else
-static inline void oz_remember_urb(struct urb *urb) {}
-static inline int oz_forget_urb(struct urb *urb) { return 0; }
-#endif /* WANT_URB_PARANOIA */
-
-
-#endif /* _OZURBPARANOIA_H */
-
diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h
deleted file mode 100644 (file)
index d2a6085..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZUSBIF_H
-#define _OZUSBIF_H
-
-#include <linux/usb.h>
-
-/* Reference counting functions.
- */
-void oz_usb_get(void *hpd);
-void oz_usb_put(void *hpd);
-
-/* Stream functions.
- */
-int oz_usb_stream_create(void *hpd, u8 ep_num);
-int oz_usb_stream_delete(void *hpd, u8 ep_num);
-
-/* Request functions.
- */
-int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
-               const u8 *data, int data_len);
-int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
-       u8 index, __le16 windex, int offset, int len);
-int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb);
-void oz_usb_request_heartbeat(void *hpd);
-
-/* Confirmation functions.
- */
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status,
-       const u8 *desc, u8 length, u16 offset, u16 total_size);
-void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode,
-       const u8 *data, int data_len);
-
-/* Indication functions.
- */
-void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len);
-
-int oz_hcd_heartbeat(void *hport);
-
-#endif /* _OZUSBIF_H */
diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c
deleted file mode 100644 (file)
index bf15dc3..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- *
- * This file provides protocol independent part of the implementation of the USB
- * service for a PD.
- * The implementation of this service is split into two parts the first of which
- * is protocol independent and the second contains protocol specific details.
- * This split is to allow alternative protocols to be defined.
- * The implementation of this service uses ozhcd.c to implement a USB HCD.
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <asm/unaligned.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozusbif.h"
-#include "ozhcd.h"
-#include "ozusbsvc.h"
-
-/*
- * This is called once when the driver is loaded to initialise the USB service.
- * Context: process
- */
-int oz_usb_init(void)
-{
-       return oz_hcd_init();
-}
-
-/*
- * This is called once when the driver is unloaded to terminate the USB service.
- * Context: process
- */
-void oz_usb_term(void)
-{
-       oz_hcd_term();
-}
-
-/*
- * This is called when the USB service is started or resumed for a PD.
- * Context: softirq
- */
-int oz_usb_start(struct oz_pd *pd, int resume)
-{
-       int rc = 0;
-       struct oz_usb_ctx *usb_ctx;
-       struct oz_usb_ctx *old_ctx;
-
-       if (resume) {
-               oz_dbg(ON, "USB service resumed\n");
-               return 0;
-       }
-       oz_dbg(ON, "USB service started\n");
-       /* Create a USB context in case we need one. If we find the PD already
-        * has a USB context then we will destroy it.
-        */
-       usb_ctx = kzalloc(sizeof(struct oz_usb_ctx), GFP_ATOMIC);
-       if (usb_ctx == NULL)
-               return -ENOMEM;
-       atomic_set(&usb_ctx->ref_count, 1);
-       usb_ctx->pd = pd;
-       usb_ctx->stopped = 0;
-       /* Install the USB context if the PD doesn't already have one.
-        * If it does already have one then destroy the one we have just
-        * created.
-        */
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-       old_ctx = pd->app_ctx[OZ_APPID_USB];
-       if (old_ctx == NULL)
-               pd->app_ctx[OZ_APPID_USB] = usb_ctx;
-       oz_usb_get(pd->app_ctx[OZ_APPID_USB]);
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-       if (old_ctx) {
-               oz_dbg(ON, "Already have USB context\n");
-               kfree(usb_ctx);
-               usb_ctx = old_ctx;
-       } else if (usb_ctx) {
-               /* Take a reference to the PD. This will be released when
-                * the USB context is destroyed.
-                */
-               oz_pd_get(pd);
-       }
-       /* If we already had a USB context and had obtained a port from
-        * the USB HCD then just reset the port. If we didn't have a port
-        * then report the arrival to the USB HCD so we get one.
-        */
-       if (usb_ctx->hport) {
-               oz_hcd_pd_reset(usb_ctx, usb_ctx->hport);
-       } else {
-               usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx);
-               if (usb_ctx->hport == NULL) {
-                       oz_dbg(ON, "USB hub returned null port\n");
-                       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-                       pd->app_ctx[OZ_APPID_USB] = NULL;
-                       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-                       oz_usb_put(usb_ctx);
-                       rc = -1;
-               }
-       }
-       oz_usb_put(usb_ctx);
-       return rc;
-}
-
-/*
- * This is called when the USB service is stopped or paused for a PD.
- * Context: softirq or process
- */
-void oz_usb_stop(struct oz_pd *pd, int pause)
-{
-       struct oz_usb_ctx *usb_ctx;
-
-       if (pause) {
-               oz_dbg(ON, "USB service paused\n");
-               return;
-       }
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-       usb_ctx = (struct oz_usb_ctx *) pd->app_ctx[OZ_APPID_USB];
-       pd->app_ctx[OZ_APPID_USB] = NULL;
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-       if (usb_ctx) {
-               struct timespec ts, now;
-
-               getnstimeofday(&ts);
-               oz_dbg(ON, "USB service stopping...\n");
-               usb_ctx->stopped = 1;
-               /* At this point the reference count on the usb context should
-                * be 2 - one from when we created it and one from the hcd
-                * which claims a reference. Since stopped = 1 no one else
-                * should get in but someone may already be in. So wait
-                * until they leave but timeout after 1 second.
-                */
-               while ((atomic_read(&usb_ctx->ref_count) > 2)) {
-                       getnstimeofday(&now);
-                       /*Approx 1 Sec. this is not perfect calculation*/
-                       if (now.tv_sec != ts.tv_sec)
-                               break;
-               }
-               oz_dbg(ON, "USB service stopped\n");
-               oz_hcd_pd_departed(usb_ctx->hport);
-               /* Release the reference taken in oz_usb_start.
-                */
-               oz_usb_put(usb_ctx);
-       }
-}
-
-/*
- * This increments the reference count of the context area for a specific PD.
- * This ensures this context area does not disappear while still in use.
- * Context: softirq
- */
-void oz_usb_get(void *hpd)
-{
-       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
-       atomic_inc(&usb_ctx->ref_count);
-}
-
-/*
- * This decrements the reference count of the context area for a specific PD
- * and destroys the context area if the reference count becomes zero.
- * Context: irq or process
- */
-void oz_usb_put(void *hpd)
-{
-       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
-       if (atomic_dec_and_test(&usb_ctx->ref_count)) {
-               oz_dbg(ON, "Dealloc USB context\n");
-               oz_pd_put(usb_ctx->pd);
-               kfree(usb_ctx);
-       }
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_heartbeat(struct oz_pd *pd)
-{
-       struct oz_usb_ctx *usb_ctx;
-       int rc = 0;
-
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-       usb_ctx = (struct oz_usb_ctx *) pd->app_ctx[OZ_APPID_USB];
-       if (usb_ctx)
-               oz_usb_get(usb_ctx);
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-       if (usb_ctx == NULL)
-               return rc;
-       if (usb_ctx->stopped)
-               goto done;
-       if (usb_ctx->hport)
-               if (oz_hcd_heartbeat(usb_ctx->hport))
-                       rc = 1;
-done:
-       oz_usb_put(usb_ctx);
-       return rc;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_stream_create(void *hpd, u8 ep_num)
-{
-       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-
-       oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num);
-       if (pd->mode & OZ_F_ISOC_NO_ELTS) {
-               oz_isoc_stream_create(pd, ep_num);
-       } else {
-               oz_pd_get(pd);
-               if (oz_elt_stream_create(&pd->elt_buff, ep_num,
-                       4*pd->max_tx_size)) {
-                       oz_pd_put(pd);
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_stream_delete(void *hpd, u8 ep_num)
-{
-       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
-       if (usb_ctx) {
-               struct oz_pd *pd = usb_ctx->pd;
-
-               if (pd) {
-                       oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num);
-                       if (pd->mode & OZ_F_ISOC_NO_ELTS) {
-                               oz_isoc_stream_delete(pd, ep_num);
-                       } else {
-                               if (oz_elt_stream_delete(&pd->elt_buff, ep_num))
-                                       return -1;
-                               oz_pd_put(pd);
-                       }
-               }
-       }
-       return 0;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_usb_request_heartbeat(void *hpd)
-{
-       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
-       if (usb_ctx && usb_ctx->pd)
-               oz_pd_request_heartbeat(usb_ctx->pd);
-}
diff --git a/drivers/staging/ozwpan/ozusbsvc.h b/drivers/staging/ozwpan/ozusbsvc.h
deleted file mode 100644 (file)
index 58e05a5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZUSBSVC_H
-#define _OZUSBSVC_H
-
-/*------------------------------------------------------------------------------
- * Per PD context info stored in application context area of PD.
- * This object is reference counted to ensure it doesn't disappear while
- * still in use.
- */
-struct oz_usb_ctx {
-       atomic_t ref_count;
-       u8 tx_seq_num;
-       u8 rx_seq_num;
-       struct oz_pd *pd;
-       void *hport;
-       int stopped;
-};
-
-int oz_usb_init(void);
-void oz_usb_term(void);
-int oz_usb_start(struct oz_pd *pd, int resume);
-void oz_usb_stop(struct oz_pd *pd, int pause);
-void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt);
-int oz_usb_heartbeat(struct oz_pd *pd);
-void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len);
-
-#endif /* _OZUSBSVC_H */
-
diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c
deleted file mode 100644 (file)
index 301fee8..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- *
- * This file implements the protocol specific parts of the USB service for a PD.
- * -----------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <asm/unaligned.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozusbif.h"
-#include "ozhcd.h"
-#include "ozusbsvc.h"
-
-#define MAX_ISOC_FIXED_DATA    (253-sizeof(struct oz_isoc_fixed))
-
-/*
- * Context: softirq
- */
-static int oz_usb_submit_elt(struct oz_elt_buf *eb, struct oz_elt_info *ei,
-       struct oz_usb_ctx *usb_ctx, u8 strid, u8 isoc)
-{
-       int ret;
-       struct oz_elt *elt = (struct oz_elt *)ei->data;
-       struct oz_app_hdr *app_hdr = (struct oz_app_hdr *)(elt+1);
-
-       elt->type = OZ_ELT_APP_DATA;
-       ei->app_id = OZ_APPID_USB;
-       ei->length = elt->length + sizeof(struct oz_elt);
-       app_hdr->app_id = OZ_APPID_USB;
-       spin_lock_bh(&eb->lock);
-       if (isoc == 0) {
-               app_hdr->elt_seq_num = usb_ctx->tx_seq_num++;
-               if (usb_ctx->tx_seq_num == 0)
-                       usb_ctx->tx_seq_num = 1;
-       }
-       ret = oz_queue_elt_info(eb, isoc, strid, ei);
-       if (ret)
-               oz_elt_info_free(eb, ei);
-       spin_unlock_bh(&eb->lock);
-       return ret;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
-       u8 index, __le16 windex, int offset, int len)
-{
-       struct oz_usb_ctx *usb_ctx = hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-       struct oz_elt *elt;
-       struct oz_get_desc_req *body;
-       struct oz_elt_buf *eb = &pd->elt_buff;
-       struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-
-       oz_dbg(ON, "    req_type = 0x%x\n", req_type);
-       oz_dbg(ON, "    desc_type = 0x%x\n", desc_type);
-       oz_dbg(ON, "    index = 0x%x\n", index);
-       oz_dbg(ON, "    windex = 0x%x\n", windex);
-       oz_dbg(ON, "    offset = 0x%x\n", offset);
-       oz_dbg(ON, "    len = 0x%x\n", len);
-       if (len > 200)
-               len = 200;
-       if (ei == NULL)
-               return -1;
-       elt = (struct oz_elt *)ei->data;
-       elt->length = sizeof(struct oz_get_desc_req);
-       body = (struct oz_get_desc_req *)(elt+1);
-       body->type = OZ_GET_DESC_REQ;
-       body->req_id = req_id;
-       put_unaligned(cpu_to_le16(offset), &body->offset);
-       put_unaligned(cpu_to_le16(len), &body->size);
-       body->req_type = req_type;
-       body->desc_type = desc_type;
-       body->w_index = windex;
-       body->index = index;
-       return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_set_config_req(void *hpd, u8 req_id, u8 index)
-{
-       struct oz_usb_ctx *usb_ctx = hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-       struct oz_elt *elt;
-       struct oz_elt_buf *eb = &pd->elt_buff;
-       struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-       struct oz_set_config_req *body;
-
-       if (ei == NULL)
-               return -1;
-       elt = (struct oz_elt *)ei->data;
-       elt->length = sizeof(struct oz_set_config_req);
-       body = (struct oz_set_config_req *)(elt+1);
-       body->type = OZ_SET_CONFIG_REQ;
-       body->req_id = req_id;
-       body->index = index;
-       return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_set_interface_req(void *hpd, u8 req_id, u8 index, u8 alt)
-{
-       struct oz_usb_ctx *usb_ctx = hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-       struct oz_elt *elt;
-       struct oz_elt_buf *eb = &pd->elt_buff;
-       struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-       struct oz_set_interface_req *body;
-
-       if (ei == NULL)
-               return -1;
-       elt = (struct oz_elt *)ei->data;
-       elt->length = sizeof(struct oz_set_interface_req);
-       body = (struct oz_set_interface_req *)(elt+1);
-       body->type = OZ_SET_INTERFACE_REQ;
-       body->req_id = req_id;
-       body->index = index;
-       body->alternative = alt;
-       return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type,
-                       u8 recipient, u8 index, __le16 feature)
-{
-       struct oz_usb_ctx *usb_ctx = hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-       struct oz_elt *elt;
-       struct oz_elt_buf *eb = &pd->elt_buff;
-       struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-       struct oz_feature_req *body;
-
-       if (ei == NULL)
-               return -1;
-       elt = (struct oz_elt *)ei->data;
-       elt->length = sizeof(struct oz_feature_req);
-       body = (struct oz_feature_req *)(elt+1);
-       body->type = type;
-       body->req_id = req_id;
-       body->recipient = recipient;
-       body->index = index;
-       put_unaligned(feature, &body->feature);
-       return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type,
-       u8 request, __le16 value, __le16 index, const u8 *data, int data_len)
-{
-       struct oz_usb_ctx *usb_ctx = hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-       struct oz_elt *elt;
-       struct oz_elt_buf *eb = &pd->elt_buff;
-       struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-       struct oz_vendor_class_req *body;
-
-       if (ei == NULL)
-               return -1;
-       elt = (struct oz_elt *)ei->data;
-       elt->length = sizeof(struct oz_vendor_class_req) - 1 + data_len;
-       body = (struct oz_vendor_class_req *)(elt+1);
-       body->type = OZ_VENDOR_CLASS_REQ;
-       body->req_id = req_id;
-       body->req_type = req_type;
-       body->request = request;
-       put_unaligned(value, &body->value);
-       put_unaligned(index, &body->index);
-       if (data_len)
-               memcpy(body->data, data, data_len);
-       return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
-                       const u8 *data, int data_len)
-{
-       unsigned wvalue = le16_to_cpu(setup->wValue);
-       unsigned windex = le16_to_cpu(setup->wIndex);
-       unsigned wlength = le16_to_cpu(setup->wLength);
-       int rc = 0;
-
-       if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               switch (setup->bRequest) {
-               case USB_REQ_GET_DESCRIPTOR:
-                       rc = oz_usb_get_desc_req(hpd, req_id,
-                               setup->bRequestType, (u8)(wvalue>>8),
-                               (u8)wvalue, setup->wIndex, 0, wlength);
-                       break;
-               case USB_REQ_SET_CONFIGURATION:
-                       rc = oz_usb_set_config_req(hpd, req_id, (u8)wvalue);
-                       break;
-               case USB_REQ_SET_INTERFACE: {
-                               u8 if_num = (u8)windex;
-                               u8 alt = (u8)wvalue;
-
-                               rc = oz_usb_set_interface_req(hpd, req_id,
-                                       if_num, alt);
-                       }
-                       break;
-               case USB_REQ_SET_FEATURE:
-                       rc = oz_usb_set_clear_feature_req(hpd, req_id,
-                               OZ_SET_FEATURE_REQ,
-                               setup->bRequestType & 0xf, (u8)windex,
-                               setup->wValue);
-                       break;
-               case USB_REQ_CLEAR_FEATURE:
-                       rc = oz_usb_set_clear_feature_req(hpd, req_id,
-                               OZ_CLEAR_FEATURE_REQ,
-                               setup->bRequestType & 0xf,
-                               (u8)windex, setup->wValue);
-                       break;
-               }
-       } else {
-               rc = oz_usb_vendor_class_req(hpd, req_id, setup->bRequestType,
-                       setup->bRequest, setup->wValue, setup->wIndex,
-                       data, data_len);
-       }
-       return rc;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb)
-{
-       struct oz_usb_ctx *usb_ctx = hpd;
-       struct oz_pd *pd = usb_ctx->pd;
-       struct oz_elt_buf *eb;
-       int i;
-       int hdr_size;
-       u8 *data;
-       struct usb_iso_packet_descriptor *desc;
-
-       if (pd->mode & OZ_F_ISOC_NO_ELTS) {
-               for (i = 0; i < urb->number_of_packets; i++) {
-                       u8 *data;
-
-                       desc = &urb->iso_frame_desc[i];
-                       data = ((u8 *)urb->transfer_buffer)+desc->offset;
-                       oz_send_isoc_unit(pd, ep_num, data, desc->length);
-               }
-               return 0;
-       }
-
-       hdr_size = sizeof(struct oz_isoc_fixed) - 1;
-       eb = &pd->elt_buff;
-       i = 0;
-       while (i < urb->number_of_packets) {
-               struct oz_elt_info *ei = oz_elt_info_alloc(eb);
-               struct oz_elt *elt;
-               struct oz_isoc_fixed *body;
-               int unit_count;
-               int unit_size;
-               int rem;
-
-               if (ei == NULL)
-                       return -1;
-               rem = MAX_ISOC_FIXED_DATA;
-               elt = (struct oz_elt *)ei->data;
-               body = (struct oz_isoc_fixed *)(elt + 1);
-               body->type = OZ_USB_ENDPOINT_DATA;
-               body->endpoint = ep_num;
-               body->format = OZ_DATA_F_ISOC_FIXED;
-               unit_size = urb->iso_frame_desc[i].length;
-               body->unit_size = (u8)unit_size;
-               data = ((u8 *)(elt+1)) + hdr_size;
-               unit_count = 0;
-               while (i < urb->number_of_packets) {
-                       desc = &urb->iso_frame_desc[i];
-                       if ((unit_size == desc->length) &&
-                               (desc->length <= rem)) {
-                               memcpy(data, ((u8 *)urb->transfer_buffer) +
-                                       desc->offset, unit_size);
-                               data += unit_size;
-                               rem -= unit_size;
-                               unit_count++;
-                               desc->status = 0;
-                               desc->actual_length = desc->length;
-                               i++;
-                       } else {
-                               break;
-                       }
-               }
-               elt->length = hdr_size + MAX_ISOC_FIXED_DATA - rem;
-               /* Store the number of units in body->frame_number for the
-                * moment. This field will be correctly determined before
-                * the element is sent. */
-               body->frame_number = (u8)unit_count;
-               oz_usb_submit_elt(eb, ei, usb_ctx, ep_num,
-                       pd->mode & OZ_F_ISOC_ANYTIME);
-       }
-       return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx,
-       struct oz_usb_hdr *usb_hdr, int len)
-{
-       struct oz_data *data_hdr = (struct oz_data *)usb_hdr;
-
-       switch (data_hdr->format) {
-       case OZ_DATA_F_MULTIPLE_FIXED: {
-                       struct oz_multiple_fixed *body =
-                               (struct oz_multiple_fixed *)data_hdr;
-                       u8 *data = body->data;
-                       unsigned int n;
-                       if (!body->unit_size ||
-                               len < sizeof(struct oz_multiple_fixed) - 1)
-                               break;
-                       n = (len - (sizeof(struct oz_multiple_fixed) - 1))
-                               / body->unit_size;
-                       while (n--) {
-                               oz_hcd_data_ind(usb_ctx->hport, body->endpoint,
-                                       data, body->unit_size);
-                               data += body->unit_size;
-                       }
-               }
-               break;
-       case OZ_DATA_F_ISOC_FIXED: {
-                       struct oz_isoc_fixed *body =
-                               (struct oz_isoc_fixed *)data_hdr;
-                       int data_len;
-                       int unit_size = body->unit_size;
-                       u8 *data = body->data;
-                       int count;
-                       int i;
-
-                       if (len < sizeof(struct oz_isoc_fixed) - 1)
-                               break;
-                       data_len = len - (sizeof(struct oz_isoc_fixed) - 1);
-
-                       if (!unit_size)
-                               break;
-                       count = data_len/unit_size;
-                       for (i = 0; i < count; i++) {
-                               oz_hcd_data_ind(usb_ctx->hport,
-                                       body->endpoint, data, unit_size);
-                               data += unit_size;
-                       }
-               }
-               break;
-       }
-
-}
-
-/*
- * This is called when the PD has received a USB element. The type of element
- * is determined and is then passed to an appropriate handler function.
- * Context: softirq-serialized
- */
-void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
-{
-       struct oz_usb_hdr *usb_hdr = (struct oz_usb_hdr *)(elt + 1);
-       struct oz_usb_ctx *usb_ctx;
-
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-       usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB];
-       if (usb_ctx)
-               oz_usb_get(usb_ctx);
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-       if (usb_ctx == NULL)
-               return; /* Context has gone so nothing to do. */
-       if (usb_ctx->stopped)
-               goto done;
-       /* If sequence number is non-zero then check it is not a duplicate.
-        * Zero sequence numbers are always accepted.
-        */
-       if (usb_hdr->elt_seq_num != 0) {
-               if (((usb_ctx->rx_seq_num - usb_hdr->elt_seq_num) & 0x80) == 0)
-                       /* Reject duplicate element. */
-                       goto done;
-       }
-       usb_ctx->rx_seq_num = usb_hdr->elt_seq_num;
-       switch (usb_hdr->type) {
-       case OZ_GET_DESC_RSP: {
-                       struct oz_get_desc_rsp *body =
-                               (struct oz_get_desc_rsp *)usb_hdr;
-                       u16 offs, total_size;
-                       u8 data_len;
-
-                       if (elt->length < sizeof(struct oz_get_desc_rsp) - 1)
-                               break;
-                       data_len = elt->length -
-                                       (sizeof(struct oz_get_desc_rsp) - 1);
-                       offs = le16_to_cpu(get_unaligned(&body->offset));
-                       total_size =
-                               le16_to_cpu(get_unaligned(&body->total_size));
-                       oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
-                       oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id,
-                                       body->rcode, body->data,
-                                       data_len, offs, total_size);
-               }
-               break;
-       case OZ_SET_CONFIG_RSP: {
-                       struct oz_set_config_rsp *body =
-                               (struct oz_set_config_rsp *)usb_hdr;
-                       oz_hcd_control_cnf(usb_ctx->hport, body->req_id,
-                               body->rcode, NULL, 0);
-               }
-               break;
-       case OZ_SET_INTERFACE_RSP: {
-                       struct oz_set_interface_rsp *body =
-                               (struct oz_set_interface_rsp *)usb_hdr;
-                       oz_hcd_control_cnf(usb_ctx->hport,
-                               body->req_id, body->rcode, NULL, 0);
-               }
-               break;
-       case OZ_VENDOR_CLASS_RSP: {
-                       struct oz_vendor_class_rsp *body =
-                               (struct oz_vendor_class_rsp *)usb_hdr;
-
-                       if (elt->length <
-                           sizeof(struct oz_vendor_class_rsp) - 1)
-                               break;
-
-                       oz_hcd_control_cnf(usb_ctx->hport, body->req_id,
-                               body->rcode, body->data, elt->length-
-                               sizeof(struct oz_vendor_class_rsp)+1);
-               }
-               break;
-       case OZ_USB_ENDPOINT_DATA:
-               oz_usb_handle_ep_data(usb_ctx, usb_hdr, elt->length);
-               break;
-       }
-done:
-       oz_usb_put(usb_ctx);
-}
-
-/*
- * Context: softirq, process
- */
-void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len)
-{
-       struct oz_usb_ctx *usb_ctx;
-
-       spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
-       usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB];
-       if (usb_ctx)
-               oz_usb_get(usb_ctx);
-       spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-       if (usb_ctx == NULL)
-               return; /* Context has gone so nothing to do. */
-       if (!usb_ctx->stopped) {
-               oz_dbg(ON, "Farewell indicated ep = 0x%x\n", ep_num);
-               oz_hcd_data_ind(usb_ctx->hport, ep_num, data, len);
-       }
-       oz_usb_put(usb_ctx);
-}
index bda208da514e3b5b96da3ad06d7beeda659a8651..3e9ee7ee6be2a20d40ce01a4c203c24635c89f7c 100644 (file)
@@ -781,14 +781,18 @@ static void long_sleep(int ms)
                schedule_timeout_interruptible(msecs_to_jiffies(ms));
 }
 
-/* send a serial byte to the LCD panel. The caller is responsible for locking
-   if needed. */
+/*
+ * send a serial byte to the LCD panel. The caller is responsible for locking
+ * if needed.
+ */
 static void lcd_send_serial(int byte)
 {
        int bit;
 
-       /* the data bit is set on D0, and the clock on STROBE.
-        * LCD reads D0 on STROBE's rising edge. */
+       /*
+        * the data bit is set on D0, and the clock on STROBE.
+        * LCD reads D0 on STROBE's rising edge.
+        */
        for (bit = 0; bit < 8; bit++) {
                bits.cl = BIT_CLR;      /* CLK low */
                panel_set_bits();
index 581af88e302477f9b9fe8ff46ac0411e84d71e49..5c45f8a8c2cf77053d73456be62bdc159689812c 100644 (file)
@@ -379,7 +379,8 @@ void        expire_timeout_chk(struct adapter *padapter)
                        if (pmlmeext->active_keep_alive_check) {
                                int stainfo_offset;
 
-                               stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+                               stainfo_offset =
+                                       rtw_stainfo_offset(pstapriv, psta);
                                if (stainfo_offset_valid(stainfo_offset))
                                        chk_alive_list[chk_alive_num++] = stainfo_offset;
                                continue;
@@ -1584,7 +1585,7 @@ void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
                }
        }
 
-       if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {
+       if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) {
                if (!psta->no_short_slot_time_set) {
                        psta->no_short_slot_time_set = 1;
 
index bc3fe10ff247014c32ad4445a141173ee8b28fd0..993c7db87a1a5b83e79bdd8bc6e23f414a894c05 100644 (file)
@@ -219,6 +219,7 @@ int proc_get_ht_option(char *page, char **start,
        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
        int len = 0;
+
        len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option);
        *eof = 1;
        return len;
@@ -588,6 +589,7 @@ int proc_set_rx_signal(struct file *file, const char __user *buffer,
 
        if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
                int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength);
+
                is_signal_dbg = is_signal_dbg == 0 ? 0 : 1;
                if (is_signal_dbg && num != 2)
                        return count;
@@ -917,7 +919,7 @@ int proc_get_best_channel(char *page, char **start,
                /*  5G */
                if (pmlmeext->channel_set[i].ChannelNum >= 36 &&
                    pmlmeext->channel_set[i].ChannelNum < 140) {
-                        /*  Find primary channel */
+                       /*  Find primary channel */
                        if (((pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0) &&
                            (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
                                index_5G = i;
@@ -927,7 +929,7 @@ int proc_get_best_channel(char *page, char **start,
 
                if (pmlmeext->channel_set[i].ChannelNum >= 149 &&
                    pmlmeext->channel_set[i].ChannelNum < 165) {
-                        /*  find primary channel */
+                       /*  find primary channel */
                        if (((pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0) &&
                            (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
                                index_5G = i;
index dbaba2c6cce506946ffd7ef65eea26044c2eb11c..7b99ea91a9e6caf1e212537f82a2116c473534f6 100644 (file)
@@ -551,7 +551,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
                                bContinual = false;
                        }
                } else if (ReadState & PG_STATE_DATA) {
-               /*   Data section Read ------------- */
+                       /*   Data section Read ------------- */
                        efuse_WordEnableDataRead(hworden, tmpdata, data);
                        efuse_addr = efuse_addr + (word_cnts*2)+1;
                        ReadState = PG_STATE_HEADER;
index 11b780d6c4ab6bbea68e8ccdb60ba1ba800840b2..c3c582881a091e5294376e3436546e27ee5ed604 100644 (file)
@@ -19,6 +19,8 @@
  ******************************************************************************/
 #define _IEEE80211_C
 
+#include <linux/ieee80211.h>
+
 #include <drv_types.h>
 #include <osdep_intf.h>
 #include <ieee80211.h>
@@ -1042,7 +1044,7 @@ enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
                        elems->timeout_int = pos;
                        elems->timeout_int_len = elen;
                        break;
-               case WLAN_EID_HT_CAP:
+               case WLAN_EID_HT_CAPABILITY:
                        elems->ht_capabilities = pos;
                        elems->ht_capabilities_len = elen;
                        break;
index 8c05cb021c46a467c644af2efb4b289744a7f314..22f5b45f5f7fcb68d29334801221e2c434e1c9ef 100644 (file)
@@ -183,7 +183,7 @@ u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
                                rtw_indicate_disconnect(padapter);
 
-                       rtw_free_assoc_resources(padapter, 1);
+                       rtw_free_assoc_resources(padapter);
 
                        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
@@ -271,7 +271,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
                                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
                                                rtw_indicate_disconnect(padapter);
 
-                                       rtw_free_assoc_resources(padapter, 1);
+                                       rtw_free_assoc_resources(padapter);
 
                                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
                                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
@@ -293,7 +293,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
                                rtw_indicate_disconnect(padapter);
 
-                       rtw_free_assoc_resources(padapter, 1);
+                       rtw_free_assoc_resources(padapter);
 
                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
@@ -366,7 +366,7 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
 
                if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
                    (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
-                       rtw_free_assoc_resources(padapter, 1);
+                       rtw_free_assoc_resources(padapter);
 
                if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
@@ -415,7 +415,7 @@ u8 rtw_set_802_11_disassociate(struct adapter *padapter)
 
                rtw_disassoc_cmd(padapter, 0, true);
                rtw_indicate_disconnect(padapter);
-               rtw_free_assoc_resources(padapter, 1);
+               rtw_free_assoc_resources(padapter);
                rtw_pwr_wakeup(padapter);
        }
 
index 05584515c5b4d6c00a111a92dbb5a0a9aee7e9d4..2b917a18e228734abcc66c4d73712109cb1b44f7 100644 (file)
@@ -19,6 +19,7 @@
  ******************************************************************************/
 #define _RTW_MLME_C_
 
+#include <linux/ieee80211.h>
 
 #include <osdep_service.h>
 #include <drv_types.h>
@@ -160,7 +161,7 @@ exit:
        return pnetwork;
 }
 
-static void _rtw_free_network(struct   mlme_priv *pmlmepriv , struct wlan_network *pnetwork, u8 isfreeall)
+static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
 {
        u32 curr_time, delta_time;
        u32 lifetime = SCANQUEUE_LIFETIME;
@@ -352,8 +353,8 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
                ((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) == true) &&
                ((s_cap & WLAN_CAPABILITY_IBSS) ==
                (d_cap & WLAN_CAPABILITY_IBSS)) &&
-               ((s_cap & WLAN_CAPABILITY_BSS) ==
-               (d_cap & WLAN_CAPABILITY_BSS)));
+               ((s_cap & WLAN_CAPABILITY_ESS) ==
+               (d_cap & WLAN_CAPABILITY_ESS)));
 }
 
 struct wlan_network    *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
@@ -581,7 +582,7 @@ static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *
 }
 
 /* TODO: Perry: For Power Management */
-void rtw_atimdone_event_callback(struct adapter        *adapter , u8 *pbuf)
+void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf)
 {
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n"));
        return;
@@ -614,7 +615,7 @@ void rtw_survey_event_callback(struct adapter       *adapter, u8 *pbuf)
                        spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
                        ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
                        if (ibss_wlan) {
-                               memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
+                               memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8);
                                spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
                                goto exit;
                        }
@@ -692,8 +693,8 @@ void rtw_surveydone_event_callback(struct adapter   *adapter, u8 *pbuf)
                        pmlmepriv->to_join = false;
                        s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
                        if (_SUCCESS == s_ret) {
-                            mod_timer(&pmlmepriv->assoc_timer,
-                                      jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+                               mod_timer(&pmlmepriv->assoc_timer,
+                                       jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
                        } else if (s_ret == 2) { /* there is no need to wait for join */
                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
                                rtw_indicate_connect(adapter);
@@ -703,7 +704,7 @@ void rtw_surveydone_event_callback(struct adapter   *adapter, u8 *pbuf)
                                        if (--pmlmepriv->to_roaming == 0 ||
                                            _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) {
                                                pmlmepriv->to_roaming = 0;
-                                               rtw_free_assoc_resources(adapter, 1);
+                                               rtw_free_assoc_resources(adapter);
                                                rtw_indicate_disconnect(adapter);
                                        } else {
                                                pmlmepriv->to_join = true;
@@ -757,7 +758,19 @@ static void free_scanqueue(struct  mlme_priv *pmlmepriv)
 /*
 *rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
 */
-void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
+void rtw_free_assoc_resources(struct adapter *adapter)
+{
+       struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+       spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+       rtw_free_assoc_resources_locked(adapter);
+       spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+}
+
+/*
+*rtw_free_assoc_resources_locked: the caller has to lock pmlmepriv->lock
+*/
+void rtw_free_assoc_resources_locked(struct adapter *adapter)
 {
        struct wlan_network *pwlan = NULL;
        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -792,8 +805,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
                rtw_init_bcmc_stainfo(adapter);
        }
 
-       if (lock_scanned_queue)
-               spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
 
        pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
        if (pwlan)
@@ -804,8 +815,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1)))
                rtw_free_network_nolock(pmlmepriv, pwlan);
 
-       if (lock_scanned_queue)
-               spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
        pmlmepriv->key_mask = 0;
 }
 
@@ -1301,7 +1310,7 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
 
                rtw_free_uc_swdec_pending_queue(adapter);
 
-               rtw_free_assoc_resources(adapter, 1);
+               rtw_free_assoc_resources(adapter);
                rtw_indicate_disconnect(adapter);
                spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
                /*  remove the network entry in scanned_queue */
@@ -1382,7 +1391,7 @@ void _rtw_join_timeout_handler (unsigned long data)
                                DBG_88E("%s try another roaming\n", __func__);
                                do_join_r = rtw_do_join(adapter);
                                if (_SUCCESS != do_join_r) {
-                                       DBG_88E("%s roaming do_join return %d\n", __func__ , do_join_r);
+                                       DBG_88E("%s roaming do_join return %d\n", __func__, do_join_r);
                                        continue;
                                }
                                break;
@@ -1556,7 +1565,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
 
                rtw_disassoc_cmd(adapter, 0, true);
                rtw_indicate_disconnect(adapter);
-               rtw_free_assoc_resources(adapter, 0);
+               rtw_free_assoc_resources_locked(adapter);
        }
 
        rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div));
@@ -1997,7 +2006,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
                p = rtw_get_ie(in_ie+12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
                if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
                        out_len = *pout_len;
-                       rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2 , pout_len);
+                       rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2, pout_len);
                }
        }
        return phtpriv->ht_option;
index a0b8f665fa2f5546f23b584abb9248c1ba35d652..935b48eef8b1f84a6cf57792985c216277eeb0fc 100644 (file)
@@ -1096,7 +1096,7 @@ static void issue_assocreq(struct adapter *padapter)
 
                /*  Check if the AP's supported rates are also supported by STA. */
                for (j = 0; j < sta_bssrate_len; j++) {
-                        /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
+                       /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
                        if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
                                        == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
                                break;
@@ -2932,7 +2932,7 @@ static unsigned int OnAuthClient(struct adapter *padapter,
 
        if (seq == 2) {
                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
-                        /*  legendary shared system */
+                       /*  legendary shared system */
                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
                                pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
 
@@ -3367,7 +3367,7 @@ static unsigned int OnAssocReq(struct adapter *padapter,
        spin_unlock_bh(&pstapriv->asoc_list_lock);
 
        /*  now the station is qualified to join our BSS... */
-       if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
+       if ((pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
                /* 1 bss_cap_update & sta_info_update */
                bss_cap_update_on_sta_join(padapter, pstat);
                sta_info_update(padapter, pstat);
@@ -4155,8 +4155,8 @@ static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptabl
        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
        u8 *pframe = precv_frame->rx_data;
 
-         if (ptable->func) {
-        /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
+       if (ptable->func) {
+               /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
                if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
                    memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
                        return;
index ec0a8a4cdc6e65c29aa9b6b42b752028090d7b6f..9765946466ab6ad7d7f4a55eaa2c836b83926886 100644 (file)
@@ -70,7 +70,7 @@ static int rtw_hw_suspend(struct adapter *padapter)
                }
        }
        /* s2-3. */
-       rtw_free_assoc_resources(padapter, 1);
+       rtw_free_assoc_resources(padapter);
 
        /* s2-4. */
        rtw_free_network_queue(padapter, true);
@@ -549,12 +549,6 @@ void rtw_init_pwrctrl_priv(struct adapter *padapter)
                    (unsigned long)padapter);
 }
 
-inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
-{
-       struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-       pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
-}
-
 /*
 * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
 * @adapter: pointer to struct adapter structure
index 8501eb89882491126ea4521a2dacb52124eda16f..44eeb03213e6fec788e4108d7b01fcd6befe4a74 100644 (file)
@@ -74,10 +74,8 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
 
        precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ);
 
-       if (precvpriv->pallocated_frame_buf == NULL) {
-               res = _FAIL;
-               goto exit;
-       }
+       if (!precvpriv->pallocated_frame_buf)
+               return _FAIL;
 
        precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
 
@@ -89,7 +87,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
                list_add_tail(&(precvframe->list),
                                     &(precvpriv->free_recv_queue.queue));
 
-               res = rtw_os_recv_resource_alloc(padapter, precvframe);
+               rtw_os_recv_resource_alloc(precvframe);
 
                precvframe->len = 0;
 
@@ -107,8 +105,6 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
        precvpriv->signal_stat_sampling_interval = 1000; /* ms */
 
        rtw_set_signal_stat_timer(precvpriv);
-exit:
-
 
        return res;
 }
@@ -117,7 +113,6 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv)
 {
        struct adapter  *padapter = precvpriv->adapter;
 
-
        rtw_free_uc_swdec_pending_queue(padapter);
 
        if (precvpriv->pallocated_frame_buf) {
@@ -153,7 +148,6 @@ struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
                }
        }
 
-
        return (struct recv_frame *)hdr;
 }
 
@@ -170,14 +164,6 @@ struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
        return precvframe;
 }
 
-void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv)
-{
-       /* Perry: This can be removed */
-       INIT_LIST_HEAD(&precvframe->list);
-
-       precvframe->len = 0;
-}
-
 int rtw_free_recvframe(struct recv_frame *precvframe,
                       struct __queue *pfree_recv_queue)
 {
@@ -208,7 +194,6 @@ int rtw_free_recvframe(struct recv_frame *precvframe,
 
       spin_unlock_bh(&pfree_recv_queue->lock);
 
-
        return _SUCCESS;
 }
 
@@ -217,7 +202,6 @@ int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
        struct adapter *padapter = precvframe->adapter;
        struct recv_priv *precvpriv = &padapter->recvpriv;
 
-
        list_del_init(&(precvframe->list));
        list_add_tail(&(precvframe->list), get_list_head(queue));
 
@@ -226,7 +210,6 @@ int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
                        precvpriv->free_recvframe_cnt++;
        }
 
-
        return _SUCCESS;
 }
 
@@ -421,7 +404,6 @@ static int recvframe_chkmic(struct adapter *adapter,
 
 exit:
 
-
        return res;
 }
 
@@ -483,7 +465,6 @@ static struct recv_frame *decryptor(struct adapter *padapter,
                return_packet = NULL;
        }
 
-
        return return_packet;
 }
 
@@ -502,7 +483,6 @@ static struct recv_frame *portctrl(struct adapter *adapter,
        struct rx_pkt_attrib *pattrib;
        __be16 be_tmp;
 
-
        pstapriv = &adapter->stapriv;
 
        auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
@@ -561,7 +541,6 @@ static struct recv_frame *portctrl(struct adapter *adapter,
                prtnframe = precv_frame;
        }
 
-
                return prtnframe;
 }
 
@@ -573,7 +552,6 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry,
        u16 seq_ctrl = ((precv_frame->attrib.seq_num&0xffff) << 4) |
                (precv_frame->attrib.frag_num & 0xf);
 
-
        if (tid > 15) {
                RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", seq_ctrl, tid));
 
@@ -590,7 +568,6 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry,
 
        prxcache->tid_rxseq[tid] = seq_ctrl;
 
-
        return _SUCCESS;
 }
 
@@ -727,7 +704,6 @@ int sta2sta_data_frame(struct adapter *adapter, struct recv_frame *precv_frame,
        u8 *sta_addr = NULL;
        int bmcast = IS_MCAST(pattrib->dst);
 
-
        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
            (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
                /*  filter packets that SA is myself or multicast or broadcast */
@@ -815,7 +791,6 @@ static int ap2sta_data_frame(
        u8 *myhwaddr = myid(&adapter->eeprompriv);
        int bmcast = IS_MCAST(pattrib->dst);
 
-
        if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) &&
            (check_fwstate(pmlmepriv, _FW_LINKED) == true ||
            check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
@@ -907,7 +882,6 @@ static int ap2sta_data_frame(
 
 exit:
 
-
        return ret;
 }
 
@@ -922,7 +896,6 @@ static int sta2ap_data_frame(struct adapter *adapter,
        unsigned char *mybssid  = get_bssid(pmlmepriv);
        int ret = _SUCCESS;
 
-
        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
                /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
                if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
@@ -967,7 +940,6 @@ static int sta2ap_data_frame(struct adapter *adapter,
 
 exit:
 
-
        return ret;
 }
 
@@ -1149,7 +1121,6 @@ static int validate_recv_data_frame(struct adapter *adapter,
        struct security_priv    *psecuritypriv = &adapter->securitypriv;
        int ret = _SUCCESS;
 
-
        bretry = GetRetry(ptr);
        pda = get_da(ptr);
        psa = get_sa(ptr);
@@ -1253,7 +1224,6 @@ static int validate_recv_data_frame(struct adapter *adapter,
 
 exit:
 
-
        return ret;
 }
 
@@ -1273,7 +1243,6 @@ static int validate_recv_frame(struct adapter *adapter,
        u8  ver = (unsigned char)(*ptr)&0x3;
        struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
 
-
        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
                int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter));
                if (ch_set_idx >= 0)
@@ -1362,7 +1331,6 @@ static int validate_recv_frame(struct adapter *adapter,
 
 exit:
 
-
        return retval;
 }
 
@@ -1445,7 +1413,6 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
        struct recv_frame *prframe, *pnextrframe;
        struct __queue *pfree_recv_queue;
 
-
        curfragnum = 0;
        pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
 
@@ -1510,7 +1477,6 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter,
 
        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n"));
 
-
        return prframe;
 }
 
@@ -1528,7 +1494,6 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
        struct recv_frame *prtnframe = NULL;
        struct __queue *pfree_recv_queue, *pdefrag_q;
 
-
        pstapriv = &padapter->stapriv;
 
        pfhdr = precv_frame;
@@ -1612,7 +1577,6 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
                }
        }
 
-
        return prtnframe;
 }
 
@@ -2116,7 +2080,6 @@ s32 rtw_recv_entry(struct recv_frame *precvframe)
        struct recv_priv *precvpriv;
        s32 ret = _SUCCESS;
 
-
        padapter = precvframe->adapter;
 
        precvpriv = &padapter->recvpriv;
@@ -2129,7 +2092,6 @@ s32 rtw_recv_entry(struct recv_frame *precvframe)
 
        precvpriv->rx_pkts++;
 
-
        return ret;
 
 _recv_entry_drop:
index d870a5ce858533a4fa2e16e3e12000fe00e24e8d..22839d57dc8cea02cb0a91d18f561e7cdad77179 100644 (file)
@@ -1330,7 +1330,7 @@ static int aes_decipher(u8 *key, uint     hdrlen,
                bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
 
                for (j = 0; j < 16; j++)
-                        pframe[payload_index++] = chain_buffer[j];
+                       pframe[payload_index++] = chain_buffer[j];
        }
 
        if (payload_remainder > 0) {    /* If there is a short final block, then pad it,*/
index 32300df7b99671dec4b97c130025935f75dfe402..077b39a41c60a0d0cc32479a7ca51fcfdcc682ca 100644 (file)
@@ -19,6 +19,8 @@
  ******************************************************************************/
 #define _RTW_WLAN_UTIL_C_
 
+#include <linux/ieee80211.h>
+
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <wifi.h>
index fda169d377714e52eac42b470387c286d97063de..5dc0b90e8ab56f8c6667756f6921d1f509ea5ad0 100644 (file)
@@ -868,7 +868,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr
                        /* check if enable ampdu */
                        if (pattrib->ht_en && psta->htpriv.ampdu_enable) {
                                if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
-                               pattrib->ampdu_en = true;
+                                       pattrib->ampdu_en = true;
                        }
 
                        /* re-check if enable ampdu by BA_starting_seqctrl */
@@ -1026,22 +1026,22 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct
                /* adding icv, if necessary... */
                if (pattrib->iv_len) {
                        switch (pattrib->encrypt) {
-                               case _WEP40_:
-                               case _WEP104_:
-                                       WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
-                                       break;
-                               case _TKIP_:
-                                       if (bmcst)
-                                               TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
-                                       else
-                                               TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
-                                       break;
-                               case _AES_:
-                                       if (bmcst)
-                                               AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
-                                       else
-                                               AES_IV(pattrib->iv, psta->dot11txpn, 0);
-                                       break;
+                       case _WEP40_:
+                       case _WEP104_:
+                               WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+                               break;
+                       case _TKIP_:
+                               if (bmcst)
+                                       TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+                               else
+                                       TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+                               break;
+                       case _AES_:
+                               if (bmcst)
+                                       AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+                               else
+                                       AES_IV(pattrib->iv, psta->dot11txpn, 0);
+                               break;
                        }
 
                        memcpy(pframe, pattrib->iv, pattrib->iv_len);
@@ -1769,7 +1769,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra
        int bmcst = IS_MCAST(pattrib->ra);
 
        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false)
-           return ret;
+               return ret;
 
        if (pattrib->psta)
                psta = pattrib->psta;
index 15a176596305c8cd4d7536078d5c4ed748438745..2633a13b4e5857b6e2a0cd8f356fe8c1235f5a16 100644 (file)
@@ -659,11 +659,11 @@ void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rate
 {
        struct odm_ra_info *pRaInfo = NULL;
 
+       if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+               return;
        ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
                     ("macid =%d RateID = 0x%x RateMask = 0x%x SGIEnable =%d\n",
                     macid, RateID, RateMask, SGIEnable));
-       if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
-               return;
 
        pRaInfo = &(dm_odm->RAInfo[macid]);
        pRaInfo->RateID = RateID;
@@ -676,10 +676,10 @@ void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
 {
        struct odm_ra_info *pRaInfo = NULL;
 
-       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
-                    (" macid =%d Rssi =%d\n", macid, Rssi));
        if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
                return;
+       ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+                    (" macid =%d Rssi =%d\n", macid, Rssi));
 
        pRaInfo = &(dm_odm->RAInfo[macid]);
        pRaInfo->RssiStaRA = Rssi;
index 8eb2b39a0b6737008867f2032cd8371ced743fee..9c7e626aa703e62bb3f9626a2a61ea42fdfd3135 100644 (file)
@@ -24,9 +24,9 @@
 
 #define read_next_pair(array, v1, v2, i)               \
         do {                                           \
-                i += 2;                                \
-                v1 = array[i];                         \
-                v2 = array[i+1];                       \
+               i += 2;                                 \
+               v1 = array[i];                          \
+               v2 = array[i+1];                        \
         } while (0)
 
 
index 170e3de5eab4de8f3f3e09315c6f69486d51882a..38e9fdc312d336f5d914f7757204134cf40adabb 100644 (file)
@@ -31,18 +31,7 @@ void dump_chip_info(struct HAL_VERSION       chip_vers)
        uint cnt = 0;
        char buf[128];
 
-       if (IS_81XXC(chip_vers)) {
-               cnt += sprintf((buf+cnt), "Chip Version Info: %s_",
-                              IS_92C_SERIAL(chip_vers) ?
-                              "CHIP_8192C" : "CHIP_8188C");
-       } else if (IS_92D(chip_vers)) {
-               cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8192D_");
-       } else if (IS_8723_SERIES(chip_vers)) {
-               cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8723A_");
-       } else if (IS_8188E(chip_vers)) {
-               cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
-       }
-
+       cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
        cnt += sprintf((buf+cnt), "%s_", IS_NORMAL_CHIP(chip_vers) ?
                       "Normal_Chip" : "Test_Chip");
        cnt += sprintf((buf+cnt), "%s_", IS_CHIP_VENDOR_TSMC(chip_vers) ?
@@ -60,18 +49,8 @@ void dump_chip_info(struct HAL_VERSION       chip_vers)
        else
                cnt += sprintf((buf+cnt), "UNKNOWN_CUT(%d)_",
                               chip_vers.CUTVersion);
-
-       if (IS_1T1R(chip_vers))
-               cnt += sprintf((buf+cnt), "1T1R_");
-       else if (IS_1T2R(chip_vers))
-               cnt += sprintf((buf+cnt), "1T2R_");
-       else if (IS_2T2R(chip_vers))
-               cnt += sprintf((buf+cnt), "2T2R_");
-       else
-               cnt += sprintf((buf+cnt), "UNKNOWN_RFTYPE(%d)_",
-                              chip_vers.RFType);
-
-       cnt += sprintf((buf+cnt), "RomVer(%d)\n", chip_vers.ROMVer);
+       cnt += sprintf((buf+cnt), "1T1R_");
+       cnt += sprintf((buf+cnt), "RomVer(0)\n");
 
        pr_info("%s", buf);
 }
index 5edb5c41c8e705c8ae08edae94d75d1df460c669..85c17ef942f351038c49d2796ce71103612cb7cd 100644 (file)
@@ -131,14 +131,6 @@ void rtw_hal_get_hwreg(struct adapter *adapt, u8 variable, u8 *val)
                adapt->HalFunc.GetHwRegHandler(adapt, variable, val);
 }
 
-u8 rtw_hal_set_def_var(struct adapter *adapt, enum hal_def_variable var,
-                     void *val)
-{
-       if (adapt->HalFunc.SetHalDefVarHandler)
-               return adapt->HalFunc.SetHalDefVarHandler(adapt, var, val);
-       return _FAIL;
-}
-
 u8 rtw_hal_get_def_var(struct adapter *adapt,
                       enum hal_def_variable var, void *val)
 {
@@ -156,22 +148,6 @@ void rtw_hal_set_odm_var(struct adapter *adapt,
                                                      val1, set);
 }
 
-void rtw_hal_enable_interrupt(struct adapter *adapt)
-{
-       if (adapt->HalFunc.enable_interrupt)
-               adapt->HalFunc.enable_interrupt(adapt);
-       else
-               DBG_88E("%s: HalFunc.enable_interrupt is NULL!\n", __func__);
-}
-
-void rtw_hal_disable_interrupt(struct adapter *adapt)
-{
-       if (adapt->HalFunc.disable_interrupt)
-               adapt->HalFunc.disable_interrupt(adapt);
-       else
-               DBG_88E("%s: HalFunc.disable_interrupt is NULL!\n", __func__);
-}
-
 u32 rtw_hal_inirp_init(struct adapter *adapt)
 {
        u32 rst = _FAIL;
@@ -269,14 +245,6 @@ u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
        return data;
 }
 
-void rtw_hal_write_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
-                        u32 regaddr, u32 bitmask, u32 data)
-{
-       if (adapt->HalFunc.write_rfreg)
-               adapt->HalFunc.write_rfreg(adapt, rfpath, regaddr,
-                                             bitmask, data);
-}
-
 void rtw_hal_set_bwmode(struct adapter *adapt,
                        enum ht_channel_width bandwidth, u8 offset)
 {
index 28b5e7bd4fc0223beddd07102ce3d116bf0b116b..710fdc3449f835b9ee174778c14b309d2e15ef16 100644 (file)
@@ -1170,13 +1170,10 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm)
        }
 
        for (i = 0; i < sta_cnt; i++) {
-               if (PWDB_rssi[i] != (0)) {
-                       if (pHalData->fw_ractrl) {
-                               /*  Report every sta's RSSI to FW */
-                       } else {
-                               ODM_RA_SetRSSI_8188E(
-                               &(pHalData->odmpriv), (PWDB_rssi[i]&0xFF), (u8)((PWDB_rssi[i]>>16) & 0xFF));
-                       }
+               if (PWDB_rssi[i] != 0) {
+                       ODM_RA_SetRSSI_8188E(&pHalData->odmpriv,
+                                            PWDB_rssi[i] & 0xFF,
+                                            (PWDB_rssi[i] >> 16) & 0xFF);
                }
        }
 
index 097092772a860d4b66845394ab0ca46e3b005b09..38845d17d593c155b9dab40c6f931f8857b57416 100644 (file)
@@ -102,7 +102,7 @@ void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel)
                }
        }
        rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction,
-                                       &pwrtrac_value);
+                                       &pwrtrac_value);
 
        if (direction == 1) {
                /*  Increase TX power */
index 455ecdc8d9fa7c8a0d78c5d11a4049a9142f4d11..954cade478db37b3a0394ec1dc37f9b5925fe336 100644 (file)
@@ -295,7 +295,7 @@ static bool rf6052_conf_para(struct adapter *adapt)
                        break;
                }
 
-               if (rtstatus != true)
+               if (!rtstatus)
                        return false;
        }
 
index 86347f2ccdfdab27b353c06a7621e809b585e37e..0a62bfa210febdc0f6cd58f58ab68c1d498fdc49 100644 (file)
@@ -127,27 +127,6 @@ exit:
        return ret;
 }
 
-u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask)
-{
-       u8 buf[3];
-       u8 res = _SUCCESS;
-       struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
-
-       if (haldata->fw_ractrl) {
-
-               memset(buf, 0, 3);
-               put_unaligned_le32(mask, buf);
-
-               FillH2CCmd_88E(adapt, H2C_DM_MACID_CFG, 3, buf);
-       } else {
-               DBG_88E("==>%s fw dont support RA\n", __func__);
-               res = _FAIL;
-       }
-
-
-       return res;
-}
-
 /* bitmap[0:27] = tx_rate_bitmap */
 /* bitmap[28:31]= Rate Adaptive id */
 /* arg[0:4] = macid */
index 7904d2260f2cfd6b0f0e2eafeb1727ddab5683e7..a6295ca6a73e8c429d8b44bef8d5c8e811c0e59e 100644 (file)
@@ -128,7 +128,7 @@ static void rtl8188e_free_hal_data(struct adapter *padapter)
        padapter->HalData = NULL;
 }
 
-static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter)
+static void ReadChipVersion8188E(struct adapter *padapter)
 {
        u32                             value32;
        struct HAL_VERSION              ChipVersion;
@@ -137,41 +137,17 @@ static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter)
        pHalData = GET_HAL_DATA(padapter);
 
        value32 = usb_read32(padapter, REG_SYS_CFG);
-       ChipVersion.ICType = CHIP_8188E;
        ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
-
-       ChipVersion.RFType = RF_TYPE_1T1R;
        ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
        ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /*  IC version (CUT) */
 
-       /*  For regulator mode. by tynli. 2011.01.14 */
-       pHalData->RegulatorMode = ((value32 & TRP_BT_EN) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
-
-       ChipVersion.ROMVer = 0; /*  ROM code version. */
-
        dump_chip_info(ChipVersion);
 
        pHalData->VersionID = ChipVersion;
-
-       if (IS_1T2R(ChipVersion)) {
-               pHalData->rf_type = RF_1T2R;
-               pHalData->NumTotalRFPath = 2;
-       } else if (IS_2T2R(ChipVersion)) {
-               pHalData->rf_type = RF_2T2R;
-               pHalData->NumTotalRFPath = 2;
-       } else{
-               pHalData->rf_type = RF_1T1R;
-               pHalData->NumTotalRFPath = 1;
-       }
+       pHalData->rf_type = RF_1T1R;
+       pHalData->NumTotalRFPath = 1;
 
        MSG_88E("RF_Type is %x!!\n", pHalData->rf_type);
-
-       return ChipVersion;
-}
-
-static void rtl8188e_read_chip_version(struct adapter *padapter)
-{
-       ReadChipVersion8188E(padapter);
 }
 
 static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
@@ -220,7 +196,7 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
 
        pHalFunc->dm_init = &rtl8188e_init_dm_priv;
 
-       pHalFunc->read_chip_version = &rtl8188e_read_chip_version;
+       pHalFunc->read_chip_version = &ReadChipVersion8188E;
 
        pHalFunc->set_bwmode_handler = &phy_set_bw_mode;
        pHalFunc->set_channel_handler = &phy_sw_chnl;
@@ -232,7 +208,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
        pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E;
        pHalFunc->AntDivCompareHandler = &AntDivCompare8188E;
        pHalFunc->read_rfreg = &phy_query_rf_reg;
-       pHalFunc->write_rfreg = &phy_set_rf_reg;
 
        pHalFunc->sreset_init_value = &sreset_init_value;
        pHalFunc->sreset_get_wifi_status  = &sreset_get_wifi_status;
index 8726222142648fb6e07f12a015342415ea8f2ab9..1ef878fd997bae0356d6f7d16a4106cfbef32ad8 100644 (file)
@@ -743,19 +743,16 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter)
        if (Adapter->registrypriv.mp_mode == 1) {
                _InitRxSetting(Adapter);
                Adapter->bFWReady = false;
-               haldata->fw_ractrl = false;
        } else {
                status = rtl88eu_download_fw(Adapter);
 
                if (status) {
                        DBG_88E("%s: Download Firmware failed!!\n", __func__);
                        Adapter->bFWReady = false;
-                       haldata->fw_ractrl = false;
                        return status;
                } else {
                        RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializeadapt8192CSdio(): Download Firmware Success!!\n"));
                        Adapter->bFWReady = true;
-                       haldata->fw_ractrl = false;
                }
        }
        rtl8188e_InitializeFirmwareVars(Adapter);
@@ -1703,7 +1700,7 @@ static void SetHwReg8188EU(struct adapter *Adapter, u8 variable, u8 *val)
 
                        /*  Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
                        /*  saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
-                       if ((psmode != PS_MODE_ACTIVE) && (!IS_92C_SERIAL(haldata->VersionID)))
+                       if (psmode != PS_MODE_ACTIVE)
                                ODM_RF_Saving(podmpriv, true);
                        rtl8188e_set_FwPwrMode_cmd(Adapter, psmode);
                }
@@ -1961,75 +1958,6 @@ GetHalDefVar8188EUsb(
        return bResult;
 }
 
-/*  */
-/*     Description: */
-/*             Change default setting of specified variable. */
-/*  */
-static u8 SetHalDefVar8188EUsb(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue)
-{
-       struct hal_data_8188e   *haldata = GET_HAL_DATA(Adapter);
-       u8 bResult = _SUCCESS;
-
-       switch (eVariable) {
-       case HAL_DEF_DBG_DM_FUNC:
-               {
-                       u8 dm_func = *((u8 *)pValue);
-                       struct odm_dm_struct *podmpriv = &haldata->odmpriv;
-
-                       if (dm_func == 0) { /* disable all dynamic func */
-                               podmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE;
-                               DBG_88E("==> Disable all dynamic function...\n");
-                       } else if (dm_func == 1) {/* disable DIG */
-                               podmpriv->SupportAbility  &= (~DYNAMIC_BB_DIG);
-                               DBG_88E("==> Disable DIG...\n");
-                       } else if (dm_func == 2) {/* disable High power */
-                               podmpriv->SupportAbility  &= (~DYNAMIC_BB_DYNAMIC_TXPWR);
-                       } else if (dm_func == 3) {/* disable tx power tracking */
-                               podmpriv->SupportAbility  &= (~DYNAMIC_RF_CALIBRATION);
-                               DBG_88E("==> Disable tx power tracking...\n");
-                       } else if (dm_func == 5) {/* disable antenna diversity */
-                               podmpriv->SupportAbility  &= (~DYNAMIC_BB_ANT_DIV);
-                       } else if (dm_func == 6) {/* turn on all dynamic func */
-                               if (!(podmpriv->SupportAbility  & DYNAMIC_BB_DIG)) {
-                                       struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
-                                       pDigTable->CurIGValue = usb_read8(Adapter, 0xc50);
-                               }
-                               podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
-                               DBG_88E("==> Turn on all dynamic function...\n");
-                       }
-               }
-               break;
-       case HAL_DEF_DBG_DUMP_RXPKT:
-               haldata->bDumpRxPkt = *((u8 *)pValue);
-               break;
-       case HAL_DEF_DBG_DUMP_TXPKT:
-               haldata->bDumpTxPkt = *((u8 *)pValue);
-               break;
-       case HW_DEF_FA_CNT_DUMP:
-               {
-                       u8 bRSSIDump = *((u8 *)pValue);
-                       struct odm_dm_struct *dm_ocm = &(haldata->odmpriv);
-                       if (bRSSIDump)
-                               dm_ocm->DebugComponents =       ODM_COMP_DIG|ODM_COMP_FA_CNT;
-                       else
-                               dm_ocm->DebugComponents = 0;
-               }
-               break;
-       case HW_DEF_ODM_DBG_FLAG:
-               {
-                       u64     DebugComponents = *((u64 *)pValue);
-                       struct odm_dm_struct *dm_ocm = &(haldata->odmpriv);
-                       dm_ocm->DebugComponents = DebugComponents;
-               }
-               break;
-       default:
-               bResult = _FAIL;
-               break;
-       }
-
-       return bResult;
-}
-
 static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
 {
        u8 init_rate = 0;
@@ -2085,28 +2013,9 @@ static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_l
 
        init_rate = get_highest_rate_idx(mask)&0x3f;
 
-       if (haldata->fw_ractrl) {
-               u8 arg;
-
-               arg = mac_id & 0x1f;/* MACID */
-               arg |= BIT(7);
-               if (shortGIrate)
-                       arg |= BIT(5);
-               mask |= ((raid << 28) & 0xf0000000);
-               DBG_88E("update raid entry, mask=0x%x, arg=0x%x\n", mask, arg);
-               psta->ra_mask = mask;
-               mask |= ((raid << 28) & 0xf0000000);
+       ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, mac_id,
+                                   raid, mask, shortGIrate);
 
-               /* to do ,for 8188E-SMIC */
-               rtl8188e_set_raid_cmd(adapt, mask);
-       } else {
-               ODM_RA_UpdateRateInfo_8188E(&(haldata->odmpriv),
-                               mac_id,
-                               raid,
-                               mask,
-                               shortGIrate
-                               );
-       }
        /* set ra_id */
        psta->raid = raid;
        psta->init_rate = init_rate;
@@ -2156,7 +2065,6 @@ static void rtl8188eu_init_default_value(struct adapter *adapt)
        pwrctrlpriv = &adapt->pwrctrlpriv;
 
        /* init default value */
-       haldata->fw_ractrl = false;
        if (!pwrctrlpriv->bkeepfwalive)
                haldata->LastHMEBoxNum = 0;
 
@@ -2200,7 +2108,6 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt)
        halfunc->SetHwRegHandler = &SetHwReg8188EU;
        halfunc->GetHwRegHandler = &GetHwReg8188EU;
        halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb;
-       halfunc->SetHalDefVarHandler = &SetHalDefVar8188EUsb;
 
        halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb;
        halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb;
index 97047cf06780f7ee11054a60a20ea25225c7da10..56b4ff08e509cba62a0d3a96f2ea57d2b87096d7 100644 (file)
 #ifndef __HAL_VERSION_DEF_H__
 #define __HAL_VERSION_DEF_H__
 
-enum HAL_IC_TYPE {
-       CHIP_8192S      =       0,
-       CHIP_8188C      =       1,
-       CHIP_8192C      =       2,
-       CHIP_8192D      =       3,
-       CHIP_8723A      =       4,
-       CHIP_8188E      =       5,
-       CHIP_8881A      =       6,
-       CHIP_8812A      =       7,
-       CHIP_8821A      =       8,
-       CHIP_8723B      =       9,
-       CHIP_8192E      =       10,
-};
-
 enum HAL_CHIP_TYPE {
        TEST_CHIP       =       0,
        NORMAL_CHIP     =       1,
@@ -55,48 +41,20 @@ enum HAL_VENDOR {
        CHIP_VENDOR_UMC         =       1,
 };
 
-enum HAL_RF_TYPE {
-       RF_TYPE_1T1R    =       0,
-       RF_TYPE_1T2R    =       1,
-       RF_TYPE_2T2R    =       2,
-       RF_TYPE_2T3R    =       3,
-       RF_TYPE_2T4R    =       4,
-       RF_TYPE_3T3R    =       5,
-       RF_TYPE_3T4R    =       6,
-       RF_TYPE_4T4R    =       7,
-};
-
 struct HAL_VERSION {
-       enum HAL_IC_TYPE        ICType;
        enum HAL_CHIP_TYPE      ChipType;
        enum HAL_CUT_VERSION    CUTVersion;
        enum HAL_VENDOR         VendorType;
-       enum HAL_RF_TYPE        RFType;
-       u8                      ROMVer;
 };
 
 /*  Get element */
-#define GET_CVID_IC_TYPE(version)      (((version).ICType))
 #define GET_CVID_CHIP_TYPE(version)    (((version).ChipType))
-#define GET_CVID_RF_TYPE(version)      (((version).RFType))
 #define GET_CVID_MANUFACTUER(version)  (((version).VendorType))
 #define GET_CVID_CUT_VERSION(version)  (((version).CUTVersion))
-#define GET_CVID_ROM_VERSION(version)  (((version).ROMVer) & ROM_VERSION_MASK)
 
 /* Common Macro. -- */
 /* HAL_VERSION VersionID */
 
-/*  HAL_IC_TYPE_E */
-#define IS_81XXC(version)                              \
-       (((GET_CVID_IC_TYPE(version) == CHIP_8192C) ||  \
-        (GET_CVID_IC_TYPE(version) == CHIP_8188C)) ? true : false)
-#define IS_8723_SERIES(version)                                \
-       ((GET_CVID_IC_TYPE(version) == CHIP_8723A) ? true : false)
-#define IS_92D(version)                                        \
-       ((GET_CVID_IC_TYPE(version) == CHIP_8192D) ? true : false)
-#define IS_8188E(version)                              \
-       ((GET_CVID_IC_TYPE(version) == CHIP_8188E) ? true : false)
-
 /* HAL_CHIP_TYPE_E */
 #define IS_TEST_CHIP(version)                          \
        ((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false)
@@ -122,46 +80,4 @@ struct HAL_VERSION {
 #define IS_CHIP_VENDOR_UMC(version)                    \
        ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
 
-/* HAL_RF_TYPE_E */
-#define IS_1T1R(version)                               \
-       ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T1R) ? true : false)
-#define IS_1T2R(version)                               \
-       ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
-#define IS_2T2R(version)                               \
-       ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
-
-/* Chip version Macro. -- */
-#define IS_81XXC_TEST_CHIP(version)                    \
-       ((IS_81XXC(version) && (!IS_NORMAL_CHIP(version))) ? true : false)
-
-#define IS_92C_SERIAL(version)                         \
-       ((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
-#define IS_81xxC_VENDOR_UMC_A_CUT(version)             \
-       (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ?     \
-       (IS_A_CUT(version) ? true : false) : false) : false)
-#define IS_81xxC_VENDOR_UMC_B_CUT(version)             \
-       (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ?     \
-       (IS_B_CUT(version) ? true : false) : false) : false)
-#define IS_81xxC_VENDOR_UMC_C_CUT(version)             \
-       (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
-        (IS_C_CUT(version) ? true : false) : false) : false)
-
-#define IS_NORMAL_CHIP92D(version)                     \
-       ((IS_92D(version)) ?                            \
-       ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false) : false)
-
-#define IS_92D_SINGLEPHY(version)                      \
-       ((IS_92D(version)) ? (IS_2T2R(version) ? true : false) : false)
-#define IS_92D_C_CUT(version)                          \
-       ((IS_92D(version)) ? (IS_C_CUT(version) ? true : false) : false)
-#define IS_92D_D_CUT(version)                          \
-       ((IS_92D(version)) ? (IS_D_CUT(version) ? true : false) : false)
-#define IS_92D_E_CUT(version)                          \
-       ((IS_92D(version)) ? (IS_E_CUT(version) ? true : false) : false)
-
-#define IS_8723A_A_CUT(version)                                \
-       ((IS_8723_SERIES(version)) ? (IS_A_CUT(version) ? true : false) : false)
-#define IS_8723A_B_CUT(version)                                \
-       ((IS_8723_SERIES(version)) ? (IS_B_CUT(version) ? true : false) : false)
-
 #endif
index 3b476d80f64d68430fb1c24f40a5adb5e3a0ba2f..e73c6341248eb9acbca4bf320b2bdc884ada61ff 100644 (file)
@@ -171,8 +171,6 @@ struct hal_ops {
 
        void    (*read_adapter_info)(struct adapter *padapter);
 
-       void    (*enable_interrupt)(struct adapter *padapter);
-       void    (*disable_interrupt)(struct adapter *padapter);
        s32     (*interrupt_handler)(struct adapter *padapter);
 
        void    (*set_bwmode_handler)(struct adapter *padapter,
@@ -190,9 +188,6 @@ struct hal_ops {
        u8      (*GetHalDefVarHandler)(struct adapter *padapter,
                                       enum hal_def_variable eVariable,
                                       void *pValue);
-       u8      (*SetHalDefVarHandler)(struct adapter *padapter,
-                                      enum hal_def_variable eVariable,
-                                      void *pValue);
 
        void    (*SetHalODMVarHandler)(struct adapter *padapter,
                                       enum hal_odm_variable eVariable,
@@ -216,9 +211,6 @@ struct hal_ops {
        u32     (*read_rfreg)(struct adapter *padapter,
                              enum rf_radio_path eRFPath, u32 RegAddr,
                              u32 BitMask);
-       void    (*write_rfreg)(struct adapter *padapter,
-                              enum rf_radio_path eRFPath, u32 RegAddr,
-                              u32 BitMask, u32 Data);
 
        void (*sreset_init_value)(struct adapter *padapter);
        u8 (*sreset_get_wifi_status)(struct adapter *padapter);
@@ -267,8 +259,6 @@ void rtw_hal_chip_configure(struct adapter *padapter);
 void rtw_hal_read_chip_info(struct adapter *padapter);
 void rtw_hal_read_chip_version(struct adapter *padapter);
 
-u8 rtw_hal_set_def_var(struct adapter *padapter,
-                      enum hal_def_variable eVariable, void *pValue);
 u8 rtw_hal_get_def_var(struct adapter *padapter,
                       enum hal_def_variable eVariable, void *pValue);
 
@@ -276,9 +266,6 @@ void rtw_hal_set_odm_var(struct adapter *padapter,
                         enum hal_odm_variable eVariable, void *pValue1,
                         bool bSet);
 
-void rtw_hal_enable_interrupt(struct adapter *padapter);
-void rtw_hal_disable_interrupt(struct adapter *padapter);
-
 u32    rtw_hal_inirp_init(struct adapter *padapter);
 u32    rtw_hal_inirp_deinit(struct adapter *padapter);
 
@@ -300,9 +287,6 @@ void rtw_hal_bcn_related_reg_setting(struct adapter *padapter);
 
 u32    rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath,
                           u32 RegAddr, u32 BitMask);
-void   rtw_hal_write_rfreg(struct adapter *padapter,
-                           enum rf_radio_path eRFPath, u32 RegAddr,
-                           u32 BitMask, u32 Data);
 
 void   rtw_hal_set_bwmode(struct adapter *padapter,
                           enum ht_channel_width Bandwidth, u8 Offset);
index b129ad148b4728dc283eee1b62866c274552904b..6400f75707bd54a2ba7ba40277b1364afe8afb0c 100644 (file)
@@ -477,63 +477,9 @@ struct ieee80211_snap_hdr {
 #define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG)
 #define WLAN_GET_SEQ_SEQ(seq)  ((seq) & RTW_IEEE80211_SCTL_SEQ)
 
-/* Authentication algorithms */
-#define WLAN_AUTH_OPEN 0
-#define WLAN_AUTH_SHARED_KEY 1
-
-#define WLAN_AUTH_CHALLENGE_LEN 128
-
-#define WLAN_CAPABILITY_BSS (1<<0)
-#define WLAN_CAPABILITY_IBSS (1<<1)
-#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
-#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
-#define WLAN_CAPABILITY_PRIVACY (1<<4)
-#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
-#define WLAN_CAPABILITY_PBCC (1<<6)
-#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
-#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
-
 /* Non standard?  Not in <linux/ieee80211.h> */
 #define WLAN_REASON_EXPIRATION_CHK 65535
 
-/* Information Element IDs */
-#define WLAN_EID_SSID 0
-#define WLAN_EID_SUPP_RATES 1
-#define WLAN_EID_FH_PARAMS 2
-#define WLAN_EID_DS_PARAMS 3
-#define WLAN_EID_CF_PARAMS 4
-#define WLAN_EID_TIM 5
-#define WLAN_EID_IBSS_PARAMS 6
-#define WLAN_EID_CHALLENGE 16
-/* EIDs defined by IEEE 802.11h - START */
-#define WLAN_EID_PWR_CONSTRAINT 32
-#define WLAN_EID_PWR_CAPABILITY 33
-#define WLAN_EID_TPC_REQUEST 34
-#define WLAN_EID_TPC_REPORT 35
-#define WLAN_EID_SUPPORTED_CHANNELS 36
-#define WLAN_EID_CHANNEL_SWITCH 37
-#define WLAN_EID_MEASURE_REQUEST 38
-#define WLAN_EID_MEASURE_REPORT 39
-#define WLAN_EID_QUITE 40
-#define WLAN_EID_IBSS_DFS 41
-/* EIDs defined by IEEE 802.11h - END */
-#define WLAN_EID_ERP_INFO 42
-#define WLAN_EID_HT_CAP 45
-#define WLAN_EID_RSN 48
-#define WLAN_EID_EXT_SUPP_RATES 50
-#define WLAN_EID_MOBILITY_DOMAIN 54
-#define WLAN_EID_FAST_BSS_TRANSITION 55
-#define WLAN_EID_TIMEOUT_INTERVAL 56
-#define WLAN_EID_RIC_DATA 57
-#define WLAN_EID_HT_OPERATION 61
-#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
-#define WLAN_EID_20_40_BSS_COEXISTENCE 72
-#define WLAN_EID_20_40_BSS_INTOLERANT 73
-#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
-#define WLAN_EID_MMIE 76
-#define WLAN_EID_VENDOR_SPECIFIC 221
-#define WLAN_EID_GENERIC (WLAN_EID_VENDOR_SPECIFIC)
-
 #define IEEE80211_MGMT_HDR_LEN 24
 #define IEEE80211_DATA_HDR3_LEN 24
 #define IEEE80211_DATA_HDR4_LEN 30
index 00472e0c00a0573da8a529185884c8686cba51e5..cf9ca685eb7776d69aa634ec6f603d211c3c1930 100644 (file)
@@ -123,7 +123,7 @@ static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
 #define BIT35  0x0800000000
 #define BIT36  0x1000000000
 
-extern int RTW_STATUS_CODE(int error_code);
+int RTW_STATUS_CODE(int error_code);
 
 #define rtw_update_mem_stat(flag, sz) do {} while (0)
 u8 *_rtw_malloc(u32 sz);
index 0809963ce6aa890a8f6571ebca9ad927fb432b79..fdeb603b6cc1b59315ef901c766d23fe44bc9fbd 100644 (file)
@@ -38,8 +38,7 @@ void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup);
 int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
 void rtw_free_recv_priv(struct recv_priv *precvpriv);
 
-int rtw_os_recv_resource_alloc(struct adapter *adapt,
-                              struct recv_frame *recvfr);
+void rtw_os_recv_resource_alloc(struct recv_frame *recvfr);
 
 int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf);
 
index 42b1f22424eb693b9656bbc57142e713507224c2..f813ce0563f8536d72a8c05e20ab965be0a0fa81 100644 (file)
@@ -107,7 +107,6 @@ struct P2P_PS_CTWPeriod_t {
 /*  host message to firmware cmd */
 void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode);
 void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus);
-u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask);
 void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg,
                           u8 rssi_level);
 
index 7d8e022925e013eb432362f67ea3ff2f441b9104..cbad364f189c865dc4b366417624b807e62d48fe 100644 (file)
@@ -188,15 +188,8 @@ struct txpowerinfo24g {
 
 #define EFUSE_PROTECT_BYTES_BANK       16
 
-/*  For RTL8723 regulator mode. */
-enum rt_regulator_mode {
-       RT_SWITCHING_REGULATOR = 0,
-       RT_LDO_REGULATOR = 1,
-};
-
 struct hal_data_8188e {
        struct HAL_VERSION      VersionID;
-       enum rt_regulator_mode RegulatorMode; /*  switching regulator or LDO */
        u16     CustomerID;
        u8 *pfirmware;
        u32 fwsize;
@@ -301,7 +294,6 @@ struct hal_data_8188e {
        /* for host message to fw */
        u8      LastHMEBoxNum;
 
-       u8      fw_ractrl;
        u8      RegTxPause;
        /*  Beacon function related global variable. */
        u32     RegBcnCtrlVal;
index 8c7e8a36aa13a32dd1205107fab08dd9a87b9cf7..4c992573e3ca9fe630f8ed3caad56a2f0fad4274 100644 (file)
@@ -535,7 +535,8 @@ void rtw_generate_random_ibss(u8 *pibss);
 struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr);
 struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue);
 
-void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue);
+void rtw_free_assoc_resources(struct adapter *adapter);
+void rtw_free_assoc_resources_locked(struct adapter *adapter);
 void rtw_indicate_disconnect(struct adapter *adapter);
 void rtw_indicate_connect(struct adapter *adapter);
 void rtw_indicate_scan_done(struct adapter *padapter, bool aborted);
index 2417809f3aef4a10686a594a9554cc58260b1755..9093a5f94d329a473eaee67069d94961fec72cc4 100644 (file)
@@ -457,9 +457,9 @@ struct mlme_ext_priv {
 int init_mlme_ext_priv(struct adapter *adapter);
 int init_hw_mlme_ext(struct adapter *padapter);
 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext);
-extern void init_mlme_ext_timer(struct adapter *padapter);
-extern void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
-extern struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
+void init_mlme_ext_timer(struct adapter *padapter);
+void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
+struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
 
 unsigned char networktype_to_raid(unsigned char network_type);
 u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int len);
@@ -554,7 +554,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *addr,
                          int cam_idx);
 
 void beacon_timing_control(struct adapter *padapter);
-extern u8 set_tx_beacon_cmd(struct adapter *padapter);
+u8 set_tx_beacon_cmd(struct adapter *padapter);
 unsigned int setup_beacon_frame(struct adapter *padapter,
                                unsigned char *beacon_frame);
 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate);
index aa1fd87c47fba84c561b386f42117176d833ccc0..a493d4c37ef180fc2096167d3b1b451b2b3a77cc 100644 (file)
@@ -257,7 +257,6 @@ s32 LPS_RF_ON_check(struct adapter *adapter, u32 delay_ms);
 void LPS_Enter(struct adapter *adapter);
 void LPS_Leave(struct adapter *adapter);
 
-void rtw_set_ips_deny(struct adapter *adapter, u32 ms);
 int _rtw_pwr_wakeup(struct adapter *adapter, u32 ips_defer_ms,
                    const char *caller);
 #define rtw_pwr_wakeup(adapter)                                                \
index 9612490539b36df39d780f14726dca7ea32ec9c4..d4e78326fc8d6ee1c5f26410e5731169174bf09e 100644 (file)
@@ -113,7 +113,6 @@ struct sta_info {
 
        u8      raid;
        u8      init_rate;
-       u32     ra_mask;
        u8      wireless_mode;  /*  NETWORK_TYPE */
        struct stainfo_stats sta_stats;
 
@@ -351,19 +350,19 @@ static inline u32 wifi_mac_hash(u8 *mac)
        return x;
 }
 
-extern u32     _rtw_init_sta_priv(struct sta_priv *pstapriv);
-extern u32     _rtw_free_sta_priv(struct sta_priv *pstapriv);
+u32 _rtw_init_sta_priv(struct sta_priv *pstapriv);
+u32 _rtw_free_sta_priv(struct sta_priv *pstapriv);
 
 #define stainfo_offset_valid(offset) (offset < NUM_STA && offset >= 0)
 int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta);
 struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int off);
 
-extern struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
-extern u32     rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
-extern void rtw_free_all_stainfo(struct adapter *adapt);
-extern struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
-extern u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
-extern struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
-extern u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
+struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+u32 rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
+void rtw_free_all_stainfo(struct adapter *adapt);
+struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
+struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
+u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
 
 #endif /* _STA_INFO_H_ */
index a08a2e045e594a9f63d7b7d2f8939e4278c5d24c..dba8af1ec41e183c8faf5f6973bc5899a4b2a1e0 100644 (file)
@@ -649,13 +649,6 @@ enum ht_cap_ampdu_factor {
 #define IEEE80211_MAX_AMPDU_BUF 0x40
 
 
-/* Spatial Multiplexing Power Save Modes */
-#define WLAN_HT_CAP_SM_PS_STATIC       0
-#define WLAN_HT_CAP_SM_PS_DYNAMIC      1
-#define WLAN_HT_CAP_SM_PS_INVALID      2
-#define WLAN_HT_CAP_SM_PS_DISABLED     3
-
-
 #define OP_MODE_PURE                    0
 #define OP_MODE_MAY_BE_LEGACY_STAS      1
 #define OP_MODE_20MHZ_HT_STA_ASSOCED    2
index 38dba1435c1ee23948fdfaa415dad8b16deed60e..969574926e21c939defa1e0967a614afeef0421a 100644 (file)
@@ -179,8 +179,8 @@ static char *translate_scan(struct adapter *padapter,
 
        cap = le16_to_cpu(le_tmp);
 
-       if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
-               if (cap & WLAN_CAPABILITY_BSS)
+       if (!WLAN_CAPABILITY_IS_STA_BSS(cap)) {
+               if (cap & WLAN_CAPABILITY_ESS)
                        iwe.u.mode = IW_MODE_MASTER;
                else
                        iwe.u.mode = IW_MODE_ADHOC;
@@ -1871,7 +1871,7 @@ static int rtw_wx_set_auth(struct net_device *dev,
                        rtw_disassoc_cmd(padapter, 500, false);
                        DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
                        rtw_indicate_disconnect(padapter);
-                       rtw_free_assoc_resources(padapter, 1);
+                       rtw_free_assoc_resources(padapter);
                }
                ret = wpa_set_auth_algs(dev, (u32)param->value);
                break;
@@ -2485,16 +2485,13 @@ static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int
 
 static int rtw_hostapd_sta_flush(struct net_device *dev)
 {
-       int ret = 0;
        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
 
        DBG_88E("%s\n", __func__);
 
        flush_all_cam_entry(padapter);  /* clear CAM */
 
-       ret = rtw_sta_flush(padapter);
-
-       return ret;
+       return rtw_sta_flush(padapter);
 }
 
 static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
@@ -2666,7 +2663,8 @@ static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
 
        psta = rtw_get_stainfo(pstapriv, param->sta_addr);
        if (psta) {
-               if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
+               if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+                   psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
                        int wpa_ie_len;
                        int copy_len;
 
@@ -2809,7 +2807,6 @@ static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param,
 
 static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
 {
-       int ret = 0;
        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
@@ -2820,13 +2817,11 @@ static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *p
            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
                return -EINVAL;
-       ret = rtw_acl_remove_sta(padapter, param->sta_addr);
-       return ret;
+       return rtw_acl_remove_sta(padapter, param->sta_addr);
 }
 
 static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
 {
-       int ret = 0;
        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 
@@ -2837,8 +2832,7 @@ static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *para
            param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
            param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
                return -EINVAL;
-       ret = rtw_acl_add_sta(padapter, param->sta_addr);
-       return ret;
+       return rtw_acl_add_sta(padapter, param->sta_addr);
 }
 
 static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
index a14e79f31abf72d3e459cc7381c220201dac4f6d..2361bce480c3fa51b1b9c4d81aaec8047a92e8e7 100644 (file)
@@ -1175,7 +1175,7 @@ static int netdev_close(struct net_device *pnetdev)
                /* s2-2.  indicate disconnect to os */
                rtw_indicate_disconnect(padapter);
                /* s2-3. */
-               rtw_free_assoc_resources(padapter, 1);
+               rtw_free_assoc_resources(padapter);
                /* s2-4. */
                rtw_free_network_queue(padapter, true);
                /*  Close LED */
index 05701328dce408bf63d9827b42f39d998f49095b..3ebb8b206e468ce00cf25a7819b9f72cec8eea7b 100644 (file)
@@ -17,8 +17,6 @@
  *
  *
  ******************************************************************************/
-#define _RECV_OSDEP_C_
-
 #include <osdep_service.h>
 #include <drv_types.h>
 
 #include <usb_ops_linux.h>
 
 /* alloc os related resource in struct recv_frame */
-int rtw_os_recv_resource_alloc(struct adapter *padapter,
-                              struct recv_frame *precvframe)
+void rtw_os_recv_resource_alloc(struct recv_frame *precvframe)
 {
        precvframe->pkt_newalloc = NULL;
        precvframe->pkt = NULL;
-       return _SUCCESS;
 }
 
 /* alloc os related resource in struct recv_buf */
 int rtw_os_recvbuf_resource_alloc(struct adapter *padapter,
                                  struct recv_buf *precvbuf)
 {
-       int res = _SUCCESS;
-
-       precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
-       if (precvbuf->purb == NULL)
-               res = _FAIL;
        precvbuf->pskb = NULL;
        precvbuf->reuse = false;
-       return res;
+       precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!precvbuf->purb)
+               return _FAIL;
+       return _SUCCESS;
 }
 
 void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
index d0d4335b444c3eea93883c944cd361ca9a12a3f9..33bfe054f8677d5d4cc129c9b4111a4d9bf81a72 100644 (file)
@@ -17,8 +17,8 @@
  *
  *
  ******************************************************************************/
-#define _HCI_INTF_C_
 
+#define pr_fmt(fmt) "R8188EU: " fmt
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <recv_osdep.h>
@@ -55,7 +55,6 @@ MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
 static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
 {
        int     i;
-       int     status = _FAIL;
        struct dvobj_priv *pdvobjpriv;
        struct usb_host_config          *phost_conf;
        struct usb_config_descriptor    *pconf_desc;
@@ -64,10 +63,9 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
        struct usb_endpoint_descriptor  *pendp_desc;
        struct usb_device       *pusbd;
 
-
        pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
        if (pdvobjpriv == NULL)
-               goto exit;
+               return NULL;
 
        pdvobjpriv->pusbintf = usb_intf;
        pusbd = interface_to_usbdev(usb_intf);
@@ -115,20 +113,13 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
        mutex_init(&pdvobjpriv->usb_vendor_req_mutex);
        pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL);
 
-       if (!pdvobjpriv->usb_vendor_req_buf)
-               goto free_dvobj;
-
-       usb_get_dev(pusbd);
-
-       status = _SUCCESS;
-
-free_dvobj:
-       if (status != _SUCCESS && pdvobjpriv) {
+       if (!pdvobjpriv->usb_vendor_req_buf) {
                usb_set_intfdata(usb_intf, NULL);
                kfree(pdvobjpriv);
-               pdvobjpriv = NULL;
+               return NULL;
        }
-exit:
+       usb_get_dev(pusbd);
+
        return pdvobjpriv;
 }
 
@@ -136,7 +127,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf)
 {
        struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
 
-
        usb_set_intfdata(usb_intf, NULL);
        if (dvobj) {
                /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
@@ -150,7 +140,7 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf)
                                 * on sitesurvey for the first time when
                                 * device is up . Reset usb port for sitesurvey
                                 * fail issue. */
-                               DBG_88E("usb attached..., try to reset usb device\n");
+                               pr_debug("usb attached..., try to reset usb device\n");
                                usb_reset_device(interface_to_usbdev(usb_intf));
                        }
                }
@@ -201,7 +191,7 @@ static void rtw_dev_unload(struct adapter *padapter)
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
 
        if (padapter->bup) {
-               DBG_88E("===> rtw_dev_unload\n");
+               pr_debug("===> rtw_dev_unload\n");
                padapter->bDriverStopped = true;
                if (padapter->xmitpriv.ack_tx)
                        rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
@@ -224,7 +214,7 @@ static void rtw_dev_unload(struct adapter *padapter)
                         ("r871x_dev_unload():padapter->bup == false\n"));
        }
 
-       DBG_88E("<=== rtw_dev_unload\n");
+       pr_debug("<=== rtw_dev_unload\n");
 
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
 }
@@ -236,16 +226,13 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
        struct net_device *pnetdev = padapter->pnetdev;
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
-       int ret = 0;
        u32 start_time = jiffies;
 
-
-       DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+       pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
 
        if ((!padapter->bup) || (padapter->bDriverStopped) ||
            (padapter->bSurpriseRemoved)) {
-               DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+               pr_debug("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
                        padapter->bup, padapter->bDriverStopped,
                        padapter->bSurpriseRemoved);
                goto exit;
@@ -267,7 +254,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
 
        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
            check_fwstate(pmlmepriv, _FW_LINKED)) {
-               DBG_88E("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
+               pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
                        __func__, __LINE__,
                        pmlmepriv->cur_network.network.Ssid.Ssid,
                        pmlmepriv->cur_network.network.MacAddress,
@@ -279,7 +266,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
        /* s2-2.  indicate disconnect to os */
        rtw_indicate_disconnect(padapter);
        /* s2-3. */
-       rtw_free_assoc_resources(padapter, 1);
+       rtw_free_assoc_resources(padapter);
        /* s2-4. */
        rtw_free_network_queue(padapter, true);
 
@@ -293,10 +280,10 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
                rtw_indicate_disconnect(padapter);
 
 exit:
-       DBG_88E("<===  %s return %d.............. in %dms\n", __func__
-               , ret, rtw_get_passing_time_ms(start_time));
+       pr_debug("<===  %s .............. in %dms\n", __func__,
+                rtw_get_passing_time_ms(start_time));
 
-       return ret;
+       return 0;
 }
 
 static int rtw_resume_process(struct adapter *padapter)
@@ -306,7 +293,7 @@ static int rtw_resume_process(struct adapter *padapter)
        int ret = -1;
        u32 start_time = jiffies;
 
-       DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+       pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
 
        if (padapter) {
                pnetdev = padapter->pnetdev;
@@ -319,7 +306,7 @@ static int rtw_resume_process(struct adapter *padapter)
        rtw_reset_drv_sw(padapter);
        pwrpriv->bkeepfwalive = false;
 
-       DBG_88E("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
+       pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
        if (pm_netdev_open(pnetdev, true) != 0)
                goto exit;
 
@@ -334,10 +321,9 @@ static int rtw_resume_process(struct adapter *padapter)
 exit:
        if (pwrpriv)
                pwrpriv->bInSuspend = false;
-       DBG_88E("<===  %s return %d.............. in %dms\n", __func__,
+       pr_debug("<===  %s return %d.............. in %dms\n", __func__,
                ret, rtw_get_passing_time_ms(start_time));
 
-
        return ret;
 }
 
@@ -407,8 +393,8 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
                dvobj->pusbdev->do_remote_wakeup = 1;
                pusb_intf->needs_remote_wakeup = 1;
                device_init_wakeup(&pusb_intf->dev, 1);
-               DBG_88E("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
-               DBG_88E("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
+               pr_debug("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
+               pr_debug("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
                        device_may_wakeup(&pusb_intf->dev));
        }
 #endif
@@ -416,13 +402,13 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
        /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto
         * suspend influence */
        if (usb_autopm_get_interface(pusb_intf) < 0)
-                       DBG_88E("can't get autopm:\n");
+                       pr_debug("can't get autopm:\n");
 
        /*  alloc dev name after read efuse. */
        rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
        rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
        memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
-       DBG_88E("MAC Address from pnetdev->dev_addr =  %pM\n",
+       pr_debug("MAC Address from pnetdev->dev_addr =  %pM\n",
                pnetdev->dev_addr);
 
        /* step 6. Tell the network stack we exist */
@@ -431,7 +417,7 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
                goto free_hal_data;
        }
 
-       DBG_88E("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
+       pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
                , padapter->bDriverStopped
                , padapter->bSurpriseRemoved
                , padapter->bup
@@ -475,7 +461,7 @@ static void rtw_usb_if1_deinit(struct adapter *if1)
        rtw_cancel_all_timer(if1);
 
        rtw_dev_unload(if1);
-       DBG_88E("+r871xu_dev_remove, hw_init_completed=%d\n",
+       pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n",
                if1->hw_init_completed);
        rtw_free_drv_sw(if1);
        if (pnetdev)
@@ -485,7 +471,6 @@ static void rtw_usb_if1_deinit(struct adapter *if1)
 static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
 {
        struct adapter *if1 = NULL;
-       int status = _FAIL;
        struct dvobj_priv *dvobj;
 
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
@@ -500,19 +485,18 @@ static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device
 
        if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
        if (if1 == NULL) {
-               DBG_88E("rtw_init_primarystruct adapter Failed!\n");
+               pr_debug("rtw_init_primarystruct adapter Failed!\n");
                goto free_dvobj;
        }
 
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-871x_drv - drv_init, success!\n"));
 
-       status = _SUCCESS;
+       return 0;
 
 free_dvobj:
-       if (status != _SUCCESS)
-               usb_dvobj_deinit(pusb_intf);
+       usb_dvobj_deinit(pusb_intf);
 exit:
-       return status == _SUCCESS ? 0 : -ENODEV;
+       return -ENODEV;
 }
 
 /*
@@ -524,8 +508,7 @@ static void rtw_dev_remove(struct usb_interface *pusb_intf)
        struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
        struct adapter *padapter = dvobj->if1;
 
-
-       DBG_88E("+rtw_dev_remove\n");
+       pr_debug("+rtw_dev_remove\n");
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
 
        if (!pusb_intf->unregistering)
@@ -541,7 +524,7 @@ static void rtw_dev_remove(struct usb_interface *pusb_intf)
        usb_dvobj_deinit(pusb_intf);
 
        RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
-       DBG_88E("-r871xu_dev_remove, done\n");
+       pr_debug("-r871xu_dev_remove, done\n");
 }
 
 static struct usb_driver rtl8188e_usb_drv = {
index ef9da863c3357ec33bbb856831334d74ec77f251..fcf9b3bcf76a9dc39069c943be460a389a778b18 100644 (file)
@@ -160,21 +160,6 @@ void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
        pDot11dInfo->State = DOT11D_STATE_LEARNED;
 }
 
-u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel)
-{
-       struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
-       u8 MaxTxPwrInDbm = 255;
-
-       if (MAX_CHANNEL_NUMBER < Channel) {
-               netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
-               return MaxTxPwrInDbm;
-       }
-       if (pDot11dInfo->channel_map[Channel])
-               MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
-
-       return MaxTxPwrInDbm;
-}
-
 void DOT11D_ScanComplete(struct rtllib_device *dev)
 {
        struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
@@ -190,27 +175,3 @@ void DOT11D_ScanComplete(struct rtllib_device *dev)
                break;
        }
 }
-
-int ToLegalChannel(struct rtllib_device *dev, u8 channel)
-{
-       struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
-       u8 default_chn = 0;
-       u32 i;
-
-       for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
-               if (pDot11dInfo->channel_map[i] > 0) {
-                       default_chn = i;
-                       break;
-               }
-       }
-
-       if (MAX_CHANNEL_NUMBER < channel) {
-               netdev_err(dev->dev, "%s(): Invalid Channel\n", __func__);
-               return default_chn;
-       }
-
-       if (pDot11dInfo->channel_map[channel] > 0)
-               return channel;
-
-       return default_chn;
-}
index 69e0f8f7e3f8b3e6a2eeecfd138b493c77306b31..129ebed2e3cc294b96fb79bb6cfb6bd9d58b6486 100644 (file)
@@ -79,7 +79,6 @@ static inline void cpMacAddr(unsigned char *des, unsigned char *src)
 #define UPDATE_CIE_SRC(__pIeeeDev, __pTa)              \
        cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
 
-#define CIE_WATCHDOG_TH 1
 #define GET_CIE_WATCHDOG(__pIeeeDev)                           \
         (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
 static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev)
@@ -88,16 +87,11 @@ static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev)
 }
 #define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
 
-#define IS_DOT11D_STATE_DONE(__pIeeeDev)                       \
-       (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-
 void dot11d_init(struct rtllib_device *dev);
 void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee);
 void Dot11d_Reset(struct rtllib_device *dev);
 void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
                            u16 CoutryIeLen, u8 *pCoutryIe);
-u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel);
 void DOT11D_ScanComplete(struct rtllib_device *dev);
-int ToLegalChannel(struct rtllib_device *dev, u8 channel);
 
 #endif
index d0b08301b88f22bac941a58b40a2b4a00f565e25..dba4584c70067f5b8a4cdaf9bd1e0183987a6b05 100644 (file)
@@ -26,8 +26,6 @@
 #define                MAX_SILENT_RESET_RX_SLOT_NUM    10
 
 #define RX_MPDU_QUEUE                          0
-#define RX_CMD_QUEUE                           1
-
 
 enum rtl819x_loopback {
        RTL819X_NO_LOOPBACK = 0,
@@ -36,11 +34,6 @@ enum rtl819x_loopback {
        RTL819X_CCK_LOOPBACK = 3,
 };
 
-
-#define RESET_DELAY_8185                       20
-
-#define RT_IBSS_INT_MASKS (IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER)
-
 #define DESC90_RATE1M                          0x00
 #define DESC90_RATE2M                          0x01
 #define DESC90_RATE5_5M                                0x02
@@ -74,17 +67,6 @@ enum rtl819x_loopback {
 #define SHORT_SLOT_TIME                                9
 #define NON_SHORT_SLOT_TIME            20
 
-
-#define        MAX_LINES_HWCONFIG_TXT                  1000
-#define MAX_BYTES_LINE_HWCONFIG_TXT            128
-
-#define SW_THREE_WIRE                  0
-#define HW_THREE_WIRE                  2
-
-#define BT_DEMO_BOARD                  0
-#define BT_QA_BOARD                            1
-#define BT_FPGA                                        2
-
 #define        RX_SMOOTH                               20
 
 #define QSLT_BK                                        0x1
@@ -96,25 +78,14 @@ enum rtl819x_loopback {
 #define        QSLT_MGNT                               0x12
 #define        QSLT_CMD                                0x13
 
-#define NUM_OF_FIRMWARE_QUEUE                          10
-#define NUM_OF_PAGES_IN_FW                                     0x100
 #define NUM_OF_PAGE_IN_FW_QUEUE_BK             0x007
 #define NUM_OF_PAGE_IN_FW_QUEUE_BE             0x0aa
 #define NUM_OF_PAGE_IN_FW_QUEUE_VI             0x024
 #define NUM_OF_PAGE_IN_FW_QUEUE_VO             0x007
-#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA           0
-#define NUM_OF_PAGE_IN_FW_QUEUE_CMD            0x2
 #define NUM_OF_PAGE_IN_FW_QUEUE_MGNT           0x10
-#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH           0
 #define NUM_OF_PAGE_IN_FW_QUEUE_BCN            0x4
 #define NUM_OF_PAGE_IN_FW_QUEUE_PUB            0xd
 
-#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026
-#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048
-#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048
-#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026
-#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM        0x00
-
 #define APPLIED_RESERVED_QUEUE_IN_FW           0x80000000
 #define RSVD_FW_QUEUE_PAGE_BK_SHIFT            0x00
 #define RSVD_FW_QUEUE_PAGE_BE_SHIFT            0x08
@@ -197,23 +168,6 @@ struct tx_fwinfo_8190pci {
 
 };
 
-
-#define TX_DESC_SIZE                   32
-
-#define TX_DESC_CMD_SIZE       32
-
-
-#define TX_STATUS_DESC_SIZE    32
-
-#define TX_FWINFO_SIZE 8
-
-
-#define RX_DESC_SIZE   16
-
-#define RX_STATUS_DESC_SIZE    16
-
-#define RX_DRIVER_INFO_SIZE    8
-
 struct log_int_8190 {
        u32     nIMR_COMDOK;
        u32     nIMR_MGNTDOK;
index facc6f1f302bf212f24a8634a47a3987f156c17b..c8f25ade25355c42022de5593df7457cb9b6dc0f 100644 (file)
 #include "r8192E_phy.h"
 #include "r8190P_rtl8256.h"
 
-void PHY_SetRF8256Bandwidth(struct net_device *dev,
-                           enum ht_channel_width Bandwidth)
+void rtl92e_set_bandwidth(struct net_device *dev,
+                         enum ht_channel_width Bandwidth)
 {
        u8      eRFPath;
        struct r8192_priv *priv = rtllib_priv(dev);
 
+       if (priv->card_8192_version != VERSION_8190_BD &&
+           priv->card_8192_version != VERSION_8190_BE) {
+               netdev_warn(dev, "%s(): Unknown HW version.\n", __func__);
+               return;
+       }
+
        for (eRFPath = 0; eRFPath < priv->NumTotalRFPath; eRFPath++) {
-               if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+               if (!rtl92e_is_legal_rf_path(dev, eRFPath))
                                continue;
 
                switch (Bandwidth) {
                case HT_CHANNEL_WIDTH_20:
-                       if (priv->card_8192_version == VERSION_8190_BD ||
-                           priv->card_8192_version == VERSION_8190_BE) {
-                               rtl8192_phy_SetRFReg(dev,
-                                               (enum rf90_radio_path)eRFPath,
-                                               0x0b, bMask12Bits, 0x100);
-                               rtl8192_phy_SetRFReg(dev,
-                                               (enum rf90_radio_path)eRFPath,
-                                               0x2c, bMask12Bits, 0x3d7);
-                               rtl8192_phy_SetRFReg(dev,
-                                               (enum rf90_radio_path)eRFPath,
-                                               0x0e, bMask12Bits, 0x021);
-
-                       } else {
-                               netdev_warn(dev, "%s(): Unknown HW version.\n",
-                                           __func__);
-                       }
-
+                       rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+                                         0x0b, bMask12Bits, 0x100);
+                       rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+                                         0x2c, bMask12Bits, 0x3d7);
+                       rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+                                         0x0e, bMask12Bits, 0x021);
                        break;
                case HT_CHANNEL_WIDTH_20_40:
-                       if (priv->card_8192_version == VERSION_8190_BD ||
-                           priv->card_8192_version == VERSION_8190_BE) {
-                               rtl8192_phy_SetRFReg(dev,
-                                                (enum rf90_radio_path)eRFPath,
-                                                0x0b, bMask12Bits, 0x300);
-                               rtl8192_phy_SetRFReg(dev,
-                                                (enum rf90_radio_path)eRFPath,
-                                                0x2c, bMask12Bits, 0x3ff);
-                               rtl8192_phy_SetRFReg(dev,
-                                                (enum rf90_radio_path)eRFPath,
-                                                0x0e, bMask12Bits, 0x0e1);
-
-                       } else {
-                               netdev_warn(dev, "%s(): Unknown HW version.\n",
-                                           __func__);
-                       }
-
-
+                       rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+                                         0x0b, bMask12Bits, 0x300);
+                       rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+                                         0x2c, bMask12Bits, 0x3ff);
+                       rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+                                         0x0e, bMask12Bits, 0x0e1);
                        break;
                default:
                        netdev_err(dev, "%s(): Unknown bandwidth: %#X\n",
@@ -81,15 +64,7 @@ void PHY_SetRF8256Bandwidth(struct net_device *dev,
        }
 }
 
-bool PHY_RF8256_Config(struct net_device *dev)
-{
-       struct r8192_priv *priv = rtllib_priv(dev);
-
-       priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
-       return phy_RF8256_Config_ParaFile(dev);
-}
-
-bool phy_RF8256_Config_ParaFile(struct net_device *dev)
+bool rtl92e_config_rf(struct net_device *dev)
 {
        u32     u4RegValue = 0;
        u8      eRFPath;
@@ -102,9 +77,11 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
        u8      ConstRetryTimes = 5, RetryTimes = 5;
        u8 ret = 0;
 
+       priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
+
        for (eRFPath = (enum rf90_radio_path)RF90_PATH_A;
             eRFPath < priv->NumTotalRFPath; eRFPath++) {
-               if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+               if (!rtl92e_is_legal_rf_path(dev, eRFPath))
                                continue;
 
                pPhyReg = &priv->PHYRegDef[eRFPath];
@@ -113,114 +90,63 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
                switch (eRFPath) {
                case RF90_PATH_A:
                case RF90_PATH_C:
-                       u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs,
-                                                       bRFSI_RFENV);
+                       u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs,
+                                                      bRFSI_RFENV);
                        break;
                case RF90_PATH_B:
                case RF90_PATH_D:
-                       u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs,
-                                                       bRFSI_RFENV<<16);
+                       u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs,
+                                                      bRFSI_RFENV<<16);
                        break;
                }
 
-               rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
+               rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
 
-               rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+               rtl92e_set_bb_reg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
 
-               rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,
-                                b3WireAddressLength, 0x0);
-               rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,
-                                b3WireDataLength, 0x0);
+               rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2,
+                                 b3WireAddressLength, 0x0);
+               rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2,
+                                 b3WireDataLength, 0x0);
 
-               rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path) eRFPath, 0x0,
-                                    bMask12Bits, 0xbf);
+               rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, 0x0,
+                                 bMask12Bits, 0xbf);
 
-               rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF,
-                                               (enum rf90_radio_path)eRFPath);
+               rtStatus = rtl92e_check_bb_and_rf(dev, HW90_BLOCK_RF,
+                                                 (enum rf90_radio_path)eRFPath);
                if (!rtStatus) {
                        netdev_err(dev, "%s(): Failed to check RF Path %d.\n",
                                   __func__, eRFPath);
-                       goto phy_RF8256_Config_ParaFile_Fail;
+                       goto fail;
                }
 
                RetryTimes = ConstRetryTimes;
                RF3_Final_Value = 0;
-               switch (eRFPath) {
-               case RF90_PATH_A:
-                       while (RF3_Final_Value != RegValueToBeCheck &&
-                              RetryTimes != 0) {
-                               ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
-                                               (enum rf90_radio_path)eRFPath);
-                               RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
-                                                (enum rf90_radio_path)eRFPath,
-                                                RegOffSetToBeCheck,
-                                                bMask12Bits);
-                               RT_TRACE(COMP_RF,
-                                        "RF %d %d register final value: %x\n",
-                                        eRFPath, RegOffSetToBeCheck,
-                                        RF3_Final_Value);
-                               RetryTimes--;
-                       }
-                       break;
-               case RF90_PATH_B:
-                       while (RF3_Final_Value != RegValueToBeCheck &&
-                              RetryTimes != 0) {
-                               ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
-                                               (enum rf90_radio_path)eRFPath);
-                               RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
-                                                (enum rf90_radio_path)eRFPath,
-                                                RegOffSetToBeCheck,
-                                                bMask12Bits);
-                               RT_TRACE(COMP_RF,
-                                        "RF %d %d register final value: %x\n",
-                                        eRFPath, RegOffSetToBeCheck,
-                                        RF3_Final_Value);
-                               RetryTimes--;
-                       }
-                       break;
-               case RF90_PATH_C:
-                       while (RF3_Final_Value != RegValueToBeCheck &&
-                              RetryTimes != 0) {
-                               ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
+               while (RF3_Final_Value != RegValueToBeCheck &&
+                      RetryTimes != 0) {
+                       ret = rtl92e_config_rf_path(dev,
                                                (enum rf90_radio_path)eRFPath);
-                               RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
+                       RF3_Final_Value = rtl92e_get_rf_reg(dev,
                                                (enum rf90_radio_path)eRFPath,
                                                RegOffSetToBeCheck,
                                                bMask12Bits);
-                               RT_TRACE(COMP_RF,
-                                        "RF %d %d register final value: %x\n",
-                                        eRFPath, RegOffSetToBeCheck,
-                                        RF3_Final_Value);
-                               RetryTimes--;
-                       }
-                       break;
-               case RF90_PATH_D:
-                       while (RF3_Final_Value != RegValueToBeCheck &&
-                              RetryTimes != 0) {
-                               ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
-                                              (enum rf90_radio_path)eRFPath);
-                               RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
-                                              (enum rf90_radio_path)eRFPath,
-                                              RegOffSetToBeCheck, bMask12Bits);
-                               RT_TRACE(COMP_RF,
-                                        "RF %d %d register final value: %x\n",
-                                        eRFPath, RegOffSetToBeCheck,
-                                        RF3_Final_Value);
-                               RetryTimes--;
-                       }
-                       break;
+                       RT_TRACE(COMP_RF,
+                                "RF %d %d register final value: %x\n",
+                                eRFPath, RegOffSetToBeCheck,
+                                RF3_Final_Value);
+                       RetryTimes--;
                }
 
                switch (eRFPath) {
                case RF90_PATH_A:
                case RF90_PATH_C:
-                       rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV,
-                                        u4RegValue);
+                       rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, bRFSI_RFENV,
+                                         u4RegValue);
                        break;
                case RF90_PATH_B:
                case RF90_PATH_D:
-                       rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16,
-                                        u4RegValue);
+                       rtl92e_set_bb_reg(dev, pPhyReg->rfintfs,
+                                         bRFSI_RFENV<<16, u4RegValue);
                        break;
                }
 
@@ -228,7 +154,7 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
                        netdev_err(dev,
                                   "%s(): Failed to initialize RF Path %d.\n",
                                   __func__, eRFPath);
-                       goto phy_RF8256_Config_ParaFile_Fail;
+                       goto fail;
                }
 
        }
@@ -236,11 +162,11 @@ bool phy_RF8256_Config_ParaFile(struct net_device *dev)
        RT_TRACE(COMP_PHY, "PHY Initialization Success\n");
        return true;
 
-phy_RF8256_Config_ParaFile_Fail:
+fail:
        return false;
 }
 
-void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8        powerlevel)
+void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel)
 {
        u32     TxAGC = 0;
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -254,11 +180,11 @@ void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8   powerlevel)
        }
        if (TxAGC > 0x24)
                TxAGC = 0x24;
-       rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
+       rtl92e_set_bb_reg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
 }
 
 
-void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel)
+void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
@@ -300,7 +226,7 @@ void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel)
                else
                        writeVal = (byte3 << 24) | (byte2 << 16) |
                                   (byte1 << 8) | byte0;
-               rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+               rtl92e_set_bb_reg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
        }
 
 }
index 64e831d2f4e565b89a90e3ed529b6c1da268d5ac..3e4363f417286f24f37e13b4be160cd080c6a695 100644 (file)
 #define RTL8225H
 
 #define RTL819X_TOTAL_RF_PATH 2
-extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
-                                  enum ht_channel_width Bandwidth);
-extern bool PHY_RF8256_Config(struct net_device *dev);
-extern bool phy_RF8256_Config_ParaFile(struct net_device *dev);
-extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
-extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+void rtl92e_set_bandwidth(struct net_device *dev,
+                         enum ht_channel_width Bandwidth);
+bool rtl92e_config_rf(struct net_device *dev);
+void rtl92e_set_cck_tx_power(struct net_device *dev, u8        powerlevel);
+void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel);
 
 #endif
index ebd08a16685ecd7eefb67c5bd924dfcf0599c582..9ddabf59784c5c6809b2ea3e3a7ad3b26907aad6 100644 (file)
 #include "r8192E_hw.h"
 #include "r8192E_cmdpkt.h"
 
-bool cmpk_message_handle_tx(
-       struct net_device *dev,
-       u8      *code_virtual_address,
-       u32     packettype,
-       u32     buffer_len)
+bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *code_virtual_address,
+                        u32 packettype, u32 buffer_len)
 {
 
        bool                            rt_status = true;
@@ -41,7 +38,7 @@ bool cmpk_message_handle_tx(
        struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
 
        RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len);
-       firmware_init_param(dev);
+       rtl92e_init_fw_param(dev);
        frag_threshold = pfirmware->cmdpacket_frag_thresold;
 
        do {
@@ -84,7 +81,7 @@ bool cmpk_message_handle_tx(
 
        } while (frag_offset < buffer_len);
 
-       write_nic_byte(dev, TPPoll, TPPoll_CQ);
+       rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
 Failed:
        return rt_status;
 }
index f714d5100059ab3d841a59b4f242a725cba21afd..2a8b165cb8e16518119d1878ba9babd83f286aaf 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef R819XUSB_CMDPKT_H
 #define R819XUSB_CMDPKT_H
 
-extern bool cmpk_message_handle_tx(struct net_device *dev,
-                                  u8 *codevirtualaddress, u32 packettype,
-                                  u32 buffer_len);
+bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *codevirtualaddress,
+                        u32 packettype, u32 buffer_len);
 #endif
index f6661bbae7a8150e197fd685c350f9b518fc6e3e..c28cabc23fc05b6e25cb5b506a2238611c401277 100644 (file)
@@ -33,7 +33,7 @@
 static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI,
                             EDCAPARA_VO};
 
-void rtl8192e_start_beacon(struct net_device *dev)
+void rtl92e_start_beacon(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
        struct rtllib_network *net = &priv->rtllib->current_network;
@@ -41,21 +41,20 @@ void rtl8192e_start_beacon(struct net_device *dev)
        u16 BcnCW = 6;
        u16 BcnIFS = 0xf;
 
-       DMESG("Enabling beacon TX");
-       rtl8192_irq_disable(dev);
+       rtl92e_irq_disable(dev);
 
-       write_nic_word(dev, ATIMWND, 2);
+       rtl92e_writew(dev, ATIMWND, 2);
 
-       write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
-       write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
-       write_nic_word(dev, BCN_DMATIME, 256);
+       rtl92e_writew(dev, BCN_INTERVAL, net->beacon_interval);
+       rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10);
+       rtl92e_writew(dev, BCN_DMATIME, 256);
 
-       write_nic_byte(dev, BCN_ERR_THRESH, 100);
+       rtl92e_writeb(dev, BCN_ERR_THRESH, 100);
 
        BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
        BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
-       write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
-       rtl8192_irq_enable(dev);
+       rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg);
+       rtl92e_irq_enable(dev);
 }
 
 static void rtl8192e_update_msr(struct net_device *dev)
@@ -64,7 +63,7 @@ static void rtl8192e_update_msr(struct net_device *dev)
        u8 msr;
        enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
 
-       msr  = read_nic_byte(dev, MSR);
+       msr  = rtl92e_readb(dev, MSR);
        msr &= ~MSR_LINK_MASK;
 
        switch (priv->rtllib->iw_mode) {
@@ -91,26 +90,26 @@ static void rtl8192e_update_msr(struct net_device *dev)
                break;
        }
 
-       write_nic_byte(dev, MSR, msr);
+       rtl92e_writeb(dev, MSR, msr);
        if (priv->rtllib->LedControlHandler)
                priv->rtllib->LedControlHandler(dev, LedAction);
 }
 
-void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
+void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
        switch (variable) {
        case HW_VAR_BSSID:
-               write_nic_dword(dev, BSSIDR, ((u32 *)(val))[0]);
-               write_nic_word(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
+               rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]);
+               rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
                break;
 
        case HW_VAR_MEDIA_STATUS:
        {
                enum rt_op_mode OpMode = *((enum rt_op_mode *)(val));
                enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
-               u8              btMsr = read_nic_byte(dev, MSR);
+               u8 btMsr = rtl92e_readb(dev, MSR);
 
                btMsr &= 0xfc;
 
@@ -134,7 +133,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                        break;
                }
 
-               write_nic_byte(dev, MSR, btMsr);
+               rtl92e_writeb(dev, MSR, btMsr);
 
        }
        break;
@@ -144,7 +143,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                u32     RegRCR, Type;
 
                Type = ((u8 *)(val))[0];
-               RegRCR = read_nic_dword(dev, RCR);
+               RegRCR = rtl92e_readl(dev, RCR);
                priv->ReceiveConfig = RegRCR;
 
                if (Type == true)
@@ -152,7 +151,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                else if (Type == false)
                        RegRCR &= (~RCR_CBSSID);
 
-               write_nic_dword(dev, RCR, RegRCR);
+               rtl92e_writel(dev, RCR, RegRCR);
                priv->ReceiveConfig = RegRCR;
 
        }
@@ -161,7 +160,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
        case HW_VAR_SLOT_TIME:
 
                priv->slot_time = val[0];
-               write_nic_byte(dev, SLOT_TIME, val[0]);
+               rtl92e_writeb(dev, SLOT_TIME, val[0]);
 
                break;
 
@@ -173,12 +172,12 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                regTmp = priv->basic_rate;
                if (priv->short_preamble)
                        regTmp |= BRSR_AckShortPmb;
-               write_nic_dword(dev, RRSR, regTmp);
+               rtl92e_writel(dev, RRSR, regTmp);
                break;
        }
 
        case HW_VAR_CPU_RST:
-               write_nic_dword(dev, CPU_GEN, ((u32 *)(val))[0]);
+               rtl92e_writel(dev, CPU_GEN, ((u32 *)(val))[0]);
                break;
 
        case HW_VAR_AC_PARAM:
@@ -194,7 +193,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                u1bAIFS = qop->aifs[pAcParam] *
                          ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
 
-               dm_init_edca_turbo(dev);
+               rtl92e_dm_init_edca_turbo(dev);
 
                u4bAcParam = (le16_to_cpu(qop->tx_op_limit[pAcParam]) <<
                              AC_PARAM_TXOP_LIMIT_OFFSET) |
@@ -208,19 +207,19 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                         __func__, eACI, u4bAcParam);
                switch (eACI) {
                case AC1_BK:
-                       write_nic_dword(dev, EDCAPARA_BK, u4bAcParam);
+                       rtl92e_writel(dev, EDCAPARA_BK, u4bAcParam);
                        break;
 
                case AC0_BE:
-                       write_nic_dword(dev, EDCAPARA_BE, u4bAcParam);
+                       rtl92e_writel(dev, EDCAPARA_BE, u4bAcParam);
                        break;
 
                case AC2_VI:
-                       write_nic_dword(dev, EDCAPARA_VI, u4bAcParam);
+                       rtl92e_writel(dev, EDCAPARA_VI, u4bAcParam);
                        break;
 
                case AC3_VO:
-                       write_nic_dword(dev, EDCAPARA_VO, u4bAcParam);
+                       rtl92e_writel(dev, EDCAPARA_VO, u4bAcParam);
                        break;
 
                default:
@@ -242,7 +241,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                union aci_aifsn *pAciAifsn = (union aci_aifsn *) &
                                              (qos_parameters->aifs[0]);
                u8 acm = pAciAifsn->f.acm;
-               u8 AcmCtrl = read_nic_byte(dev, AcmHwCtrl);
+               u8 AcmCtrl = rtl92e_readb(dev, AcmHwCtrl);
 
                RT_TRACE(COMP_DBG, "===========>%s():HW_VAR_ACM_CTRL:%x\n",
                         __func__, eACI);
@@ -290,20 +289,20 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
                RT_TRACE(COMP_QOS,
                         "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
                         AcmCtrl);
-               write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
+               rtl92e_writeb(dev, AcmHwCtrl, AcmCtrl);
                break;
        }
 
        case HW_VAR_SIFS:
-               write_nic_byte(dev, SIFS, val[0]);
-               write_nic_byte(dev, SIFS+1, val[0]);
+               rtl92e_writeb(dev, SIFS, val[0]);
+               rtl92e_writeb(dev, SIFS+1, val[0]);
                break;
 
        case HW_VAR_RF_TIMING:
        {
                u8 Rf_Timing = *((u8 *)val);
 
-               write_nic_byte(dev, rFPGA0_RFTiming1, Rf_Timing);
+               rtl92e_writeb(dev, rFPGA0_RFTiming1, Rf_Timing);
                break;
        }
 
@@ -324,7 +323,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
 
        RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n");
 
-       EEPROMId = eprom_read(dev, 0);
+       EEPROMId = rtl92e_eeprom_read(dev, 0);
        if (EEPROMId != RTL8190_EEPROM_ID) {
                netdev_err(dev, "%s(): Invalid EEPROM ID: %x\n", __func__,
                           EEPROMId);
@@ -334,12 +333,14 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
        }
 
        if (!priv->AutoloadFailFlag) {
-               priv->eeprom_vid = eprom_read(dev, EEPROM_VID >> 1);
-               priv->eeprom_did = eprom_read(dev, EEPROM_DID >> 1);
+               priv->eeprom_vid = rtl92e_eeprom_read(dev, EEPROM_VID >> 1);
+               priv->eeprom_did = rtl92e_eeprom_read(dev, EEPROM_DID >> 1);
 
-               usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8;
+               usValue = rtl92e_eeprom_read(dev,
+                                            (u16)(EEPROM_Customer_ID>>1)) >> 8;
                priv->eeprom_CustomerID = (u8)(usValue & 0xff);
-               usValue = eprom_read(dev, EEPROM_ICVersion_ChannelPlan>>1);
+               usValue = rtl92e_eeprom_read(dev,
+                                            EEPROM_ICVersion_ChannelPlan>>1);
                priv->eeprom_ChannelPlan = usValue&0xff;
                IC_Version = (usValue & 0xff00)>>8;
 
@@ -377,7 +378,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
 
        if (!priv->AutoloadFailFlag) {
                for (i = 0; i < 6; i += 2) {
-                       usValue = eprom_read(dev,
+                       usValue = rtl92e_eeprom_read(dev,
                                 (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i) >> 1));
                        *(u16 *)(&dev->dev_addr[i]) = usValue;
                }
@@ -397,8 +398,8 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
 
        if (priv->card_8192_version > VERSION_8190_BD) {
                if (!priv->AutoloadFailFlag) {
-                       tempval = (eprom_read(dev, (EEPROM_RFInd_PowerDiff >>
-                                             1))) & 0xff;
+                       tempval = (rtl92e_eeprom_read(dev,
+                                                     (EEPROM_RFInd_PowerDiff >> 1))) & 0xff;
                        priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf;
 
                        if (tempval&0x80)
@@ -412,7 +413,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                        priv->EEPROMLegacyHTTxPowerDiff);
 
                if (!priv->AutoloadFailFlag)
-                       priv->EEPROMThermalMeter = (u8)(((eprom_read(dev,
+                       priv->EEPROMThermalMeter = (u8)(((rtl92e_eeprom_read(dev,
                                                   (EEPROM_ThermalMeter>>1))) &
                                                   0xff00)>>8);
                else
@@ -423,7 +424,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
 
                if (priv->epromtype == EEPROM_93C46) {
                        if (!priv->AutoloadFailFlag) {
-                               usValue = eprom_read(dev,
+                               usValue = rtl92e_eeprom_read(dev,
                                          EEPROM_TxPwDiff_CrystalCap >> 1);
                                priv->EEPROMAntPwDiff = (usValue&0x0fff);
                                priv->EEPROMCrystalCap = (u8)((usValue & 0xf000)
@@ -441,7 +442,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
 
                        for (i = 0; i < 14; i += 2) {
                                if (!priv->AutoloadFailFlag)
-                                       usValue = eprom_read(dev,
+                                       usValue = rtl92e_eeprom_read(dev,
                                                  (u16)((EEPROM_TxPwIndex_CCK +
                                                  i) >> 1));
                                else
@@ -457,7 +458,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                        }
                        for (i = 0; i < 14; i += 2) {
                                if (!priv->AutoloadFailFlag)
-                                       usValue = eprom_read(dev,
+                                       usValue = rtl92e_eeprom_read(dev,
                                                (u16)((EEPROM_TxPwIndex_OFDM_24G
                                                + i) >> 1));
                                else
@@ -561,7 +562,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
                RT_TRACE(COMP_INIT, "\n2T4R config\n");
        }
 
-       init_rate_adaptive(dev);
+       rtl92e_init_adaptive_rate(dev);
 
        priv->rf_chip = RF_8256;
 
@@ -626,13 +627,13 @@ static void rtl8192_read_eeprom_info(struct net_device *dev)
        RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n");
 }
 
-void rtl8192_get_eeprom_size(struct net_device *dev)
+void rtl92e_get_eeprom_size(struct net_device *dev)
 {
        u16 curCR;
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
-       curCR = read_nic_dword(dev, EPROM_CMD);
+       curCR = rtl92e_readl(dev, EPROM_CMD);
        RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
                 curCR);
        priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
@@ -684,26 +685,26 @@ static void rtl8192_hwconfig(struct net_device *dev)
                break;
        }
 
-       write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+       rtl92e_writeb(dev, BW_OPMODE, regBwOpMode);
        {
                u32 ratr_value = 0;
 
                ratr_value = regRATR;
                if (priv->rf_type == RF_1T2R)
                        ratr_value &= ~(RATE_ALL_OFDM_2SS);
-               write_nic_dword(dev, RATR0, ratr_value);
-               write_nic_byte(dev, UFWP, 1);
+               rtl92e_writel(dev, RATR0, ratr_value);
+               rtl92e_writeb(dev, UFWP, 1);
        }
-       regTmp = read_nic_byte(dev, 0x313);
+       regTmp = rtl92e_readb(dev, 0x313);
        regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
-       write_nic_dword(dev, RRSR, regRRSR);
+       rtl92e_writel(dev, RRSR, regRRSR);
 
-       write_nic_word(dev, RETRY_LIMIT,
-                       priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
-                       priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
+       rtl92e_writew(dev, RETRY_LIMIT,
+                     priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
+                     priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
 }
 
-bool rtl8192_adapter_start(struct net_device *dev)
+bool rtl92e_start_adapter(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u32 ulRegRead;
@@ -719,10 +720,10 @@ bool rtl8192_adapter_start(struct net_device *dev)
        priv->being_init_adapter = true;
 
 start:
-       rtl8192_pci_resetdescring(dev);
+       rtl92e_reset_desc_ring(dev);
        priv->Rf_Mode = RF_OP_By_SW_3wire;
        if (priv->ResetProgress == RESET_TYPE_NORESET) {
-               write_nic_byte(dev, ANAPAR, 0x37);
+               rtl92e_writeb(dev, ANAPAR, 0x37);
                mdelay(500);
        }
        priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
@@ -730,7 +731,7 @@ start:
        if (priv->RegRfOff)
                priv->rtllib->eRFPowerState = eRfOff;
 
-       ulRegRead = read_nic_dword(dev, CPU_GEN);
+       ulRegRead = rtl92e_readl(dev, CPU_GEN);
        if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
                ulRegRead |= CPU_GEN_SYSTEM_RESET;
        else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
@@ -739,19 +740,19 @@ start:
                netdev_err(dev, "%s(): undefined firmware state: %d.\n",
                           __func__, priv->pFirmware->firmware_status);
 
-       write_nic_dword(dev, CPU_GEN, ulRegRead);
+       rtl92e_writel(dev, CPU_GEN, ulRegRead);
 
-       ICVersion = read_nic_byte(dev, IC_VERRSION);
+       ICVersion = rtl92e_readb(dev, IC_VERRSION);
        if (ICVersion >= 0x4) {
-               SwitchingRegulatorOutput = read_nic_byte(dev, SWREGULATOR);
+               SwitchingRegulatorOutput = rtl92e_readb(dev, SWREGULATOR);
                if (SwitchingRegulatorOutput  != 0xb8) {
-                       write_nic_byte(dev, SWREGULATOR, 0xa8);
+                       rtl92e_writeb(dev, SWREGULATOR, 0xa8);
                        mdelay(1);
-                       write_nic_byte(dev, SWREGULATOR, 0xb8);
+                       rtl92e_writeb(dev, SWREGULATOR, 0xb8);
                }
        }
        RT_TRACE(COMP_INIT, "BB Config Start!\n");
-       rtStatus = rtl8192_BBConfig(dev);
+       rtStatus = rtl92e_config_bb(dev);
        if (!rtStatus) {
                netdev_warn(dev, "%s(): Failed to configure BB\n", __func__);
                return rtStatus;
@@ -760,7 +761,7 @@ start:
 
        priv->LoopbackMode = RTL819X_NO_LOOPBACK;
        if (priv->ResetProgress == RESET_TYPE_NORESET) {
-               ulRegRead = read_nic_dword(dev, CPU_GEN);
+               ulRegRead = rtl92e_readl(dev, CPU_GEN);
                if (priv->LoopbackMode == RTL819X_NO_LOOPBACK)
                        ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) |
                                     CPU_GEN_NO_LOOPBACK_SET);
@@ -770,73 +771,73 @@ start:
                        netdev_err(dev, "%s: Invalid loopback mode setting.\n",
                                   __func__);
 
-               write_nic_dword(dev, CPU_GEN, ulRegRead);
+               rtl92e_writel(dev, CPU_GEN, ulRegRead);
 
                udelay(500);
        }
        rtl8192_hwconfig(dev);
-       write_nic_byte(dev, CMDR, CR_RE | CR_TE);
-
-       write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
-                      (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT)));
-       write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
-       write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
-       write_nic_dword(dev, RCR, priv->ReceiveConfig);
-
-       write_nic_dword(dev, RQPN1,  NUM_OF_PAGE_IN_FW_QUEUE_BK <<
-                       RSVD_FW_QUEUE_PAGE_BK_SHIFT |
-                       NUM_OF_PAGE_IN_FW_QUEUE_BE <<
-                       RSVD_FW_QUEUE_PAGE_BE_SHIFT |
-                       NUM_OF_PAGE_IN_FW_QUEUE_VI <<
-                       RSVD_FW_QUEUE_PAGE_VI_SHIFT |
-                       NUM_OF_PAGE_IN_FW_QUEUE_VO <<
-                       RSVD_FW_QUEUE_PAGE_VO_SHIFT);
-       write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT <<
-                       RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
-       write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW |
-                       NUM_OF_PAGE_IN_FW_QUEUE_BCN <<
-                       RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
-                       NUM_OF_PAGE_IN_FW_QUEUE_PUB <<
-                       RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
-
-       rtl8192_tx_enable(dev);
-       rtl8192_rx_enable(dev);
-       ulRegRead = (0xFFF00000 & read_nic_dword(dev, RRSR))  |
+       rtl92e_writeb(dev, CMDR, CR_RE | CR_TE);
+
+       rtl92e_writeb(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
+                                 (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT)));
+       rtl92e_writel(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
+       rtl92e_writew(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
+       rtl92e_writel(dev, RCR, priv->ReceiveConfig);
+
+       rtl92e_writel(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK <<
+                     RSVD_FW_QUEUE_PAGE_BK_SHIFT |
+                     NUM_OF_PAGE_IN_FW_QUEUE_BE <<
+                     RSVD_FW_QUEUE_PAGE_BE_SHIFT |
+                     NUM_OF_PAGE_IN_FW_QUEUE_VI <<
+                     RSVD_FW_QUEUE_PAGE_VI_SHIFT |
+                     NUM_OF_PAGE_IN_FW_QUEUE_VO <<
+                     RSVD_FW_QUEUE_PAGE_VO_SHIFT);
+       rtl92e_writel(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT <<
+                     RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
+       rtl92e_writel(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW |
+                     NUM_OF_PAGE_IN_FW_QUEUE_BCN <<
+                     RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
+                     NUM_OF_PAGE_IN_FW_QUEUE_PUB <<
+                     RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
+
+       rtl92e_tx_enable(dev);
+       rtl92e_rx_enable(dev);
+       ulRegRead = (0xFFF00000 & rtl92e_readl(dev, RRSR))  |
                     RATE_ALL_OFDM_AG | RATE_ALL_CCK;
-       write_nic_dword(dev, RRSR, ulRegRead);
-       write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
+       rtl92e_writel(dev, RRSR, ulRegRead);
+       rtl92e_writel(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
 
-       write_nic_byte(dev, ACK_TIMEOUT, 0x30);
+       rtl92e_writeb(dev, ACK_TIMEOUT, 0x30);
 
        if (priv->ResetProgress == RESET_TYPE_NORESET)
-               rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
-       CamResetAllEntry(dev);
+               rtl92e_set_wireless_mode(dev, priv->rtllib->mode);
+       rtl92e_cam_reset(dev);
        {
                u8 SECR_value = 0x0;
 
                SECR_value |= SCR_TxEncEnable;
                SECR_value |= SCR_RxDecEnable;
                SECR_value |= SCR_NoSKMC;
-               write_nic_byte(dev, SECR, SECR_value);
+               rtl92e_writeb(dev, SECR, SECR_value);
        }
-       write_nic_word(dev, ATIMWND, 2);
-       write_nic_word(dev, BCN_INTERVAL, 100);
+       rtl92e_writew(dev, ATIMWND, 2);
+       rtl92e_writew(dev, BCN_INTERVAL, 100);
        {
                int i;
 
                for (i = 0; i < QOS_QUEUE_NUM; i++)
-                       write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
+                       rtl92e_writel(dev, WDCAPARA_ADD[i], 0x005e4332);
        }
-       write_nic_byte(dev, 0xbe, 0xc0);
+       rtl92e_writeb(dev, 0xbe, 0xc0);
 
-       rtl8192_phy_configmac(dev);
+       rtl92e_config_mac(dev);
 
        if (priv->card_8192_version > (u8) VERSION_8190_BD) {
-               rtl8192_phy_getTxPower(dev);
-               rtl8192_phy_setTxPower(dev, priv->chan);
+               rtl92e_get_tx_power(dev);
+               rtl92e_set_tx_power(dev, priv->chan);
        }
 
-       tmpvalue = read_nic_byte(dev, IC_VERRSION);
+       tmpvalue = rtl92e_readb(dev, IC_VERRSION);
        priv->IC_Cut = tmpvalue;
        RT_TRACE(COMP_INIT, "priv->IC_Cut= 0x%x\n", priv->IC_Cut);
        if (priv->IC_Cut >= IC_VersionCut_D) {
@@ -851,7 +852,7 @@ start:
        }
 
        RT_TRACE(COMP_INIT, "Load Firmware!\n");
-       bfirmwareok = init_firmware(dev);
+       bfirmwareok = rtl92e_init_fw(dev);
        if (!bfirmwareok) {
                if (retry_times < 10) {
                        retry_times++;
@@ -864,37 +865,34 @@ start:
        RT_TRACE(COMP_INIT, "Load Firmware finished!\n");
        if (priv->ResetProgress == RESET_TYPE_NORESET) {
                RT_TRACE(COMP_INIT, "RF Config Started!\n");
-               rtStatus = rtl8192_phy_RFConfig(dev);
+               rtStatus = rtl92e_config_phy(dev);
                if (!rtStatus) {
                        netdev_info(dev, "RF Config failed\n");
                        return rtStatus;
                }
                RT_TRACE(COMP_INIT, "RF Config Finished!\n");
        }
-       rtl8192_phy_updateInitGain(dev);
 
-       rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
-       rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
+       rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
+       rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
 
-       write_nic_byte(dev, 0x87, 0x0);
+       rtl92e_writeb(dev, 0x87, 0x0);
 
        if (priv->RegRfOff) {
                RT_TRACE((COMP_INIT | COMP_RF | COMP_POWER),
                          "%s(): Turn off RF for RegRfOff ----------\n",
                          __func__);
-               MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW, true);
+               rtl92e_set_rf_state(dev, eRfOff, RF_CHANGE_BY_SW);
        } else if (priv->rtllib->RfOffReason > RF_CHANGE_BY_PS) {
                RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER),
                         "%s(): Turn off RF for RfOffReason(%d) ----------\n",
                         __func__, priv->rtllib->RfOffReason);
-               MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason,
-                                   true);
+               rtl92e_set_rf_state(dev, eRfOff, priv->rtllib->RfOffReason);
        } else if (priv->rtllib->RfOffReason >= RF_CHANGE_BY_IPS) {
                RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER),
                         "%s(): Turn off RF for RfOffReason(%d) ----------\n",
                         __func__, priv->rtllib->RfOffReason);
-               MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason,
-                                   true);
+               rtl92e_set_rf_state(dev, eRfOff, priv->rtllib->RfOffReason);
        } else {
                RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON\n",
                          __func__);
@@ -908,13 +906,13 @@ start:
                priv->Rf_Mode = RF_OP_By_SW_3wire;
 
        if (priv->ResetProgress == RESET_TYPE_NORESET) {
-               dm_initialize_txpower_tracking(dev);
+               rtl92e_dm_init_txpower_tracking(dev);
 
                if (priv->IC_Cut >= IC_VersionCut_D) {
-                       tmpRegA = rtl8192_QueryBBReg(dev,
-                                 rOFDM0_XATxIQImbalance, bMaskDWord);
-                       tmpRegC = rtl8192_QueryBBReg(dev,
-                                 rOFDM0_XCTxIQImbalance, bMaskDWord);
+                       tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                                   bMaskDWord);
+                       tmpRegC = rtl92e_get_bb_reg(dev, rOFDM0_XCTxIQImbalance,
+                                                   bMaskDWord);
                        for (i = 0; i < TxBBGainTableLength; i++) {
                                if (tmpRegA == dm_tx_bb_gain[i]) {
                                        priv->rfa_txpowertrackingindex = (u8)i;
@@ -926,8 +924,8 @@ start:
                                }
                        }
 
-                       TempCCk = rtl8192_QueryBBReg(dev,
-                                 rCCK0_TxFilter1, bMaskByte2);
+                       TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1,
+                                                   bMaskByte2);
 
                        for (i = 0; i < CCKTxBBGainTableLength; i++) {
                                if (TempCCk == dm_cck_tx_bb_gain[i][0]) {
@@ -954,7 +952,7 @@ start:
                        priv->btxpower_tracking = false;
                }
        }
-       rtl8192_irq_enable(dev);
+       rtl92e_irq_enable(dev);
 end:
        priv->being_init_adapter = false;
        return rtStatus;
@@ -969,27 +967,27 @@ static void rtl8192_net_update(struct net_device *dev)
        u16 rate_config = 0;
 
        net = &priv->rtllib->current_network;
-       rtl8192_config_rate(dev, &rate_config);
+       rtl92e_config_rate(dev, &rate_config);
        priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
         priv->basic_rate = rate_config &= 0x15f;
-       write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
-       write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+       rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]);
+       rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
 
        if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
-               write_nic_word(dev, ATIMWND, 2);
-               write_nic_word(dev, BCN_DMATIME, 256);
-               write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
-               write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
-               write_nic_byte(dev, BCN_ERR_THRESH, 100);
+               rtl92e_writew(dev, ATIMWND, 2);
+               rtl92e_writew(dev, BCN_DMATIME, 256);
+               rtl92e_writew(dev, BCN_INTERVAL, net->beacon_interval);
+               rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10);
+               rtl92e_writeb(dev, BCN_ERR_THRESH, 100);
 
                BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
                BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
 
-               write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+               rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg);
        }
 }
 
-void rtl8192_link_change(struct net_device *dev)
+void rtl92e_link_change(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
@@ -1002,16 +1000,16 @@ void rtl8192_link_change(struct net_device *dev)
                priv->ops->update_ratr_table(dev);
                if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
                    (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
-                       EnableHWSecurityConfig8192(dev);
+                       rtl92e_enable_hw_security_config(dev);
        } else {
-               write_nic_byte(dev, 0x173, 0);
+               rtl92e_writeb(dev, 0x173, 0);
        }
        rtl8192e_update_msr(dev);
 
        if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
                u32 reg = 0;
 
-               reg = read_nic_dword(dev, RCR);
+               reg = rtl92e_readl(dev, RCR);
                if (priv->rtllib->state == RTLLIB_LINKED) {
                        if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn)
                                ;
@@ -1020,12 +1018,12 @@ void rtl8192_link_change(struct net_device *dev)
                } else
                        priv->ReceiveConfig = reg &= ~RCR_CBSSID;
 
-               write_nic_dword(dev, RCR, reg);
+               rtl92e_writel(dev, RCR, reg);
        }
 }
 
-void rtl8192_AllowAllDestAddr(struct net_device *dev,
-                             bool bAllowAllDA, bool WriteIntoReg)
+void rtl92e_set_monitor_mode(struct net_device *dev, bool bAllowAllDA,
+                            bool WriteIntoReg)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1035,7 +1033,7 @@ void rtl8192_AllowAllDestAddr(struct net_device *dev,
                priv->ReceiveConfig &= ~RCR_AAP;
 
        if (WriteIntoReg)
-               write_nic_dword(dev, RCR, priv->ReceiveConfig);
+               rtl92e_writel(dev, RCR, priv->ReceiveConfig);
 }
 
 static u8 MRateToHwRate8190Pci(u8 rate)
@@ -1177,8 +1175,20 @@ static u8 rtl8192_MapHwQueueToFirmwareQueue(struct net_device *dev, u8 QueueID,
        return QueueSelect;
 }
 
-void  rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
-                          struct cb_desc *cb_desc, struct sk_buff *skb)
+static u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc)
+{
+       u8   tmp_Short;
+
+       tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) :
+                       ((tcb_desc->bUseShortPreamble) ? 1 : 0);
+       if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
+               tmp_Short = 0;
+
+       return tmp_Short;
+}
+
+void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
+                         struct cb_desc *cb_desc, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
@@ -1286,9 +1296,8 @@ void  rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
        pdesc->TxBuffAddr = mapping;
 }
 
-void  rtl8192_tx_fill_cmd_desc(struct net_device *dev,
-                              struct tx_desc_cmd *entry,
-                              struct cb_desc *cb_desc, struct sk_buff *skb)
+void  rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry,
+                             struct cb_desc *cb_desc, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
@@ -1506,8 +1515,9 @@ static void rtl8192_query_rxphystatus(
        pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
        pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
        if (check_reg824 == 0) {
-               reg824_bit9 = rtl8192_QueryBBReg(priv->rtllib->dev,
-                             rFPGA0_XA_HSSIParameter2, 0x200);
+               reg824_bit9 = rtl92e_get_bb_reg(priv->rtllib->dev,
+                                               rFPGA0_XA_HSSIParameter2,
+                                               0x200);
                check_reg824 = 1;
        }
 
@@ -1575,7 +1585,7 @@ static void rtl8192_query_rxphystatus(
                        }
                }
 
-               pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+               pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all);
                pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
                pstats->RecvSignalPower = rx_pwr_all;
 
@@ -1615,7 +1625,7 @@ static void rtl8192_query_rxphystatus(
                        rx_snrX /= 2;
                        priv->stats.rxSNRdB[i] = (long)rx_snrX;
 
-                       RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
+                       RSSI = rtl92e_rx_db_to_percent(rx_pwr[i]);
                        if (priv->brfpath_rxenable[i])
                                total_rssi += RSSI;
 
@@ -1628,7 +1638,7 @@ static void rtl8192_query_rxphystatus(
 
 
                rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106;
-               pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+               pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all);
 
                pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
                pstats->RxPower = precord_stats->RxPower =      rx_pwr_all;
@@ -1645,7 +1655,7 @@ static void rtl8192_query_rxphystatus(
 
                        rx_evmX /= 2;
 
-                       evm = rtl819x_evm_dbtopercentage(rx_evmX);
+                       evm = rtl92e_evm_db_to_percent(rx_evmX);
                        if (bpacket_match_bssid) {
                                if (i == 0) {
                                        pstats->SignalQuality = (u8)(evm &
@@ -1721,8 +1731,8 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
                slide_rssi_index = 0;
 
        tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
-       priv->stats.signal_strength = rtl819x_translate_todbm(priv,
-                                     (u8)tmp_val);
+       priv->stats.signal_strength = rtl92e_translate_to_dbm(priv,
+                                                             (u8)tmp_val);
        curr_st->rssi = priv->stats.signal_strength;
        if (!prev_st->bPacketMatchBSSID) {
                if (!prev_st->bToSelfBA)
@@ -1732,13 +1742,10 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
        if (!bcheck)
                return;
 
-       rtl819x_process_cck_rxpathsel(priv, prev_st);
-
        priv->stats.num_process_phyinfo++;
        if (!prev_st->bIsCCK && prev_st->bPacketToSelf) {
                for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++) {
-                       if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev,
-                           rfpath))
+                       if (!rtl92e_is_legal_rf_path(priv->rtllib->dev, rfpath))
                                continue;
                        RT_TRACE(COMP_DBG,
                                 "Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath]  = %d\n",
@@ -1813,7 +1820,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
                                        (RX_SMOOTH-1)) +
                                        (prev_st->RxPWDBAll)) / (RX_SMOOTH);
                }
-               rtl819x_update_rxsignalstatistics8190pci(priv, prev_st);
+               rtl92e_update_rx_statistics(priv, prev_st);
        }
 
        if (prev_st->SignalQuality != 0) {
@@ -1900,7 +1907,7 @@ static void rtl8192_TranslateRxSignalStuff(struct net_device *dev,
        rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo,
                                  &previous_stats, bpacket_match_bssid,
                                  bpacket_toself, bPacketBeacon, bToSelfBA);
-       rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
+       rtl92e_copy_mpdu_stats(pstats, &previous_stats);
 }
 
 static void rtl8192_UpdateReceivedRateHistogramStatistics(
@@ -2016,10 +2023,8 @@ static void rtl8192_UpdateReceivedRateHistogramStatistics(
        priv->stats.received_rate_histogram[rcvType][rateIndex]++;
 }
 
-bool rtl8192_rx_query_status_desc(struct net_device *dev,
-                                 struct rtllib_rx_stats *stats,
-                                 struct rx_desc *pdesc,
-                                 struct sk_buff *skb)
+bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats,
+                        struct rx_desc *pdesc, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rx_fwinfo *pDrvInfo = NULL;
@@ -2063,9 +2068,9 @@ bool rtl8192_rx_query_status_desc(struct net_device *dev,
                            (pDrvInfo->FirstAGGR == 1);
 
        stats->TimeStampLow = pDrvInfo->TSFL;
-       stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
+       stats->TimeStampHigh = rtl92e_readl(dev, TSFR+4);
 
-       rtl819x_UpdateRxPktTimeStamp(dev, stats);
+       rtl92e_update_rx_pkt_timestamp(dev, stats);
 
        if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0)
                stats->bShift = 1;
@@ -2089,7 +2094,7 @@ bool rtl8192_rx_query_status_desc(struct net_device *dev,
        return true;
 }
 
-void rtl8192_halt_adapter(struct net_device *dev, bool reset)
+void rtl92e_stop_adapter(struct net_device *dev, bool reset)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        int i;
@@ -2102,7 +2107,7 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset)
 
        if (!priv->rtllib->bSupportRemoteWakeUp) {
                u1bTmp = 0x0;
-               write_nic_byte(dev, CMDR, u1bTmp);
+               rtl92e_writeb(dev, CMDR, u1bTmp);
        }
 
        mdelay(20);
@@ -2113,18 +2118,18 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset)
                priv->bHwRfOffAction = 2;
 
                if (!priv->rtllib->bSupportRemoteWakeUp) {
-                       PHY_SetRtl8192eRfOff(dev);
-                       ulRegRead = read_nic_dword(dev, CPU_GEN);
+                       rtl92e_set_rf_off(dev);
+                       ulRegRead = rtl92e_readl(dev, CPU_GEN);
                        ulRegRead |= CPU_GEN_SYSTEM_RESET;
-                       write_nic_dword(dev, CPU_GEN, ulRegRead);
+                       rtl92e_writel(dev, CPU_GEN, ulRegRead);
                } else {
-                       write_nic_dword(dev, WFCRC0, 0xffffffff);
-                       write_nic_dword(dev, WFCRC1, 0xffffffff);
-                       write_nic_dword(dev, WFCRC2, 0xffffffff);
+                       rtl92e_writel(dev, WFCRC0, 0xffffffff);
+                       rtl92e_writel(dev, WFCRC1, 0xffffffff);
+                       rtl92e_writel(dev, WFCRC2, 0xffffffff);
 
 
-                       write_nic_byte(dev, PMR, 0x5);
-                       write_nic_byte(dev, MacBlkCtrl, 0xa);
+                       rtl92e_writeb(dev, PMR, 0x5);
+                       rtl92e_writeb(dev, MacBlkCtrl, 0xa);
                }
        }
 
@@ -2136,7 +2141,7 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset)
        skb_queue_purge(&priv->skb_queue);
 }
 
-void rtl8192_update_ratr_table(struct net_device *dev)
+void rtl92e_update_ratr_table(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
@@ -2145,7 +2150,7 @@ void rtl8192_update_ratr_table(struct net_device *dev)
        u16 rate_config = 0;
        u8 rate_index = 0;
 
-       rtl8192_config_rate(dev, &rate_config);
+       rtl92e_config_rate(dev, &rate_config);
        ratr_value = rate_config | *pMcsRate << 12;
        switch (ieee->mode) {
        case IEEE_A:
@@ -2179,12 +2184,12 @@ void rtl8192_update_ratr_table(struct net_device *dev)
        else if (!ieee->pHTInfo->bCurTxBW40MHz &&
                  ieee->pHTInfo->bCurShortGI20MHz)
                ratr_value |= 0x80000000;
-       write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
-       write_nic_byte(dev, UFWP, 1);
+       rtl92e_writel(dev, RATR0+rate_index*4, ratr_value);
+       rtl92e_writeb(dev, UFWP, 1);
 }
 
 void
-rtl8192_InitializeVariables(struct net_device  *dev)
+rtl92e_init_variables(struct net_device  *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -2218,66 +2223,65 @@ rtl8192_InitializeVariables(struct net_device  *dev)
        priv->bfirst_after_down = false;
 }
 
-void rtl8192_EnableInterrupt(struct net_device *dev)
+void rtl92e_enable_irq(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
        priv->irq_enabled = 1;
 
-       write_nic_dword(dev, INTA_MASK, priv->irq_mask[0]);
+       rtl92e_writel(dev, INTA_MASK, priv->irq_mask[0]);
 
 }
 
-void rtl8192_DisableInterrupt(struct net_device *dev)
+void rtl92e_disable_irq(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
-       write_nic_dword(dev, INTA_MASK, 0);
+       rtl92e_writel(dev, INTA_MASK, 0);
 
        priv->irq_enabled = 0;
 }
 
-void rtl8192_ClearInterrupt(struct net_device *dev)
+void rtl92e_clear_irq(struct net_device *dev)
 {
        u32 tmp = 0;
 
-       tmp = read_nic_dword(dev, ISR);
-       write_nic_dword(dev, ISR, tmp);
+       tmp = rtl92e_readl(dev, ISR);
+       rtl92e_writel(dev, ISR, tmp);
 }
 
 
-void rtl8192_enable_rx(struct net_device *dev)
+void rtl92e_enable_rx(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
-       write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
+       rtl92e_writel(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
 }
 
 static const u32 TX_DESC_BASE[] = {
        BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA
 };
 
-void rtl8192_enable_tx(struct net_device *dev)
+void rtl92e_enable_tx(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
        u32 i;
 
        for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
-               write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
+               rtl92e_writel(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
 }
 
 
-void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta,
-                                 u32 *p_intb)
+void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb)
 {
-       *p_inta = read_nic_dword(dev, ISR);
-       write_nic_dword(dev, ISR, *p_inta);
+       *p_inta = rtl92e_readl(dev, ISR);
+       rtl92e_writel(dev, ISR, *p_inta);
 }
 
-bool rtl8192_HalRxCheckStuck(struct net_device *dev)
+bool rtl92e_is_rx_stuck(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
-       u16               RegRxCounter = read_nic_word(dev, 0x130);
+       u16               RegRxCounter = rtl92e_readw(dev, 0x130);
        bool              bStuck = false;
        static u8         rx_chk_cnt;
        u32             SlotIndex = 0, TotalRxStuckCount = 0;
@@ -2338,11 +2342,11 @@ bool rtl8192_HalRxCheckStuck(struct net_device *dev)
        return bStuck;
 }
 
-bool rtl8192_HalTxCheckStuck(struct net_device *dev)
+bool rtl92e_is_tx_stuck(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        bool    bStuck = false;
-       u16     RegTxCounter = read_nic_word(dev, 0x128);
+       u16     RegTxCounter = rtl92e_readw(dev, 0x128);
 
        RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n",
                 __func__, RegTxCounter, priv->TxCounter);
@@ -2355,7 +2359,7 @@ bool rtl8192_HalTxCheckStuck(struct net_device *dev)
        return bStuck;
 }
 
-bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev)
+bool rtl92e_get_nmode_support_by_sec(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
@@ -2369,34 +2373,10 @@ bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev)
        }
 }
 
-bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev)
+bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev)
 {
-       bool Reval;
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
 
-       if (ieee->bHalfWirelessN24GMode == true)
-               Reval = true;
-       else
-               Reval =  false;
-
-       return Reval;
-}
-
-u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc)
-{
-       u8   tmp_Short;
-
-       tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) :
-                       ((tcb_desc->bUseShortPreamble) ? 1 : 0);
-       if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
-               tmp_Short = 0;
-
-       return tmp_Short;
-}
-
-void ActUpdateChannelAccessSetting(struct net_device *dev,
-       enum wireless_mode WirelessMode,
-       struct channel_access_setting *ChnlAccessSetting)
-{
+       return ieee->bHalfWirelessN24GMode;
 }
index dbe0e1c87056bea9ef480f399a9227c41b29a033..6bd6b3a4fcea617ea35255124b3b1fd014541ee1 100644 (file)
 
 #include "r8190P_def.h"
 
-u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc);
-bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev);
-bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev);
-bool rtl8192_HalTxCheckStuck(struct net_device *dev);
-bool rtl8192_HalRxCheckStuck(struct net_device *dev);
-void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta,
-                                 u32 *p_intb);
-void rtl8192_enable_rx(struct net_device *dev);
-void rtl8192_enable_tx(struct net_device *dev);
-void rtl8192_EnableInterrupt(struct net_device *dev);
-void rtl8192_DisableInterrupt(struct net_device *dev);
-void rtl8192_ClearInterrupt(struct net_device *dev);
-void rtl8192_InitializeVariables(struct net_device  *dev);
-void rtl8192e_start_beacon(struct net_device *dev);
-void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val);
-void rtl8192_get_eeprom_size(struct net_device *dev);
-bool rtl8192_adapter_start(struct net_device *dev);
-void rtl8192_link_change(struct net_device *dev);
-void rtl8192_AllowAllDestAddr(struct net_device *dev, bool bAllowAllDA,
-                             bool WriteIntoReg);
-void  rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
-                          struct cb_desc *cb_desc,
-                          struct sk_buff *skb);
-void  rtl8192_tx_fill_cmd_desc(struct net_device *dev,
-                              struct tx_desc_cmd *entry,
-                              struct cb_desc *cb_desc, struct sk_buff *skb);
-bool rtl8192_rx_query_status_desc(struct net_device *dev,
-                                 struct rtllib_rx_stats *stats,
-                                 struct rx_desc *pdesc,
-                                 struct sk_buff *skb);
-void rtl8192_halt_adapter(struct net_device *dev, bool reset);
-void rtl8192_update_ratr_table(struct net_device *dev);
+bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev);
+bool rtl92e_get_nmode_support_by_sec(struct net_device *dev);
+bool rtl92e_is_tx_stuck(struct net_device *dev);
+bool rtl92e_is_rx_stuck(struct net_device *dev);
+void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb);
+void rtl92e_enable_rx(struct net_device *dev);
+void rtl92e_enable_tx(struct net_device *dev);
+void rtl92e_enable_irq(struct net_device *dev);
+void rtl92e_disable_irq(struct net_device *dev);
+void rtl92e_clear_irq(struct net_device *dev);
+void rtl92e_init_variables(struct net_device  *dev);
+void rtl92e_start_beacon(struct net_device *dev);
+void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val);
+void rtl92e_get_eeprom_size(struct net_device *dev);
+bool rtl92e_start_adapter(struct net_device *dev);
+void rtl92e_link_change(struct net_device *dev);
+void rtl92e_set_monitor_mode(struct net_device *dev, bool bAllowAllDA,
+                            bool WriteIntoReg);
+void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
+                         struct cb_desc *cb_desc, struct sk_buff *skb);
+void  rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry,
+                             struct cb_desc *cb_desc, struct sk_buff *skb);
+bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats,
+                        struct rx_desc *pdesc, struct sk_buff *skb);
+void rtl92e_stop_adapter(struct net_device *dev, bool reset);
+void rtl92e_update_ratr_table(struct net_device *dev);
 #endif
index 17d2a1540cc8b3635f4f89017eb18b4ff4424275..5c527c419bc9eeb474ebd01f82ed526324594c7c 100644 (file)
@@ -23,7 +23,7 @@
 #include "r8192E_firmware.h"
 #include <linux/firmware.h>
 
-void firmware_init_param(struct net_device *dev)
+void rtl92e_init_fw_param(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rt_firmware *pfirmware = priv->pFirmware;
@@ -46,7 +46,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
        struct cb_desc *tcb_desc;
        u8                  bLastIniPkt;
 
-       firmware_init_param(dev);
+       rtl92e_init_fw_param(dev);
        frag_threshold = pfirmware->cmdpacket_frag_thresold;
        do {
                if ((buffer_len - frag_offset) > frag_threshold) {
@@ -96,7 +96,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 
        } while (frag_offset < buffer_len);
 
-       write_nic_byte(dev, TPPoll, TPPoll_CQ);
+       rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
 
        return true;
 }
@@ -109,7 +109,7 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 
        timeout = jiffies + msecs_to_jiffies(200);
        while (time_before(jiffies, timeout)) {
-               CPU_status = read_nic_dword(dev, CPU_GEN);
+               CPU_status = rtl92e_readl(dev, CPU_GEN);
                if (CPU_status & CPU_GEN_PUT_CODE_OK)
                        break;
                mdelay(2);
@@ -122,14 +122,14 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
                RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
        }
 
-       CPU_status = read_nic_dword(dev, CPU_GEN);
-       write_nic_byte(dev, CPU_GEN,
-                      (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
+       CPU_status = rtl92e_readl(dev, CPU_GEN);
+       rtl92e_writeb(dev, CPU_GEN,
+                     (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
        mdelay(1);
 
        timeout = jiffies + msecs_to_jiffies(200);
        while (time_before(jiffies, timeout)) {
-               CPU_status = read_nic_dword(dev, CPU_GEN);
+               CPU_status = rtl92e_readl(dev, CPU_GEN);
                if (CPU_status&CPU_GEN_BOOT_RDY)
                        break;
                mdelay(2);
@@ -158,7 +158,7 @@ static bool CPUcheck_firmware_ready(struct net_device *dev)
 
        timeout = jiffies + msecs_to_jiffies(20);
        while (time_before(jiffies, timeout)) {
-               CPU_status = read_nic_dword(dev, CPU_GEN);
+               CPU_status = rtl92e_readl(dev, CPU_GEN);
                if (CPU_status&CPU_GEN_FIRM_RDY)
                        break;
                mdelay(2);
@@ -223,7 +223,7 @@ static bool firmware_check_ready(struct net_device *dev,
        return rt_status;
 }
 
-bool init_firmware(struct net_device *dev)
+bool rtl92e_init_fw(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        bool                    rt_status = true;
index d79e5420319983a71ce599bc8d53af97d4e8cfda..fa760f7ac1450eab5c4416f24c6e18f09152af92 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef __INC_FIRMWARE_H
 #define __INC_FIRMWARE_H
 
-#define RTL8190_CPU_START_OFFSET       0x80
-
 #define GET_COMMAND_PACKET_FRAG_THRESHOLD(v)   (4*(v/4) - 8)
 
 #define RTL8192E_BOOT_IMG_FW   "RTL8192E/boot.img"
@@ -61,7 +59,7 @@ struct rt_firmware {
        u16               firmware_buf_size[MAX_FW_INIT_STEP];
 };
 
-bool init_firmware(struct net_device *dev);
-extern void firmware_init_param(struct net_device *dev);
+bool rtl92e_init_fw(struct net_device *dev);
+void rtl92e_init_fw_param(struct net_device *dev);
 
 #endif
index 43c3fb859d10e1692acf55e07c27420036827e04..c81832dcf1817bef47f1fc11e22e5ab23612d0f7 100644 (file)
@@ -119,10 +119,10 @@ enum _RTL8192Pci_HW {
 #define EPROM_CMD_NORMAL 0
 #define EPROM_CMD_LOAD 1
 #define EPROM_CMD_PROGRAM 2
-#define EPROM_CS_SHIFT 3
-#define EPROM_CK_SHIFT 2
-#define EPROM_W_SHIFT 1
-#define EPROM_R_SHIFT 0
+#define EPROM_CS_BIT 3
+#define EPROM_CK_BIT 2
+#define EPROM_W_BIT 1
+#define EPROM_R_BIT 0
 
        AFR                      = 0x010,
 #define AFR_CardBEn            (1<<0)
index fba7654160e807ab6be3aa432cb099144bbfc62d..3a15a0f5b479626c49238e7b8807e0cfae7ec952 100644 (file)
@@ -64,7 +64,7 @@ static u32 rtl8192_CalculateBitShift(u32 dwBitMask)
        return i;
 }
 
-u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath)
+u8 rtl92e_is_legal_rf_path(struct net_device *dev, u32 eRFPath)
 {
        u8 ret = 1;
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -80,27 +80,27 @@ u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath)
        return ret;
 }
 
-void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
-                     u32 dwData)
+void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
+                      u32 dwData)
 {
 
        u32 OriginalValue, BitShift, NewValue;
 
        if (dwBitMask != bMaskDWord) {
-               OriginalValue = read_nic_dword(dev, dwRegAddr);
+               OriginalValue = rtl92e_readl(dev, dwRegAddr);
                BitShift = rtl8192_CalculateBitShift(dwBitMask);
                NewValue = (((OriginalValue) & (~dwBitMask)) |
                            (dwData << BitShift));
-               write_nic_dword(dev, dwRegAddr, NewValue);
+               rtl92e_writel(dev, dwRegAddr, NewValue);
        } else
-               write_nic_dword(dev, dwRegAddr, dwData);
+               rtl92e_writel(dev, dwRegAddr, dwData);
 }
 
-u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
+u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
 {
        u32 Ret = 0, OriginalValue, BitShift;
 
-       OriginalValue = read_nic_dword(dev, dwRegAddr);
+       OriginalValue = rtl92e_readl(dev, dwRegAddr);
        BitShift = rtl8192_CalculateBitShift(dwBitMask);
        Ret = (OriginalValue & dwBitMask) >> BitShift;
 
@@ -117,19 +117,19 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device *dev,
        Offset &= 0x3f;
 
        if (priv->rf_chip == RF_8256) {
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
                if (Offset >= 31) {
                        priv->RfReg0Value[eRFPath] |= 0x140;
-                       rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
-                                        bMaskDWord,
-                                        (priv->RfReg0Value[eRFPath]<<16));
+                       rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+                                         bMaskDWord,
+                                         (priv->RfReg0Value[eRFPath]<<16));
                        NewOffset = Offset - 30;
                } else if (Offset >= 16) {
                        priv->RfReg0Value[eRFPath] |= 0x100;
                        priv->RfReg0Value[eRFPath] &= (~0x40);
-                       rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
-                                        bMaskDWord,
-                                        (priv->RfReg0Value[eRFPath]<<16));
+                       rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+                                         bMaskDWord,
+                                         (priv->RfReg0Value[eRFPath]<<16));
 
                        NewOffset = Offset - 15;
                } else
@@ -139,23 +139,23 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device *dev,
                         "check RF type here, need to be 8256\n");
                NewOffset = Offset;
        }
-       rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress,
-                        NewOffset);
-       rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x0);
-       rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x1);
+       rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress,
+                         NewOffset);
+       rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x0);
+       rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x1);
 
        mdelay(1);
 
-       ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack,
-                                bLSSIReadBackData);
+       ret = rtl92e_get_bb_reg(dev, pPhyReg->rfLSSIReadBack,
+                               bLSSIReadBackData);
 
        if (priv->rf_chip == RF_8256) {
                priv->RfReg0Value[eRFPath] &= 0xebf;
 
-               rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord,
-                               (priv->RfReg0Value[eRFPath] << 16));
+               rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord,
+                                 (priv->RfReg0Value[eRFPath] << 16));
 
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
        }
 
 
@@ -173,20 +173,20 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev,
 
        Offset &= 0x3f;
        if (priv->rf_chip == RF_8256) {
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
 
                if (Offset >= 31) {
                        priv->RfReg0Value[eRFPath] |= 0x140;
-                       rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
-                                        bMaskDWord,
-                                        (priv->RfReg0Value[eRFPath] << 16));
+                       rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+                                         bMaskDWord,
+                                         (priv->RfReg0Value[eRFPath] << 16));
                        NewOffset = Offset - 30;
                } else if (Offset >= 16) {
                        priv->RfReg0Value[eRFPath] |= 0x100;
                        priv->RfReg0Value[eRFPath] &= (~0x40);
-                       rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
-                                        bMaskDWord,
-                                        (priv->RfReg0Value[eRFPath] << 16));
+                       rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+                                         bMaskDWord,
+                                         (priv->RfReg0Value[eRFPath] << 16));
                        NewOffset = Offset - 15;
                } else
                        NewOffset = Offset;
@@ -198,7 +198,7 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev,
 
        DataAndAddr = (Data<<16) | (NewOffset&0x3f);
 
-       rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+       rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
 
        if (Offset == 0x0)
                priv->RfReg0Value[eRFPath] = Data;
@@ -206,23 +206,21 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev,
        if (priv->rf_chip == RF_8256) {
                if (Offset != 0) {
                        priv->RfReg0Value[eRFPath] &= 0xebf;
-                       rtl8192_setBBreg(
-                               dev,
-                               pPhyReg->rf3wireOffset,
-                               bMaskDWord,
-                               (priv->RfReg0Value[eRFPath] << 16));
+                       rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+                                         bMaskDWord,
+                                         (priv->RfReg0Value[eRFPath] << 16));
                }
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
        }
 }
 
-void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
-                         u32 RegAddr, u32 BitMask, u32 Data)
+void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+                      u32 RegAddr, u32 BitMask, u32 Data)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u32 Original_Value, BitShift, New_Value;
 
-       if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+       if (!rtl92e_is_legal_rf_path(dev, eRFPath))
                return;
        if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter)
                return;
@@ -256,13 +254,13 @@ void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
        }
 }
 
-u32 rtl8192_phy_QueryRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
-                          u32 RegAddr, u32 BitMask)
+u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+                     u32 RegAddr, u32 BitMask)
 {
        u32 Original_Value, Readback_Value, BitShift;
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+       if (!rtl92e_is_legal_rf_path(dev, eRFPath))
                return 0;
        if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter)
                return  0;
@@ -289,20 +287,20 @@ static u32 phy_FwRFSerialRead(struct net_device *dev,
        Data |= ((Offset & 0xFF) << 12);
        Data |= ((eRFPath & 0x3) << 20);
        Data |= 0x80000000;
-       while (read_nic_dword(dev, QPNR)&0x80000000) {
+       while (rtl92e_readl(dev, QPNR) & 0x80000000) {
                if (time++ < 100)
                        udelay(10);
                else
                        break;
        }
-       write_nic_dword(dev, QPNR, Data);
-       while (read_nic_dword(dev, QPNR) & 0x80000000) {
+       rtl92e_writel(dev, QPNR, Data);
+       while (rtl92e_readl(dev, QPNR) & 0x80000000) {
                if (time++ < 100)
                        udelay(10);
                else
                        return 0;
        }
-       return read_nic_dword(dev, RF_DATA);
+       return rtl92e_readl(dev, RF_DATA);
 
 }
 
@@ -317,18 +315,18 @@ static void phy_FwRFSerialWrite(struct net_device *dev,
        Data |= 0x400000;
        Data |= 0x80000000;
 
-       while (read_nic_dword(dev, QPNR) & 0x80000000) {
+       while (rtl92e_readl(dev, QPNR) & 0x80000000) {
                if (time++ < 100)
                        udelay(10);
                else
                        break;
        }
-       write_nic_dword(dev, QPNR, Data);
+       rtl92e_writel(dev, QPNR, Data);
 
 }
 
 
-void rtl8192_phy_configmac(struct net_device *dev)
+void rtl92e_config_mac(struct net_device *dev)
 {
        u32 dwArrayLen = 0, i = 0;
        u32 *pdwArray = NULL;
@@ -350,14 +348,14 @@ void rtl8192_phy_configmac(struct net_device *dev)
                         pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
                if (pdwArray[i] == 0x318)
                        pdwArray[i+2] = 0x00000800;
-               rtl8192_setBBreg(dev, pdwArray[i], pdwArray[i+1],
-                                pdwArray[i+2]);
+               rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i+1],
+                                 pdwArray[i+2]);
        }
        return;
 
 }
 
-void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
+static void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
 {
        int i;
        u32 *Rtl819XPHY_REGArray_Table = NULL;
@@ -377,9 +375,9 @@ void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
 
        if (ConfigType == BaseBand_Config_PHY_REG) {
                for (i = 0; i < PHY_REGArrayLen; i += 2) {
-                       rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table[i],
-                                        bMaskDWord,
-                                        Rtl819XPHY_REGArray_Table[i+1]);
+                       rtl92e_set_bb_reg(dev, Rtl819XPHY_REGArray_Table[i],
+                                         bMaskDWord,
+                                         Rtl819XPHY_REGArray_Table[i+1]);
                        RT_TRACE(COMP_DBG,
                                 "i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x\n",
                                 i, Rtl819XPHY_REGArray_Table[i],
@@ -387,9 +385,9 @@ void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
                }
        } else if (ConfigType == BaseBand_Config_AGC_TAB) {
                for (i = 0; i < AGCTAB_ArrayLen; i += 2) {
-                       rtl8192_setBBreg(dev, Rtl819XAGCTAB_Array_Table[i],
-                                        bMaskDWord,
-                                        Rtl819XAGCTAB_Array_Table[i+1]);
+                       rtl92e_set_bb_reg(dev, Rtl819XAGCTAB_Array_Table[i],
+                                         bMaskDWord,
+                                         Rtl819XAGCTAB_Array_Table[i+1]);
                        RT_TRACE(COMP_DBG,
                                 "i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x\n",
                                 i, Rtl819XAGCTAB_Array_Table[i],
@@ -489,9 +487,8 @@ static void rtl8192_InitBBRFRegDef(struct net_device *dev)
 
 }
 
-bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
-                             enum hw90_block CheckBlock,
-                             enum rf90_radio_path eRFPath)
+bool rtl92e_check_bb_and_rf(struct net_device *dev, enum hw90_block CheckBlock,
+                           enum rf90_radio_path eRFPath)
 {
        bool ret = true;
        u32 i, CheckTimes = 4, dwRegRead = 0;
@@ -515,20 +512,20 @@ bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
                switch (CheckBlock) {
                case HW90_BLOCK_PHY0:
                case HW90_BLOCK_PHY1:
-                       write_nic_dword(dev, WriteAddr[CheckBlock],
-                                       WriteData[i]);
-                       dwRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]);
+                       rtl92e_writel(dev, WriteAddr[CheckBlock],
+                                     WriteData[i]);
+                       dwRegRead = rtl92e_readl(dev, WriteAddr[CheckBlock]);
                        break;
 
                case HW90_BLOCK_RF:
                        WriteData[i] &= 0xfff;
-                       rtl8192_phy_SetRFReg(dev, eRFPath,
-                                                WriteAddr[HW90_BLOCK_RF],
-                                                bMask12Bits, WriteData[i]);
+                       rtl92e_set_rf_reg(dev, eRFPath,
+                                         WriteAddr[HW90_BLOCK_RF],
+                                         bMask12Bits, WriteData[i]);
                        mdelay(10);
-                       dwRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath,
-                                                WriteAddr[HW90_BLOCK_RF],
-                                                bMaskDWord);
+                       dwRegRead = rtl92e_get_rf_reg(dev, eRFPath,
+                                                     WriteAddr[HW90_BLOCK_RF],
+                                                     bMaskDWord);
                        mdelay(10);
                        break;
 
@@ -555,29 +552,29 @@ static bool rtl8192_BB_Config_ParaFile(struct net_device *dev)
        u8 bRegValue = 0, eCheckItem = 0;
        u32 dwRegValue = 0;
 
-       bRegValue = read_nic_byte(dev, BB_GLOBAL_RESET);
-       write_nic_byte(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT));
+       bRegValue = rtl92e_readb(dev, BB_GLOBAL_RESET);
+       rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT));
 
-       dwRegValue = read_nic_dword(dev, CPU_GEN);
-       write_nic_dword(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
+       dwRegValue = rtl92e_readl(dev, CPU_GEN);
+       rtl92e_writel(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
 
        for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0;
             eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) {
-               rtStatus  = rtl8192_phy_checkBBAndRF(dev,
-                                        (enum hw90_block)eCheckItem,
-                                        (enum rf90_radio_path)0);
+               rtStatus  = rtl92e_check_bb_and_rf(dev,
+                                                  (enum hw90_block)eCheckItem,
+                                                  (enum rf90_radio_path)0);
                if (!rtStatus) {
                        RT_TRACE((COMP_ERR | COMP_PHY),
-                                "PHY_RF8256_Config():Check PHY%d Fail!!\n",
+                                "rtl92e_config_rf():Check PHY%d Fail!!\n",
                                 eCheckItem-1);
                        return rtStatus;
                }
        }
-       rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
+       rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
        rtl8192_phyConfigBB(dev, BaseBand_Config_PHY_REG);
 
-       dwRegValue = read_nic_dword(dev, CPU_GEN);
-       write_nic_dword(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
+       dwRegValue = rtl92e_readl(dev, CPU_GEN);
+       rtl92e_writel(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
 
        rtl8192_phyConfigBB(dev, BaseBand_Config_AGC_TAB);
 
@@ -588,57 +585,57 @@ static bool rtl8192_BB_Config_ParaFile(struct net_device *dev)
                                      priv->AntennaTxPwDiff[0]);
                else
                        dwRegValue = 0x0;
-               rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
-                       (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
+               rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage,
+                                 (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
 
 
                dwRegValue = priv->CrystalCap;
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap92x,
-                                dwRegValue);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, bXtalCap92x,
+                                 dwRegValue);
        }
 
        return rtStatus;
 }
-bool rtl8192_BBConfig(struct net_device *dev)
+bool rtl92e_config_bb(struct net_device *dev)
 {
        rtl8192_InitBBRFRegDef(dev);
        return rtl8192_BB_Config_ParaFile(dev);
 }
 
-void rtl8192_phy_getTxPower(struct net_device *dev)
+void rtl92e_get_tx_power(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
        priv->MCSTxPowerLevelOriginalOffset[0] =
-               read_nic_dword(dev, rTxAGC_Rate18_06);
+               rtl92e_readl(dev, rTxAGC_Rate18_06);
        priv->MCSTxPowerLevelOriginalOffset[1] =
-               read_nic_dword(dev, rTxAGC_Rate54_24);
+               rtl92e_readl(dev, rTxAGC_Rate54_24);
        priv->MCSTxPowerLevelOriginalOffset[2] =
-               read_nic_dword(dev, rTxAGC_Mcs03_Mcs00);
+               rtl92e_readl(dev, rTxAGC_Mcs03_Mcs00);
        priv->MCSTxPowerLevelOriginalOffset[3] =
-               read_nic_dword(dev, rTxAGC_Mcs07_Mcs04);
+               rtl92e_readl(dev, rTxAGC_Mcs07_Mcs04);
        priv->MCSTxPowerLevelOriginalOffset[4] =
-               read_nic_dword(dev, rTxAGC_Mcs11_Mcs08);
+               rtl92e_readl(dev, rTxAGC_Mcs11_Mcs08);
        priv->MCSTxPowerLevelOriginalOffset[5] =
-               read_nic_dword(dev, rTxAGC_Mcs15_Mcs12);
+               rtl92e_readl(dev, rTxAGC_Mcs15_Mcs12);
 
-       priv->DefaultInitialGain[0] = read_nic_byte(dev, rOFDM0_XAAGCCore1);
-       priv->DefaultInitialGain[1] = read_nic_byte(dev, rOFDM0_XBAGCCore1);
-       priv->DefaultInitialGain[2] = read_nic_byte(dev, rOFDM0_XCAGCCore1);
-       priv->DefaultInitialGain[3] = read_nic_byte(dev, rOFDM0_XDAGCCore1);
+       priv->DefaultInitialGain[0] = rtl92e_readb(dev, rOFDM0_XAAGCCore1);
+       priv->DefaultInitialGain[1] = rtl92e_readb(dev, rOFDM0_XBAGCCore1);
+       priv->DefaultInitialGain[2] = rtl92e_readb(dev, rOFDM0_XCAGCCore1);
+       priv->DefaultInitialGain[3] = rtl92e_readb(dev, rOFDM0_XDAGCCore1);
        RT_TRACE(COMP_INIT,
                 "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
                 priv->DefaultInitialGain[0], priv->DefaultInitialGain[1],
                 priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]);
 
-       priv->framesync = read_nic_byte(dev, rOFDM0_RxDetector3);
-       priv->framesyncC34 = read_nic_dword(dev, rOFDM0_RxDetector2);
+       priv->framesync = rtl92e_readb(dev, rOFDM0_RxDetector3);
+       priv->framesyncC34 = rtl92e_readl(dev, rOFDM0_RxDetector2);
        RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
                rOFDM0_RxDetector3, priv->framesync);
-       priv->SifsTime = read_nic_word(dev, SIFS);
+       priv->SifsTime = rtl92e_readw(dev, SIFS);
 }
 
-void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
+void rtl92e_set_tx_power(struct net_device *dev, u8 channel)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u8      powerlevel = 0, powerlevelOFDM24G = 0;
@@ -671,16 +668,17 @@ void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
                                      priv->AntennaTxPwDiff[1]<<4 |
                                      priv->AntennaTxPwDiff[0]);
 
-                       rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
-                       (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+                       rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage,
+                                         (bXBTxAGC|bXCTxAGC|bXDTxAGC),
+                                         u4RegValue);
                }
        }
        switch (priv->rf_chip) {
        case RF_8225:
                break;
        case RF_8256:
-               PHY_SetRF8256CCKTxPower(dev, powerlevel);
-               PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
+               rtl92e_set_cck_tx_power(dev, powerlevel);
+               rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G);
                break;
        case RF_8258:
                break;
@@ -690,7 +688,7 @@ void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
        }
 }
 
-bool rtl8192_phy_RFConfig(struct net_device *dev)
+bool rtl92e_config_phy(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        bool rtStatus = true;
@@ -699,7 +697,7 @@ bool rtl8192_phy_RFConfig(struct net_device *dev)
        case RF_8225:
                break;
        case RF_8256:
-               rtStatus = PHY_RF8256_Config(dev);
+               rtStatus = rtl92e_config_rf(dev);
                break;
 
        case RF_8258:
@@ -714,12 +712,7 @@ bool rtl8192_phy_RFConfig(struct net_device *dev)
        return rtStatus;
 }
 
-void rtl8192_phy_updateInitGain(struct net_device *dev)
-{
-}
-
-u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
-                                     enum rf90_radio_path eRFPath)
+u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath)
 {
 
        int i;
@@ -731,10 +724,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
                                msleep(100);
                                continue;
                        }
-                       rtl8192_phy_SetRFReg(dev, eRFPath,
-                                            Rtl819XRadioA_Array[i],
-                                            bMask12Bits,
-                                            Rtl819XRadioA_Array[i+1]);
+                       rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioA_Array[i],
+                                         bMask12Bits,
+                                         Rtl819XRadioA_Array[i+1]);
 
                }
                break;
@@ -744,10 +736,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
                                msleep(100);
                                continue;
                        }
-                       rtl8192_phy_SetRFReg(dev, eRFPath,
-                                            Rtl819XRadioB_Array[i],
-                                            bMask12Bits,
-                                            Rtl819XRadioB_Array[i+1]);
+                       rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioB_Array[i],
+                                         bMask12Bits,
+                                         Rtl819XRadioB_Array[i+1]);
 
                }
                break;
@@ -757,10 +748,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
                                msleep(100);
                                continue;
                        }
-                       rtl8192_phy_SetRFReg(dev, eRFPath,
-                                            Rtl819XRadioC_Array[i],
-                                            bMask12Bits,
-                                            Rtl819XRadioC_Array[i+1]);
+                       rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioC_Array[i],
+                                         bMask12Bits,
+                                         Rtl819XRadioC_Array[i+1]);
 
                }
                break;
@@ -770,9 +760,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
                                        msleep(100);
                                        continue;
                        }
-                       rtl8192_phy_SetRFReg(dev, eRFPath,
-                                        Rtl819XRadioD_Array[i], bMask12Bits,
-                                        Rtl819XRadioD_Array[i+1]);
+                       rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioD_Array[i],
+                                         bMask12Bits,
+                                         Rtl819XRadioD_Array[i+1]);
 
                }
                break;
@@ -794,8 +784,8 @@ static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel)
                break;
 
        case RF_8256:
-               PHY_SetRF8256CCKTxPower(dev, powerlevel);
-               PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
+               rtl92e_set_cck_tx_power(dev, powerlevel);
+               rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G);
                break;
 
        case RF_8258:
@@ -941,21 +931,21 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
                                        rtl8192_SetTxPowerLevel(dev, channel);
                                break;
                        case CmdID_WritePortUlong:
-                               write_nic_dword(dev, CurrentCmd->Para1,
-                                               CurrentCmd->Para2);
+                               rtl92e_writel(dev, CurrentCmd->Para1,
+                                             CurrentCmd->Para2);
                                break;
                        case CmdID_WritePortUshort:
-                               write_nic_word(dev, CurrentCmd->Para1,
-                                              (u16)CurrentCmd->Para2);
+                               rtl92e_writew(dev, CurrentCmd->Para1,
+                                             (u16)CurrentCmd->Para2);
                                break;
                        case CmdID_WritePortUchar:
-                               write_nic_byte(dev, CurrentCmd->Para1,
-                                              (u8)CurrentCmd->Para2);
+                               rtl92e_writeb(dev, CurrentCmd->Para1,
+                                             (u8)CurrentCmd->Para2);
                                break;
                        case CmdID_RF_WriteReg:
                                for (eRFPath = 0; eRFPath <
                                     priv->NumTotalRFPath; eRFPath++)
-                                       rtl8192_phy_SetRFReg(dev,
+                                       rtl92e_set_rf_reg(dev,
                                                 (enum rf90_radio_path)eRFPath,
                                                 CurrentCmd->Para1, bMask12Bits,
                                                 CurrentCmd->Para2<<7);
@@ -986,7 +976,7 @@ static void rtl8192_phy_FinishSwChnlNow(struct net_device *dev, u8 channel)
                        break;
        }
 }
-void rtl8192_SwChnl_WorkItem(struct net_device *dev)
+static void rtl8192_SwChnl_WorkItem(struct net_device *dev)
 {
 
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -1001,7 +991,7 @@ void rtl8192_SwChnl_WorkItem(struct net_device *dev)
        RT_TRACE(COMP_TRACE, "<== SwChnlCallback819xUsbWorkItem()\n");
 }
 
-u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel)
+u8 rtl92e_set_channel(struct net_device *dev, u8 channel)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1082,13 +1072,13 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev)
                if (priv->rtllib->current_network.channel == 14 &&
                    !priv->bcck_in_ch14) {
                        priv->bcck_in_ch14 = true;
-                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                } else if (priv->rtllib->current_network.channel !=
                           14 && priv->bcck_in_ch14) {
                        priv->bcck_in_ch14 = false;
-                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                } else {
-                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                }
                break;
 
@@ -1110,13 +1100,13 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev)
                if (priv->rtllib->current_network.channel == 14 &&
                    !priv->bcck_in_ch14) {
                        priv->bcck_in_ch14 = true;
-                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                } else if (priv->rtllib->current_network.channel != 14
                           && priv->bcck_in_ch14) {
                        priv->bcck_in_ch14 = false;
-                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                } else {
-                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                }
                break;
        }
@@ -1150,7 +1140,7 @@ static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct net_device *dev)
                         priv->CCK_index);
        break;
        }
-       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
 }
 
 static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev)
@@ -1163,7 +1153,7 @@ static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev)
                CCK_Tx_Power_Track_BW_Switch_ThermalMeter(dev);
 }
 
-void rtl8192_SetBWModeWorkItem(struct net_device *dev)
+static void rtl8192_SetBWModeWorkItem(struct net_device *dev)
 {
 
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -1183,17 +1173,17 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
                netdev_err(dev, "%s(): Driver is not initialized\n", __func__);
                return;
        }
-       regBwOpMode = read_nic_byte(dev, BW_OPMODE);
+       regBwOpMode = rtl92e_readb(dev, BW_OPMODE);
 
        switch (priv->CurrentChannelBW) {
        case HT_CHANNEL_WIDTH_20:
                regBwOpMode |= BW_OPMODE_20MHZ;
-               write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+               rtl92e_writeb(dev, BW_OPMODE, regBwOpMode);
                break;
 
        case HT_CHANNEL_WIDTH_20_40:
                regBwOpMode &= ~BW_OPMODE_20MHZ;
-               write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+               rtl92e_writeb(dev, BW_OPMODE, regBwOpMode);
                break;
 
        default:
@@ -1204,38 +1194,38 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
 
        switch (priv->CurrentChannelBW) {
        case HT_CHANNEL_WIDTH_20:
-               rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
-               rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
+               rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
+               rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
 
                if (!priv->btxpower_tracking) {
-                       write_nic_dword(dev, rCCK0_TxFilter1, 0x1a1b0000);
-                       write_nic_dword(dev, rCCK0_TxFilter2, 0x090e1317);
-                       write_nic_dword(dev, rCCK0_DebugPort, 0x00000204);
+                       rtl92e_writel(dev, rCCK0_TxFilter1, 0x1a1b0000);
+                       rtl92e_writel(dev, rCCK0_TxFilter2, 0x090e1317);
+                       rtl92e_writel(dev, rCCK0_DebugPort, 0x00000204);
                } else {
                        CCK_Tx_Power_Track_BW_Switch(dev);
                }
 
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
 
                break;
        case HT_CHANNEL_WIDTH_20_40:
-               rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
-               rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
+               rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
+               rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
 
                if (!priv->btxpower_tracking) {
-                       write_nic_dword(dev, rCCK0_TxFilter1, 0x35360000);
-                       write_nic_dword(dev, rCCK0_TxFilter2, 0x121c252e);
-                       write_nic_dword(dev, rCCK0_DebugPort, 0x00000409);
+                       rtl92e_writel(dev, rCCK0_TxFilter1, 0x35360000);
+                       rtl92e_writel(dev, rCCK0_TxFilter2, 0x121c252e);
+                       rtl92e_writel(dev, rCCK0_DebugPort, 0x00000409);
                } else {
                        CCK_Tx_Power_Track_BW_Switch(dev);
                }
 
-               rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand,
-                                (priv->nCur40MhzPrimeSC>>1));
-               rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00,
-                                priv->nCur40MhzPrimeSC);
+               rtl92e_set_bb_reg(dev, rCCK0_System, bCCKSideBand,
+                                 (priv->nCur40MhzPrimeSC>>1));
+               rtl92e_set_bb_reg(dev, rOFDM1_LSTF, 0xC00,
+                                 priv->nCur40MhzPrimeSC);
 
-               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
+               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
                break;
        default:
                netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__,
@@ -1249,7 +1239,7 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
                break;
 
        case RF_8256:
-               PHY_SetRF8256Bandwidth(dev, priv->CurrentChannelBW);
+               rtl92e_set_bandwidth(dev, priv->CurrentChannelBW);
                break;
 
        case RF_8258:
@@ -1270,8 +1260,8 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
        RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()");
 }
 
-void rtl8192_SetBWMode(struct net_device *dev, enum ht_channel_width Bandwidth,
-                      enum ht_extchnl_offset Offset)
+void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width Bandwidth,
+                       enum ht_extchnl_offset Offset)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1295,7 +1285,7 @@ void rtl8192_SetBWMode(struct net_device *dev, enum ht_channel_width Bandwidth,
 
 }
 
-void InitialGain819xPci(struct net_device *dev, u8 Operation)
+void rtl92e_init_gain(struct net_device *dev, u8 Operation)
 {
 #define SCAN_RX_INITIAL_GAIN   0x17
 #define POWER_DETECTION_TH     0x08
@@ -1312,21 +1302,21 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
                        BitMask = bMaskByte0;
                        if (dm_digtable.dig_algorithm ==
                            DIG_ALGO_BY_FALSE_ALARM)
-                               rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+                               rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
                        priv->initgain_backup.xaagccore1 =
-                                (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1,
-                                BitMask);
+                                (u8)rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1,
+                                                      BitMask);
                        priv->initgain_backup.xbagccore1 =
-                                (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1,
-                                BitMask);
+                                (u8)rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1,
+                                                      BitMask);
                        priv->initgain_backup.xcagccore1 =
-                                (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1,
-                                BitMask);
+                                (u8)rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1,
+                                                      BitMask);
                        priv->initgain_backup.xdagccore1 =
-                                (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1,
-                                BitMask);
+                                (u8)rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1,
+                                                      BitMask);
                        BitMask = bMaskByte2;
-                       priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev,
+                       priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev,
                                                    rCCK0_CCA, BitMask);
 
                        RT_TRACE(COMP_SCAN,
@@ -1347,13 +1337,13 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
 
                        RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x\n",
                                 initial_gain);
-                       write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
-                       write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
-                       write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
-                       write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+                       rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain);
+                       rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain);
+                       rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain);
+                       rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain);
                        RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x\n",
                                 POWER_DETECTION_TH);
-                       write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH);
+                       rtl92e_writeb(dev, 0xa0a, POWER_DETECTION_TH);
                        break;
                case IG_Restore:
                        RT_TRACE(COMP_SCAN,
@@ -1361,18 +1351,18 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
                        BitMask = 0x7f;
                        if (dm_digtable.dig_algorithm ==
                            DIG_ALGO_BY_FALSE_ALARM)
-                               rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+                               rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
 
-                       rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, BitMask,
+                       rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, BitMask,
                                         (u32)priv->initgain_backup.xaagccore1);
-                       rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, BitMask,
+                       rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, BitMask,
                                         (u32)priv->initgain_backup.xbagccore1);
-                       rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, BitMask,
+                       rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, BitMask,
                                         (u32)priv->initgain_backup.xcagccore1);
-                       rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, BitMask,
+                       rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, BitMask,
                                         (u32)priv->initgain_backup.xdagccore1);
                        BitMask  = bMaskByte2;
-                       rtl8192_setBBreg(dev, rCCK0_CCA, BitMask,
+                       rtl92e_set_bb_reg(dev, rCCK0_CCA, BitMask,
                                         (u32)priv->initgain_backup.cca);
 
                        RT_TRACE(COMP_SCAN,
@@ -1391,12 +1381,12 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
                                 "Scan BBInitialGainRestore 0xa0a is %x\n",
                                 priv->initgain_backup.cca);
 
-                       rtl8192_phy_setTxPower(dev,
+                       rtl92e_set_tx_power(dev,
                                         priv->rtllib->current_network.channel);
 
                        if (dm_digtable.dig_algorithm ==
                            DIG_ALGO_BY_FALSE_ALARM)
-                               rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+                               rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
                        break;
                default:
                        RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n");
@@ -1405,17 +1395,17 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
        }
 }
 
-void PHY_SetRtl8192eRfOff(struct net_device *dev)
+void rtl92e_set_rf_off(struct net_device *dev)
 {
 
-       rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
-       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
-       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
-       rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
-       rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
-       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
-       rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
-       write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
+       rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+       rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+       rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+       rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+       rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+       rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
+       rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+       rtl92e_writeb(dev, ANAPAR_FOR_8192PciE, 0x07);
 
 }
 
@@ -1447,7 +1437,7 @@ static bool SetRFPowerState8190(struct net_device *dev,
                                do {
                                        InitilizeCount--;
                                        priv->RegRfOff = false;
-                                       rtstatus = NicIFEnableNIC(dev);
+                                       rtstatus = rtl92e_enable_nic(dev);
                                } while (!rtstatus && (InitilizeCount > 0));
 
                                if (!rtstatus) {
@@ -1461,24 +1451,24 @@ static bool SetRFPowerState8190(struct net_device *dev,
                                RT_CLEAR_PS_LEVEL(pPSC,
                                                  RT_RF_OFF_LEVL_HALT_NIC);
                        } else {
-                               write_nic_byte(dev, ANAPAR, 0x37);
+                               rtl92e_writeb(dev, ANAPAR, 0x37);
                                mdelay(1);
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
+                               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1,
                                                 0x4, 0x1);
                                priv->bHwRfOffAction = 0;
 
-                               rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE,
-                                                BIT4, 0x1);
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4,
-                                                0x300, 0x3);
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
-                                                0x18, 0x3);
-                               rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3,
-                                                0x3);
-                               rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3,
-                                                0x3);
-                               rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
-                                                0x60, 0x3);
+                               rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE,
+                                                 BIT4, 0x1);
+                               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4,
+                                                 0x300, 0x3);
+                               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1,
+                                                 0x18, 0x3);
+                               rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable,
+                                                 0x3, 0x3);
+                               rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable,
+                                                 0x3, 0x3);
+                               rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1,
+                                                 0x60, 0x3);
 
                        }
 
@@ -1511,7 +1501,7 @@ static bool SetRFPowerState8190(struct net_device *dev,
                                        break;
                                }
                        }
-                       PHY_SetRtl8192eRfOff(dev);
+                       rtl92e_set_rf_off(dev);
                        break;
 
                case eRfOff:
@@ -1543,11 +1533,11 @@ static bool SetRFPowerState8190(struct net_device *dev,
 
                        if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC &&
                            !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) {
-                               NicIFDisableNIC(dev);
+                               rtl92e_disable_nic(dev);
                                RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
                        } else if (!(pPSC->RegRfPsLevel &
                                   RT_RF_OFF_LEVL_HALT_NIC)) {
-                               PHY_SetRtl8192eRfOff(dev);
+                               rtl92e_set_rf_off(dev);
                        }
 
                        break;
@@ -1586,32 +1576,34 @@ static bool SetRFPowerState8190(struct net_device *dev,
        return bResult;
 }
 
-bool SetRFPowerState(struct net_device *dev,
-                    enum rt_rf_power_state eRFPowerState)
+bool rtl92e_set_rf_power_state(struct net_device *dev,
+                              enum rt_rf_power_state eRFPowerState)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
        bool bResult = false;
 
-       RT_TRACE(COMP_PS, "---------> SetRFPowerState(): eRFPowerState(%d)\n",
+       RT_TRACE(COMP_PS,
+                "---------> rtl92e_set_rf_power_state(): eRFPowerState(%d)\n",
                 eRFPowerState);
        if (eRFPowerState == priv->rtllib->eRFPowerState &&
            priv->bHwRfOffAction == 0) {
                RT_TRACE(COMP_PS,
-                        "<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n",
+                        "<--------- rtl92e_set_rf_power_state(): discard the request for eRFPowerState(%d) is the same.\n",
                         eRFPowerState);
                return bResult;
        }
 
        bResult = SetRFPowerState8190(dev, eRFPowerState);
 
-       RT_TRACE(COMP_PS, "<--------- SetRFPowerState(): bResult(%d)\n",
+       RT_TRACE(COMP_PS,
+                "<--------- rtl92e_set_rf_power_state(): bResult(%d)\n",
                 bResult);
 
        return bResult;
 }
 
-void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation)
+void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
index 18bc58240fbeb4455e2d99f423c73c82a72b5035..96015d342009c204594438ccd7b57828d310ef86 100644 (file)
@@ -67,48 +67,36 @@ enum rf90_radio_path {
 #define bMaskLWord                0x0000ffff
 #define bMaskDWord                0xffffffff
 
-extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev,
-                                        u32 eRFPath);
-extern void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr,
-                            u32 dwBitMask, u32 dwData);
-extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr,
-                             u32 dwBitMask);
-extern void rtl8192_phy_SetRFReg(struct net_device *dev,
-                                enum rf90_radio_path eRFPath,
-                                u32 RegAddr, u32 BitMask, u32 Data);
-extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
-                                 enum rf90_radio_path eRFPath,
-                                 u32 RegAddr, u32 BitMask);
-extern void rtl8192_phy_configmac(struct net_device *dev);
-extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
-extern bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
-                                    enum hw90_block CheckBlock,
-                                    enum rf90_radio_path eRFPath);
-extern bool rtl8192_BBConfig(struct net_device *dev);
-extern void rtl8192_phy_getTxPower(struct net_device *dev);
-extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
-extern bool rtl8192_phy_RFConfig(struct net_device *dev);
-extern void rtl8192_phy_updateInitGain(struct net_device *dev);
-extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
-                                            enum rf90_radio_path eRFPath);
+u8 rtl92e_is_legal_rf_path(struct net_device *dev, u32 eRFPath);
+void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr,
+                      u32 dwBitMask, u32 dwData);
+u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask);
+void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+                      u32 RegAddr, u32 BitMask, u32 Data);
+u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+                     u32 RegAddr, u32 BitMask);
+void rtl92e_config_mac(struct net_device *dev);
+bool rtl92e_check_bb_and_rf(struct net_device *dev,
+                           enum hw90_block CheckBlock,
+                           enum rf90_radio_path eRFPath);
+bool rtl92e_config_bb(struct net_device *dev);
+void rtl92e_get_tx_power(struct net_device *dev);
+void rtl92e_set_tx_power(struct net_device *dev, u8 channel);
+bool rtl92e_config_phy(struct net_device *dev);
+u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath);
 
-extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
-extern void rtl8192_SetBWMode(struct net_device *dev,
-                             enum ht_channel_width Bandwidth,
-                             enum ht_extchnl_offset Offset);
-extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
-extern void rtl8192_SetBWModeWorkItem(struct net_device *dev);
-extern void InitialGain819xPci(struct net_device *dev, u8 Operation);
+u8 rtl92e_set_channel(struct net_device *dev, u8 channel);
+void rtl92e_set_bw_mode(struct net_device *dev,
+                       enum ht_channel_width Bandwidth,
+                       enum ht_extchnl_offset Offset);
+void rtl92e_init_gain(struct net_device *dev, u8 Operation);
 
-extern void PHY_SetRtl8192eRfOff(struct net_device *dev);
+void rtl92e_set_rf_off(struct net_device *dev);
 
-bool
-SetRFPowerState(
-       struct net_device *dev,
-       enum rt_rf_power_state eRFPowerState
-       );
-#define PHY_SetRFPowerState SetRFPowerState
+bool rtl92e_set_rf_power_state(struct net_device *dev,
+                              enum rt_rf_power_state eRFPowerState);
+#define PHY_SetRFPowerState rtl92e_set_rf_power_state
 
-extern void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation);
+void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation);
 
 #endif
index f246222e5fc954e83cc8fb8be0344aaf057d48a2..29dd93ac5e93fdfd4e3eacc67116023e01746408 100644 (file)
 #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
 #include "r8192E_cmdpkt.h"
 
-void CamResetAllEntry(struct net_device *dev)
+void rtl92e_cam_reset(struct net_device *dev)
 {
        u32 ulcommand = 0;
 
        ulcommand |= BIT31|BIT30;
-       write_nic_dword(dev, RWCAM, ulcommand);
+       rtl92e_writel(dev, RWCAM, ulcommand);
 }
 
-void EnableHWSecurityConfig8192(struct net_device *dev)
+void rtl92e_enable_hw_security_config(struct net_device *dev)
 {
        u8 SECR_value = 0x0;
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -65,11 +65,12 @@ void EnableHWSecurityConfig8192(struct net_device *dev)
        RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
                 __func__, ieee->hwsec_active, ieee->pairwise_key_type,
                 SECR_value);
-       write_nic_byte(dev, SECR,  SECR_value);
+       rtl92e_writeb(dev, SECR, SECR_value);
 }
 
-void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
-              const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh)
+void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+                     u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+                     u32 *KeyContent, u8 is_mesh)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
@@ -77,6 +78,10 @@ void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
        RT_TRACE(COMP_DBG,
                 "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
                 __func__, EntryNo, KeyIndex, KeyType, is_mesh);
+
+       if (EntryNo >= TOTAL_CAM_ENTRY)
+               return;
+
        if (!is_mesh) {
                ieee->swcamtable[EntryNo].bused = true;
                ieee->swcamtable[EntryNo].key_index = KeyIndex;
@@ -87,8 +92,9 @@ void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
        }
 }
 
-void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
-           const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
+void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+                   u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+                   u32 *KeyContent)
 {
        u32 TargetCommand = 0;
        u32 TargetContent = 0;
@@ -106,16 +112,18 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
                                return;
                        }
                        down(&priv->rtllib->ips_sem);
-                       IPSLeave(dev);
+                       rtl92e_ips_leave(dev);
                        up(&priv->rtllib->ips_sem);
                }
        }
        priv->rtllib->is_set_key = true;
-       if (EntryNo >= TOTAL_CAM_ENTRY)
+       if (EntryNo >= TOTAL_CAM_ENTRY) {
                netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
+               return;
+       }
 
        RT_TRACE(COMP_SEC,
-                "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
+                "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
                 dev, EntryNo, KeyIndex, KeyType, MacAddr);
 
        if (DefaultKey)
@@ -133,20 +141,20 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
                                (u32)(*(MacAddr+1)) << 24 |
                                (u32)usConfig;
 
-                       write_nic_dword(dev, WCAMI, TargetContent);
-                       write_nic_dword(dev, RWCAM, TargetCommand);
+                       rtl92e_writel(dev, WCAMI, TargetContent);
+                       rtl92e_writel(dev, RWCAM, TargetCommand);
                } else if (i == 1) {
                        TargetContent = (u32)(*(MacAddr+2)) |
                                (u32)(*(MacAddr+3)) <<  8 |
                                (u32)(*(MacAddr+4)) << 16 |
                                (u32)(*(MacAddr+5)) << 24;
-                       write_nic_dword(dev, WCAMI, TargetContent);
-                       write_nic_dword(dev, RWCAM, TargetCommand);
+                       rtl92e_writel(dev, WCAMI, TargetContent);
+                       rtl92e_writel(dev, RWCAM, TargetCommand);
                } else {
                        if (KeyContent != NULL) {
-                               write_nic_dword(dev, WCAMI,
-                                               (u32)(*(KeyContent+i-2)));
-                               write_nic_dword(dev, RWCAM, TargetCommand);
+                               rtl92e_writel(dev, WCAMI,
+                                             (u32)(*(KeyContent+i-2)));
+                               rtl92e_writel(dev, RWCAM, TargetCommand);
                                udelay(100);
                        }
                }
@@ -154,7 +162,7 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
        RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
 }
 
-void CamRestoreAllEntry(struct net_device *dev)
+void rtl92e_cam_restore(struct net_device *dev)
 {
        u8 EntryId = 0;
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -170,7 +178,7 @@ void CamRestoreAllEntry(struct net_device *dev)
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff
        };
 
-       RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
+       RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n");
 
 
        if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
@@ -179,36 +187,41 @@ void CamRestoreAllEntry(struct net_device *dev)
                for (EntryId = 0; EntryId < 4; EntryId++) {
                        MacAddr = CAM_CONST_ADDR[EntryId];
                        if (priv->rtllib->swcamtable[EntryId].bused) {
-                               setKey(dev, EntryId, EntryId,
-                                      priv->rtllib->pairwise_key_type, MacAddr,
-                                      0, (u32 *)(&priv->rtllib->swcamtable
-                                     [EntryId].key_buf[0]));
+                               rtl92e_set_key(dev, EntryId, EntryId,
+                                              priv->rtllib->pairwise_key_type,
+                                              MacAddr, 0,
+                                              (u32 *)(&priv->rtllib->swcamtable
+                                                      [EntryId].key_buf[0]));
                        }
                }
 
        } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
-                       setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
-                              (u8 *)dev->dev_addr, 0,
-                              (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
+                       rtl92e_set_key(dev, 4, 0,
+                                      priv->rtllib->pairwise_key_type,
+                                      (u8 *)dev->dev_addr, 0,
+                                      (u32 *)(&priv->rtllib->swcamtable[4].
+                                      key_buf[0]));
                } else {
-                       setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
-                              MacAddr, 0,
-                              (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
+                       rtl92e_set_key(dev, 4, 0,
+                                      priv->rtllib->pairwise_key_type,
+                                      MacAddr, 0,
+                                      (u32 *)(&priv->rtllib->swcamtable[4].
+                                      key_buf[0]));
                }
 
        } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
-                       setKey(dev, 4, 0,
-                              priv->rtllib->pairwise_key_type,
-                              (u8 *)dev->dev_addr, 0,
-                              (u32 *)(&priv->rtllib->swcamtable[4].
-                              key_buf[0]));
+                       rtl92e_set_key(dev, 4, 0,
+                                      priv->rtllib->pairwise_key_type,
+                                      (u8 *)dev->dev_addr, 0,
+                                      (u32 *)(&priv->rtllib->swcamtable[4].
+                                      key_buf[0]));
                } else {
-                       setKey(dev, 4, 0,
-                              priv->rtllib->pairwise_key_type, MacAddr,
-                              0, (u32 *)(&priv->rtllib->swcamtable[4].
-                              key_buf[0]));
+                       rtl92e_set_key(dev, 4, 0,
+                                      priv->rtllib->pairwise_key_type, MacAddr,
+                                      0, (u32 *)(&priv->rtllib->swcamtable[4].
+                                      key_buf[0]));
                        }
        }
 
@@ -216,20 +229,18 @@ void CamRestoreAllEntry(struct net_device *dev)
                MacAddr = CAM_CONST_BROAD;
                for (EntryId = 1; EntryId < 4; EntryId++) {
                        if (priv->rtllib->swcamtable[EntryId].bused) {
-                               setKey(dev, EntryId, EntryId,
-                                       priv->rtllib->group_key_type,
-                                       MacAddr, 0,
-                                       (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
-                                    );
+                               rtl92e_set_key(dev, EntryId, EntryId,
+                                              priv->rtllib->group_key_type,
+                                              MacAddr, 0,
+                                              (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
                        }
                }
                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
                        if (priv->rtllib->swcamtable[0].bused) {
-                               setKey(dev, 0, 0,
-                                      priv->rtllib->group_key_type,
-                                      CAM_CONST_ADDR[0], 0,
-                                      (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
-                                    );
+                               rtl92e_set_key(dev, 0, 0,
+                                              priv->rtllib->group_key_type,
+                                              CAM_CONST_ADDR[0], 0,
+                                              (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
                        } else {
                                netdev_warn(dev,
                                            "%s(): ADHOC TKIP: missing key entry.\n",
@@ -241,19 +252,19 @@ void CamRestoreAllEntry(struct net_device *dev)
                MacAddr = CAM_CONST_BROAD;
                for (EntryId = 1; EntryId < 4; EntryId++) {
                        if (priv->rtllib->swcamtable[EntryId].bused) {
-                               setKey(dev, EntryId, EntryId,
-                                      priv->rtllib->group_key_type,
-                                      MacAddr, 0,
-                                      (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
+                               rtl92e_set_key(dev, EntryId, EntryId,
+                                              priv->rtllib->group_key_type,
+                                              MacAddr, 0,
+                                              (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
                        }
                }
 
                if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
                        if (priv->rtllib->swcamtable[0].bused) {
-                               setKey(dev, 0, 0,
-                                       priv->rtllib->group_key_type,
-                                       CAM_CONST_ADDR[0], 0,
-                                       (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
+                               rtl92e_set_key(dev, 0, 0,
+                                              priv->rtllib->group_key_type,
+                                              CAM_CONST_ADDR[0], 0,
+                                              (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
                        } else {
                                netdev_warn(dev,
                                            "%s(): ADHOC CCMP: missing key entry.\n",
index f23ab46c77e7f7fb962d0d0e821a20888efa8ac8..9ef8b36fc6b51bfb965ada3322fb3bbdaacb1f61 100644 (file)
 #include <linux/types.h>
 struct net_device;
 
-void CamResetAllEntry(struct net_device *dev);
-void EnableHWSecurityConfig8192(struct net_device *dev);
-void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
-           const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
-void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
-              const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh);
-void CamRestoreAllEntry(struct net_device *dev);
+void rtl92e_cam_reset(struct net_device *dev);
+void rtl92e_enable_hw_security_config(struct net_device *dev);
+void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+                   u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+                   u32 *KeyContent);
+void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+                     u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+                     u32 *KeyContent, u8 is_mesh);
+void rtl92e_cam_restore(struct net_device *dev);
 
 #endif
index c6cdb43b864c1996813c5d83b0042416335f71f7..d6b46dfd01e133bbb16de5f636ae52e4c812c488 100644 (file)
  * Contact Information:
  * wlanfae <wlanfae@realtek.com>
 ******************************************************************************/
-#undef RX_DONT_PASS_UL
-#undef DEBUG_EPROM
-#undef DEBUG_RX_VERBOSE
-#undef DUMMY_RX
-#undef DEBUG_ZERO_RX
-#undef DEBUG_RX_SKB
-#undef DEBUG_TX_FRAG
-#undef DEBUG_RX_FRAG
-#undef DEBUG_TX_FILLDESC
-#undef DEBUG_TX
-#undef DEBUG_IRQ
-#undef DEBUG_RX
-#undef DEBUG_RXALLOC
-#undef DEBUG_REGISTERS
-#undef DEBUG_RING
-#undef DEBUG_IRQ_TASKLET
-#undef DEBUG_TX_ALLOC
-#undef DEBUG_TX_DESC
-
 #include <linux/uaccess.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
@@ -63,24 +44,24 @@ static char *ifname = "wlan%d";
 
 static struct rtl819x_ops rtl819xp_ops = {
        .nic_type                       = NIC_8192E,
-       .get_eeprom_size                = rtl8192_get_eeprom_size,
-       .init_adapter_variable          = rtl8192_InitializeVariables,
-       .initialize_adapter             = rtl8192_adapter_start,
-       .link_change                    = rtl8192_link_change,
-       .tx_fill_descriptor             = rtl8192_tx_fill_desc,
-       .tx_fill_cmd_descriptor         = rtl8192_tx_fill_cmd_desc,
-       .rx_query_status_descriptor     = rtl8192_rx_query_status_desc,
+       .get_eeprom_size                = rtl92e_get_eeprom_size,
+       .init_adapter_variable          = rtl92e_init_variables,
+       .initialize_adapter             = rtl92e_start_adapter,
+       .link_change                    = rtl92e_link_change,
+       .tx_fill_descriptor             = rtl92e_fill_tx_desc,
+       .tx_fill_cmd_descriptor         = rtl92e_fill_tx_cmd_desc,
+       .rx_query_status_descriptor     = rtl92e_get_rx_stats,
        .rx_command_packet_handler = NULL,
-       .stop_adapter                   = rtl8192_halt_adapter,
-       .update_ratr_table              = rtl8192_update_ratr_table,
-       .irq_enable                     = rtl8192_EnableInterrupt,
-       .irq_disable                    = rtl8192_DisableInterrupt,
-       .irq_clear                      = rtl8192_ClearInterrupt,
-       .rx_enable                      = rtl8192_enable_rx,
-       .tx_enable                      = rtl8192_enable_tx,
-       .interrupt_recognized           = rtl8192_interrupt_recognized,
-       .TxCheckStuckHandler            = rtl8192_HalTxCheckStuck,
-       .RxCheckStuckHandler            = rtl8192_HalRxCheckStuck,
+       .stop_adapter                   = rtl92e_stop_adapter,
+       .update_ratr_table              = rtl92e_update_ratr_table,
+       .irq_enable                     = rtl92e_enable_irq,
+       .irq_disable                    = rtl92e_disable_irq,
+       .irq_clear                      = rtl92e_clear_irq,
+       .rx_enable                      = rtl92e_enable_rx,
+       .tx_enable                      = rtl92e_enable_tx,
+       .interrupt_recognized           = rtl92e_ack_irq,
+       .TxCheckStuckHandler            = rtl92e_is_tx_stuck,
+       .RxCheckStuckHandler            = rtl92e_is_rx_stuck,
 };
 
 static struct pci_device_id rtl8192_pci_id_tbl[] = {
@@ -102,202 +83,61 @@ static struct pci_driver rtl8192_pci_driver = {
        .id_table = rtl8192_pci_id_tbl, /* PCI_ID table  */
        .probe  = rtl8192_pci_probe,    /* probe fn      */
        .remove  = rtl8192_pci_disconnect,      /* remove fn */
-       .suspend = rtl8192E_suspend,    /* PM suspend fn */
-       .resume = rtl8192E_resume,                 /* PM resume fn  */
+       .suspend = rtl92e_suspend,      /* PM suspend fn */
+       .resume = rtl92e_resume,                 /* PM resume fn  */
 };
 
+static short rtl8192_is_tx_queue_empty(struct net_device *dev);
+static void rtl819x_watchdog_wqcallback(void *data);
+static void watch_dog_timer_callback(unsigned long data);
+static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+                                  int rate);
+static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb);
+static short rtl8192_tx(struct net_device *dev, struct sk_buff *skb);
+static short rtl8192_pci_initdescring(struct net_device *dev);
+static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
+static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
+static void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
+static int _rtl8192_up(struct net_device *dev, bool is_silent_reset);
+static int rtl8192_up(struct net_device *dev);
+static int rtl8192_down(struct net_device *dev, bool shutdownrf);
+static void rtl8192_restart(void *data);
+
 /****************************************************************************
    -----------------------------IO STUFF-------------------------
 *****************************************************************************/
-static bool PlatformIOCheckPageLegalAndGetRegMask(u32 u4bPage, u8 *pu1bPageMask)
-{
-       bool            bReturn = false;
-
-       *pu1bPageMask = 0xfe;
-
-       switch (u4bPage) {
-       case 1: case 2: case 3: case 4:
-       case 8: case 9: case 10: case 12: case 13:
-               bReturn = true;
-               *pu1bPageMask = 0xf0;
-               break;
-
-       default:
-               bReturn = false;
-               break;
-       }
-
-       return bReturn;
-}
-
-void write_nic_io_byte(struct net_device *dev, int x, u8 y)
-{
-       u32 u4bPage = x >> 8;
-       u8 u1PageMask = 0;
-       bool    bIsLegalPage = false;
-
-       if (u4bPage == 0) {
-               outb(y&0xff, dev->base_addr + x);
-
-       } else {
-               bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                              &u1PageMask);
-               if (bIsLegalPage) {
-                       u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
-                       write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
-                                         (u8)u4bPage));
-                       write_nic_io_byte(dev, (x & 0xff), y);
-                       write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-               }
-       }
-}
-
-void write_nic_io_word(struct net_device *dev, int x, u16 y)
-{
-       u32 u4bPage = x >> 8;
-       u8 u1PageMask = 0;
-       bool    bIsLegalPage = false;
-
-       if (u4bPage == 0) {
-               outw(y, dev->base_addr + x);
-       } else {
-               bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                                                        &u1PageMask);
-               if (bIsLegalPage) {
-                       u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
-                       write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
-                                         (u8)u4bPage));
-                       write_nic_io_word(dev, (x & 0xff), y);
-                       write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-
-               }
-       }
-}
-
-void write_nic_io_dword(struct net_device *dev, int x, u32 y)
-{
-       u32 u4bPage = x >> 8;
-       u8 u1PageMask = 0;
-       bool    bIsLegalPage = false;
-
-       if (u4bPage == 0) {
-               outl(y, dev->base_addr + x);
-       } else {
-               bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                                                &u1PageMask);
-               if (bIsLegalPage) {
-                       u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
-                       write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
-                                         (u8)u4bPage));
-                       write_nic_io_dword(dev, (x & 0xff), y);
-                       write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-               }
-       }
-}
-
-u8 read_nic_io_byte(struct net_device *dev, int x)
-{
-       u32 u4bPage = x >> 8;
-       u8 u1PageMask = 0;
-       bool    bIsLegalPage = false;
-       u8      Data = 0;
-
-       if (u4bPage == 0)
-               return 0xff&inb(dev->base_addr + x);
-
-       bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                                                            &u1PageMask);
-       if (bIsLegalPage) {
-               u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
-               write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
-                                 (u8)u4bPage));
-               Data = read_nic_io_byte(dev, (x & 0xff));
-               write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-       }
-
-       return Data;
-}
-
-u16 read_nic_io_word(struct net_device *dev, int x)
-{
-       u32 u4bPage = x >> 8;
-       u8 u1PageMask = 0;
-       bool    bIsLegalPage = false;
-       u16     Data = 0;
-
-       if (u4bPage == 0)
-               return inw(dev->base_addr + x);
-       bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                                                            &u1PageMask);
-       if (bIsLegalPage) {
-               u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
-               write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
-                                 (u8)u4bPage));
-               Data = read_nic_io_word(dev, (x & 0xff));
-               write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-       }
-
-       return Data;
-}
 
-u32 read_nic_io_dword(struct net_device *dev, int x)
-{
-       u32 u4bPage = x >> 8;
-       u8 u1PageMask = 0;
-       bool    bIsLegalPage = false;
-       u32     Data = 0;
-
-       if (u4bPage == 0)
-               return inl(dev->base_addr + x);
-       bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
-                      &u1PageMask);
-       if (bIsLegalPage) {
-               u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
-               write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
-                                 (u8)u4bPage));
-               Data = read_nic_io_dword(dev, (x & 0xff));
-               write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-       }
-
-       return Data;
-}
-
-u8 read_nic_byte(struct net_device *dev, int x)
+u8 rtl92e_readb(struct net_device *dev, int x)
 {
        return 0xff & readb((u8 __iomem *)dev->mem_start + x);
 }
 
-u32 read_nic_dword(struct net_device *dev, int x)
+u32 rtl92e_readl(struct net_device *dev, int x)
 {
        return readl((u8 __iomem *)dev->mem_start + x);
 }
 
-u16 read_nic_word(struct net_device *dev, int x)
+u16 rtl92e_readw(struct net_device *dev, int x)
 {
        return readw((u8 __iomem *)dev->mem_start + x);
 }
 
-void write_nic_byte(struct net_device *dev, int x, u8 y)
+void rtl92e_writeb(struct net_device *dev, int x, u8 y)
 {
        writeb(y, (u8 __iomem *)dev->mem_start + x);
 
        udelay(20);
 }
 
-void write_nic_dword(struct net_device *dev, int x, u32 y)
+void rtl92e_writel(struct net_device *dev, int x, u32 y)
 {
        writel(y, (u8 __iomem *)dev->mem_start + x);
 
        udelay(20);
 }
 
-void write_nic_word(struct net_device *dev, int x, u16 y)
+void rtl92e_writew(struct net_device *dev, int x, u16 y)
 {
        writew(y, (u8 __iomem *)dev->mem_start + x);
 
@@ -307,10 +147,9 @@ void write_nic_word(struct net_device *dev, int x, u16 y)
 /****************************************************************************
    -----------------------------GENERAL FUNCTION-------------------------
 *****************************************************************************/
-bool MgntActSet_RF_State(struct net_device *dev,
+bool rtl92e_set_rf_state(struct net_device *dev,
                         enum rt_rf_power_state StateToSet,
-                        RT_RF_CHANGE_SOURCE ChangeSource,
-                        bool   ProtectOrNot)
+                        RT_RF_CHANGE_SOURCE ChangeSource)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
@@ -321,39 +160,34 @@ bool MgntActSet_RF_State(struct net_device *dev,
        unsigned long flag;
 
        RT_TRACE((COMP_PS | COMP_RF),
-                "===>MgntActSet_RF_State(): StateToSet(%d)\n", StateToSet);
-
-       ProtectOrNot = false;
+                "===>rtl92e_set_rf_state(): StateToSet(%d)\n", StateToSet);
 
+       while (true) {
+               spin_lock_irqsave(&priv->rf_ps_lock, flag);
+               if (priv->RFChangeInProgress) {
+                       spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+                       RT_TRACE((COMP_PS | COMP_RF),
+                                "rtl92e_set_rf_state(): RF Change in progress! Wait to set..StateToSet(%d).\n",
+                                StateToSet);
 
-       if (!ProtectOrNot) {
-               while (true) {
-                       spin_lock_irqsave(&priv->rf_ps_lock, flag);
-                       if (priv->RFChangeInProgress) {
-                               spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+                       while (priv->RFChangeInProgress) {
+                               RFWaitCounter++;
                                RT_TRACE((COMP_PS | COMP_RF),
-                                        "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n",
-                                        StateToSet);
-
-                               while (priv->RFChangeInProgress) {
-                                       RFWaitCounter++;
-                                       RT_TRACE((COMP_PS | COMP_RF),
-                                                "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n",
-                                                RFWaitCounter);
-                                       mdelay(1);
-
-                                       if (RFWaitCounter > 100) {
-                                               netdev_warn(dev,
-                                                           "%s(): Timeout waiting for RF change.\n",
-                                                           __func__);
-                                               return false;
-                                       }
+                                        "rtl92e_set_rf_state(): Wait 1 ms (%d times)...\n",
+                                        RFWaitCounter);
+                               mdelay(1);
+
+                               if (RFWaitCounter > 100) {
+                                       netdev_warn(dev,
+                                                   "%s(): Timeout waiting for RF change.\n",
+                                                   __func__);
+                                       return false;
                                }
-                       } else {
-                               priv->RFChangeInProgress = true;
-                               spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
-                               break;
                        }
+               } else {
+                       priv->RFChangeInProgress = true;
+                       spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+                       break;
                }
        }
 
@@ -376,7 +210,7 @@ bool MgntActSet_RF_State(struct net_device *dev,
                                bConnectBySSID = true;
                } else {
                        RT_TRACE((COMP_PS | COMP_RF),
-                                "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n",
+                                "rtl92e_set_rf_state - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n",
                                  priv->rtllib->RfOffReason, ChangeSource);
        }
 
@@ -413,7 +247,7 @@ bool MgntActSet_RF_State(struct net_device *dev,
 
        if (bActionAllowed) {
                RT_TRACE((COMP_PS | COMP_RF),
-                        "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n",
+                        "rtl92e_set_rf_state(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n",
                         StateToSet, priv->rtllib->RfOffReason);
                PHY_SetRFPowerState(dev, StateToSet);
                if (StateToSet == eRfOn) {
@@ -426,17 +260,15 @@ bool MgntActSet_RF_State(struct net_device *dev,
                }
        } else {
                RT_TRACE((COMP_PS | COMP_RF),
-                        "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n",
+                        "rtl92e_set_rf_state(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n",
                         StateToSet, ChangeSource, priv->rtllib->RfOffReason);
        }
 
-       if (!ProtectOrNot) {
-               spin_lock_irqsave(&priv->rf_ps_lock, flag);
-               priv->RFChangeInProgress = false;
-               spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
-       }
+       spin_lock_irqsave(&priv->rf_ps_lock, flag);
+       priv->RFChangeInProgress = false;
+       spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
 
-       RT_TRACE((COMP_PS | COMP_RF), "<===MgntActSet_RF_State()\n");
+       RT_TRACE((COMP_PS | COMP_RF), "<===rtl92e_set_rf_state()\n");
        return bActionAllowed;
 }
 
@@ -450,7 +282,7 @@ static short rtl8192_check_nic_enough_desc(struct net_device *dev, int prio)
        return 0;
 }
 
-void rtl8192_tx_timeout(struct net_device *dev)
+static void rtl8192_tx_timeout(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -458,7 +290,7 @@ void rtl8192_tx_timeout(struct net_device *dev)
        netdev_info(dev, "TXTIMEOUT");
 }
 
-void rtl8192_irq_enable(struct net_device *dev)
+void rtl92e_irq_enable(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
@@ -467,7 +299,7 @@ void rtl8192_irq_enable(struct net_device *dev)
        priv->ops->irq_enable(dev);
 }
 
-void rtl8192_irq_disable(struct net_device *dev)
+void rtl92e_irq_disable(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
@@ -476,7 +308,7 @@ void rtl8192_irq_disable(struct net_device *dev)
        priv->irq_enabled = 0;
 }
 
-void rtl8192_set_chan(struct net_device *dev, short ch)
+static void rtl8192_set_chan(struct net_device *dev, short ch)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
@@ -490,7 +322,7 @@ void rtl8192_set_chan(struct net_device *dev, short ch)
                priv->rf_set_chan(dev, priv->chan);
 }
 
-void rtl8192_update_cap(struct net_device *dev, u16 cap)
+static void rtl8192_update_cap(struct net_device *dev, u16 cap)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_network *net = &priv->rtllib->current_network;
@@ -683,7 +515,7 @@ static int rtl8192_qos_association_resp(struct r8192_priv *priv,
        RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __func__,
                 network->flags, priv->rtllib->current_network.qos_data.active);
        if (set_qos_param == 1) {
-               dm_init_edca_turbo(priv->rtllib->dev);
+               rtl92e_dm_init_edca_turbo(priv->rtllib->dev);
                queue_work_rsl(priv->priv_wq, &priv->qos_activate);
        }
        return 0;
@@ -733,7 +565,7 @@ static void rtl8192_stop_beacon(struct net_device *dev)
 {
 }
 
-void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
+void rtl92e_config_rate(struct net_device *dev, u16 *rate_config)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_network *net;
@@ -864,7 +696,7 @@ static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
        return ret;
 }
 
-void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
+void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
@@ -895,9 +727,6 @@ void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
 
        priv->rtllib->mode = wireless_mode;
 
-       ActUpdateChannelAccessSetting(dev, wireless_mode,
-                                     &priv->ChannelAccessSetting);
-
        if ((wireless_mode == WIRELESS_MODE_N_24G) ||
            (wireless_mode == WIRELESS_MODE_N_5G)) {
                priv->rtllib->pHTInfo->bEnableHT = 1;
@@ -941,7 +770,7 @@ static int _rtl8192_sta_up(struct net_device *dev, bool is_silent_reset)
        priv->bfirst_init = false;
 
        if (priv->polling_timer_on == 0)
-               check_rfctrl_gpio_timer((unsigned long)dev);
+               rtl92e_check_rfctrl_gpio_timer((unsigned long)dev);
 
        if (priv->rtllib->state != RTLLIB_LINKED)
                rtllib_softmac_start_protocol(priv->rtllib, 0);
@@ -969,7 +798,7 @@ static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf)
                priv->rtllib->rtllib_ips_leave(dev);
 
        if (priv->rtllib->state == RTLLIB_LINKED)
-               LeisurePSLeave(dev);
+               rtl92e_leisure_ps_leave(dev);
 
        priv->bDriverIsGoingToUnload = true;
        priv->up = 0;
@@ -982,9 +811,9 @@ static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf)
        priv->rtllib->wpa_ie_len = 0;
        kfree(priv->rtllib->wpa_ie);
        priv->rtllib->wpa_ie = NULL;
-       CamResetAllEntry(dev);
+       rtl92e_cam_reset(dev);
        memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
-       rtl8192_irq_disable(dev);
+       rtl92e_irq_disable(dev);
 
        del_timer_sync(&priv->watch_dog_timer);
        rtl8192_cancel_deferred_work(priv);
@@ -1027,38 +856,36 @@ static void rtl8192_init_priv_handler(struct net_device *dev)
        priv->rtllib->set_chan                  = rtl8192_set_chan;
        priv->rtllib->link_change               = priv->ops->link_change;
        priv->rtllib->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
-       priv->rtllib->data_hard_stop            = rtl8192_data_hard_stop;
-       priv->rtllib->data_hard_resume          = rtl8192_data_hard_resume;
        priv->rtllib->check_nic_enough_desc     = rtl8192_check_nic_enough_desc;
        priv->rtllib->handle_assoc_response     = rtl8192_handle_assoc_response;
        priv->rtllib->handle_beacon             = rtl8192_handle_beacon;
-       priv->rtllib->SetWirelessMode           = rtl8192_SetWirelessMode;
-       priv->rtllib->LeisurePSLeave            = LeisurePSLeave;
-       priv->rtllib->SetBWModeHandler          = rtl8192_SetBWMode;
-       priv->rf_set_chan                       = rtl8192_phy_SwChnl;
+       priv->rtllib->SetWirelessMode           = rtl92e_set_wireless_mode;
+       priv->rtllib->LeisurePSLeave            = rtl92e_leisure_ps_leave;
+       priv->rtllib->SetBWModeHandler          = rtl92e_set_bw_mode;
+       priv->rf_set_chan                       = rtl92e_set_channel;
 
-       priv->rtllib->start_send_beacons = rtl8192e_start_beacon;
+       priv->rtllib->start_send_beacons = rtl92e_start_beacon;
        priv->rtllib->stop_send_beacons = rtl8192_stop_beacon;
 
-       priv->rtllib->sta_wake_up = rtl8192_hw_wakeup;
-       priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep;
+       priv->rtllib->sta_wake_up = rtl92e_hw_wakeup;
+       priv->rtllib->enter_sleep_state = rtl92e_enter_sleep;
        priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
 
-       priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg;
+       priv->rtllib->GetNmodeSupportBySecCfg = rtl92e_get_nmode_support_by_sec;
        priv->rtllib->GetHalfNmodeSupportByAPsHandler =
-                                        rtl8192_GetHalfNmodeSupportByAPs;
+                                               rtl92e_is_halfn_supported_by_ap;
 
-       priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg;
-       priv->rtllib->AllowAllDestAddrHandler = rtl8192_AllowAllDestAddr;
+       priv->rtllib->SetHwRegHandler = rtl92e_set_reg;
+       priv->rtllib->AllowAllDestAddrHandler = rtl92e_set_monitor_mode;
        priv->rtllib->SetFwCmdHandler = NULL;
-       priv->rtllib->InitialGainHandler = InitialGain819xPci;
-       priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
-       priv->rtllib->rtllib_ips_leave = rtllib_ips_leave;
+       priv->rtllib->InitialGainHandler = rtl92e_init_gain;
+       priv->rtllib->rtllib_ips_leave_wq = rtl92e_rtllib_ips_leave_wq;
+       priv->rtllib->rtllib_ips_leave = rtl92e_rtllib_ips_leave;
 
        priv->rtllib->LedControlHandler = NULL;
        priv->rtllib->UpdateBeaconInterruptHandler = NULL;
 
-       priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192;
+       priv->rtllib->ScanOperationBackupHandler = rtl92e_scan_op_backup;
 }
 
 static void rtl8192_init_priv_constant(struct net_device *dev)
@@ -1181,20 +1008,21 @@ static void rtl8192_init_priv_task(struct net_device *dev)
 
        priv->priv_wq = create_workqueue(DRV_NAME);
        INIT_WORK_RSL(&priv->reset_wq, (void *)rtl8192_restart, dev);
-       INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)IPSLeave_wq, dev);
+       INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)rtl92e_ips_leave_wq,
+                     dev);
        INIT_DELAYED_WORK_RSL(&priv->watch_dog_wq,
                              (void *)rtl819x_watchdog_wqcallback, dev);
        INIT_DELAYED_WORK_RSL(&priv->txpower_tracking_wq,
-                             (void *)dm_txpower_trackingcallback, dev);
+                             (void *)rtl92e_dm_txpower_tracking_wq, dev);
        INIT_DELAYED_WORK_RSL(&priv->rfpath_check_wq,
-                             (void *)dm_rf_pathcheck_workitemcallback, dev);
+                             (void *)rtl92e_dm_rf_pathcheck_wq, dev);
        INIT_DELAYED_WORK_RSL(&priv->update_beacon_wq,
                              (void *)rtl8192_update_beacon, dev);
        INIT_WORK_RSL(&priv->qos_activate, (void *)rtl8192_qos_activate, dev);
        INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_wakeup_wq,
-                             (void *) rtl8192_hw_wakeup_wq, dev);
+                             (void *) rtl92e_hw_wakeup_wq, dev);
        INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_sleep_wq,
-                             (void *) rtl8192_hw_sleep_wq, dev);
+                             (void *) rtl92e_hw_sleep_wq, dev);
        tasklet_init(&priv->irq_rx_tasklet,
                     (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
                     (unsigned long)priv);
@@ -1250,17 +1078,17 @@ static short rtl8192_init(struct net_device *dev)
        priv->ops->init_adapter_variable(dev);
        rtl8192_get_channel_map(dev);
 
-       init_hal_dm(dev);
+       rtl92e_dm_init(dev);
 
        setup_timer(&priv->watch_dog_timer,
                    watch_dog_timer_callback,
                    (unsigned long) dev);
 
        setup_timer(&priv->gpio_polling_timer,
-                   check_rfctrl_gpio_timer,
+                   rtl92e_check_rfctrl_gpio_timer,
                    (unsigned long)dev);
 
-       rtl8192_irq_disable(dev);
+       rtl92e_irq_disable(dev);
        if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED,
            dev->name, dev)) {
                netdev_err(dev, "Error allocating IRQ %d", dev->irq);
@@ -1282,7 +1110,7 @@ static short rtl8192_init(struct net_device *dev)
 /***************************************************************************
        -------------------------------WATCHDOG STUFF---------------------------
 ***************************************************************************/
-short rtl8192_is_tx_queue_empty(struct net_device *dev)
+static short rtl8192_is_tx_queue_empty(struct net_device *dev)
 {
        int i = 0;
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -1439,7 +1267,7 @@ RESET_START:
                down(&priv->wx_sem);
 
                if (priv->rtllib->state == RTLLIB_LINKED)
-                       LeisurePSLeave(dev);
+                       rtl92e_leisure_ps_leave(dev);
 
                if (priv->up) {
                        netdev_info(dev, "%s():the driver is not up.\n",
@@ -1459,10 +1287,10 @@ RESET_START:
                if (!netif_queue_stopped(dev))
                        netif_stop_queue(dev);
 
-               rtl8192_irq_disable(dev);
+               rtl92e_irq_disable(dev);
                del_timer_sync(&priv->watch_dog_timer);
                rtl8192_cancel_deferred_work(priv);
-               deinit_hal_dm(dev);
+               rtl92e_dm_deinit(dev);
                rtllib_stop_scan_syncro(ieee);
 
                if (ieee->state == RTLLIB_LINKED) {
@@ -1479,7 +1307,7 @@ RESET_START:
                        rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
                }
 
-               dm_backup_dynamic_mechanism_state(dev);
+               rtl92e_dm_backup_state(dev);
 
                up(&priv->wx_sem);
                RT_TRACE(COMP_RESET,
@@ -1508,7 +1336,7 @@ RESET_START:
                priv->RFChangeInProgress = false;
                spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
 
-               EnableHWSecurityConfig8192(dev);
+               rtl92e_enable_hw_security_config(dev);
 
                if (ieee->state == RTLLIB_LINKED && ieee->iw_mode ==
                    IW_MODE_INFRA) {
@@ -1527,15 +1355,13 @@ RESET_START:
 
                        rtllib_start_send_beacons(ieee);
 
-                       if (ieee->data_hard_resume)
-                               ieee->data_hard_resume(ieee->dev);
                        netif_carrier_on(ieee->dev);
                } else if (ieee->iw_mode == IW_MODE_MESH) {
                        rtl819x_silentreset_mesh_bk(dev, IsPortal);
                }
 
-               CamRestoreAllEntry(dev);
-               dm_restore_dynamic_mechanism_state(dev);
+               rtl92e_cam_restore(dev);
+               rtl92e_dm_restore_state(dev);
 END:
                priv->ResetProgress = RESET_TYPE_NORESET;
                priv->reset_count++;
@@ -1543,7 +1369,7 @@ END:
                priv->bForcedSilentReset = false;
                priv->bResetInProgress = false;
 
-               write_nic_byte(dev, UFWP, 1);
+               rtl92e_writeb(dev, UFWP, 1);
                RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n",
                         priv->reset_count);
        }
@@ -1570,8 +1396,7 @@ static void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
        }
 }
 
-
-void   rtl819x_watchdog_wqcallback(void *data)
+static void rtl819x_watchdog_wqcallback(void *data)
 {
        struct r8192_priv *priv = container_of_dwork_rsl(data,
                                  struct r8192_priv, watch_dog_wq);
@@ -1597,7 +1422,7 @@ void      rtl819x_watchdog_wqcallback(void *data)
                priv->rtllib->CntAfterLink = 0;
        }
 
-       hal_dm_watchdog(dev);
+       rtl92e_dm_watchdog(dev);
 
        if (rtllib_act_scanning(priv->rtllib, false) == false) {
                if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state ==
@@ -1608,8 +1433,8 @@ void      rtl819x_watchdog_wqcallback(void *data)
                             IPS_CALLBACK_NONE) &&
                             (!ieee->bNetPromiscuousMode)) {
                                RT_TRACE(COMP_PS,
-                                        "====================>haha: IPSEnter()\n");
-                               IPSEnter(dev);
+                                        "====================>haha: rtl92e_ips_enter()\n");
+                               rtl92e_ips_enter(dev);
                        }
                }
        }
@@ -1640,13 +1465,13 @@ void    rtl819x_watchdog_wqcallback(void *data)
                        bEnterPS = false;
 
                if (bEnterPS)
-                       LeisurePSEnter(dev);
+                       rtl92e_leisure_ps_enter(dev);
                else
-                       LeisurePSLeave(dev);
+                       rtl92e_leisure_ps_leave(dev);
 
        } else {
                RT_TRACE(COMP_LPS, "====>no link LPS leave\n");
-               LeisurePSLeave(dev);
+               rtl92e_leisure_ps_leave(dev);
        }
 
        ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
@@ -1725,7 +1550,7 @@ void      rtl819x_watchdog_wqcallback(void *data)
        RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
 }
 
-void watch_dog_timer_callback(unsigned long data)
+static void watch_dog_timer_callback(unsigned long data)
 {
        struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
 
@@ -1737,14 +1562,14 @@ void watch_dog_timer_callback(unsigned long data)
 /****************************************************************************
  ---------------------------- NIC TX/RX STUFF---------------------------
 *****************************************************************************/
-void rtl8192_rx_enable(struct net_device *dev)
+void rtl92e_rx_enable(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
        priv->ops->rx_enable(dev);
 }
 
-void rtl8192_tx_enable(struct net_device *dev)
+void rtl92e_tx_enable(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
@@ -1802,16 +1627,7 @@ static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
        ring->desc = NULL;
 }
 
-void rtl8192_data_hard_stop(struct net_device *dev)
-{
-}
-
-
-void rtl8192_data_hard_resume(struct net_device *dev)
-{
-}
-
-void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
                            int rate)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -1826,8 +1642,8 @@ void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
                return;
        }
 
-       if (queue_index != TXCMD_QUEUE)
-               netdev_warn(dev, "%s(): queue index != TXCMD_QUEUE\n",
+       if (queue_index == TXCMD_QUEUE)
+               netdev_warn(dev, "%s(): queue index == TXCMD_QUEUE\n",
                            __func__);
 
        memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
@@ -1843,7 +1659,7 @@ void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
        }
 }
 
-int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
        int ret;
@@ -1902,7 +1718,7 @@ static void rtl8192_tx_isr(struct net_device *dev, int prio)
                tasklet_schedule(&priv->irq_tx_tasklet);
 }
 
-void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
+static void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtl8192_tx_ring *ring;
@@ -1925,7 +1741,7 @@ void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
        spin_unlock_irqrestore(&priv->irq_th_lock, flags);
 }
 
-short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
+static short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtl8192_tx_ring  *ring;
@@ -1997,7 +1813,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
        spin_unlock_irqrestore(&priv->irq_th_lock, flags);
        dev->trans_start = jiffies;
 
-       write_nic_word(dev, TPPoll, 0x01 << tcb_desc->queue_index);
+       rtl92e_writew(dev, TPPoll, 0x01 << tcb_desc->queue_index);
        return 0;
 }
 
@@ -2077,8 +1893,7 @@ static int rtl8192_alloc_tx_desc_ring(struct net_device *dev,
        return 0;
 }
 
-
-short rtl8192_pci_initdescring(struct net_device *dev)
+static short rtl8192_pci_initdescring(struct net_device *dev)
 {
        u32 ret;
        int i;
@@ -2104,7 +1919,7 @@ err_free_rings:
        return 1;
 }
 
-void rtl8192_pci_resetdescring(struct net_device *dev)
+void rtl92e_reset_desc_ring(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        int i, rx_queue_idx;
@@ -2144,8 +1959,8 @@ void rtl8192_pci_resetdescring(struct net_device *dev)
        spin_unlock_irqrestore(&priv->irq_th_lock, flags);
 }
 
-void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
-                                 struct rtllib_rx_stats *stats)
+void rtl92e_update_rx_pkt_timestamp(struct net_device *dev,
+                                   struct rtllib_rx_stats *stats)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
@@ -2155,7 +1970,7 @@ void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
                priv->LastRxDescTSF = stats->mac_time;
 }
 
-long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index)
+long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index)
 {
        long    signal_power;
 
@@ -2166,11 +1981,8 @@ long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index)
 }
 
 
-void
-rtl819x_update_rxsignalstatistics8190pci(
-       struct r8192_priv *priv,
-       struct rtllib_rx_stats *pprevious_stats
-       )
+void rtl92e_update_rx_statistics(struct r8192_priv *priv,
+                                struct rtllib_rx_stats *pprevious_stats)
 {
        int weighting = 0;
 
@@ -2189,13 +2001,7 @@ rtl819x_update_rxsignalstatistics8190pci(
                                        weighting) / 6;
 }
 
-void rtl819x_process_cck_rxpathsel(struct r8192_priv *priv,
-                                  struct rtllib_rx_stats *pprevious_stats)
-{
-}
-
-
-u8 rtl819x_query_rxpwrpercentage(char antpower)
+u8 rtl92e_rx_db_to_percent(char antpower)
 {
        if ((antpower <= -100) || (antpower >= 20))
                return  0;
@@ -2206,10 +2012,7 @@ u8 rtl819x_query_rxpwrpercentage(char antpower)
 
 }      /* QueryRxPwrPercentage */
 
-u8
-rtl819x_evm_dbtopercentage(
-       char value
-       )
+u8 rtl92e_evm_db_to_percent(char value)
 {
        char ret_val;
 
@@ -2226,11 +2029,8 @@ rtl819x_evm_dbtopercentage(
        return ret_val;
 }
 
-void
-rtl8192_record_rxdesc_forlateruse(
-       struct rtllib_rx_stats *psrc_stats,
-       struct rtllib_rx_stats *ptarget_stats
-)
+void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats,
+                           struct rtllib_rx_stats *ptarget_stats)
 {
        ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
        ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
@@ -2344,11 +2144,6 @@ done:
 
 }
 
-static void rtl8192_rx_cmd(struct net_device *dev)
-{
-}
-
-
 static void rtl8192_tx_resume(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -2366,26 +2161,23 @@ static void rtl8192_tx_resume(struct net_device *dev)
        }
 }
 
-void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
+static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
 {
        rtl8192_tx_resume(priv->rtllib->dev);
 }
 
-void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
+static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
 {
        rtl8192_rx_normal(priv->rtllib->dev);
 
-       if (MAX_RX_QUEUE > 1)
-               rtl8192_rx_cmd(priv->rtllib->dev);
-
-       write_nic_dword(priv->rtllib->dev, INTA_MASK,
-                       read_nic_dword(priv->rtllib->dev, INTA_MASK) | IMR_RDU);
+       rtl92e_writel(priv->rtllib->dev, INTA_MASK,
+                     rtl92e_readl(priv->rtllib->dev, INTA_MASK) | IMR_RDU);
 }
 
 /****************************************************************************
  ---------------------------- NIC START/CLOSE STUFF---------------------------
 *****************************************************************************/
-void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
+static void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
 {
        cancel_delayed_work(&priv->watch_dog_wq);
        cancel_delayed_work(&priv->update_beacon_wq);
@@ -2394,14 +2186,13 @@ void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
        cancel_work_sync(&priv->qos_activate);
 }
 
-int _rtl8192_up(struct net_device *dev, bool is_silent_reset)
+static int _rtl8192_up(struct net_device *dev, bool is_silent_reset)
 {
        if (_rtl8192_sta_up(dev, is_silent_reset) == -1)
                return -1;
        return 0;
 }
 
-
 static int rtl8192_open(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -2414,8 +2205,7 @@ static int rtl8192_open(struct net_device *dev)
 
 }
 
-
-int rtl8192_up(struct net_device *dev)
+static int rtl8192_up(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -2445,7 +2235,7 @@ static int rtl8192_close(struct net_device *dev)
 
 }
 
-int rtl8192_down(struct net_device *dev, bool shutdownrf)
+static int rtl8192_down(struct net_device *dev, bool shutdownrf)
 {
        if (rtl8192_sta_down(dev, shutdownrf) == -1)
                return -1;
@@ -2453,19 +2243,19 @@ int rtl8192_down(struct net_device *dev, bool shutdownrf)
        return 0;
 }
 
-void rtl8192_commit(struct net_device *dev)
+void rtl92e_commit(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
        if (priv->up == 0)
                return;
        rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
-       rtl8192_irq_disable(dev);
+       rtl92e_irq_disable(dev);
        priv->ops->stop_adapter(dev, true);
        _rtl8192_up(dev, false);
 }
 
-void rtl8192_restart(void *data)
+static void rtl8192_restart(void *data)
 {
        struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv,
                                  reset_wq);
@@ -2473,7 +2263,7 @@ void rtl8192_restart(void *data)
 
        down(&priv->wx_sem);
 
-       rtl8192_commit(dev);
+       rtl92e_commit(dev);
 
        up(&priv->wx_sem);
 }
@@ -2552,30 +2342,34 @@ static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                        if (is_zero_ether_addr(ieee->ap_mac_addr))
                                                ieee->iw_mode = IW_MODE_ADHOC;
                                        memcpy((u8 *)key, ipw->u.crypt.key, 16);
-                                       EnableHWSecurityConfig8192(dev);
-                                       set_swcam(dev, 4, ipw->u.crypt.idx,
-                                                 ieee->pairwise_key_type,
-                                                 (u8 *)ieee->ap_mac_addr,
-                                                 0, key, 0);
-                                       setKey(dev, 4, ipw->u.crypt.idx,
-                                              ieee->pairwise_key_type,
-                                              (u8 *)ieee->ap_mac_addr, 0, key);
-                                       if (ieee->iw_mode == IW_MODE_ADHOC) {
-                                               set_swcam(dev, ipw->u.crypt.idx,
-                                                       ipw->u.crypt.idx,
-                                                       ieee->pairwise_key_type,
-                                                       (u8 *)ieee->ap_mac_addr,
-                                                       0, key, 0);
-                                               setKey(dev, ipw->u.crypt.idx,
-                                                      ipw->u.crypt.idx,
+                                       rtl92e_enable_hw_security_config(dev);
+                                       rtl92e_set_swcam(dev, 4,
+                                                        ipw->u.crypt.idx,
+                                                        ieee->pairwise_key_type,
+                                                        (u8 *)ieee->ap_mac_addr,
+                                                        0, key, 0);
+                                       rtl92e_set_key(dev, 4, ipw->u.crypt.idx,
                                                       ieee->pairwise_key_type,
                                                       (u8 *)ieee->ap_mac_addr,
                                                       0, key);
+                                       if (ieee->iw_mode == IW_MODE_ADHOC) {
+                                               rtl92e_set_swcam(dev,
+                                                                ipw->u.crypt.idx,
+                                                                ipw->u.crypt.idx,
+                                                                ieee->pairwise_key_type,
+                                                                (u8 *)ieee->ap_mac_addr,
+                                                                0, key, 0);
+                                               rtl92e_set_key(dev,
+                                                              ipw->u.crypt.idx,
+                                                              ipw->u.crypt.idx,
+                                                              ieee->pairwise_key_type,
+                                                              (u8 *)ieee->ap_mac_addr,
+                                                              0, key);
                                        }
                                }
                                if ((ieee->pairwise_key_type == KEY_TYPE_CCMP)
                                     && ieee->pHTInfo->bCurrentHTSupport) {
-                                       write_nic_byte(dev, 0x173, 1);
+                                       rtl92e_writeb(dev, 0x173, 1);
                                }
 
                        } else {
@@ -2595,14 +2389,15 @@ static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                        ieee->group_key_type = KEY_TYPE_NA;
 
                                if (ieee->group_key_type) {
-                                       set_swcam(dev, ipw->u.crypt.idx,
-                                                 ipw->u.crypt.idx,
-                                                 ieee->group_key_type,
-                                                 broadcast_addr, 0, key, 0);
-                                       setKey(dev, ipw->u.crypt.idx,
-                                              ipw->u.crypt.idx,
-                                              ieee->group_key_type,
-                                              broadcast_addr, 0, key);
+                                       rtl92e_set_swcam(dev, ipw->u.crypt.idx,
+                                                        ipw->u.crypt.idx,
+                                                        ieee->group_key_type,
+                                                        broadcast_addr, 0, key,
+                                                        0);
+                                       rtl92e_set_key(dev, ipw->u.crypt.idx,
+                                                      ipw->u.crypt.idx,
+                                                      ieee->group_key_type,
+                                                      broadcast_addr, 0, key);
                                }
                        }
                }
@@ -2707,8 +2502,8 @@ static irqreturn_t rtl8192_interrupt(int irq, void *netdev)
        if (inta & IMR_RDU) {
                RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
                priv->stats.rxrdu++;
-               write_nic_dword(dev, INTA_MASK,
-                               read_nic_dword(dev, INTA_MASK) & ~IMR_RDU);
+               rtl92e_writel(dev, INTA_MASK,
+                             rtl92e_readl(dev, INTA_MASK) & ~IMR_RDU);
                tasklet_schedule(&priv->irq_rx_tasklet);
        }
 
@@ -2782,7 +2577,6 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
        struct rtl819x_ops *ops = (struct rtl819x_ops *)(id->driver_data);
        unsigned long pmem_start, pmem_len, pmem_flags;
        int err = -ENOMEM;
-       bool bdma64 = false;
        u8 revision_id;
 
        RT_TRACE(COMP_INIT, "Configuring chip resources");
@@ -2806,8 +2600,6 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
                goto err_pci_disable;
 
        err = -ENODEV;
-       if (bdma64)
-               dev->features |= NETIF_F_HIGHDMA;
 
        pci_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
@@ -2850,12 +2642,12 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
        pci_read_config_byte(pdev, 0x08, &revision_id);
        /* If the revisionid is 0x10, the device uses rtl8192se. */
        if (pdev->device == 0x8192 && revision_id == 0x10)
-               goto err_rel_mem;
+               goto err_unmap;
 
        priv->ops = ops;
 
-       if (rtl8192_pci_findadapter(pdev, dev) == false)
-               goto err_rel_mem;
+       if (rtl92e_check_adapter(pdev, dev) == false)
+               goto err_unmap;
 
        dev->irq = pdev->irq;
        priv->irq = 0;
@@ -2888,7 +2680,7 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
        RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name);
 
        if (priv->polling_timer_on == 0)
-               check_rfctrl_gpio_timer((unsigned long)dev);
+               rtl92e_check_rfctrl_gpio_timer((unsigned long)dev);
 
        RT_TRACE(COMP_INIT, "Driver probe completed\n");
        return 0;
@@ -2896,12 +2688,12 @@ static int rtl8192_pci_probe(struct pci_dev *pdev,
 err_free_irq:
        free_irq(dev->irq, dev);
        priv->irq = 0;
+err_unmap:
+       iounmap((void __iomem *)ioaddr);
 err_rel_mem:
        release_mem_region(pmem_start, pmem_len);
 err_rel_rtllib:
        free_rtllib(dev);
-
-       DMESG("wlan driver load failed\n");
 err_pci_disable:
        pci_disable_device(pdev);
        return err;
@@ -2922,7 +2714,7 @@ static void rtl8192_pci_disconnect(struct pci_dev *pdev)
                cancel_delayed_work(&priv->gpio_change_rf_wq);
                priv->polling_timer_on = 0;
                rtl8192_down(dev, true);
-               deinit_hal_dm(dev);
+               rtl92e_dm_deinit(dev);
                if (priv->pFirmware) {
                        vfree(priv->pFirmware);
                        priv->pFirmware = NULL;
@@ -2952,7 +2744,7 @@ static void rtl8192_pci_disconnect(struct pci_dev *pdev)
        RT_TRACE(COMP_DOWN, "wlan driver removed\n");
 }
 
-bool NicIFEnableNIC(struct net_device *dev)
+bool rtl92e_enable_nic(struct net_device *dev)
 {
        bool init_status = true;
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -2977,12 +2769,12 @@ bool NicIFEnableNIC(struct net_device *dev)
        RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
        priv->bfirst_init = false;
 
-       rtl8192_irq_enable(dev);
+       rtl92e_irq_enable(dev);
        priv->bdisable_nic = false;
        RT_TRACE(COMP_PS, "<===========%s()\n", __func__);
        return init_status;
 }
-bool NicIFDisableNIC(struct net_device *dev)
+bool rtl92e_disable_nic(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u8 tmp_state = 0;
@@ -2993,7 +2785,7 @@ bool NicIFDisableNIC(struct net_device *dev)
        rtllib_softmac_stop_protocol(priv->rtllib, 0, false);
        priv->rtllib->state = tmp_state;
        rtl8192_cancel_deferred_work(priv);
-       rtl8192_irq_disable(dev);
+       rtl92e_irq_disable(dev);
 
        priv->ops->stop_adapter(dev, false);
        RT_TRACE(COMP_PS, "<=========%s()\n", __func__);
@@ -3007,7 +2799,6 @@ static int __init rtl8192_pci_module_init(void)
        pr_info("Copyright (c) 2007-2008, Realsil Wlan Driver\n");
 
        if (0 != pci_register_driver(&rtl8192_pci_driver)) {
-               DMESG("No device found");
                /*pci_unregister_driver (&rtl8192_pci_driver);*/
                return -ENODEV;
        }
@@ -3021,7 +2812,7 @@ static void __exit rtl8192_pci_module_exit(void)
        RT_TRACE(COMP_DOWN, "Exiting");
 }
 
-void check_rfctrl_gpio_timer(unsigned long data)
+void rtl92e_check_rfctrl_gpio_timer(unsigned long data)
 {
        struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
 
index 776d950655cba16763189bd11c7ce4732ec8621f..cd948bb1384018169b2b6686735ac380e0ff7424 100644 (file)
@@ -578,84 +578,44 @@ struct r8192_priv {
 
 extern const struct ethtool_ops rtl819x_ethtool_ops;
 
-void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb);
-short rtl8192_tx(struct net_device *dev, struct sk_buff *skb);
-
-u8 read_nic_io_byte(struct net_device *dev, int x);
-u32 read_nic_io_dword(struct net_device *dev, int x);
-u16 read_nic_io_word(struct net_device *dev, int x);
-void write_nic_io_byte(struct net_device *dev, int x, u8 y);
-void write_nic_io_word(struct net_device *dev, int x, u16 y);
-void write_nic_io_dword(struct net_device *dev, int x, u32 y);
-
-u8 read_nic_byte(struct net_device *dev, int x);
-u32 read_nic_dword(struct net_device *dev, int x);
-u16 read_nic_word(struct net_device *dev, int x);
-void write_nic_byte(struct net_device *dev, int x, u8 y);
-void write_nic_word(struct net_device *dev, int x, u16 y);
-void write_nic_dword(struct net_device *dev, int x, u32 y);
+u8 rtl92e_readb(struct net_device *dev, int x);
+u32 rtl92e_readl(struct net_device *dev, int x);
+u16 rtl92e_readw(struct net_device *dev, int x);
+void rtl92e_writeb(struct net_device *dev, int x, u8 y);
+void rtl92e_writew(struct net_device *dev, int x, u16 y);
+void rtl92e_writel(struct net_device *dev, int x, u32 y);
 
 void force_pci_posting(struct net_device *dev);
 
-void rtl8192_rx_enable(struct net_device *);
-void rtl8192_tx_enable(struct net_device *);
-
-int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
-void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
-                           int rate);
-void rtl8192_data_hard_stop(struct net_device *dev);
-void rtl8192_data_hard_resume(struct net_device *dev);
-void rtl8192_restart(void *data);
-void rtl819x_watchdog_wqcallback(void *data);
-void rtl8192_hw_sleep_wq(void *data);
-void watch_dog_timer_callback(unsigned long data);
-void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
-void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
-int rtl8192_down(struct net_device *dev, bool shutdownrf);
-int rtl8192_up(struct net_device *dev);
-void rtl8192_commit(struct net_device *dev);
-void rtl8192_set_chan(struct net_device *dev, short ch);
-
-void check_rfctrl_gpio_timer(unsigned long data);
-
-void rtl8192_hw_wakeup_wq(void *data);
-short rtl8192_pci_initdescring(struct net_device *dev);
-
-void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
-
-int _rtl8192_up(struct net_device *dev, bool is_silent_reset);
-
-short rtl8192_is_tx_queue_empty(struct net_device *dev);
-void rtl8192_irq_disable(struct net_device *dev);
-
-void rtl8192_tx_timeout(struct net_device *dev);
-void rtl8192_pci_resetdescring(struct net_device *dev);
-void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode);
-void rtl8192_irq_enable(struct net_device *dev);
-void rtl8192_config_rate(struct net_device *dev, u16 *rate_config);
-void rtl8192_update_cap(struct net_device *dev, u16 cap);
-void rtl8192_irq_disable(struct net_device *dev);
-
-void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
-                                 struct rtllib_rx_stats *stats);
-long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index);
-void rtl819x_update_rxsignalstatistics8190pci(struct r8192_priv *priv,
-                                     struct rtllib_rx_stats *pprevious_stats);
-u8 rtl819x_evm_dbtopercentage(char value);
-void rtl819x_process_cck_rxpathsel(struct r8192_priv *priv,
-                                  struct rtllib_rx_stats *pprevious_stats);
-u8 rtl819x_query_rxpwrpercentage(char antpower);
-void rtl8192_record_rxdesc_forlateruse(struct rtllib_rx_stats *psrc_stats,
-                                      struct rtllib_rx_stats *ptarget_stats);
-bool NicIFEnableNIC(struct net_device *dev);
-bool NicIFDisableNIC(struct net_device *dev);
-
-bool MgntActSet_RF_State(struct net_device *dev,
-                        enum rt_rf_power_state StateToSet,
-                        RT_RF_CHANGE_SOURCE ChangeSource,
-                        bool   ProtectOrNot);
-void ActUpdateChannelAccessSetting(struct net_device *dev,
-                          enum wireless_mode WirelessMode,
-                          struct channel_access_setting *ChnlAccessSetting);
+void rtl92e_rx_enable(struct net_device *);
+void rtl92e_tx_enable(struct net_device *);
+
+void rtl92e_hw_sleep_wq(void *data);
+void rtl92e_commit(struct net_device *dev);
+
+void rtl92e_check_rfctrl_gpio_timer(unsigned long data);
+
+void rtl92e_hw_wakeup_wq(void *data);
 
+void rtl92e_reset_desc_ring(struct net_device *dev);
+void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode);
+void rtl92e_irq_enable(struct net_device *dev);
+void rtl92e_config_rate(struct net_device *dev, u16 *rate_config);
+void rtl92e_irq_disable(struct net_device *dev);
+
+void rtl92e_update_rx_pkt_timestamp(struct net_device *dev,
+                                   struct rtllib_rx_stats *stats);
+long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index);
+void rtl92e_update_rx_statistics(struct r8192_priv *priv,
+                                struct rtllib_rx_stats *pprevious_stats);
+u8 rtl92e_evm_db_to_percent(char value);
+u8 rtl92e_rx_db_to_percent(char antpower);
+void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats,
+                           struct rtllib_rx_stats *ptarget_stats);
+bool rtl92e_enable_nic(struct net_device *dev);
+bool rtl92e_disable_nic(struct net_device *dev);
+
+bool rtl92e_set_rf_state(struct net_device *dev,
+                        enum rt_rf_power_state StateToSet,
+                        RT_RF_CHANGE_SOURCE ChangeSource);
 #endif
index 3de7cc549794803cfaac646a6b96440544e73040..1a0c690bfa075d45adb3ca3dcf8efa2d185c73a8 100644 (file)
@@ -58,9 +58,6 @@ static u32 edca_setting_UL[HT_IOT_PEER_MAX] = {
        0x5e4332
 };
 
-#define RTK_UL_EDCA 0xa44f
-#define RTK_DL_EDCA 0x5e4322
-
 const u32 dm_tx_bb_gain[TxBBGainTableLength] = {
        0x7f8001fe, /* 12 dB */
        0x788001e2, /* 11 dB */
@@ -213,6 +210,9 @@ static void dm_deInit_fsync(struct net_device *dev);
 
 static void dm_check_txrateandretrycount(struct net_device *dev);
 static  void dm_check_ac_dc_power(struct net_device *dev);
+static void dm_check_fsync(struct net_device *dev);
+static void dm_CheckRfCtrlGPIO(void *data);
+static void dm_fsync_timer_callback(unsigned long data);
 
 /*---------------------Define local function prototype-----------------------*/
 
@@ -224,7 +224,7 @@ static      void dm_send_rssi_tofw(struct net_device *dev);
 static void    dm_ctstoself(struct net_device *dev);
 /*---------------------------Define function prototype------------------------*/
 
-void init_hal_dm(struct net_device *dev)
+void rtl92e_dm_init(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -234,10 +234,10 @@ void init_hal_dm(struct net_device *dev)
 
        dm_init_dynamic_txpower(dev);
 
-       init_rate_adaptive(dev);
+       rtl92e_init_adaptive_rate(dev);
 
        dm_dig_init(dev);
-       dm_init_edca_turbo(dev);
+       rtl92e_dm_init_edca_turbo(dev);
        dm_init_bandwidth_autoswitch(dev);
        dm_init_fsync(dev);
        dm_init_rxpath_selection(dev);
@@ -249,14 +249,14 @@ void init_hal_dm(struct net_device *dev)
                              (void *)dm_CheckRfCtrlGPIO, dev);
 }
 
-void deinit_hal_dm(struct net_device *dev)
+void rtl92e_dm_deinit(struct net_device *dev)
 {
 
        dm_deInit_fsync(dev);
 
 }
 
-void hal_dm_watchdog(struct net_device *dev)
+void rtl92e_dm_watchdog(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -307,7 +307,7 @@ static void dm_check_ac_dc_power(struct net_device *dev)
 };
 
 
-void init_rate_adaptive(struct net_device *dev)
+void rtl92e_init_adaptive_rate(struct net_device *dev)
 {
 
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -444,7 +444,7 @@ static void dm_check_rate_adaptive(struct net_device *dev)
                if (priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev))
                        targetRATR &=  0xf00fffff;
 
-               currentRATR = read_nic_dword(dev, RATR0);
+               currentRATR = rtl92e_readl(dev, RATR0);
                if (targetRATR !=  currentRATR) {
                        u32 ratr_value;
 
@@ -454,8 +454,8 @@ static void dm_check_rate_adaptive(struct net_device *dev)
                                 currentRATR, targetRATR);
                        if (priv->rf_type == RF_1T2R)
                                ratr_value &= ~(RATE_ALL_OFDM_2SS);
-                       write_nic_dword(dev, RATR0, ratr_value);
-                       write_nic_byte(dev, UFWP, 1);
+                       rtl92e_writel(dev, RATR0, ratr_value);
+                       rtl92e_writeb(dev, UFWP, 1);
 
                        pra->last_ratr = targetRATR;
                }
@@ -561,40 +561,40 @@ static void dm_tx_update_tssi_weak_signal(struct net_device *dev, u8 RF_Type)
                        p->rfa_txpowertrackingindex--;
                        if (p->rfa_txpowertrackingindex_real > 4) {
                                p->rfa_txpowertrackingindex_real--;
-                               rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                                bMaskDWord,
-                                                dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+                               rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                                 bMaskDWord,
+                                                 dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
                        }
 
                        p->rfc_txpowertrackingindex--;
                        if (p->rfc_txpowertrackingindex_real > 4) {
                                p->rfc_txpowertrackingindex_real--;
-                               rtl8192_setBBreg(dev,
-                                                rOFDM0_XCTxIQImbalance,
-                                                bMaskDWord,
-                                                dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
+                               rtl92e_set_bb_reg(dev,
+                                                 rOFDM0_XCTxIQImbalance,
+                                                 bMaskDWord,
+                                                 dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
                        }
                } else {
-                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                        bMaskDWord,
-                                        dm_tx_bb_gain[4]);
-                       rtl8192_setBBreg(dev,
-                                        rOFDM0_XCTxIQImbalance,
-                                        bMaskDWord, dm_tx_bb_gain[4]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[4]);
+                       rtl92e_set_bb_reg(dev,
+                                         rOFDM0_XCTxIQImbalance,
+                                         bMaskDWord, dm_tx_bb_gain[4]);
                }
        } else {
                if (p->rfa_txpowertrackingindex > 0) {
                        p->rfa_txpowertrackingindex--;
                        if (p->rfa_txpowertrackingindex_real > 4) {
                                p->rfa_txpowertrackingindex_real--;
-                               rtl8192_setBBreg(dev,
-                                                rOFDM0_XATxIQImbalance,
-                                                bMaskDWord,
-                                                dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+                               rtl92e_set_bb_reg(dev,
+                                                 rOFDM0_XATxIQImbalance,
+                                                 bMaskDWord,
+                                                 dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
                        }
                } else {
-                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                        bMaskDWord, dm_tx_bb_gain[4]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                         bMaskDWord, dm_tx_bb_gain[4]);
                }
        }
 }
@@ -608,36 +608,33 @@ static void dm_tx_update_tssi_strong_signal(struct net_device *dev, u8 RF_Type)
                    (p->rfc_txpowertrackingindex < TxBBGainTableLength - 1)) {
                        p->rfa_txpowertrackingindex++;
                        p->rfa_txpowertrackingindex_real++;
-                       rtl8192_setBBreg(dev,
-                                rOFDM0_XATxIQImbalance,
-                                bMaskDWord,
-                                dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
                        p->rfc_txpowertrackingindex++;
                        p->rfc_txpowertrackingindex_real++;
-                       rtl8192_setBBreg(dev,
-                                rOFDM0_XCTxIQImbalance,
-                                bMaskDWord,
-                                dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
                } else {
-                       rtl8192_setBBreg(dev,
-                                rOFDM0_XATxIQImbalance,
-                                bMaskDWord,
-                                dm_tx_bb_gain[TxBBGainTableLength - 1]);
-                       rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance,
-                                        bMaskDWord,
-                                        dm_tx_bb_gain[TxBBGainTableLength - 1]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[TxBBGainTableLength - 1]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[TxBBGainTableLength - 1]);
                }
        } else {
                if (p->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) {
                        p->rfa_txpowertrackingindex++;
                        p->rfa_txpowertrackingindex_real++;
-                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                        bMaskDWord,
-                                        dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
                } else {
-                       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
-                                        bMaskDWord,
-                                        dm_tx_bb_gain[TxBBGainTableLength - 1]);
+                       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                         bMaskDWord,
+                                         dm_tx_bb_gain[TxBBGainTableLength - 1]);
                }
        }
 }
@@ -656,8 +653,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
        u32     delta = 0;
 
        RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__);
-       write_nic_byte(dev, Pw_Track_Flag, 0);
-       write_nic_byte(dev, FW_Busy_Flag, 0);
+       rtl92e_writeb(dev, Pw_Track_Flag, 0);
+       rtl92e_writeb(dev, FW_Busy_Flag, 0);
        priv->rtllib->bdynamic_txpower_enable = false;
        bHighpowerstate = priv->bDynamicTxHighPower;
 
@@ -674,12 +671,11 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                tx_cmd.Op               = TXCMD_SET_TX_PWR_TRACKING;
                tx_cmd.Length   = 4;
                tx_cmd.Value            = Value;
-               cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
-                                      DESC_PACKET_TYPE_INIT,
-                                      sizeof(struct dcmd_txcmd));
+               rtl92e_send_cmd_pkt(dev, (u8 *)&tx_cmd, DESC_PACKET_TYPE_INIT,
+                                   sizeof(struct dcmd_txcmd));
                mdelay(1);
                for (i = 0; i <= 30; i++) {
-                       Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag);
+                       Pwr_Flag = rtl92e_readb(dev, Pw_Track_Flag);
 
                        if (Pwr_Flag == 0) {
                                mdelay(1);
@@ -687,35 +683,35 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                                if (priv->bResetInProgress) {
                                        RT_TRACE(COMP_POWER_TRACKING,
                                                 "we are in silent reset progress, so return\n");
-                                       write_nic_byte(dev, Pw_Track_Flag, 0);
-                                       write_nic_byte(dev, FW_Busy_Flag, 0);
+                                       rtl92e_writeb(dev, Pw_Track_Flag, 0);
+                                       rtl92e_writeb(dev, FW_Busy_Flag, 0);
                                        return;
                                }
                                if (priv->rtllib->eRFPowerState != eRfOn) {
                                        RT_TRACE(COMP_POWER_TRACKING,
                                                 "we are in power save, so return\n");
-                                       write_nic_byte(dev, Pw_Track_Flag, 0);
-                                       write_nic_byte(dev, FW_Busy_Flag, 0);
+                                       rtl92e_writeb(dev, Pw_Track_Flag, 0);
+                                       rtl92e_writeb(dev, FW_Busy_Flag, 0);
                                        return;
                                }
 
                                continue;
                        }
 
-                       Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value);
+                       Avg_TSSI_Meas = rtl92e_readw(dev, Tssi_Mea_Value);
 
                        if (Avg_TSSI_Meas == 0) {
-                               write_nic_byte(dev, Pw_Track_Flag, 0);
-                               write_nic_byte(dev, FW_Busy_Flag, 0);
+                               rtl92e_writeb(dev, Pw_Track_Flag, 0);
+                               rtl92e_writeb(dev, FW_Busy_Flag, 0);
                                return;
                        }
 
                        for (k = 0; k < 5; k++) {
                                if (k != 4)
-                                       tmp_report[k] = read_nic_byte(dev,
+                                       tmp_report[k] = rtl92e_readb(dev,
                                                         Tssi_Report_Value1+k);
                                else
-                                       tmp_report[k] = read_nic_byte(dev,
+                                       tmp_report[k] = rtl92e_readb(dev,
                                                         Tssi_Report_Value2);
 
                                RT_TRACE(COMP_POWER_TRACKING,
@@ -729,7 +725,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                        }
 
                        if (viviflag) {
-                               write_nic_byte(dev, Pw_Track_Flag, 0);
+                               rtl92e_writeb(dev, Pw_Track_Flag, 0);
                                viviflag = false;
                                RT_TRACE(COMP_POWER_TRACKING,
                                         "we filted this data\n");
@@ -756,8 +752,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
 
                        if (delta <= E_FOR_TX_POWER_TRACK) {
                                priv->rtllib->bdynamic_txpower_enable = true;
-                               write_nic_byte(dev, Pw_Track_Flag, 0);
-                               write_nic_byte(dev, FW_Busy_Flag, 0);
+                               rtl92e_writeb(dev, Pw_Track_Flag, 0);
+                               rtl92e_writeb(dev, FW_Busy_Flag, 0);
                                RT_TRACE(COMP_POWER_TRACKING,
                                         "tx power track is done\n");
                                RT_TRACE(COMP_POWER_TRACKING,
@@ -806,12 +802,12 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                                if (priv->rtllib->current_network.channel == 14 &&
                                    !priv->bcck_in_ch14) {
                                        priv->bcck_in_ch14 = true;
-                                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                                } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) {
                                        priv->bcck_in_ch14 = false;
-                                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                                } else
-                                       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+                                       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
                        }
                        RT_TRACE(COMP_POWER_TRACKING,
                                 "priv->rfa_txpowertrackingindex = %d\n",
@@ -829,23 +825,23 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
                        if (priv->CCKPresentAttentuation_difference <= -12 ||
                            priv->CCKPresentAttentuation_difference >= 24) {
                                priv->rtllib->bdynamic_txpower_enable = true;
-                               write_nic_byte(dev, Pw_Track_Flag, 0);
-                               write_nic_byte(dev, FW_Busy_Flag, 0);
+                               rtl92e_writeb(dev, Pw_Track_Flag, 0);
+                               rtl92e_writeb(dev, FW_Busy_Flag, 0);
                                RT_TRACE(COMP_POWER_TRACKING,
                                         "tx power track--->limited\n");
                                return;
                        }
 
-                       write_nic_byte(dev, Pw_Track_Flag, 0);
+                       rtl92e_writeb(dev, Pw_Track_Flag, 0);
                        Avg_TSSI_Meas_from_driver = 0;
                        for (k = 0; k < 5; k++)
                                tmp_report[k] = 0;
                        break;
                }
-               write_nic_byte(dev, FW_Busy_Flag, 0);
+               rtl92e_writeb(dev, FW_Busy_Flag, 0);
        }
        priv->rtllib->bdynamic_txpower_enable = true;
-       write_nic_byte(dev, Pw_Track_Flag, 0);
+       rtl92e_writeb(dev, Pw_Track_Flag, 0);
 }
 
 static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
@@ -857,8 +853,8 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
        int i = 0, CCKSwingNeedUpdate = 0;
 
        if (!priv->btxpower_trackingInit) {
-               tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance,
-                                            bMaskDWord);
+               tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance,
+                                           bMaskDWord);
                for (i = 0; i < OFDM_Table_Length; i++) {
                        if (tmpRegA == OFDMSwingTable[i]) {
                                priv->OFDM_index[0] = (u8)i;
@@ -869,7 +865,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
                        }
                }
 
-               TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
+               TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2);
                for (i = 0; i < CCK_Table_length; i++) {
                        if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
                                priv->CCK_index = (u8) i;
@@ -884,7 +880,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
                return;
        }
 
-       tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);
+       tmpRegA = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078);
        RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
        if (tmpRegA < 3 || tmpRegA > 13)
                return;
@@ -939,11 +935,11 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
        }
 
        if (CCKSwingNeedUpdate)
-               dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+               rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
        if (priv->OFDM_index[0] != tmpOFDMindex) {
                priv->OFDM_index[0] = tmpOFDMindex;
-               rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
-                                OFDMSwingTable[priv->OFDM_index[0]]);
+               rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
+                                 OFDMSwingTable[priv->OFDM_index[0]]);
                RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
                         priv->OFDM_index[0],
                         OFDMSwingTable[priv->OFDM_index[0]]);
@@ -951,7 +947,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
        priv->txpower_count = 0;
 }
 
-void   dm_txpower_trackingcallback(void *data)
+void rtl92e_dm_txpower_tracking_wq(void *data)
 {
        struct r8192_priv *priv = container_of_dwork_rsl(data,
                                  struct r8192_priv, txpower_tracking_wq);
@@ -989,7 +985,7 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
                 priv->btxpower_tracking);
 }
 
-void dm_initialize_txpower_tracking(struct net_device *dev)
+void rtl92e_dm_init_txpower_tracking(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1005,7 +1001,7 @@ static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
        static u32 tx_power_track_counter;
 
        RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__);
-       if (read_nic_byte(dev, 0x11e) == 1)
+       if (rtl92e_readb(dev, 0x11e) == 1)
                return;
        if (!priv->btxpower_tracking)
                return;
@@ -1039,10 +1035,10 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
 
        if (!TM_Trigger) {
                {
-               rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
-               rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
-               rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
-               rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+               rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+               rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+               rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+               rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
                }
                TM_Trigger = 1;
                return;
@@ -1074,30 +1070,30 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
                TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][0] +
                          (dm_cck_tx_bb_gain[attenuation][1] << 8));
 
-               rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                TempVal = (u32)((dm_cck_tx_bb_gain[attenuation][2]) +
                          (dm_cck_tx_bb_gain[attenuation][3] << 8) +
                          (dm_cck_tx_bb_gain[attenuation][4] << 16)+
                          (dm_cck_tx_bb_gain[attenuation][5] << 24));
-               rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
                TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][6] +
                          (dm_cck_tx_bb_gain[attenuation][7] << 8));
 
-               rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
        } else {
                TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][0]) +
                          (dm_cck_tx_bb_gain_ch14[attenuation][1] << 8));
 
-               rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][2]) +
                          (dm_cck_tx_bb_gain_ch14[attenuation][3] << 8) +
                          (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16)+
                          (dm_cck_tx_bb_gain_ch14[attenuation][5] << 24));
-               rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
                TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][6]) +
                          (dm_cck_tx_bb_gain_ch14[attenuation][7] << 8));
 
-               rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
        }
 }
 
@@ -1111,7 +1107,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,
        if (!bInCH14) {
                TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
                          (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1] << 8);
-               rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING,
                         "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1,
                         TempVal);
@@ -1119,14 +1115,14 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,
                          (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3] << 8) +
                          (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4] << 16)+
                          (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5] << 24);
-               rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING,
                         "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2,
                         TempVal);
                TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
                          (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7] << 8);
 
-               rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING,
                         "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_DebugPort,
                         TempVal);
@@ -1134,26 +1130,26 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,
                TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] +
                          (CCKSwingTable_Ch14[priv->CCK_index][1] << 8);
 
-               rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
                        rCCK0_TxFilter1, TempVal);
                TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] +
                          (CCKSwingTable_Ch14[priv->CCK_index][3] << 8) +
                          (CCKSwingTable_Ch14[priv->CCK_index][4] << 16)+
                          (CCKSwingTable_Ch14[priv->CCK_index][5] << 24);
-               rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
                        rCCK0_TxFilter2, TempVal);
                TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] +
                          (CCKSwingTable_Ch14[priv->CCK_index][7]<<8);
 
-               rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+               rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
                RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
                        rCCK0_DebugPort, TempVal);
        }
 }
 
-void dm_cck_txpower_adjust(struct net_device *dev, bool  binch14)
+void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1168,8 +1164,8 @@ static void dm_txpower_reset_recovery(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n");
-       rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
-                        dm_tx_bb_gain[priv->rfa_txpowertrackingindex]);
+       rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
+                         dm_tx_bb_gain[priv->rfa_txpowertrackingindex]);
        RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",
                 dm_tx_bb_gain[priv->rfa_txpowertrackingindex]);
        RT_TRACE(COMP_POWER_TRACKING,
@@ -1181,10 +1177,10 @@ static void dm_txpower_reset_recovery(struct net_device *dev)
        RT_TRACE(COMP_POWER_TRACKING,
                 "Reset Recovery: CCK Attenuation is %d dB\n",
                 priv->CCKPresentAttentuation);
-       dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+       rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
 
-       rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord,
-                        dm_tx_bb_gain[priv->rfc_txpowertrackingindex]);
+       rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord,
+                         dm_tx_bb_gain[priv->rfc_txpowertrackingindex]);
        RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",
                 dm_tx_bb_gain[priv->rfc_txpowertrackingindex]);
        RT_TRACE(COMP_POWER_TRACKING,
@@ -1195,7 +1191,7 @@ static void dm_txpower_reset_recovery(struct net_device *dev)
                 dm_tx_bb_gain_idx_to_amplify(priv->rfc_txpowertrackingindex));
 }
 
-void dm_restore_dynamic_mechanism_state(struct net_device *dev)
+void rtl92e_dm_restore_state(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        u32     reg_ratr = priv->rate_adaptive.last_ratr;
@@ -1203,7 +1199,7 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev)
 
        if (!priv->up) {
                RT_TRACE(COMP_RATE,
-                        "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
+                        "<---- rtl92e_dm_restore_state(): driver is going to unload\n");
                return;
        }
 
@@ -1215,8 +1211,8 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev)
        ratr_value = reg_ratr;
        if (priv->rf_type == RF_1T2R)
                ratr_value &= ~(RATE_ALL_OFDM_2SS);
-       write_nic_dword(dev, RATR0, ratr_value);
-       write_nic_byte(dev, UFWP, 1);
+       rtl92e_writel(dev, RATR0, ratr_value);
+       rtl92e_writeb(dev, UFWP, 1);
        if (priv->btxpower_trackingInit && priv->btxpower_tracking)
                dm_txpower_reset_recovery(dev);
 
@@ -1232,18 +1228,18 @@ static void dm_bb_initialgain_restore(struct net_device *dev)
        if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
                return;
 
-       rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
-       rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask,
-                        (u32)priv->initgain_backup.xaagccore1);
-       rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask,
-                        (u32)priv->initgain_backup.xbagccore1);
-       rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask,
-                        (u32)priv->initgain_backup.xcagccore1);
-       rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask,
-                        (u32)priv->initgain_backup.xdagccore1);
+       rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
+       rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, bit_mask,
+                         (u32)priv->initgain_backup.xaagccore1);
+       rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, bit_mask,
+                         (u32)priv->initgain_backup.xbagccore1);
+       rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, bit_mask,
+                         (u32)priv->initgain_backup.xcagccore1);
+       rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, bit_mask,
+                         (u32)priv->initgain_backup.xdagccore1);
        bit_mask  = bMaskByte2;
-       rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask,
-                        (u32)priv->initgain_backup.cca);
+       rtl92e_set_bb_reg(dev, rCCK0_CCA, bit_mask,
+                         (u32)priv->initgain_backup.cca);
 
        RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",
                 priv->initgain_backup.xaagccore1);
@@ -1255,12 +1251,12 @@ static void dm_bb_initialgain_restore(struct net_device *dev)
                 priv->initgain_backup.xdagccore1);
        RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",
                 priv->initgain_backup.cca);
-       rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+       rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
 
 }
 
 
-void dm_backup_dynamic_mechanism_state(struct net_device *dev)
+void rtl92e_dm_backup_state(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1279,13 +1275,13 @@ static void dm_bb_initialgain_backup(struct net_device *dev)
        if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
                return;
 
-       rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
-       priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask);
-       priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask);
-       priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask);
-       priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask);
+       rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
+       priv->initgain_backup.xaagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1, bit_mask);
+       priv->initgain_backup.xbagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1, bit_mask);
+       priv->initgain_backup.xcagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1, bit_mask);
+       priv->initgain_backup.xdagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1, bit_mask);
        bit_mask  = bMaskByte2;
-       priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask);
+       priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev, rCCK0_CCA, bit_mask);
 
        RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",
                 priv->initgain_backup.xaagccore1);
@@ -1376,7 +1372,7 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi(
                fw_dig = 0;
        if (fw_dig <= 3) {
                for (i = 0; i < 3; i++)
-                       rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+                       rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
                fw_dig++;
                dm_digtable.dig_state = DM_STA_DIG_OFF;
        }
@@ -1410,7 +1406,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
        if (dm_digtable.dig_algorithm_switch) {
                dm_digtable.dig_state = DM_STA_DIG_MAX;
                for (i = 0; i < 3; i++)
-                       rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+                       rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
                dm_digtable.dig_algorithm_switch = 0;
        }
 
@@ -1429,19 +1425,19 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
                dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
                dm_digtable.dig_state = DM_STA_DIG_OFF;
 
-               rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+               rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
 
-               write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17);
-               write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17);
-               write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17);
-               write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17);
+               rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x17);
+               rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x17);
+               rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x17);
+               rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x17);
 
                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                       write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+                       rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00);
                else
-                       write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+                       rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42);
 
-               write_nic_byte(dev, 0xa0a, 0x08);
+               rtl92e_writeb(dev, 0xa0a, 0x08);
 
                return;
        }
@@ -1462,25 +1458,25 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
                dm_digtable.dig_state = DM_STA_DIG_ON;
 
                if (reset_flag == 1) {
-                       write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c);
-                       write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c);
-                       write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c);
-                       write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c);
+                       rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x2c);
+                       rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x2c);
+                       rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x2c);
+                       rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x2c);
                } else {
-                       write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20);
-                       write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20);
-                       write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20);
-                       write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20);
+                       rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x20);
+                       rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x20);
+                       rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x20);
+                       rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x20);
                }
 
                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                       write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+                       rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
                else
-                       write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+                       rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
 
-               write_nic_byte(dev, 0xa0a, 0xcd);
+               rtl92e_writeb(dev, 0xa0a, 0xcd);
 
-               rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+               rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
        }
        dm_ctrl_initgain_byrssi_highpwr(dev);
 }
@@ -1505,9 +1501,9 @@ static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
                dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
 
                if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                               write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+                               rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10);
                else
-                       write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+                       rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43);
        } else {
                if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF &&
                        (priv->reset_count == reset_cnt_highpwr))
@@ -1519,9 +1515,9 @@ static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
                    (priv->undecorated_smoothed_pwdb >=
                    dm_digtable.rssi_high_thresh)) {
                        if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                               write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+                               rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
                        else
-                               write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+                               rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
                }
        }
        reset_cnt_highpwr = priv->reset_count;
@@ -1568,16 +1564,16 @@ static void dm_initial_gain(struct net_device *dev)
                reset_cnt = priv->reset_count;
        }
 
-       if (dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1))
+       if (dm_digtable.pre_ig_value != rtl92e_readb(dev, rOFDM0_XAAGCCore1))
                force_write = 1;
 
        if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
            || !initialized || force_write) {
                initial_gain = (u8)dm_digtable.cur_ig_value;
-               write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
-               write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
-               write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
-               write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+               rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain);
+               rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain);
+               rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain);
+               rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain);
                dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
                initialized = 1;
                force_write = 0;
@@ -1630,20 +1626,20 @@ static void dm_pd_th(struct net_device *dev)
            (initialized <= 3) || force_write) {
                if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) {
                        if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                               write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+                               rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00);
                        else
-                               write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+                               rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42);
                } else if (dm_digtable.curpd_thstate ==
                           DIG_PD_AT_NORMAL_POWER) {
                        if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                               write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+                               rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
                        else
-                               write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+                               rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
                } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) {
                        if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
-                               write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+                               rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10);
                        else
-                               write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+                               rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43);
                }
                dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
                if (initialized <= 3)
@@ -1687,16 +1683,16 @@ static  void dm_cs_ratio(struct net_device *dev)
        if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
            !initialized || force_write) {
                if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
-                       write_nic_byte(dev, 0xa0a, 0x08);
+                       rtl92e_writeb(dev, 0xa0a, 0x08);
                else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
-                       write_nic_byte(dev, 0xa0a, 0xcd);
+                       rtl92e_writeb(dev, 0xa0a, 0xcd);
                dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
                initialized = 1;
                force_write = 0;
        }
 }
 
-void dm_init_edca_turbo(struct net_device *dev)
+void rtl92e_dm_init_edca_turbo(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -1745,21 +1741,19 @@ static void dm_check_edca_turbo(struct net_device *dev)
                        if (curTxOkCnt > 4*curRxOkCnt) {
                                if (priv->bis_cur_rdlstate ||
                                    !priv->bcurrent_turbo_EDCA) {
-                                       write_nic_dword(dev, EDCAPARA_BE,
-                                                edca_setting_UL[pHTInfo->IOTPeer]);
+                                       rtl92e_writel(dev, EDCAPARA_BE,
+                                                     edca_setting_UL[pHTInfo->IOTPeer]);
                                        priv->bis_cur_rdlstate = false;
                                }
                        } else {
                                if (!priv->bis_cur_rdlstate ||
                                    !priv->bcurrent_turbo_EDCA) {
                                        if (priv->rtllib->mode == WIRELESS_MODE_G)
-                                               write_nic_dword(dev,
-                                                               EDCAPARA_BE,
-                                                        edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+                                               rtl92e_writel(dev, EDCAPARA_BE,
+                                                             edca_setting_DL_GMode[pHTInfo->IOTPeer]);
                                        else
-                                               write_nic_dword(dev,
-                                                               EDCAPARA_BE,
-                                                        edca_setting_DL[pHTInfo->IOTPeer]);
+                                               rtl92e_writel(dev, EDCAPARA_BE,
+                                                             edca_setting_DL[pHTInfo->IOTPeer]);
                                        priv->bis_cur_rdlstate = true;
                                }
                        }
@@ -1769,20 +1763,18 @@ static void dm_check_edca_turbo(struct net_device *dev)
                                if (!priv->bis_cur_rdlstate ||
                                    !priv->bcurrent_turbo_EDCA) {
                                        if (priv->rtllib->mode == WIRELESS_MODE_G)
-                                               write_nic_dword(dev,
-                                                               EDCAPARA_BE,
-                                                        edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+                                               rtl92e_writel(dev, EDCAPARA_BE,
+                                                             edca_setting_DL_GMode[pHTInfo->IOTPeer]);
                                        else
-                                               write_nic_dword(dev,
-                                                               EDCAPARA_BE,
-                                                        edca_setting_DL[pHTInfo->IOTPeer]);
+                                               rtl92e_writel(dev, EDCAPARA_BE,
+                                                             edca_setting_DL[pHTInfo->IOTPeer]);
                                        priv->bis_cur_rdlstate = true;
                                }
                        } else {
                                if (priv->bis_cur_rdlstate ||
                                    !priv->bcurrent_turbo_EDCA) {
-                                       write_nic_dword(dev, EDCAPARA_BE,
-                                                       edca_setting_UL[pHTInfo->IOTPeer]);
+                                       rtl92e_writel(dev, EDCAPARA_BE,
+                                                     edca_setting_UL[pHTInfo->IOTPeer]);
                                        priv->bis_cur_rdlstate = false;
                                }
 
@@ -1854,7 +1846,7 @@ static    void    dm_check_pbc_gpio(struct net_device *dev)
 {
 }
 
-void dm_CheckRfCtrlGPIO(void *data)
+static void dm_CheckRfCtrlGPIO(void *data)
 {
        struct r8192_priv *priv = container_of_dwork_rsl(data,
                                  struct r8192_priv, gpio_change_rf_wq);
@@ -1877,7 +1869,7 @@ void dm_CheckRfCtrlGPIO(void *data)
                return;
        }
 
-       tmp1byte = read_nic_byte(dev, GPI);
+       tmp1byte = rtl92e_readb(dev, GPI);
 
        eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
 
@@ -1896,8 +1888,7 @@ void dm_CheckRfCtrlGPIO(void *data)
        if (bActuallySet) {
                mdelay(1000);
                priv->bHwRfOffAction = 1;
-               MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW,
-                                   true);
+               rtl92e_set_rf_state(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
                if (priv->bHwRadioOff)
                        argv[1] = "RFOFF";
                else
@@ -1909,7 +1900,7 @@ void dm_CheckRfCtrlGPIO(void *data)
        }
 }
 
-void   dm_rf_pathcheck_workitemcallback(void *data)
+void rtl92e_dm_rf_pathcheck_wq(void *data)
 {
        struct r8192_priv *priv = container_of_dwork_rsl(data,
                                  struct r8192_priv,
@@ -1917,7 +1908,7 @@ void      dm_rf_pathcheck_workitemcallback(void *data)
        struct net_device *dev = priv->rtllib->dev;
        u8 rfpath = 0, i;
 
-       rfpath = read_nic_byte(dev, 0xc04);
+       rfpath = rtl92e_readb(dev, 0xc04);
 
        for (i = 0; i < RF90_PATH_MAX; i++) {
                if (rfpath & (0x01<<i))
@@ -1974,12 +1965,12 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev)
                return;
 
        if (!cck_Rx_Path_initialized) {
-               DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf);
+               DM_RxPathSelTable.cck_Rx_path = (rtl92e_readb(dev, 0xa07)&0xf);
                cck_Rx_Path_initialized = 1;
        }
 
        DM_RxPathSelTable.disabledRF = 0xf;
-       DM_RxPathSelTable.disabledRF &= ~(read_nic_byte(dev, 0xc04));
+       DM_RxPathSelTable.disabledRF &= ~(rtl92e_readb(dev, 0xc04));
 
        if (priv->rtllib->mode == WIRELESS_MODE_B)
                DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
@@ -2116,10 +2107,10 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev)
                     DM_RxPathSelTable.diff_TH) {
                        DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] =
                                 tmp_max_rssi+5;
-                       rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable,
-                                0x1<<min_rssi_index, 0x0);
-                       rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable,
-                                0x1<<min_rssi_index, 0x0);
+                       rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable,
+                                         0x1<<min_rssi_index, 0x0);
+                       rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable,
+                                         0x1<<min_rssi_index, 0x0);
                        disabled_rf_cnt++;
                }
                if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) {
@@ -2133,8 +2124,8 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev)
        if (update_cck_rx_path) {
                DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2) |
                                                (cck_optional_Rx);
-               rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000,
-                                DM_RxPathSelTable.cck_Rx_path);
+               rtl92e_set_bb_reg(dev, rCCK0_AFESetting, 0x0f000000,
+                                 DM_RxPathSelTable.cck_Rx_path);
        }
 
        if (DM_RxPathSelTable.disabledRF) {
@@ -2142,12 +2133,12 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev)
                        if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) {
                                if (tmp_max_rssi >=
                                    DM_RxPathSelTable.rf_enable_rssi_th[i]) {
-                                       rtl8192_setBBreg(dev,
-                                                rOFDM0_TRxPathEnable, 0x1 << i,
-                                                0x1);
-                                       rtl8192_setBBreg(dev,
-                                                rOFDM1_TRxPathEnable,
-                                                0x1 << i, 0x1);
+                                       rtl92e_set_bb_reg(dev,
+                                                         rOFDM0_TRxPathEnable,
+                                                         0x1 << i, 0x1);
+                                       rtl92e_set_bb_reg(dev,
+                                                         rOFDM1_TRxPathEnable,
+                                                         0x1 << i, 0x1);
                                        DM_RxPathSelTable.rf_enable_rssi_th[i]
                                                 = 100;
                                        disabled_rf_cnt--;
@@ -2191,7 +2182,7 @@ static void dm_deInit_fsync(struct net_device *dev)
        del_timer_sync(&priv->fsync_timer);
 }
 
-void dm_fsync_timer_callback(unsigned long data)
+static void dm_fsync_timer_callback(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
        struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
@@ -2252,18 +2243,18 @@ void dm_fsync_timer_callback(unsigned long data)
                        bDoubleTimeInterval = true;
                        priv->bswitch_fsync = !priv->bswitch_fsync;
                        if (priv->bswitch_fsync) {
-                               write_nic_byte(dev, 0xC36, 0x1c);
-                               write_nic_byte(dev, 0xC3e, 0x90);
+                               rtl92e_writeb(dev, 0xC36, 0x1c);
+                               rtl92e_writeb(dev, 0xC3e, 0x90);
                        } else {
-                               write_nic_byte(dev, 0xC36, 0x5c);
-                               write_nic_byte(dev, 0xC3e, 0x96);
+                               rtl92e_writeb(dev, 0xC36, 0x5c);
+                               rtl92e_writeb(dev, 0xC3e, 0x96);
                        }
                } else if (priv->undecorated_smoothed_pwdb <=
                           priv->rtllib->fsync_rssi_threshold) {
                        if (priv->bswitch_fsync) {
                                priv->bswitch_fsync  = false;
-                               write_nic_byte(dev, 0xC36, 0x5c);
-                               write_nic_byte(dev, 0xC3e, 0x96);
+                               rtl92e_writeb(dev, 0xC36, 0x5c);
+                               rtl92e_writeb(dev, 0xC3e, 0x96);
                        }
                }
                if (bDoubleTimeInterval) {
@@ -2283,11 +2274,11 @@ void dm_fsync_timer_callback(unsigned long data)
        } else {
                if (priv->bswitch_fsync) {
                        priv->bswitch_fsync  = false;
-                       write_nic_byte(dev, 0xC36, 0x5c);
-                       write_nic_byte(dev, 0xC3e, 0x96);
+                       rtl92e_writeb(dev, 0xC36, 0x5c);
+                       rtl92e_writeb(dev, 0xC3e, 0x96);
                }
                priv->ContinueDiffCount = 0;
-               write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+               rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd);
        }
        RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
        RT_TRACE(COMP_HALDM,
@@ -2302,10 +2293,10 @@ static void dm_StartHWFsync(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_HALDM, "%s\n", __func__);
-       write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf);
+       rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cf);
        priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING,
                                      (u8 *)(&rf_timing));
-       write_nic_byte(dev, 0xc3b, 0x41);
+       rtl92e_writeb(dev, 0xc3b, 0x41);
 }
 
 static void dm_EndHWFsync(struct net_device *dev)
@@ -2314,10 +2305,10 @@ static void dm_EndHWFsync(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_HALDM, "%s\n", __func__);
-       write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+       rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd);
        priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8 *)
                                     (&rf_timing));
-       write_nic_byte(dev, 0xc3b, 0x49);
+       rtl92e_writeb(dev, 0xc3b, 0x49);
 }
 
 static void dm_EndSWFsync(struct net_device *dev)
@@ -2330,13 +2321,13 @@ static void dm_EndSWFsync(struct net_device *dev)
        if (priv->bswitch_fsync) {
                priv->bswitch_fsync  = false;
 
-               write_nic_byte(dev, 0xC36, 0x5c);
+               rtl92e_writeb(dev, 0xC36, 0x5c);
 
-               write_nic_byte(dev, 0xC3e, 0x96);
+               rtl92e_writeb(dev, 0xC3e, 0x96);
        }
 
        priv->ContinueDiffCount = 0;
-       write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+       rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd);
 }
 
 static void dm_StartSWFsync(struct net_device *dev)
@@ -2371,11 +2362,11 @@ static void dm_StartSWFsync(struct net_device *dev)
                                    msecs_to_jiffies(priv->rtllib->fsync_time_interval);
        add_timer(&priv->fsync_timer);
 
-       write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
+       rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cd);
 
 }
 
-void dm_check_fsync(struct net_device *dev)
+static void dm_check_fsync(struct net_device *dev)
 {
 #define        RegC38_Default                  0
 #define        RegC38_NonFsync_Other_AP        1
@@ -2431,7 +2422,7 @@ void dm_check_fsync(struct net_device *dev)
                }
                if (priv->framesyncMonitor) {
                        if (reg_c38_State != RegC38_Fsync_AP_BCM) {
-                               write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
+                               rtl92e_writeb(dev, rOFDM0_RxDetector3, 0x95);
 
                                reg_c38_State = RegC38_Fsync_AP_BCM;
                        }
@@ -2457,7 +2448,7 @@ void dm_check_fsync(struct net_device *dev)
                                    RegC38_TH) {
                                        if (reg_c38_State !=
                                            RegC38_NonFsync_Other_AP) {
-                                                       write_nic_byte(dev,
+                                                       rtl92e_writeb(dev,
                                                            rOFDM0_RxDetector3,
                                                            0x90);
 
@@ -2467,7 +2458,7 @@ void dm_check_fsync(struct net_device *dev)
                                } else if (priv->undecorated_smoothed_pwdb >=
                                           (RegC38_TH+5)) {
                                        if (reg_c38_State) {
-                                               write_nic_byte(dev,
+                                               rtl92e_writeb(dev,
                                                        rOFDM0_RxDetector3,
                                                        priv->framesync);
                                                reg_c38_State = RegC38_Default;
@@ -2475,8 +2466,8 @@ void dm_check_fsync(struct net_device *dev)
                                }
                        } else {
                                if (reg_c38_State) {
-                                       write_nic_byte(dev, rOFDM0_RxDetector3,
-                                                      priv->framesync);
+                                       rtl92e_writeb(dev, rOFDM0_RxDetector3,
+                                                     priv->framesync);
                                        reg_c38_State = RegC38_Default;
                                }
                        }
@@ -2484,14 +2475,14 @@ void dm_check_fsync(struct net_device *dev)
        }
        if (priv->framesyncMonitor) {
                if (priv->reset_count != reset_cnt) {
-                       write_nic_byte(dev, rOFDM0_RxDetector3,
+                       rtl92e_writeb(dev, rOFDM0_RxDetector3,
                                       priv->framesync);
                        reg_c38_State = RegC38_Default;
                        reset_cnt = priv->reset_count;
                }
        } else {
                if (reg_c38_State) {
-                       write_nic_byte(dev, rOFDM0_RxDetector3,
+                       rtl92e_writeb(dev, rOFDM0_RxDetector3,
                                       priv->framesync);
                        reg_c38_State = RegC38_Default;
                }
@@ -2556,8 +2547,7 @@ static void dm_dynamic_txpower(struct net_device *dev)
                RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190()  channel = %d\n",
                         priv->rtllib->current_network.channel);
 
-               rtl8192_phy_setTxPower(dev,
-                                priv->rtllib->current_network.channel);
+               rtl92e_set_tx_power(dev, priv->rtllib->current_network.channel);
        }
        priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
        priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
@@ -2569,13 +2559,13 @@ static void dm_check_txrateandretrycount(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rtllib_device *ieee = priv->rtllib;
 
-       ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev,
+       ieee->softmac_stats.CurrentShowTxate = rtl92e_readb(dev,
                                                 Current_Tx_Rate_Reg);
 
-       ieee->softmac_stats.last_packet_rate = read_nic_byte(dev,
+       ieee->softmac_stats.last_packet_rate = rtl92e_readb(dev,
                                                 Initial_Tx_Rate_Reg);
 
-       ieee->softmac_stats.txretrycount = read_nic_dword(dev,
+       ieee->softmac_stats.txretrycount = rtl92e_readl(dev,
                                                 Tx_Retry_Count_Reg);
 }
 
@@ -2583,5 +2573,5 @@ static void dm_send_rssi_tofw(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
-       write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
+       rtl92e_writeb(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
 }
index b037451c3ada4c5e71543b8a5f78d4bdfad80362..097f0dc2056dada403493919f883a111d43aa233 100644 (file)
 #define                DM_DIG_THRESH_HIGH                                      40
 #define                DM_DIG_THRESH_LOW                                       35
 
-#define                DM_FALSEALARM_THRESH_LOW        40
-#define                DM_FALSEALARM_THRESH_HIGH       1000
-
 #define                DM_DIG_HIGH_PWR_THRESH_HIGH             75
 #define                DM_DIG_HIGH_PWR_THRESH_LOW              70
 
 #define                BW_AUTO_SWITCH_HIGH_LOW                 25
 #define                BW_AUTO_SWITCH_LOW_HIGH                 30
 
-#define                DM_check_fsync_time_interval                            500
-
-
 #define                DM_DIG_BACKOFF                          12
 #define                DM_DIG_MAX                                      0x36
 #define                DM_DIG_MIN                                      0x1c
 #define                DM_DIG_MIN_Netcore                      0x12
 
-#define                DM_DIG_BACKOFF_MAX                      12
-#define                DM_DIG_BACKOFF_MIN                      -4
-
 #define                RxPathSelection_SS_TH_low               30
 #define                RxPathSelection_diff_TH                 18
 
@@ -55,8 +46,6 @@
 #define                RateAdaptiveTH_Low_40M          10
 #define                VeryLowRSSI                                     15
 
-#define                CTSToSelfTHVal                                  35
-
 #define                WAIotTHVal                                              25
 
 #define                E_FOR_TX_POWER_TRACK           300
 #define                        Tx_Retry_Count_Reg       0x1ac
 #define                RegC38_TH                                20
 
-#define                TX_POWER_NEAR_FIELD_THRESH_LVL2 74
-#define                TX_POWER_NEAR_FIELD_THRESH_LVL1 67
-
-#define                TxHighPwrLevel_Normal           0
-#define                TxHighPwrLevel_Level1           1
-#define                TxHighPwrLevel_Level2           2
-
-#define                DM_Type_ByFW                    0
 #define                DM_Type_ByDriver                1
 
 /*--------------------------Define Parameters-------------------------------*/
@@ -207,23 +188,20 @@ extern const u8 dm_cck_tx_bb_gain_ch14[CCKTxBBGainTableLength][8];
 /*--------------------------Exported Function prototype---------------------*/
 /*--------------------------Exported Function prototype---------------------*/
 
-extern  void    init_hal_dm(struct net_device *dev);
-extern  void deinit_hal_dm(struct net_device *dev);
+void rtl92e_dm_init(struct net_device *dev);
+void rtl92e_dm_deinit(struct net_device *dev);
 
-extern void hal_dm_watchdog(struct net_device *dev);
+void rtl92e_dm_watchdog(struct net_device *dev);
 
 
-extern  void    init_rate_adaptive(struct net_device *dev);
-extern  void    dm_txpower_trackingcallback(void *data);
+void    rtl92e_init_adaptive_rate(struct net_device *dev);
+void    rtl92e_dm_txpower_tracking_wq(void *data);
 
-extern  void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
+void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
 
-extern  void    dm_restore_dynamic_mechanism_state(struct net_device *dev);
-extern  void    dm_backup_dynamic_mechanism_state(struct net_device *dev);
-extern  void    dm_init_edca_turbo(struct net_device *dev);
-extern  void    dm_rf_pathcheck_workitemcallback(void *data);
-extern  void dm_fsync_timer_callback(unsigned long data);
-extern  void dm_check_fsync(struct net_device *dev);
-extern  void dm_initialize_txpower_tracking(struct net_device *dev);
-extern  void    dm_CheckRfCtrlGPIO(void *data);
+void    rtl92e_dm_restore_state(struct net_device *dev);
+void    rtl92e_dm_backup_state(struct net_device *dev);
+void    rtl92e_dm_init_edca_turbo(struct net_device *dev);
+void    rtl92e_dm_rf_pathcheck_wq(void *data);
+void rtl92e_dm_init_txpower_tracking(struct net_device *dev);
 #endif /*__R8192UDM_H__ */
index a6778e0853c7251de0ff3efe801a8ba943e22c45..039ccfd41230276f083db2fd700e928f0fb4947b 100644 (file)
 #include "rtl_core.h"
 #include "rtl_eeprom.h"
 
-static void eprom_cs(struct net_device *dev, short bit)
+static void _rtl92e_gpio_write_bit(struct net_device *dev, int no, bool val)
 {
-       if (bit)
-               write_nic_byte(dev, EPROM_CMD,
-                              (1 << EPROM_CS_SHIFT) |
-                              read_nic_byte(dev, EPROM_CMD));
+       u8 reg = rtl92e_readb(dev, EPROM_CMD);
+
+       if (val)
+               reg |= 1 << no;
        else
-               write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
-                              & ~(1<<EPROM_CS_SHIFT));
+               reg &= ~(1 << no);
 
+       rtl92e_writeb(dev, EPROM_CMD, reg);
        udelay(EPROM_DELAY);
 }
 
-
-static void eprom_ck_cycle(struct net_device *dev)
+static bool _rtl92e_gpio_get_bit(struct net_device *dev, int no)
 {
-       write_nic_byte(dev, EPROM_CMD,
-                      (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
-       udelay(EPROM_DELAY);
-       write_nic_byte(dev, EPROM_CMD,
-                      read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
-       udelay(EPROM_DELAY);
-}
+       u8 reg = rtl92e_readb(dev, EPROM_CMD);
 
+       return (reg >> no) & 0x1;
+}
 
-static void eprom_w(struct net_device *dev, short bit)
+static void _rtl92e_eeprom_ck_cycle(struct net_device *dev)
 {
-       if (bit)
-               write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) |
-                              read_nic_byte(dev, EPROM_CMD));
-       else
-               write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
-                              & ~(1<<EPROM_W_SHIFT));
-
-       udelay(EPROM_DELAY);
+       _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 1);
+       _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 0);
 }
 
-
-static short eprom_r(struct net_device *dev)
+static u16 _rtl92e_eeprom_xfer(struct net_device *dev, u16 data, int tx_len)
 {
-       short bit;
+       u16 ret = 0;
+       int rx_len = 16;
 
-       bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
-       udelay(EPROM_DELAY);
+       _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 1);
+       _rtl92e_eeprom_ck_cycle(dev);
 
-       if (bit)
-               return 1;
-       return 0;
-}
+       while (tx_len--) {
+               _rtl92e_gpio_write_bit(dev, EPROM_W_BIT,
+                                      (data >> tx_len) & 0x1);
+               _rtl92e_eeprom_ck_cycle(dev);
+       }
 
-static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
-{
-       int i;
+       _rtl92e_gpio_write_bit(dev, EPROM_W_BIT, 0);
 
-       for (i = 0; i < len; i++) {
-               eprom_w(dev, b[i]);
-               eprom_ck_cycle(dev);
+       while (rx_len--) {
+               _rtl92e_eeprom_ck_cycle(dev);
+               ret |= _rtl92e_gpio_get_bit(dev, EPROM_R_BIT) << rx_len;
        }
+
+       _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 0);
+       _rtl92e_eeprom_ck_cycle(dev);
+
+       return ret;
 }
 
-u32 eprom_read(struct net_device *dev, u32 addr)
+u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
-       short read_cmd[] = {1, 1, 0};
-       short addr_str[8];
-       int i;
-       int addr_len;
-       u32 ret;
-
-       ret = 0;
-       write_nic_byte(dev, EPROM_CMD,
-                      (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
-       udelay(EPROM_DELAY);
+       u32 ret = 0;
 
-       if (priv->epromtype == EEPROM_93C56) {
-               addr_str[7] = addr & 1;
-               addr_str[6] = addr & (1<<1);
-               addr_str[5] = addr & (1<<2);
-               addr_str[4] = addr & (1<<3);
-               addr_str[3] = addr & (1<<4);
-               addr_str[2] = addr & (1<<5);
-               addr_str[1] = addr & (1<<6);
-               addr_str[0] = addr & (1<<7);
-               addr_len = 8;
-       } else {
-               addr_str[5] = addr & 1;
-               addr_str[4] = addr & (1<<1);
-               addr_str[3] = addr & (1<<2);
-               addr_str[2] = addr & (1<<3);
-               addr_str[1] = addr & (1<<4);
-               addr_str[0] = addr & (1<<5);
-               addr_len = 6;
-       }
-       eprom_cs(dev, 1);
-       eprom_ck_cycle(dev);
-       eprom_send_bits_string(dev, read_cmd, 3);
-       eprom_send_bits_string(dev, addr_str, addr_len);
-
-       eprom_w(dev, 0);
-
-       for (i = 0; i < 16; i++) {
-               eprom_ck_cycle(dev);
-               ret |= (eprom_r(dev)<<(15-i));
-       }
+       rtl92e_writeb(dev, EPROM_CMD,
+                     (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
+       udelay(EPROM_DELAY);
 
-       eprom_cs(dev, 0);
-       eprom_ck_cycle(dev);
+       /* EEPROM is configured as x16 */
+       if (priv->epromtype == EEPROM_93C56)
+               ret = _rtl92e_eeprom_xfer(dev, (addr & 0xFF) | (0x6 << 8), 11);
+       else
+               ret = _rtl92e_eeprom_xfer(dev, (addr & 0x3F) | (0x6 << 6), 9);
 
-       write_nic_byte(dev, EPROM_CMD,
-                      (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
+       rtl92e_writeb(dev, EPROM_CMD,
+                     (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
        return ret;
 }
index adea2b4c7a449eb943caa1c3b326e9d3af57d4a5..8d23aea5fb4f3d11833c5858aa9996011af2860d 100644 (file)
@@ -26,4 +26,4 @@
 
 #define EPROM_DELAY 10
 
-u32 eprom_read(struct net_device *dev, u32 addr);
+u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr);
index 6bbd1c626e24293bec5c25f2fc60c268827c3748..9fcb099e6edd3b28dc26d46e5cc26e0317e656df 100644 (file)
@@ -45,7 +45,7 @@ static void rtl8192_parse_pci_configuration(struct pci_dev *pdev,
        pci_write_config_byte(pdev, 0x70f, tmp);
 }
 
-bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev)
+bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
        u16 VenderID;
index e8d5527a5f046d415ddea5c847a1909dc945ce64..6246841bde1555f535178a88721bdd44b10bad79 100644 (file)
@@ -29,6 +29,6 @@
 #include <linux/pci.h>
 
 struct net_device;
-bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev);
+bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev);
 
 #endif
index e4908672421ce1a1f712f986e68e0a19235490a8..b0268fdc100f4c9e37fb4fedc4f1678118fd6633 100644 (file)
@@ -23,7 +23,7 @@
 #include "rtl_pm.h"
 
 
-int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state)
+int rtl92e_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -45,16 +45,16 @@ int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state)
        netif_device_detach(dev);
 
        if (!priv->rtllib->bSupportRemoteWakeUp) {
-               MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT, true);
-               ulRegRead = read_nic_dword(dev, CPU_GEN);
+               rtl92e_set_rf_state(dev, eRfOff, RF_CHANGE_BY_INIT);
+               ulRegRead = rtl92e_readl(dev, CPU_GEN);
                ulRegRead |= CPU_GEN_SYSTEM_RESET;
-               write_nic_dword(dev, CPU_GEN, ulRegRead);
+               rtl92e_writel(dev, CPU_GEN, ulRegRead);
        } else {
-               write_nic_dword(dev, WFCRC0, 0xffffffff);
-               write_nic_dword(dev, WFCRC1, 0xffffffff);
-               write_nic_dword(dev, WFCRC2, 0xffffffff);
-               write_nic_byte(dev, PMR, 0x5);
-               write_nic_byte(dev, MacBlkCtrl, 0xa);
+               rtl92e_writel(dev, WFCRC0, 0xffffffff);
+               rtl92e_writel(dev, WFCRC1, 0xffffffff);
+               rtl92e_writel(dev, WFCRC2, 0xffffffff);
+               rtl92e_writeb(dev, PMR, 0x5);
+               rtl92e_writeb(dev, MacBlkCtrl, 0xa);
        }
 out_pci_suspend:
        netdev_info(dev, "WOL is %s\n", priv->rtllib->bSupportRemoteWakeUp ?
@@ -70,7 +70,7 @@ out_pci_suspend:
        return 0;
 }
 
-int rtl8192E_resume(struct pci_dev *pdev)
+int rtl92e_resume(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct r8192_priv *priv = rtllib_priv(dev);
@@ -95,7 +95,7 @@ int rtl8192E_resume(struct pci_dev *pdev)
        pci_enable_wake(pdev, PCI_D0, 0);
 
        if (priv->polling_timer_on == 0)
-               check_rfctrl_gpio_timer((unsigned long)dev);
+               rtl92e_check_rfctrl_gpio_timer((unsigned long)dev);
 
        if (!netif_running(dev)) {
                netdev_info(dev,
@@ -108,7 +108,7 @@ int rtl8192E_resume(struct pci_dev *pdev)
                dev->netdev_ops->ndo_open(dev);
 
        if (!priv->rtllib->bSupportRemoteWakeUp)
-               MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_INIT, true);
+               rtl92e_set_rf_state(dev, eRfOn, RF_CHANGE_BY_INIT);
 
 out:
        RT_TRACE(COMP_POWER, "<================r8192E resume call.\n");
index 7bfe44817f230d8e1d0f721538d88b1ce4cfc9da..cdc45f7fb33934a2d419c86e25af73bd8f48c1be 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-int rtl8192E_suspend(struct pci_dev *dev, pm_message_t state);
-int rtl8192E_resume(struct pci_dev *dev);
+int rtl92e_suspend(struct pci_dev *dev, pm_message_t state);
+int rtl92e_resume(struct pci_dev *dev);
 
 #endif
index 404cb83153d9409d5c0111b50817579d0256eb66..f09560d60dc4f2c96add5d3c33c356988506441a 100644 (file)
@@ -45,10 +45,10 @@ static void rtl8192_hw_sleep_down(struct net_device *dev)
        spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
        RT_TRACE(COMP_DBG, "%s()============>come to sleep down\n", __func__);
 
-       MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS, false);
+       rtl92e_set_rf_state(dev, eRfSleep, RF_CHANGE_BY_PS);
 }
 
-void rtl8192_hw_sleep_wq(void *data)
+void rtl92e_hw_sleep_wq(void *data)
 {
        struct rtllib_device *ieee = container_of_dwork_rsl(data,
                                     struct rtllib_device, hw_sleep_wq);
@@ -57,7 +57,7 @@ void rtl8192_hw_sleep_wq(void *data)
        rtl8192_hw_sleep_down(dev);
 }
 
-void rtl8192_hw_wakeup(struct net_device *dev)
+void rtl92e_hw_wakeup(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        unsigned long flags = 0;
@@ -66,7 +66,7 @@ void rtl8192_hw_wakeup(struct net_device *dev)
        if (priv->RFChangeInProgress) {
                spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
                RT_TRACE(COMP_DBG,
-                        "rtl8192_hw_wakeup(): RF Change in progress!\n");
+                        "rtl92e_hw_wakeup(): RF Change in progress!\n");
                queue_delayed_work_rsl(priv->rtllib->wq,
                                       &priv->rtllib->hw_wakeup_wq,
                                       msecs_to_jiffies(10));
@@ -74,21 +74,21 @@ void rtl8192_hw_wakeup(struct net_device *dev)
        }
        spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
        RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __func__);
-       MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS, false);
+       rtl92e_set_rf_state(dev, eRfOn, RF_CHANGE_BY_PS);
 }
 
-void rtl8192_hw_wakeup_wq(void *data)
+void rtl92e_hw_wakeup_wq(void *data)
 {
        struct rtllib_device *ieee = container_of_dwork_rsl(data,
                                     struct rtllib_device, hw_wakeup_wq);
        struct net_device *dev = ieee->dev;
 
-       rtl8192_hw_wakeup(dev);
+       rtl92e_hw_wakeup(dev);
 }
 
 #define MIN_SLEEP_TIME 50
 #define MAX_SLEEP_TIME 10000
-void rtl8192_hw_to_sleep(struct net_device *dev, u64 time)
+void rtl92e_enter_sleep(struct net_device *dev, u64 time)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
 
@@ -133,14 +133,13 @@ static void InactivePsWorkItemCallback(struct net_device *dev)
 
        RT_TRACE(COMP_PS, "InactivePsWorkItemCallback(): Set RF to %s.\n",
                 pPSC->eInactivePowerState == eRfOff ? "OFF" : "ON");
-       MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS,
-                           false);
+       rtl92e_set_rf_state(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
 
        pPSC->bSwRfProcessing = false;
        RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() <---------\n");
 }
 
-void IPSEnter(struct net_device *dev)
+void rtl92e_ips_enter(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
@@ -152,7 +151,7 @@ void IPSEnter(struct net_device *dev)
                if (rtState == eRfOn && !pPSC->bSwRfProcessing &&
                        (priv->rtllib->state != RTLLIB_LINKED) &&
                        (priv->rtllib->iw_mode != IW_MODE_MASTER)) {
-                       RT_TRACE(COMP_PS, "IPSEnter(): Turn off RF.\n");
+                       RT_TRACE(COMP_PS, "rtl92e_ips_enter(): Turn off RF.\n");
                        pPSC->eInactivePowerState = eRfOff;
                        priv->isRFOff = true;
                        priv->bInPowerSaveMode = true;
@@ -161,7 +160,7 @@ void IPSEnter(struct net_device *dev)
        }
 }
 
-void IPSLeave(struct net_device *dev)
+void rtl92e_ips_leave(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
@@ -172,7 +171,7 @@ void IPSLeave(struct net_device *dev)
                rtState = priv->rtllib->eRFPowerState;
                if (rtState != eRfOn  && !pPSC->bSwRfProcessing &&
                    priv->rtllib->RfOffReason <= RF_CHANGE_BY_IPS) {
-                       RT_TRACE(COMP_PS, "IPSLeave(): Turn on RF.\n");
+                       RT_TRACE(COMP_PS, "rtl92e_ips_leave(): Turn on RF.\n");
                        pPSC->eInactivePowerState = eRfOn;
                        priv->bInPowerSaveMode = false;
                        InactivePsWorkItemCallback(dev);
@@ -180,7 +179,7 @@ void IPSLeave(struct net_device *dev)
        }
 }
 
-void IPSLeave_wq(void *data)
+void rtl92e_ips_leave_wq(void *data)
 {
        struct rtllib_device *ieee = container_of_work_rsl(data,
                                     struct rtllib_device, ips_leave_wq);
@@ -188,11 +187,11 @@ void IPSLeave_wq(void *data)
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
        down(&priv->rtllib->ips_sem);
-       IPSLeave(dev);
+       rtl92e_ips_leave(dev);
        up(&priv->rtllib->ips_sem);
 }
 
-void rtllib_ips_leave_wq(struct net_device *dev)
+void rtl92e_rtllib_ips_leave_wq(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
        enum rt_rf_power_state rtState;
@@ -206,7 +205,7 @@ void rtllib_ips_leave_wq(struct net_device *dev)
                                            __func__);
                                return;
                        }
-                       netdev_info(dev, "=========>%s(): IPSLeave\n",
+                       netdev_info(dev, "=========>%s(): rtl92e_ips_leave\n",
                                    __func__);
                        queue_work_rsl(priv->rtllib->wq,
                                       &priv->rtllib->ips_leave_wq);
@@ -214,12 +213,12 @@ void rtllib_ips_leave_wq(struct net_device *dev)
        }
 }
 
-void rtllib_ips_leave(struct net_device *dev)
+void rtl92e_rtllib_ips_leave(struct net_device *dev)
 {
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
        down(&priv->rtllib->ips_sem);
-       IPSLeave(dev);
+       rtl92e_ips_leave(dev);
        up(&priv->rtllib->ips_sem);
 }
 
@@ -238,7 +237,7 @@ static bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,
            rtPsMode == RTLLIB_PS_DISABLED) {
                unsigned long flags;
 
-               rtl8192_hw_wakeup(dev);
+               rtl92e_hw_wakeup(dev);
                priv->rtllib->sta_sleep = LPS_IS_WAKE;
 
                spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags);
@@ -251,13 +250,13 @@ static bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,
        return true;
 }
 
-void LeisurePSEnter(struct net_device *dev)
+void rtl92e_leisure_ps_enter(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
                                        &(priv->rtllib->PowerSaveControl);
 
-       RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+       RT_TRACE(COMP_PS, "rtl92e_leisure_ps_enter()...\n");
        RT_TRACE(COMP_PS,
                 "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
                 pPSC->bLeisurePs, priv->rtllib->ps, pPSC->LpsIdleCount,
@@ -275,7 +274,7 @@ void LeisurePSEnter(struct net_device *dev)
                        if (priv->rtllib->ps == RTLLIB_PS_DISABLED) {
 
                                RT_TRACE(COMP_LPS,
-                                        "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+                                        "rtl92e_leisure_ps_enter(): Enter 802.11 power save mode...\n");
 
                                if (!pPSC->bFwCtrlLPS) {
                                        if (priv->rtllib->SetFwCmdHandler)
@@ -291,21 +290,21 @@ void LeisurePSEnter(struct net_device *dev)
        }
 }
 
-void LeisurePSLeave(struct net_device *dev)
+void rtl92e_leisure_ps_leave(struct net_device *dev)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
        struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
                                        &(priv->rtllib->PowerSaveControl);
 
 
-       RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+       RT_TRACE(COMP_PS, "rtl92e_leisure_ps_leave()...\n");
        RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
                pPSC->bLeisurePs, priv->rtllib->ps);
 
        if (pPSC->bLeisurePs) {
                if (priv->rtllib->ps != RTLLIB_PS_DISABLED) {
                        RT_TRACE(COMP_LPS,
-                                "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+                                "rtl92e_leisure_ps_leave(): Busy Traffic , Leave 802.11 power save..\n");
                        MgntActSet_802_11_PowerSaveMode(dev,
                                         RTLLIB_PS_DISABLED);
 
index 962f2e5b8bf826b420e26fad94615733ba56ceb8..35fc9e2a3365ba9b7c38a7923b28dd039bb42878 100644 (file)
 struct net_device;
 
 #define RT_CHECK_FOR_HANG_PERIOD 2
-#define INIT_DEFAULT_CHAN       1
 
-void rtl8192_hw_wakeup(struct net_device *dev);
-void rtl8192_hw_to_sleep(struct net_device *dev, u64 time);
-void rtllib_ips_leave_wq(struct net_device *dev);
-void rtllib_ips_leave(struct net_device *dev);
-void IPSLeave_wq(void *data);
+void rtl92e_hw_wakeup(struct net_device *dev);
+void rtl92e_enter_sleep(struct net_device *dev, u64 time);
+void rtl92e_rtllib_ips_leave_wq(struct net_device *dev);
+void rtl92e_rtllib_ips_leave(struct net_device *dev);
+void rtl92e_ips_leave_wq(void *data);
 
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
+void rtl92e_ips_enter(struct net_device *dev);
+void rtl92e_ips_leave(struct net_device *dev);
 
-void LeisurePSEnter(struct net_device *dev);
-void LeisurePSLeave(struct net_device *dev);
+void rtl92e_leisure_ps_enter(struct net_device *dev);
+void rtl92e_leisure_ps_leave(struct net_device *dev);
 
 #endif
index f5e4961677d2f5f74d2eebe79ee37c4b89fd6b00..7e3ca7ef997b9f5a5e8a22caf200c7c052e499c2 100644 (file)
@@ -192,7 +192,7 @@ static int r8192_wx_adapter_power_status(struct net_device *dev,
                pPSC->bLeisurePs = true;
        } else {
                if (priv->rtllib->state == RTLLIB_LINKED)
-                       LeisurePSLeave(dev);
+                       rtl92e_leisure_ps_leave(dev);
 
                priv->ps_force = true;
                pPSC->bLeisurePs = false;
@@ -282,10 +282,11 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
                                        up(&priv->wx_sem);
                                        return -1;
                                }
-                               netdev_info(dev,  "=========>%s(): IPSLeave\n",
+                               netdev_info(dev,
+                                           "=========>%s(): rtl92e_ips_leave\n",
                                            __func__);
                                down(&priv->rtllib->ips_sem);
-                               IPSLeave(dev);
+                               rtl92e_ips_leave(dev);
                                up(&priv->rtllib->ips_sem);
                        }
                }
@@ -442,10 +443,11 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
                                        up(&priv->wx_sem);
                                        return -1;
                                }
-                               RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n",
+                               RT_TRACE(COMP_PS,
+                                        "=========>%s(): rtl92e_ips_leave\n",
                                         __func__);
                                down(&priv->rtllib->ips_sem);
-                               IPSLeave(dev);
+                               rtl92e_ips_leave(dev);
                                up(&priv->rtllib->ips_sem);
                        }
                }
@@ -700,7 +702,7 @@ static int r8192_wx_set_enc(struct net_device *dev,
 
        priv->rtllib->wx_set_enc = 1;
        down(&priv->rtllib->ips_sem);
-       IPSLeave(dev);
+       rtl92e_ips_leave(dev);
        up(&priv->rtllib->ips_sem);
        down(&priv->wx_sem);
 
@@ -711,7 +713,7 @@ static int r8192_wx_set_enc(struct net_device *dev,
 
        if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
                ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
-               CamResetAllEntry(dev);
+               rtl92e_cam_reset(dev);
                memset(priv->rtllib->swcamtable, 0,
                       sizeof(struct sw_cam_table) * 32);
                goto end_hw_sec;
@@ -729,9 +731,6 @@ static int r8192_wx_set_enc(struct net_device *dev,
                        hwkey[i] |= (key[4 * i + 3] & mask) << 24;
                }
 
-               #define CONF_WEP40  0x4
-               #define CONF_WEP104 0x14
-
                switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
                case 0:
                        key_idx = ieee->crypt_info.tx_keyidx;
@@ -753,16 +752,16 @@ static int r8192_wx_set_enc(struct net_device *dev,
                }
                if (wrqu->encoding.length == 0x5) {
                        ieee->pairwise_key_type = KEY_TYPE_WEP40;
-                       EnableHWSecurityConfig8192(dev);
+                       rtl92e_enable_hw_security_config(dev);
                }
 
                else if (wrqu->encoding.length == 0xd) {
                        ieee->pairwise_key_type = KEY_TYPE_WEP104;
-                               EnableHWSecurityConfig8192(dev);
-                       setKey(dev, key_idx, key_idx, KEY_TYPE_WEP104,
-                              zero_addr[key_idx], 0, hwkey);
-                       set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
-                                 zero_addr[key_idx], 0, hwkey, 0);
+                               rtl92e_enable_hw_security_config(dev);
+                       rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104,
+                                      zero_addr[key_idx], 0, hwkey);
+                       rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
+                                        zero_addr[key_idx], 0, hwkey, 0);
                } else {
                        netdev_info(dev,
                                    "wrong type in WEP, not WEP40 and WEP104\n");
@@ -821,17 +820,13 @@ static int r8192_wx_set_retry(struct net_device *dev,
        }
        if (wrqu->retry.flags & IW_RETRY_MAX) {
                priv->retry_rts = wrqu->retry.value;
-               DMESG("Setting retry for RTS/CTS data to %d",
-                     wrqu->retry.value);
 
        } else {
                priv->retry_data = wrqu->retry.value;
-               DMESG("Setting retry for non RTS/CTS data to %d",
-                     wrqu->retry.value);
        }
 
 
-       rtl8192_commit(dev);
+       rtl92e_commit(dev);
 exit:
        up(&priv->wx_sem);
 
@@ -917,7 +912,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
 
        priv->rtllib->wx_set_enc = 1;
        down(&priv->rtllib->ips_sem);
-       IPSLeave(dev);
+       rtl92e_ips_leave(dev);
        up(&priv->rtllib->ips_sem);
 
        ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra);
@@ -933,7 +928,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
                     ext->alg == IW_ENCODE_ALG_NONE) {
                        ieee->pairwise_key_type = ieee->group_key_type
                                                = KEY_TYPE_NA;
-                       CamResetAllEntry(dev);
+                       rtl92e_cam_reset(dev);
                        memset(priv->rtllib->swcamtable, 0,
                               sizeof(struct sw_cam_table) * 32);
                        goto end_hw_sec;
@@ -950,28 +945,29 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
                        if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
                                alg = KEY_TYPE_WEP104;
                        ieee->pairwise_key_type = alg;
-                       EnableHWSecurityConfig8192(dev);
+                       rtl92e_enable_hw_security_config(dev);
                }
                memcpy((u8 *)key, ext->key, 16);
 
                if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
                        if (ext->key_len == 13)
                                ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
-                       setKey(dev, idx, idx, alg, zero, 0, key);
-                       set_swcam(dev, idx, idx, alg, zero, 0, key, 0);
+                       rtl92e_set_key(dev, idx, idx, alg, zero, 0, key);
+                       rtl92e_set_swcam(dev, idx, idx, alg, zero, 0, key, 0);
                } else if (group) {
                        ieee->group_key_type = alg;
-                       setKey(dev, idx, idx, alg, broadcast_addr, 0, key);
-                       set_swcam(dev, idx, idx, alg, broadcast_addr, 0,
-                                 key, 0);
+                       rtl92e_set_key(dev, idx, idx, alg, broadcast_addr, 0,
+                                      key);
+                       rtl92e_set_swcam(dev, idx, idx, alg, broadcast_addr, 0,
+                                        key, 0);
                } else {
                        if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) &&
                             ieee->pHTInfo->bCurrentHTSupport)
-                               write_nic_byte(dev, 0x173, 1);
-                       setKey(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr,
-                              0, key);
-                       set_swcam(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr,
-                                 0, key, 0);
+                               rtl92e_writeb(dev, 0x173, 1);
+                       rtl92e_set_key(dev, 4, idx, alg,
+                                      (u8 *)ieee->ap_mac_addr, 0, key);
+                       rtl92e_set_swcam(dev, 4, idx, alg,
+                                        (u8 *)ieee->ap_mac_addr, 0, key, 0);
                }
 
 
@@ -1119,41 +1115,41 @@ static int r8192_wx_get_PromiscuousMode(struct net_device *dev,
 }
 
 
-#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
+#define IW_IOCTL(x) ((x) - SIOCSIWCOMMIT)
 static iw_handler r8192_wx_handlers[] = {
-       IW_IOCTL(SIOCGIWNAME) = r8192_wx_get_name,
-       IW_IOCTL(SIOCSIWFREQ) = r8192_wx_set_freq,
-       IW_IOCTL(SIOCGIWFREQ) = r8192_wx_get_freq,
-       IW_IOCTL(SIOCSIWMODE) = r8192_wx_set_mode,
-       IW_IOCTL(SIOCGIWMODE) = r8192_wx_get_mode,
-       IW_IOCTL(SIOCSIWSENS) = r8192_wx_set_sens,
-       IW_IOCTL(SIOCGIWSENS) = r8192_wx_get_sens,
-       IW_IOCTL(SIOCGIWRANGE) = rtl8192_wx_get_range,
-       IW_IOCTL(SIOCSIWAP) = r8192_wx_set_wap,
-       IW_IOCTL(SIOCGIWAP) = r8192_wx_get_wap,
-       IW_IOCTL(SIOCSIWSCAN) = r8192_wx_set_scan,
-       IW_IOCTL(SIOCGIWSCAN) = r8192_wx_get_scan,
-       IW_IOCTL(SIOCSIWESSID) = r8192_wx_set_essid,
-       IW_IOCTL(SIOCGIWESSID) = r8192_wx_get_essid,
-       IW_IOCTL(SIOCSIWNICKN) = r8192_wx_set_nick,
-               IW_IOCTL(SIOCGIWNICKN) = r8192_wx_get_nick,
-       IW_IOCTL(SIOCSIWRATE) = r8192_wx_set_rate,
-       IW_IOCTL(SIOCGIWRATE) = r8192_wx_get_rate,
-       IW_IOCTL(SIOCSIWRTS) = r8192_wx_set_rts,
-       IW_IOCTL(SIOCGIWRTS) = r8192_wx_get_rts,
-       IW_IOCTL(SIOCSIWFRAG) = r8192_wx_set_frag,
-       IW_IOCTL(SIOCGIWFRAG) = r8192_wx_get_frag,
-       IW_IOCTL(SIOCSIWRETRY) = r8192_wx_set_retry,
-       IW_IOCTL(SIOCGIWRETRY) = r8192_wx_get_retry,
-       IW_IOCTL(SIOCSIWENCODE) = r8192_wx_set_enc,
-       IW_IOCTL(SIOCGIWENCODE) = r8192_wx_get_enc,
-       IW_IOCTL(SIOCSIWPOWER) = r8192_wx_set_power,
-       IW_IOCTL(SIOCGIWPOWER) = r8192_wx_get_power,
-       IW_IOCTL(SIOCSIWGENIE) = r8192_wx_set_gen_ie,
-       IW_IOCTL(SIOCGIWGENIE) = r8192_wx_get_gen_ie,
-       IW_IOCTL(SIOCSIWMLME) = r8192_wx_set_mlme,
-       IW_IOCTL(SIOCSIWAUTH) = r8192_wx_set_auth,
-       IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext,
+       [IW_IOCTL(SIOCGIWNAME)] = r8192_wx_get_name,
+       [IW_IOCTL(SIOCSIWFREQ)] = r8192_wx_set_freq,
+       [IW_IOCTL(SIOCGIWFREQ)] = r8192_wx_get_freq,
+       [IW_IOCTL(SIOCSIWMODE)] = r8192_wx_set_mode,
+       [IW_IOCTL(SIOCGIWMODE)] = r8192_wx_get_mode,
+       [IW_IOCTL(SIOCSIWSENS)] = r8192_wx_set_sens,
+       [IW_IOCTL(SIOCGIWSENS)] = r8192_wx_get_sens,
+       [IW_IOCTL(SIOCGIWRANGE)] = rtl8192_wx_get_range,
+       [IW_IOCTL(SIOCSIWAP)] = r8192_wx_set_wap,
+       [IW_IOCTL(SIOCGIWAP)] = r8192_wx_get_wap,
+       [IW_IOCTL(SIOCSIWSCAN)] = r8192_wx_set_scan,
+       [IW_IOCTL(SIOCGIWSCAN)] = r8192_wx_get_scan,
+       [IW_IOCTL(SIOCSIWESSID)] = r8192_wx_set_essid,
+       [IW_IOCTL(SIOCGIWESSID)] = r8192_wx_get_essid,
+       [IW_IOCTL(SIOCSIWNICKN)] = r8192_wx_set_nick,
+       [IW_IOCTL(SIOCGIWNICKN)] = r8192_wx_get_nick,
+       [IW_IOCTL(SIOCSIWRATE)] = r8192_wx_set_rate,
+       [IW_IOCTL(SIOCGIWRATE)] = r8192_wx_get_rate,
+       [IW_IOCTL(SIOCSIWRTS)] = r8192_wx_set_rts,
+       [IW_IOCTL(SIOCGIWRTS)] = r8192_wx_get_rts,
+       [IW_IOCTL(SIOCSIWFRAG)] = r8192_wx_set_frag,
+       [IW_IOCTL(SIOCGIWFRAG)] = r8192_wx_get_frag,
+       [IW_IOCTL(SIOCSIWRETRY)] = r8192_wx_set_retry,
+       [IW_IOCTL(SIOCGIWRETRY)] = r8192_wx_get_retry,
+       [IW_IOCTL(SIOCSIWENCODE)] = r8192_wx_set_enc,
+       [IW_IOCTL(SIOCGIWENCODE)] = r8192_wx_get_enc,
+       [IW_IOCTL(SIOCSIWPOWER)] = r8192_wx_set_power,
+       [IW_IOCTL(SIOCGIWPOWER)] = r8192_wx_get_power,
+       [IW_IOCTL(SIOCSIWGENIE)] = r8192_wx_set_gen_ie,
+       [IW_IOCTL(SIOCGIWGENIE)] = r8192_wx_get_gen_ie,
+       [IW_IOCTL(SIOCSIWMLME)] = r8192_wx_set_mlme,
+       [IW_IOCTL(SIOCSIWAUTH)] = r8192_wx_set_auth,
+       [IW_IOCTL(SIOCSIWENCODEEXT)] = r8192_wx_set_enc_ext,
 };
 
 /* the following rule need to be following,
index 613e14c12df36496b3268522bb7e04b2df71d300..89466646515279af44141667d33ad13f09526dc9 100644 (file)
 #ifndef _BATYPE_H_
 #define _BATYPE_H_
 
-#define                TOTAL_TXBA_NUM  16
-#define        TOTAL_RXBA_NUM  16
-
 #define        BA_SETUP_TIMEOUT        200
-#define        BA_INACT_TIMEOUT        60000
 
 #define        BA_POLICY_DELAYED               0
 #define        BA_POLICY_IMMEDIATE     1
@@ -32,7 +28,6 @@
 #define        ADDBA_STATUS_REFUSED            37
 #define        ADDBA_STATUS_INVALID_PARAM      38
 
-#define        DELBA_REASON_QSTA_LEAVING       36
 #define        DELBA_REASON_END_BA                     37
 #define        DELBA_REASON_UNKNOWN_BA 38
 #define        DELBA_REASON_TIMEOUT                    39
index 60f536c295abe3ddb43e0373357b1a51a6ea1513..78ede4a817fc6a39b81c7b8c21ef2f8d7f112880 100644 (file)
@@ -428,7 +428,6 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
 {
         struct rtllib_hdr_3addr *delba = NULL;
        union delba_param_set *pDelBaParamSet = NULL;
-       u16 *pReasonCode = NULL;
        u8 *dst = NULL;
 
        if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
@@ -453,9 +452,7 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
 #endif
        delba = (struct rtllib_hdr_3addr *)skb->data;
        dst = (u8 *)(&delba->addr2[0]);
-       delba += sizeof(struct rtllib_hdr_3addr);
-       pDelBaParamSet = (union delba_param_set *)(delba+2);
-       pReasonCode = (u16 *)(delba+4);
+       pDelBaParamSet = (union delba_param_set *)&delba->payload[2];
 
        if (pDelBaParamSet->field.Initiator == 1) {
                struct rx_ts_record *pRxTs;
index 0c263d9f724639b1b66f5e216ae4bf49b9be2db0..51711dcdc8ef40d41f82ad790e60ca343ed73cd1 100644 (file)
@@ -20,8 +20,6 @@
 #define _RTL819XU_HTTYPE_H_
 
 #define MIMO_PS_STATIC                         0
-#define MIMO_PS_DYNAMIC                        1
-#define MIMO_PS_NOLIMIT                        3
 
 #define sHTCLng        4
 
index b5c3647b0f80492af8996c0b717962126b36b57b..555745b2a75e47c4224691f5e923722ecb5b2632 100644 (file)
@@ -117,7 +117,7 @@ void HTUpdateDefaultSetting(struct rtllib_device *ieee)
        pHTInfo->RxReorderPendingTime = 30;
 }
 
-u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
+static u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
 {
        struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
 
@@ -502,7 +502,8 @@ u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
        return mcsRate | 0x80;
 }
 
-u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS, u8 *pOperateMCS)
+static u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS,
+                         u8 *pOperateMCS)
 {
 
        u8 i;
index 3aa35ced2b8b5cad68f72dbbc8893e420642e566..fcc8fabbebb7ab2861a3db0ec0ee4dbadeeab3e1 100644 (file)
@@ -96,11 +96,6 @@ struct octet_string {
        u16 Length;
 };
 
-enum ack_policy {
-       eAckPlc0_ACK            = 0x00,
-       eAckPlc1_NoACK          = 0x01,
-};
-
 #define AC0_BE 0
 #define AC1_BK 1
 #define AC2_VI 2
index b8fed556928cd458c5a189aad3018a3e8ca3328a..a93348c37f17e1298a87107fd8ff1b165078d4c1 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef _TSTYPE_H_
 #define _TSTYPE_H_
 #include "rtl819x_Qos.h"
-#define TS_SETUP_TIMEOUT       60
-#define TS_INACT_TIMEOUT       60
 #define TS_ADDBA_DELAY         60
 
 #define TOTAL_TS_NUM           16
index 05aea4321b9def15b83ec322bb861d015e0157ae..7087959443cb40e634519fd12df3e5e991292681 100644 (file)
@@ -113,7 +113,7 @@ static void TsAddBaProcess(unsigned long data)
 
 static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
 {
-       memset(pTsCommonInfo->Addr, 0, 6);
+       eth_zero_addr(pTsCommonInfo->Addr);
        memset(&pTsCommonInfo->TSpec, 0, sizeof(union tspec_body));
        memset(&pTsCommonInfo->TClass, 0, sizeof(union qos_tclas)*TCLAS_NUM);
        pTsCommonInfo->TClasProc = 0;
index fd38c6dd146be78c569ef69da62089613a447a2f..563ac12f0b2c387d5d10de385e8af9324762fad0 100644 (file)
@@ -84,9 +84,6 @@
 #define iwe_stream_add_point_rsl(info, start, stop, iwe, p)    \
        iwe_stream_add_point(info, start, stop, iwe, p)
 
-#define usb_alloc_urb_rsl(x, y) usb_alloc_urb(x, y)
-#define usb_submit_urb_rsl(x, y) usb_submit_urb(x, y)
-
 static inline void *netdev_priv_rsl(struct net_device *dev)
 {
        return netdev_priv(dev);
@@ -110,27 +107,14 @@ static inline void *netdev_priv_rsl(struct net_device *dev)
 #define HIGH_QUEUE                          7
 #define BEACON_QUEUE                      8
 
-#define LOW_QUEUE                            BE_QUEUE
-#define NORMAL_QUEUE                      MGNT_QUEUE
-
 #ifndef IW_MODE_MESH
 #define IW_MODE_MESH                   7
 #endif
-#define AMSDU_SUBHEADER_LEN 14
-#define SWRF_TIMEOUT                           50
 
 #define IE_CISCO_FLAG_POSITION         0x08
 #define SUPPORT_CKIP_MIC                       0x08
 #define SUPPORT_CKIP_PK                        0x10
-#define        RT_RF_OFF_LEVL_ASPM                     BIT0
-#define        RT_RF_OFF_LEVL_CLK_REQ          BIT1
-#define        RT_RF_OFF_LEVL_PCI_D3                   BIT2
 #define        RT_RF_OFF_LEVL_HALT_NIC         BIT3
-#define        RT_RF_OFF_LEVL_FREE_FW          BIT4
-#define        RT_RF_OFF_LEVL_FW_32K           BIT5
-#define        RT_RF_PS_LEVEL_ALWAYS_ASPM      BIT6
-#define        RT_RF_LPS_DISALBE_2R                    BIT30
-#define        RT_RF_LPS_LEVEL_ASPM                    BIT31
 #define        RT_IN_PS_LEVEL(pPSC, _PS_FLAG)          \
        ((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
 #define        RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG)       \
@@ -244,22 +228,6 @@ struct sw_chnl_cmd {
 #define MGN_MCS13             0x8d
 #define MGN_MCS14             0x8e
 #define MGN_MCS15             0x8f
-#define        MGN_MCS0_SG                     0x90
-#define        MGN_MCS1_SG                     0x91
-#define        MGN_MCS2_SG                     0x92
-#define        MGN_MCS3_SG                     0x93
-#define        MGN_MCS4_SG                     0x94
-#define        MGN_MCS5_SG                     0x95
-#define        MGN_MCS6_SG                     0x96
-#define        MGN_MCS7_SG                     0x97
-#define        MGN_MCS8_SG                     0x98
-#define        MGN_MCS9_SG                     0x99
-#define        MGN_MCS10_SG            0x9a
-#define        MGN_MCS11_SG            0x9b
-#define        MGN_MCS12_SG            0x9c
-#define        MGN_MCS13_SG            0x9d
-#define        MGN_MCS14_SG            0x9e
-#define        MGN_MCS15_SG            0x9f
 
 enum hw_variables {
        HW_VAR_ETHER_ADDR,
@@ -722,42 +690,13 @@ struct rtllib_frag_entry {
        u8 dst_addr[ETH_ALEN];
 };
 
-struct rtllib_stats {
-       unsigned int tx_unicast_frames;
-       unsigned int tx_multicast_frames;
-       unsigned int tx_fragments;
-       unsigned int tx_unicast_octets;
-       unsigned int tx_multicast_octets;
-       unsigned int tx_deferred_transmissions;
-       unsigned int tx_single_retry_frames;
-       unsigned int tx_multiple_retry_frames;
-       unsigned int tx_retry_limit_exceeded;
-       unsigned int tx_discards;
-       unsigned int rx_unicast_frames;
-       unsigned int rx_multicast_frames;
-       unsigned int rx_fragments;
-       unsigned int rx_unicast_octets;
-       unsigned int rx_multicast_octets;
-       unsigned int rx_fcs_errors;
-       unsigned int rx_discards_no_buffer;
-       unsigned int tx_discards_wrong_sa;
-       unsigned int rx_discards_undecryptable;
-       unsigned int rx_message_in_msg_fragments;
-       unsigned int rx_message_in_bad_msg_fragments;
-};
-
 struct rtllib_device;
 
-#define SEC_KEY_1       (1<<0)
-#define SEC_KEY_2       (1<<1)
-#define SEC_KEY_3       (1<<2)
-#define SEC_KEY_4       (1<<3)
 #define SEC_ACTIVE_KEY    (1<<4)
 #define SEC_AUTH_MODE     (1<<5)
 #define SEC_UNICAST_GROUP (1<<6)
 #define SEC_LEVEL       (1<<7)
 #define SEC_ENABLED       (1<<8)
-#define SEC_ENCRYPT       (1<<9)
 
 #define SEC_LEVEL_0      0 /* None */
 #define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
@@ -772,7 +711,6 @@ struct rtllib_device;
 
 #define WEP_KEY_LEN            13
 #define SCM_KEY_LEN            32
-#define SCM_TEMPORAL_KEY_LENGTH 16
 
 struct rtllib_security {
        u16 active_key:2,
@@ -1187,8 +1125,6 @@ enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
 #define WME_AC_BE   0x01
 #define WME_AC_VI   0x02
 #define WME_AC_VO   0x03
-#define WME_ACI_MASK 0x03
-#define WME_AIFSN_MASK 0x03
 #define WME_AC_PRAM_LEN 16
 
 #define MAX_RECEIVE_BUFFER_SIZE 9100
@@ -1204,12 +1140,6 @@ enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
 #define ETHERNET_HEADER_SIZE    14      /* length of two Ethernet address
                                         * plus ether type*/
 
-struct ether_header {
-       u8 ether_dhost[ETHER_ADDR_LEN];
-       u8 ether_shost[ETHER_ADDR_LEN];
-       u16 ether_type;
-} __packed;
-
 enum erp_t {
        ERP_NonERPpresent       = 0x01,
        ERP_UseProtection       = 0x02,
@@ -1591,7 +1521,6 @@ struct rtllib_device {
 
        /* Bookkeeping structures */
        struct net_device_stats stats;
-       struct rtllib_stats ieee_stats;
        struct rtllib_softmac_stats softmac_stats;
 
        /* Probe / Beacon management */
@@ -1673,7 +1602,6 @@ struct rtllib_device {
        int short_slot;
        int mode;       /* A, B, G */
        int modulation; /* CCK, OFDM */
-       int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
 
        /* used for forcing the ibss workqueue to terminate
         * without wait for the syncro scan to terminate
@@ -2056,244 +1984,199 @@ static inline int rtllib_is_cck_rate(u8 rate)
 
 
 /* rtllib.c */
-extern void free_rtllib(struct net_device *dev);
-extern struct net_device *alloc_rtllib(int sizeof_priv);
+void free_rtllib(struct net_device *dev);
+struct net_device *alloc_rtllib(int sizeof_priv);
 
 /* rtllib_tx.c */
 
-extern int rtllib_encrypt_fragment(
+int rtllib_encrypt_fragment(
        struct rtllib_device *ieee,
        struct sk_buff *frag,
        int hdr_len);
 
-extern int rtllib_xmit(struct sk_buff *skb,  struct net_device *dev);
-extern int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev);
-extern void rtllib_txb_free(struct rtllib_txb *);
+int rtllib_xmit(struct sk_buff *skb,  struct net_device *dev);
+void rtllib_txb_free(struct rtllib_txb *);
 
 /* rtllib_rx.c */
-extern int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
-                       struct rtllib_rx_stats *rx_stats);
-extern void rtllib_rx_mgt(struct rtllib_device *ieee,
-                            struct sk_buff *skb,
-                            struct rtllib_rx_stats *stats);
-extern void rtllib_rx_probe_rq(struct rtllib_device *ieee,
-                          struct sk_buff *skb);
-extern int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel);
+int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+             struct rtllib_rx_stats *rx_stats);
+void rtllib_rx_probe_rq(struct rtllib_device *ieee,
+                       struct sk_buff *skb);
+int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel);
 
 /* rtllib_wx.c */
-extern int rtllib_wx_get_scan(struct rtllib_device *ieee,
-                                struct iw_request_info *info,
-                                union iwreq_data *wrqu, char *key);
-extern int rtllib_wx_set_encode(struct rtllib_device *ieee,
-                                  struct iw_request_info *info,
-                                  union iwreq_data *wrqu, char *key);
-extern int rtllib_wx_get_encode(struct rtllib_device *ieee,
-                                  struct iw_request_info *info,
-                                  union iwreq_data *wrqu, char *key);
-extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
-                           struct iw_request_info *info,
-                           union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_auth(struct rtllib_device *ieee,
-                              struct iw_request_info *info,
-                              struct iw_param *data, char *extra);
-extern int rtllib_wx_set_mlme(struct rtllib_device *ieee,
-                              struct iw_request_info *info,
-                              union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
+int rtllib_wx_get_scan(struct rtllib_device *ieee,
+                      struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *key);
+int rtllib_wx_set_encode(struct rtllib_device *ieee,
+                        struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *key);
+int rtllib_wx_get_encode(struct rtllib_device *ieee,
+                        struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *key);
+int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_auth(struct rtllib_device *ieee,
+                      struct iw_request_info *info,
+                      struct iw_param *data, char *extra);
+int rtllib_wx_set_mlme(struct rtllib_device *ieee,
+                      struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
 
 /* rtllib_softmac.c */
-extern short rtllib_is_54g(struct rtllib_network *net);
-extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
-                                  struct sk_buff *skb,
-                                  struct rtllib_rx_stats *rx_stats, u16 type,
-                                  u16 stype);
-extern void rtllib_softmac_new_net(struct rtllib_device *ieee,
-                                  struct rtllib_network *net);
+int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb,
+                           struct rtllib_rx_stats *rx_stats, u16 type,
+                           u16 stype);
+void rtllib_softmac_new_net(struct rtllib_device *ieee,
+                           struct rtllib_network *net);
 
 void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn);
-extern void rtllib_softmac_xmit(struct rtllib_txb *txb,
-                               struct rtllib_device *ieee);
-
-extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
-extern void notify_wx_assoc_event(struct rtllib_device *ieee);
-extern void rtllib_softmac_check_all_nets(struct rtllib_device *ieee);
-extern void rtllib_start_bss(struct rtllib_device *ieee);
-extern void rtllib_start_master_bss(struct rtllib_device *ieee);
-extern void rtllib_start_ibss(struct rtllib_device *ieee);
-extern void rtllib_softmac_init(struct rtllib_device *ieee);
-extern void rtllib_softmac_free(struct rtllib_device *ieee);
-extern void rtllib_associate_abort(struct rtllib_device *ieee);
-extern void rtllib_disassociate(struct rtllib_device *ieee);
-extern void rtllib_stop_scan(struct rtllib_device *ieee);
-extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan);
-extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee);
-extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
-extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee,
-                                         short pwr);
-extern void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
-extern void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee);
-extern void rtllib_start_protocol(struct rtllib_device *ieee);
-extern void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
-
-extern void rtllib_EnableNetMonitorMode(struct net_device *dev,
+void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee);
+
+void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+void notify_wx_assoc_event(struct rtllib_device *ieee);
+void rtllib_start_ibss(struct rtllib_device *ieee);
+void rtllib_softmac_init(struct rtllib_device *ieee);
+void rtllib_softmac_free(struct rtllib_device *ieee);
+void rtllib_disassociate(struct rtllib_device *ieee);
+void rtllib_stop_scan(struct rtllib_device *ieee);
+bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan);
+void rtllib_stop_scan_syncro(struct rtllib_device *ieee);
+void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr);
+void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee);
+void rtllib_start_protocol(struct rtllib_device *ieee);
+void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
+
+void rtllib_EnableNetMonitorMode(struct net_device *dev, bool bInitState);
+void rtllib_DisableNetMonitorMode(struct net_device *dev, bool bInitState);
+void rtllib_EnableIntelPromiscuousMode(struct net_device *dev, bool bInitState);
+void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
                                        bool bInitState);
-extern void rtllib_DisableNetMonitorMode(struct net_device *dev,
-                                        bool bInitState);
-extern void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
-                                             bool bInitState);
-extern void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
-                                              bool bInitState);
-extern void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh);
-
-extern void rtllib_softmac_stop_protocol(struct rtllib_device *ieee,
-                                        u8 mesh_flag, u8 shutdown);
-extern void rtllib_softmac_start_protocol(struct rtllib_device *ieee,
-                                         u8 mesh_flag);
-
-extern void rtllib_reset_queue(struct rtllib_device *ieee);
-extern void rtllib_wake_all_queues(struct rtllib_device *ieee);
-extern void rtllib_stop_all_queues(struct rtllib_device *ieee);
-extern struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
-extern void rtllib_start_send_beacons(struct rtllib_device *ieee);
-extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
-extern int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee,
-                                      struct iw_point *p, u8 is_mesh);
-
-extern void notify_wx_assoc_event(struct rtllib_device *ieee);
-extern void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
-
-extern void softmac_mgmt_xmit(struct sk_buff *skb,
-                             struct rtllib_device *ieee);
-extern u16 rtllib_query_seqnum(struct rtllib_device *ieee,
-                              struct sk_buff *skb, u8 *dst);
-extern u8 rtllib_ap_sec_type(struct rtllib_device *ieee);
+void rtllib_softmac_stop_protocol(struct rtllib_device *ieee,
+                                 u8 mesh_flag, u8 shutdown);
+void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag);
+
+void rtllib_reset_queue(struct rtllib_device *ieee);
+void rtllib_wake_all_queues(struct rtllib_device *ieee);
+void rtllib_stop_all_queues(struct rtllib_device *ieee);
+struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
+void rtllib_start_send_beacons(struct rtllib_device *ieee);
+void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee,
+                               struct iw_point *p, u8 is_mesh);
+
+void notify_wx_assoc_event(struct rtllib_device *ieee);
+void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
+
+void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee);
+u8 rtllib_ap_sec_type(struct rtllib_device *ieee);
 
 /* rtllib_softmac_wx.c */
 
-extern int rtllib_wx_get_wap(struct rtllib_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *ext);
+int rtllib_wx_get_wap(struct rtllib_device *ieee, struct iw_request_info *info,
+                     union iwreq_data *wrqu, char *ext);
 
-extern int rtllib_wx_set_wap(struct rtllib_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *awrq,
-                            char *extra);
+int rtllib_wx_set_wap(struct rtllib_device *ieee, struct iw_request_info *info,
+                     union iwreq_data *awrq, char *extra);
 
-extern int rtllib_wx_get_essid(struct rtllib_device *ieee,
-                              struct iw_request_info *a,
-                              union iwreq_data *wrqu, char *b);
+int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,
+                       union iwreq_data *wrqu, char *b);
 
-extern int rtllib_wx_set_rate(struct rtllib_device *ieee,
-                             struct iw_request_info *info,
-                             union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_rate(struct rtllib_device *ieee, struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_get_rate(struct rtllib_device *ieee,
-                             struct iw_request_info *info,
-                             union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_rate(struct rtllib_device *ieee, struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_set_mode(struct rtllib_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *b);
+int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+                      union iwreq_data *wrqu, char *b);
 
-extern int rtllib_wx_set_scan(struct rtllib_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *b);
+int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
+                      union iwreq_data *wrqu, char *b);
 
-extern int rtllib_wx_set_essid(struct rtllib_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_essid(struct rtllib_device *ieee, struct iw_request_info *a,
+                       union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_get_mode(struct rtllib_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *b);
+int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+                      union iwreq_data *wrqu, char *b);
 
-extern int rtllib_wx_set_freq(struct rtllib_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *b);
+int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+                      union iwreq_data *wrqu, char *b);
 
-extern int rtllib_wx_get_freq(struct rtllib_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *b);
-extern void rtllib_wx_sync_scan_wq(void *data);
+int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+                      union iwreq_data *wrqu, char *b);
+void rtllib_wx_sync_scan_wq(void *data);
 
-extern int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
-                              struct iw_request_info *info,
-                              union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
+                       struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_get_name(struct rtllib_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info,
+                      union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_set_power(struct rtllib_device *ieee,
-                                struct iw_request_info *info,
-                                union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_power(struct rtllib_device *ieee,
+                       struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_get_power(struct rtllib_device *ieee,
-                                struct iw_request_info *info,
-                                union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_power(struct rtllib_device *ieee,
+                       struct iw_request_info *info,
+                       union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_set_rts(struct rtllib_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_rts(struct rtllib_device *ieee, struct iw_request_info *info,
+                     union iwreq_data *wrqu, char *extra);
 
-extern int rtllib_wx_get_rts(struct rtllib_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_rts(struct rtllib_device *ieee, struct iw_request_info *info,
+                     union iwreq_data *wrqu, char *extra);
 #define MAX_RECEIVE_BUFFER_SIZE 9100
 
 void HTSetConnectBwMode(struct rtllib_device *ieee,
                        enum ht_channel_width Bandwidth,
                        enum ht_extchnl_offset Offset);
-extern void HTUpdateDefaultSetting(struct rtllib_device *ieee);
-extern void HTConstructCapabilityElement(struct rtllib_device *ieee,
-                                        u8 *posHTCap, u8 *len,
-                                        u8 isEncrypt, bool bAssoc);
-extern void HTConstructInfoElement(struct rtllib_device *ieee,
-                                  u8 *posHTInfo, u8 *len, u8 isEncrypt);
-extern void HTConstructRT2RTAggElement(struct rtllib_device *ieee,
-                                      u8 *posRT2RTAgg, u8 *len);
-extern void HTOnAssocRsp(struct rtllib_device *ieee);
-extern void HTInitializeHTInfo(struct rtllib_device *ieee);
-extern void HTInitializeBssDesc(struct bss_ht *pBssHT);
-extern void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
-                                         struct rtllib_network *pNetwork);
-extern void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
-                                           struct rtllib_network *pNetwork);
-extern u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
-                             u8 *pMCSFilter);
+void HTUpdateDefaultSetting(struct rtllib_device *ieee);
+void HTConstructCapabilityElement(struct rtllib_device *ieee,
+                                 u8 *posHTCap, u8 *len,
+                                 u8 isEncrypt, bool bAssoc);
+void HTConstructInfoElement(struct rtllib_device *ieee,
+                           u8 *posHTInfo, u8 *len, u8 isEncrypt);
+void HTConstructRT2RTAggElement(struct rtllib_device *ieee,
+                               u8 *posRT2RTAgg, u8 *len);
+void HTOnAssocRsp(struct rtllib_device *ieee);
+void HTInitializeHTInfo(struct rtllib_device *ieee);
+void HTInitializeBssDesc(struct bss_ht *pBssHT);
+void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
+                                  struct rtllib_network *pNetwork);
+void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
+                                    struct rtllib_network *pNetwork);
+u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
+                      u8 *pMCSFilter);
 extern u8 MCS_FILTER_ALL[];
 extern u16 MCS_DATA_RATE[2][2][77];
-extern u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame);
-extern void HTResetIOTSetting(struct rt_hi_throughput *pHTInfo);
-extern bool IsHTHalfNmodeAPs(struct rtllib_device *ieee);
-extern u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate);
-extern u16  TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate);
-extern int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb);
-extern int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb);
-extern int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb);
-extern void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
-                       u8 Policy, u8 bOverwritePending);
-extern void TsInitDelBA(struct rtllib_device *ieee,
-                       struct ts_common_info *pTsCommonInfo,
-                       enum tr_select TxRxSelect);
-extern void BaSetupTimeOut(unsigned long data);
-extern void TxBaInactTimeout(unsigned long data);
-extern void RxBaInactTimeout(unsigned long data);
-extern void ResetBaEntry(struct ba_record *pBA);
-extern bool GetTs(
-       struct rtllib_device *ieee,
-       struct ts_common_info **ppTS,
-       u8 *Addr,
-       u8 TID,
-       enum tr_select TxRxSelect,
-       bool bAddNewTs
-);
-extern void TSInitialize(struct rtllib_device *ieee);
-extern  void TsStartAddBaProcess(struct rtllib_device *ieee,
-                                 struct tx_ts_record *pTxTS);
-extern void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr);
-extern void RemoveAllTS(struct rtllib_device *ieee);
-void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame);
+void HTResetIOTSetting(struct rt_hi_throughput *pHTInfo);
+bool IsHTHalfNmodeAPs(struct rtllib_device *ieee);
+u16  TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate);
+int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb);
+int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb);
+int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb);
+void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
+                u8 Policy, u8 bOverwritePending);
+void TsInitDelBA(struct rtllib_device *ieee,
+                struct ts_common_info *pTsCommonInfo,
+                enum tr_select TxRxSelect);
+void BaSetupTimeOut(unsigned long data);
+void TxBaInactTimeout(unsigned long data);
+void RxBaInactTimeout(unsigned long data);
+void ResetBaEntry(struct ba_record *pBA);
+bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *Addr,
+          u8 TID, enum tr_select TxRxSelect, bool bAddNewTs);
+void TSInitialize(struct rtllib_device *ieee);
+void TsStartAddBaProcess(struct rtllib_device *ieee,
+                        struct tx_ts_record *pTxTS);
+void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr);
+void RemoveAllTS(struct rtllib_device *ieee);
 
 extern const long rtllib_wlan_frequencies[];
 
@@ -2317,23 +2200,19 @@ bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn);
 /* For the function is more related to hardware setting, it's better to use the
  * ieee handler to refer to it.
  */
-extern void rtllib_update_active_chan_map(struct rtllib_device *ieee);
-extern void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,
-                                       struct rx_ts_record *pTS);
-extern int rtllib_parse_info_param(struct rtllib_device *ieee,
-               struct rtllib_info_element *info_element,
-               u16 length,
-               struct rtllib_network *network,
-               struct rtllib_rx_stats *stats);
+void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,
+                                struct rx_ts_record *pTS);
+int rtllib_parse_info_param(struct rtllib_device *ieee,
+                           struct rtllib_info_element *info_element,
+                           u16 length,
+                           struct rtllib_network *network,
+                           struct rtllib_rx_stats *stats);
 
 void rtllib_indicate_packets(struct rtllib_device *ieee,
                             struct rtllib_rxb **prxbIndicateArray, u8  index);
-extern u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS,
-                         u8 *pOperateMCS);
-extern void HTUseDefaultSetting(struct rtllib_device *ieee);
+void HTUseDefaultSetting(struct rtllib_device *ieee);
 #define RT_ASOC_RETRY_LIMIT    5
 u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee);
-extern void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p);
 #define SEM_DOWN_IEEE_WX(psem) down(psem)
 #define SEM_UP_IEEE_WX(psem) up(psem)
 
index 42e88d69ae63c016f56719f848b68f7c6289b702..17c276d710582b1588babc773a55dda54b9a215a 100644 (file)
@@ -30,8 +30,6 @@
 #define DRV_NAME "rtllib_92e"
 #endif
 
-#define DMESG(x, a...)
-
 extern u32 rt_global_debug_component;
 
 /* These are the defines for rt_global_debug_component */
@@ -40,10 +38,7 @@ enum RTL_DEBUG {
        COMP_DBG                = (1 << 1),
        COMP_INIT               = (1 << 2),
        COMP_RECV               = (1 << 3),
-       COMP_SEND               = (1 << 4),
-       COMP_CMD                = (1 << 5),
        COMP_POWER              = (1 << 6),
-       COMP_EPROM              = (1 << 7),
        COMP_SWBW               = (1 << 8),
        COMP_SEC                = (1 << 9),
        COMP_LPS                = (1 << 10),
@@ -58,15 +53,12 @@ enum RTL_DEBUG {
        COMP_CH                 = (1 << 19),
        COMP_RF                 = (1 << 20),
        COMP_FIRMWARE           = (1 << 21),
-       COMP_HT                 = (1 << 22),
        COMP_RESET              = (1 << 23),
        COMP_CMDPKT             = (1 << 24),
        COMP_SCAN               = (1 << 25),
        COMP_PS                 = (1 << 26),
        COMP_DOWN               = (1 << 27),
        COMP_INTR               = (1 << 28),
-       COMP_LED                = (1 << 29),
-       COMP_MLME               = (1 << 30),
        COMP_ERR                = (1 << 31)
 };
 
index da862c3da4ce342be9afb6b673b9cf3766c755ca..09f0820fb3402c2779c706bf18fcd3bec2e19ab0 100644 (file)
@@ -44,6 +44,9 @@
 #include "rtllib.h"
 #include "dot11d.h"
 
+static void rtllib_rx_mgt(struct rtllib_device *ieee, struct sk_buff *skb,
+                         struct rtllib_rx_stats *stats);
+
 static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
                                     struct sk_buff *skb,
                                     struct rtllib_rx_stats *rx_status,
@@ -317,7 +320,6 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
                        netdev_dbg(ieee->dev,
                                   "Decryption failed ICV mismatch (key %d)\n",
                                   skb->data[hdrlen + 3] >> 6);
-               ieee->ieee_stats.rx_discards_undecryptable++;
                return -1;
        }
 
@@ -1077,7 +1079,6 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
                        netdev_dbg(ieee->dev,
                                   "Decryption failed (not set) (SA= %pM)\n",
                                   hdr->addr2);
-                       ieee->ieee_stats.rx_discards_undecryptable++;
                        return -1;
                }
        }
@@ -1743,37 +1744,61 @@ static int rtllib_parse_qos_info_param_IE(struct rtllib_device *ieee,
        return rc;
 }
 
-#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
-
 static const char *get_info_element_string(u16 id)
 {
        switch (id) {
-       MFIE_STRING(SSID);
-       MFIE_STRING(RATES);
-       MFIE_STRING(FH_SET);
-       MFIE_STRING(DS_SET);
-       MFIE_STRING(CF_SET);
-       MFIE_STRING(TIM);
-       MFIE_STRING(IBSS_SET);
-       MFIE_STRING(COUNTRY);
-       MFIE_STRING(HOP_PARAMS);
-       MFIE_STRING(HOP_TABLE);
-       MFIE_STRING(REQUEST);
-       MFIE_STRING(CHALLENGE);
-       MFIE_STRING(POWER_CONSTRAINT);
-       MFIE_STRING(POWER_CAPABILITY);
-       MFIE_STRING(TPC_REQUEST);
-       MFIE_STRING(TPC_REPORT);
-       MFIE_STRING(SUPP_CHANNELS);
-       MFIE_STRING(CSA);
-       MFIE_STRING(MEASURE_REQUEST);
-       MFIE_STRING(MEASURE_REPORT);
-       MFIE_STRING(QUIET);
-       MFIE_STRING(IBSS_DFS);
-       MFIE_STRING(RSN);
-       MFIE_STRING(RATES_EX);
-       MFIE_STRING(GENERIC);
-       MFIE_STRING(QOS_PARAMETER);
+       case MFIE_TYPE_SSID:
+               return "SSID";
+       case MFIE_TYPE_RATES:
+               return "RATES";
+       case MFIE_TYPE_FH_SET:
+               return "FH_SET";
+       case MFIE_TYPE_DS_SET:
+               return "DS_SET";
+       case MFIE_TYPE_CF_SET:
+               return "CF_SET";
+       case MFIE_TYPE_TIM:
+               return "TIM";
+       case MFIE_TYPE_IBSS_SET:
+               return "IBSS_SET";
+       case MFIE_TYPE_COUNTRY:
+               return "COUNTRY";
+       case MFIE_TYPE_HOP_PARAMS:
+               return "HOP_PARAMS";
+       case MFIE_TYPE_HOP_TABLE:
+               return "HOP_TABLE";
+       case MFIE_TYPE_REQUEST:
+               return "REQUEST";
+       case MFIE_TYPE_CHALLENGE:
+               return "CHALLENGE";
+       case MFIE_TYPE_POWER_CONSTRAINT:
+               return "POWER_CONSTRAINT";
+       case MFIE_TYPE_POWER_CAPABILITY:
+               return "POWER_CAPABILITY";
+       case MFIE_TYPE_TPC_REQUEST:
+               return "TPC_REQUEST";
+       case MFIE_TYPE_TPC_REPORT:
+               return "TPC_REPORT";
+       case MFIE_TYPE_SUPP_CHANNELS:
+               return "SUPP_CHANNELS";
+       case MFIE_TYPE_CSA:
+               return "CSA";
+       case MFIE_TYPE_MEASURE_REQUEST:
+               return "MEASURE_REQUEST";
+       case MFIE_TYPE_MEASURE_REPORT:
+               return "MEASURE_REPORT";
+       case MFIE_TYPE_QUIET:
+               return "QUIET";
+       case MFIE_TYPE_IBSS_DFS:
+               return "IBSS_DFS";
+       case MFIE_TYPE_RSN:
+               return "RSN";
+       case MFIE_TYPE_RATES_EX:
+               return "RATES_EX";
+       case MFIE_TYPE_GENERIC:
+               return "GENERIC";
+       case MFIE_TYPE_QOS_PARAMETER:
+               return "QOS_PARAMETER";
        default:
                return "UNKNOWN";
        }
@@ -2717,9 +2742,9 @@ free_network:
        kfree(network);
 }
 
-void rtllib_rx_mgt(struct rtllib_device *ieee,
-                     struct sk_buff *skb,
-                     struct rtllib_rx_stats *stats)
+static void rtllib_rx_mgt(struct rtllib_device *ieee,
+                         struct sk_buff *skb,
+                         struct rtllib_rx_stats *stats)
 {
        struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data;
 
index d320c31732f242b965635350906e3d0b1e5ab542..1503cbb3574ef7341594190aeeff7eebbd4231f2 100644 (file)
 #include <linux/ieee80211.h>
 #include "dot11d.h"
 
-short rtllib_is_54g(struct rtllib_network *net)
+static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
+
+
+static short rtllib_is_54g(struct rtllib_network *net)
 {
        return (net->rates_ex_len > 0) || (net->rates_len > 4);
 }
@@ -107,7 +110,7 @@ static void rtllib_WMM_Info(struct rtllib_device *ieee, u8 **tag_p)
        *tag_p = tag;
 }
 
-void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p)
+static void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p)
 {
        u8 *tag = *tag_p;
 
@@ -369,7 +372,7 @@ static inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee)
        return skb;
 }
 
-struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee);
+static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee);
 
 static void rtllib_send_beacon(struct rtllib_device *ieee)
 {
@@ -483,7 +486,7 @@ static void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh)
 }
 
 
-void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
+static void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
 {
        if (ieee->active_scan && (ieee->softmac_features &
            IEEE_SOFTMAC_PROBERQ)) {
@@ -492,7 +495,7 @@ void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
        }
 }
 
-void rtllib_update_active_chan_map(struct rtllib_device *ieee)
+static void rtllib_update_active_chan_map(struct rtllib_device *ieee)
 {
        memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map,
               MAX_CHANNEL_NUMBER+1);
@@ -501,7 +504,7 @@ void rtllib_update_active_chan_map(struct rtllib_device *ieee)
 /* this performs syncro scan blocking the caller until all channels
  * in the allowed channel map has been checked.
  */
-void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
+static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
 {
        union iwreq_data wrqu;
        short ch = 0;
@@ -1401,7 +1404,7 @@ inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,
        return skb;
 }
 
-void rtllib_associate_abort(struct rtllib_device *ieee)
+static void rtllib_associate_abort(struct rtllib_device *ieee)
 {
        unsigned long flags;
 
@@ -1511,7 +1514,6 @@ static void rtllib_associate_step2(struct rtllib_device *ieee)
        }
 }
 
-#define CANCELLED  2
 static void rtllib_associate_complete_wq(void *data)
 {
        struct rtllib_device *ieee = (struct rtllib_device *)
@@ -1753,7 +1755,7 @@ inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
        }
 }
 
-void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
+static void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
 {
        unsigned long flags;
        struct rtllib_network *target;
@@ -2109,7 +2111,7 @@ out:
 
 }
 
-void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
+static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
 {
        if (ieee->sta_sleep == LPS_IS_WAKE) {
                if (nl) {
@@ -2545,7 +2547,7 @@ inline void rtllib_randomize_cell(struct rtllib_device *ieee)
 }
 
 /* called in user context only */
-void rtllib_start_master_bss(struct rtllib_device *ieee)
+static void rtllib_start_master_bss(struct rtllib_device *ieee)
 {
        ieee->assoc_id = 1;
 
@@ -2720,7 +2722,7 @@ inline void rtllib_start_ibss(struct rtllib_device *ieee)
 }
 
 /* this is called only in user context, with wx_sem held */
-void rtllib_start_bss(struct rtllib_device *ieee)
+static void rtllib_start_bss(struct rtllib_device *ieee)
 {
        unsigned long flags;
 
@@ -2817,7 +2819,7 @@ exit:
        up(&ieee->wx_sem);
 }
 
-struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
+static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
 {
        const u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
@@ -3084,7 +3086,7 @@ static int rtllib_wpa_enable(struct rtllib_device *ieee, int value)
         */
        netdev_info(ieee->dev, "%s WPA\n", value ? "enabling" : "disabling");
        ieee->wpa_enabled = value;
-       memset(ieee->ap_mac_addr, 0, 6);
+       eth_zero_addr(ieee->ap_mac_addr);
        return 0;
 }
 
index e99ea5e67ef98c6f0be353930417d81ee08d49bf..b992e4612fd89990c30628b2b21246a0aa2e4773 100644 (file)
 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
 static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
 
-inline int rtllib_put_snap(u8 *data, u16 h_proto)
+static int rtllib_put_snap(u8 *data, u16 h_proto)
 {
        struct rtllib_snap_hdr *snap;
        u8 *oui;
@@ -205,7 +205,6 @@ int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
        if (res < 0) {
                netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n",
                            ieee->dev->name, frag->len);
-               ieee->ieee_stats.tx_discards++;
                return -1;
        }
 
@@ -515,8 +514,8 @@ static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
        }
 }
 
-u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
-                       u8 *dst)
+static u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
+                              u8 *dst)
 {
        u16 seqnum = 0;
 
@@ -566,7 +565,7 @@ static u8 rtllib_current_rate(struct rtllib_device *ieee)
                return ieee->rate & 0x7F;
 }
 
-int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
+static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
 {
        struct rtllib_device *ieee = (struct rtllib_device *)
                                     netdev_priv_rsl(dev);
index 23af2aad458e155fe4abf3793b74f43b797b6f80..d481a26c25ae704506c84b4220d5945a962e99fa 100644 (file)
@@ -2169,98 +2169,99 @@ static inline int ieee80211_is_cck_rate(u8 rate)
 
 
 /* ieee80211.c */
-extern void free_ieee80211(struct net_device *dev);
-extern struct net_device *alloc_ieee80211(int sizeof_priv);
+void free_ieee80211(struct net_device *dev);
+struct net_device *alloc_ieee80211(int sizeof_priv);
 
-extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
+int ieee80211_set_encryption(struct ieee80211_device *ieee);
 
 /* ieee80211_tx.c */
 
-extern int ieee80211_encrypt_fragment(
-       struct ieee80211_device *ieee,
-       struct sk_buff *frag,
-       int hdr_len);
+int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
+                              struct sk_buff *frag, int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
-                         struct net_device *dev);
-extern void ieee80211_txb_free(struct ieee80211_txb *);
+int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
+void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
-                       struct ieee80211_rx_stats *rx_stats);
-extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-                            struct rtl_80211_hdr_4addr *header,
-                            struct ieee80211_rx_stats *stats);
+int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+                struct ieee80211_rx_stats *rx_stats);
+void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+                     struct rtl_80211_hdr_4addr *header,
+                     struct ieee80211_rx_stats *stats);
 
 /* ieee80211_wx.c */
-extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
-                                struct iw_request_info *info,
-                                union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
-                                  struct iw_request_info *info,
-                                  union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
-                                  struct iw_request_info *info,
-                                  union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
+int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *key);
+int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
                            struct iw_request_info *info,
-                           union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
+                           union iwreq_data *wrqu, char *key);
+int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
                            struct iw_request_info *info,
-                           union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
-                              struct iw_request_info *info,
-                              struct iw_param *data, char *extra);
-extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
-                              struct iw_request_info *info,
-                              union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
+                           union iwreq_data *wrqu, char *key);
+int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
+                         struct iw_request_info *info,
+                         struct iw_param *data, char *extra);
+int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
 
 /* ieee80211_softmac.c */
-extern short ieee80211_is_54g(const struct ieee80211_network *net);
-extern short ieee80211_is_shortslot(const struct ieee80211_network *net);
-extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
-                       struct ieee80211_rx_stats *rx_stats, u16 type,
-                       u16 stype);
-extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
+short ieee80211_is_54g(const struct ieee80211_network *net);
+short ieee80211_is_shortslot(const struct ieee80211_network *net);
+int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee,
+                              struct sk_buff *skb,
+                              struct ieee80211_rx_stats *rx_stats,
+                              u16 type, u16 stype);
+void ieee80211_softmac_new_net(struct ieee80211_device *ieee,
+                              struct ieee80211_network *net);
 
 void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn);
-extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
-
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_master_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_ibss(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_init(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_free(struct ieee80211_device *ieee);
-extern void ieee80211_associate_abort(struct ieee80211_device *ieee);
-extern void ieee80211_disassociate(struct ieee80211_device *ieee);
-extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
-extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
-extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
-extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
-extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
-
-extern void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
+void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
+                           struct ieee80211_device *ieee);
+
+void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+void notify_wx_assoc_event(struct ieee80211_device *ieee);
+void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
+void ieee80211_start_bss(struct ieee80211_device *ieee);
+void ieee80211_start_master_bss(struct ieee80211_device *ieee);
+void ieee80211_start_ibss(struct ieee80211_device *ieee);
+void ieee80211_softmac_init(struct ieee80211_device *ieee);
+void ieee80211_softmac_free(struct ieee80211_device *ieee);
+void ieee80211_associate_abort(struct ieee80211_device *ieee);
+void ieee80211_disassociate(struct ieee80211_device *ieee);
+void ieee80211_stop_scan(struct ieee80211_device *ieee);
+void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
+void ieee80211_check_all_nets(struct ieee80211_device *ieee);
+void ieee80211_start_protocol(struct ieee80211_device *ieee);
+void ieee80211_stop_protocol(struct ieee80211_device *ieee);
+void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
+void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
+void ieee80211_reset_queue(struct ieee80211_device *ieee);
+void ieee80211_wake_queue(struct ieee80211_device *ieee);
+void ieee80211_stop_queue(struct ieee80211_device *ieee);
+struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
+void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
+void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee,
+                                  struct iw_point *p);
+void notify_wx_assoc_event(struct ieee80211_device *ieee);
+void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
+
+void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
 
 /* ieee80211_crypt_ccmp&tkip&wep.c */
-extern void ieee80211_tkip_null(void);
-extern void ieee80211_wep_null(void);
-extern void ieee80211_ccmp_null(void);
+void ieee80211_tkip_null(void);
+void ieee80211_wep_null(void);
+void ieee80211_ccmp_null(void);
 
 int ieee80211_crypto_init(void);
 void ieee80211_crypto_deinit(void);
@@ -2273,116 +2274,128 @@ void ieee80211_crypto_wep_exit(void);
 
 /* ieee80211_softmac_wx.c */
 
-extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
-                           struct iw_request_info *info,
-                           union iwreq_data *wrqu, char *ext);
+int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
+                        struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *ext);
 
-extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
+int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
                         struct iw_request_info *info,
                         union iwreq_data *awrq,
                         char *extra);
 
-extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
+int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
+                          struct iw_request_info *a,
+                          union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
-                            union iwreq_data *wrqu, char *b);
+int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
+                         struct iw_request_info *a,
+                         union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
-                            union iwreq_data *wrqu, char *b);
+int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
+                         struct iw_request_info *a,
+                         union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
-                             struct iw_request_info *a,
-                             union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
+                          struct iw_request_info *a,
+                          union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
-                            union iwreq_data *wrqu, char *b);
+int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
+                         struct iw_request_info *a,
+                         union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
-                            union iwreq_data *wrqu, char *b);
+int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
+                         struct iw_request_info *a,
+                         union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
-                            union iwreq_data *wrqu, char *b);
+int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
+                         struct iw_request_info *a,
+                         union iwreq_data *wrqu, char *b);
 
 /* ieee80211_module.c */
-extern int ieee80211_debug_init(void);
-extern void ieee80211_debug_exit(void);
+int ieee80211_debug_init(void);
+void ieee80211_debug_exit(void);
 
 //extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee);
-extern void ieee80211_wx_sync_scan_wq(struct work_struct *work);
+void ieee80211_wx_sync_scan_wq(struct work_struct *work);
 
 
-extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
-                              struct iw_request_info *info,
+int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
+                          struct iw_request_info *info,
                               union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_name(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_name(struct ieee80211_device *ieee,
+                         struct iw_request_info *info,
+                         union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_set_power(struct ieee80211_device *ieee,
-                                struct iw_request_info *info,
-                                union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_power(struct ieee80211_device *ieee,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_power(struct ieee80211_device *ieee,
-                                struct iw_request_info *info,
-                                union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_power(struct ieee80211_device *ieee,
+                          struct iw_request_info *info,
+                          union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
+                        struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
+                        struct iw_request_info *info,
+                        union iwreq_data *wrqu, char *extra);
 //HT
 #define MAX_RECEIVE_BUFFER_SIZE 9100  //
-extern void HTDebugHTCapability(u8 *CapIE, u8 *TitleString );
-extern void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
-
-void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET    Offset);
-extern void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
-extern void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u8 *len, u8 isEncrypt);
-extern void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *len, u8 isEncrypt);
-extern void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg, u8 *len);
-extern void HTOnAssocRsp(struct ieee80211_device *ieee);
-extern void HTInitializeHTInfo(struct ieee80211_device *ieee);
-extern void HTInitializeBssDesc(PBSS_HT pBssHT);
-extern void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
-extern void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee,   struct ieee80211_network *pNetwork);
-extern u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSFilter);
+void HTDebugHTCapability(u8 *CapIE, u8 *TitleString);
+void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
+
+void HTSetConnectBwMode(struct ieee80211_device *ieee,
+                       HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
+void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap,
+                                 u8 *len, u8 isEncrypt);
+void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo,
+                           u8 *len, u8 isEncrypt);
+void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg,
+                               u8 *len);
+void HTOnAssocRsp(struct ieee80211_device *ieee);
+void HTInitializeHTInfo(struct ieee80211_device *ieee);
+void HTInitializeBssDesc(PBSS_HT pBssHT);
+void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee,
+                                  struct ieee80211_network *pNetwork);
+void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee,
+                               struct ieee80211_network *pNetwork);
+u8 HTGetHighestMCSRate(struct ieee80211_device *ieee,
+                      u8 *pMCSRateSet, u8 *pMCSFilter);
 extern u8 MCS_FILTER_ALL[];
 extern u16 MCS_DATA_RATE[2][2][77] ;
-extern u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
+u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
 //extern void HTSetConnectBwModeCallback(unsigned long data);
-extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT  pHTInfo);
-extern bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
-extern u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee,  u8      nMcsRate);
-extern u16 HTMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
-extern u16  TxCountToDataRate(struct ieee80211_device *ieee, u8 nDataRate);
+void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo);
+bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
+u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
+u16 HTMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
+u16 TxCountToDataRate(struct ieee80211_device *ieee, u8 nDataRate);
 //function in BAPROC.c
-extern int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee,
-                                struct sk_buff *skb);
-extern int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee,
-                                struct sk_buff *skb);
-extern int ieee80211_rx_DELBA(struct ieee80211_device *ieee,struct sk_buff *skb);
-extern void TsInitAddBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTS,
-                       u8 Policy, u8 bOverwritePending);
-extern void TsInitDelBA(struct ieee80211_device *ieee,
-                       PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
-extern void BaSetupTimeOut(unsigned long data);
-extern void TxBaInactTimeout(unsigned long data);
-extern void RxBaInactTimeout(unsigned long data);
-extern void ResetBaEntry(PBA_RECORD pBA);
+int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb);
+int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb);
+int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb);
+void TsInitAddBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTS,
+                u8 Policy, u8 bOverwritePending);
+void TsInitDelBA(struct ieee80211_device *ieee,
+                PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
+void BaSetupTimeOut(unsigned long data);
+void TxBaInactTimeout(unsigned long data);
+void RxBaInactTimeout(unsigned long data);
+void ResetBaEntry(PBA_RECORD pBA);
 //function in TS.c
-extern bool GetTs(
+bool GetTs(
        struct ieee80211_device         *ieee,
        PTS_COMMON_INFO                 *ppTS,
        u8                              *Addr,
@@ -2390,10 +2403,10 @@ extern bool GetTs(
        TR_SELECT                       TxRxSelect,  //Rx:1, Tx:0
        bool                            bAddNewTs
        );
-extern void TSInitialize(struct ieee80211_device *ieee);
-extern  void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD   pTxTS);
-extern void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
-extern void RemoveAllTS(struct ieee80211_device *ieee);
+void TSInitialize(struct ieee80211_device *ieee);
+void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD   pTxTS);
+void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
+void RemoveAllTS(struct ieee80211_device *ieee);
 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee);
 
 extern const long ieee80211_wlan_frequencies[];
@@ -2423,14 +2436,16 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) {
 /* For the function is more related to hardware setting, it's better to use the
  * ieee handler to refer to it.
  */
-extern short check_nic_enough_desc(struct net_device *dev, int queue_index);
-extern int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
-extern int ieee80211_parse_info_param(struct ieee80211_device *ieee,
-               struct ieee80211_info_element *info_element,
-               u16 length,
-               struct ieee80211_network *network,
-               struct ieee80211_rx_stats *stats);
-
-void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray,u8  index);
+short check_nic_enough_desc(struct net_device *dev, int queue_index);
+int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
+int ieee80211_parse_info_param(struct ieee80211_device *ieee,
+                              struct ieee80211_info_element *info_element,
+                              u16 length,
+                              struct ieee80211_network *network,
+                              struct ieee80211_rx_stats *stats);
+
+void ieee80211_indicate_packets(struct ieee80211_device *ieee,
+                               struct ieee80211_rxb **prxbIndicateArray,
+                               u8 index);
 #define RT_ASOC_RETRY_LIMIT    5
 #endif /* IEEE80211_H */
index b374088c5ff87c11fa9f4baa78324d5680206ea6..0aa9021cb95e751e0c2f6c2f9f3963e5638d2ef6 100644 (file)
@@ -1014,7 +1014,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                goto rx_dropped;
 
        // if QoS enabled, should check the sequence for each of the AC
-       if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){
+       if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) {
                if (is_duplicate_packet(ieee, hdr))
                goto rx_dropped;
 
@@ -1307,7 +1307,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
        }
 
 //added by amy for reorder
-       if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
+       if (!ieee->pHTInfo->bCurRxReorderEnable || pTS == NULL){
 //added by amy for reorder
                for(i = 0; i<rxb->nr_subframes; i++) {
                        struct sk_buff *sub_skb = rxb->subframes[i];
index 1b11acb9623327d7aae801bd34ce82882cfb9e51..39e9892c3fa6a8ba04f82a6d9e9967c294aad20b 100644 (file)
@@ -1177,7 +1177,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
                        tag = skb_put(skb, ht_cap_len);
                        *tag++ = MFIE_TYPE_HT_CAP;
                        *tag++ = ht_cap_len - 2;
-                       memcpy(tag, ht_cap_buf,ht_cap_len -2);
+                       memcpy(tag, ht_cap_buf, ht_cap_len - 2);
                        tag += ht_cap_len -2;
                }
        }
@@ -1214,7 +1214,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
                        tag = skb_put(skb, realtek_ie_len);
                        *tag++ = MFIE_TYPE_GENERIC;
                        *tag++ = realtek_ie_len - 2;
-                       memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
+                       memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
                }
        }
 //     printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
@@ -1964,7 +1964,7 @@ static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
                        }
 
                        if (ieee->current_network.mode == IEEE_N_24G &&
-                                       bHalfSupportNmode == true) {
+                                       bHalfSupportNmode) {
                                netdev_dbg(ieee->dev, "enter half N mode\n");
                                ieee->bHalfWirelessN24GMode = true;
                        } else
index 714fbcace72b1bc12db648f4fb293eccf67d34bc..3e502520648ea2a8ffcbdaa3bdd3cc431a69acdb 100644 (file)
@@ -391,7 +391,7 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
                              union iwreq_data *wrqu, char *extra)
 {
 
-       int ret=0,len;
+       int ret = 0, len;
        short proto_started;
        unsigned long flags;
 
index 5353a45ffdffd411bb522e79d53f7a8c12250b40..fff8d583c62faa4501163d19da20a7f43f580671 100644 (file)
@@ -336,12 +336,12 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee,
                        printk("===>can't get TS\n");
                        return;
                }
-               if (pTxTs->TxAdmittedBARecord.bValid == false)
+               if (!pTxTs->TxAdmittedBARecord.bValid)
                {
                        TsStartAddBaProcess(ieee, pTxTs);
                        goto FORCED_AGG_SETTING;
                }
-               else if (pTxTs->bUsingBa == false)
+               else if (!pTxTs->bUsingBa)
                {
                        if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
                                pTxTs->bUsingBa = true;
index 9ff8e056ab7f10095bc05cbb0d65ead7d8a39c01..3bde744604c210eaf2dd55739b0527768b173b4b 100644 (file)
@@ -364,8 +364,8 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
        printk("====================>rx ADDBAREQ from :%pM\n", dst);
 //some other capability is not ready now.
        if ((ieee->current_network.qos_data.active == 0) ||
-               (ieee->pHTInfo->bCurrentHTSupport == false)) //||
-       //      (ieee->pStaQos->bEnableRxImmBA == false)        )
+               (!ieee->pHTInfo->bCurrentHTSupport)) //||
+       //      (!ieee->pStaQos->bEnableRxImmBA)        )
        {
                rc = ADDBA_STATUS_REFUSED;
                IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
@@ -462,8 +462,8 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
        // Check the capability
        // Since we can always receive A-MPDU, we just check if it is under HT mode.
        if (ieee->current_network.qos_data.active == 0  ||
-           ieee->pHTInfo->bCurrentHTSupport == false ||
-           ieee->pHTInfo->bCurrentAMPDUEnable == false) {
+           !ieee->pHTInfo->bCurrentHTSupport ||
+           !ieee->pHTInfo->bCurrentAMPDUEnable) {
                IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
                ReasonCode = DELBA_REASON_UNKNOWN_BA;
                goto OnADDBARsp_Reject;
@@ -502,7 +502,7 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
                IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
                return -1;
        }
-       else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
+       else if((!pPendingBA->bValid) ||(*pDialogToken != pPendingBA->DialogToken))
        {
                IEEE80211_DEBUG(IEEE80211_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
                ReasonCode = DELBA_REASON_UNKNOWN_BA;
@@ -571,7 +571,6 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
 {
         struct rtl_80211_hdr_3addr *delba = NULL;
        PDELBA_PARAM_SET        pDelBaParamSet = NULL;
-       u16                     *pReasonCode = NULL;
        u8                      *dst = NULL;
 
        if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) {
@@ -583,7 +582,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
        }
 
        if (ieee->current_network.qos_data.active == 0 ||
-               ieee->pHTInfo->bCurrentHTSupport == false )
+           !ieee->pHTInfo->bCurrentHTSupport)
        {
                IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
                return -1;
@@ -592,9 +591,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
        IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
        delba = (struct rtl_80211_hdr_3addr *)skb->data;
        dst = (u8 *)(&delba->addr2[0]);
-       delba += sizeof(struct rtl_80211_hdr_3addr);
-       pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
-       pReasonCode = (u16 *)(delba+4);
+       pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2];
 
        if(pDelBaParamSet->field.Initiator == 1)
        {
index c2588f80625b99e23c9aaf519e35ef22f62c1746..c27397b14adb86874aa745ec1dc3bf027f76e173 100644 (file)
@@ -224,9 +224,9 @@ static bool IsHTHalfNmode40Bandwidth(struct ieee80211_device *ieee)
        bool                    retValue = false;
        PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
 
-       if(pHTInfo->bCurrentHTSupport == false )        // wireless is n mode
+       if(!pHTInfo->bCurrentHTSupport)         // wireless is n mode
                retValue = false;
-       else if(pHTInfo->bRegBW40MHz == false)  // station supports 40 bw
+       else if(!pHTInfo->bRegBW40MHz)          // station supports 40 bw
                retValue = false;
        else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))      // station in half n mode
                retValue = false;
@@ -243,7 +243,7 @@ static bool IsHTHalfNmodeSGI(struct ieee80211_device *ieee, bool is40MHz)
        bool                    retValue = false;
        PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
 
-       if(pHTInfo->bCurrentHTSupport == false )        // wireless is n mode
+       if(!pHTInfo->bCurrentHTSupport)         // wireless is n mode
                retValue = false;
        else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))      // station in half n mode
                retValue = false;
@@ -675,7 +675,7 @@ void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *le
        if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) //ap mode is not currently supported
        {
                pHTInfoEle->ControlChl                  = ieee->current_network.channel;
-               pHTInfoEle->ExtChlOffset                        = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
+               pHTInfoEle->ExtChlOffset                        = ((!pHT->bRegBW40MHz)?HT_EXTCHNL_OFFSET_NO_EXT:
                                                                                        (ieee->current_network.channel<=6)?
                                                                                                HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
                pHTInfoEle->RecommemdedTxWidth  = pHT->bRegBW40MHz;
@@ -945,7 +945,7 @@ void HTOnAssocRsp(struct ieee80211_device *ieee)
        static u8                               EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};               // For 11n EWC definition, 2007.07.17, by Emily
        static u8                               EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};      // For 11n EWC definition, 2007.07.17, by Emily
 
-       if (pHTInfo->bCurrentHTSupport == false) {
+       if (!pHTInfo->bCurrentHTSupport) {
                IEEE80211_DEBUG(IEEE80211_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n");
                return;
        }
@@ -956,7 +956,7 @@ void HTOnAssocRsp(struct ieee80211_device *ieee)
 //     HTDebugHTCapability(pHTInfo->PeerHTCapBuf,"HTOnAssocRsp_wq");
 //     HTDebugHTInfo(pHTInfo->PeerHTInfoBuf,"HTOnAssocRsp_wq");
        //
-       if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap)))
+       if (!memcmp(pHTInfo->PeerHTCapBuf, EWC11NHTCap, sizeof(EWC11NHTCap)))
                pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]);
        else
                pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf);
@@ -976,7 +976,7 @@ void HTOnAssocRsp(struct ieee80211_device *ieee)
        //
        HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset));
 
-//     if(pHTInfo->bCurBW40MHz == true)
+//     if (pHTInfo->bCurBW40MHz)
                pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false);
 
        //
@@ -1341,7 +1341,7 @@ void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH   Bandwidt
        PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
 //     u32 flags = 0;
 
-       if(pHTInfo->bRegBW40MHz == false)
+       if(!pHTInfo->bRegBW40MHz)
                return;
 
 
index ea92fdebe5a748a9f762f482f97ad706d428271e..f33c74342cf3bf1f4629b09e0bbc54f956c5f50f 100644 (file)
@@ -112,7 +112,7 @@ static void TsAddBaProcess(unsigned long data)
 
 static void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo)
 {
-       memset(pTsCommonInfo->Addr, 0, 6);
+       eth_zero_addr(pTsCommonInfo->Addr);
        memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
        memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
        pTsCommonInfo->TClasProc = 0;
@@ -584,7 +584,7 @@ void RemoveAllTS(struct ieee80211_device *ieee)
 
 void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD  pTxTS)
 {
-       if(pTxTS->bAddBaReqInProgress == false)
+       if(!pTxTS->bAddBaReqInProgress)
        {
                pTxTS->bAddBaReqInProgress = true;
                if(pTxTS->bAddBaReqDelayed)
index 6e5662f7951c9ffd96c875173522eaec7e17e1ca..1ba4f83b520e8881d8b0690b42513a1a836b7a28 100644 (file)
 #define RTL8225H
 
 #define RTL819X_TOTAL_RF_PATH 2 /* for 8192U */
-extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
-                                  HT_CHANNEL_WIDTH Bandwidth);
-extern void PHY_RF8256_Config(struct net_device *dev);
-extern void phy_RF8256_Config_ParaFile(struct net_device *dev);
-extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
-extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+void PHY_SetRF8256Bandwidth(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth);
+void PHY_RF8256_Config(struct net_device *dev);
+void phy_RF8256_Config_ParaFile(struct net_device *dev);
+void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8        powerlevel);
+void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
 
 #endif
index 6c2e438c9af498fbcc63e9d251d1903d7e8452ee..785fd027a00d2f0b7ca6f919f7e008df1e6441b4 100644 (file)
@@ -1187,7 +1187,7 @@ void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
 void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
 void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
 void rtl8192_set_rxconf(struct net_device *dev);
-extern void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate);
+void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate);
 
 void EnableHWSecurityConfig8192(struct net_device *dev);
 void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
index b852396d21e6af5a4bbd48fab8e486f3061c2ae5..6f6fe38081bcefff290d832db78818dac63ec7a7 100644 (file)
@@ -2043,16 +2043,9 @@ static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
 
 static bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
 {
-       bool                    Reval;
        struct r8192_priv *priv = ieee80211_priv(dev);
-       struct ieee80211_device *ieee = priv->ieee80211;
-
-       if (ieee->bHalfWirelessN24GMode == true)
-               Reval = true;
-       else
-               Reval =  false;
 
-       return Reval;
+       return priv->ieee80211->bHalfWirelessN24GMode;
 }
 
 static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
@@ -2762,7 +2755,7 @@ static bool rtl8192_adapter_start(struct net_device *dev)
        //
 #ifdef TO_DO_LIST
        if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
-               if (pMgntInfo->RegRfOff == true) { /* User disable RF via registry. */
+               if (pMgntInfo->RegRfOff) { /* User disable RF via registry. */
                        RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
                        MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
                        // Those actions will be discard in MgntActSet_RF_State because of the same state
@@ -4406,7 +4399,8 @@ static void query_rxdesc_status(struct sk_buff *skb,
        /* RTL8190 set this bit to indicate that Hw does not decrypt packet */
        stats->Decrypted = !desc->SWDec;
 
-       if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
+       if ((priv->ieee80211->pHTInfo->bCurrentHTSupport) &&
+           (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
                stats->bHwError = false;
        else
                stats->bHwError = stats->bCRC|stats->bICV;
index 7ca5d8fbc57fe3faeb5416170d859185aabbbef4..5277f2eec0339537000c716ec9d65fda75cb2d99 100644 (file)
@@ -438,7 +438,7 @@ static void dm_bandwidth_autoswitch(struct net_device *dev)
 
        if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable)
                return;
-       if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */
+       if (!priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz) { /* If send packets in 40 Mhz in 20/40 */
                if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
                        priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true;
        } else { /* in force send packets in 20 Mhz in 20/40 */
@@ -1731,7 +1731,7 @@ static void dm_dig_init(struct net_device *dev)
  *---------------------------------------------------------------------------*/
 static void dm_ctrl_initgain_byrssi(struct net_device *dev)
 {
-       if (dm_digtable.dig_enable_flag == false)
+       if (!dm_digtable.dig_enable_flag)
                return;
 
        if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
@@ -1750,7 +1750,7 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi(
        u8 i;
        static u8       fw_dig;
 
-       if (dm_digtable.dig_enable_flag == false)
+       if (!dm_digtable.dig_enable_flag)
                return;
 
        /*DbgPrint("Dig by Sw Rssi\n");*/
@@ -1792,7 +1792,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
        static u32 reset_cnt;
        u8 i;
 
-       if (dm_digtable.dig_enable_flag == false)
+       if (!dm_digtable.dig_enable_flag)
                return;
 
        if (dm_digtable.dig_algorithm_switch) {
index 6cd32eb440852e513b1cc2bc60b128447fb4612d..2d0232fb3f9b49283c46fc71771c5c7521a0d2df 100644 (file)
@@ -212,24 +212,24 @@ extern struct dynamic_rx_path_sel DM_RxPathSelTable;
 
 
 /*--------------------------Exported Function prototype---------------------*/
-extern void init_hal_dm(struct net_device *dev);
-extern void deinit_hal_dm(struct net_device *dev);
-extern void hal_dm_watchdog(struct net_device *dev);
-extern void init_rate_adaptive(struct net_device *dev);
-extern void dm_txpower_trackingcallback(struct work_struct *work);
-extern void dm_restore_dynamic_mechanism_state(struct net_device *dev);
-extern void dm_backup_dynamic_mechanism_state(struct net_device *dev);
-extern void dm_change_dynamic_initgain_thresh(struct net_device *dev,
-                                             u32 dm_type, u32 dm_value);
-extern void dm_force_tx_fw_info(struct net_device *dev,
-                               u32 force_type, u32 force_value);
-extern void dm_init_edca_turbo(struct net_device *dev);
-extern void dm_rf_operation_test_callback(unsigned long data);
-extern void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
-extern void dm_fsync_timer_callback(unsigned long data);
-extern void dm_cck_txpower_adjust(struct net_device *dev, bool  binch14);
-extern void dm_shadow_init(struct net_device *dev);
-extern void dm_initialize_txpower_tracking(struct net_device *dev);
+void init_hal_dm(struct net_device *dev);
+void deinit_hal_dm(struct net_device *dev);
+void hal_dm_watchdog(struct net_device *dev);
+void init_rate_adaptive(struct net_device *dev);
+void dm_txpower_trackingcallback(struct work_struct *work);
+void dm_restore_dynamic_mechanism_state(struct net_device *dev);
+void dm_backup_dynamic_mechanism_state(struct net_device *dev);
+void dm_change_dynamic_initgain_thresh(struct net_device *dev,
+                                      u32 dm_type, u32 dm_value);
+void dm_force_tx_fw_info(struct net_device *dev,
+                        u32 force_type, u32 force_value);
+void dm_init_edca_turbo(struct net_device *dev);
+void dm_rf_operation_test_callback(unsigned long data);
+void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
+void dm_fsync_timer_callback(unsigned long data);
+void dm_cck_txpower_adjust(struct net_device *dev, bool  binch14);
+void dm_shadow_init(struct net_device *dev);
+void dm_initialize_txpower_tracking(struct net_device *dev);
 /*--------------------------Exported Function prototype---------------------*/
 
 
index d6a2d975653166b8c07d0d7c5aa53abc6393054f..fb5f808433d1af6435efd5f29cd3be5f1a969885 100644 (file)
@@ -19,6 +19,6 @@
 
 extern struct iw_handler_def r8192_wx_handlers_def;
 /* Enable  the rtl819x_core.c to share this function, david 2008.9.22 */
-extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
+struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
 
 #endif
index 52cd437ef7bb52d058c652ac9594de1e9666b20c..cc8029a15df4d1b46cc9c7eed6450389a8131b4f 100644 (file)
@@ -182,10 +182,10 @@ typedef enum _rt_status {
        RT_STATUS_RESOURCE
 } rt_status, *prt_status;
 
-extern u32 cmpk_message_handle_rx(struct net_device *dev,
-               struct ieee80211_rx_stats *pstats);
-extern rt_status SendTxCommandPacket(struct net_device *dev,
-               void *pData, u32 DataLen);
+u32 cmpk_message_handle_rx(struct net_device *dev,
+                          struct ieee80211_rx_stats *pstats);
+rt_status SendTxCommandPacket(struct net_device *dev,
+                             void *pData, u32 DataLen);
 
 
 #endif
index d27b1e24ca4a1829141179bf7f2e617fa2eba79f..08302dfb0d90dd884d8889f245a5d804b0bd0dd3 100644 (file)
@@ -66,7 +66,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
                skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
                if (!skb)
                        return false;
-               memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+               memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
                tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
                tcb_desc->queue_index = TXCMD_QUEUE;
                tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
@@ -91,7 +91,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
                if (!priv->ieee80211->check_nic_enough_desc(dev, index) ||
                       (!skb_queue_empty(&priv->ieee80211->skb_waitQ[index])) ||
                       (priv->ieee80211->queue_stop)) {
-                       RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
+                       RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n");
                        skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
                } else {
                        priv->ieee80211->softmac_hard_start_xmit(skb, dev);
@@ -144,7 +144,8 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 
        /* Turn On CPU */
        read_nic_dword(dev, CPU_GEN, &CPU_status);
-       write_nic_byte(dev, CPU_GEN, (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
+       write_nic_byte(dev, CPU_GEN,
+                      (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
        mdelay(1000);
 
        /* Check whether CPU boot OK */
@@ -242,7 +243,7 @@ bool init_firmware(struct net_device *dev)
                 * or read image file from array. Default load from IMG file
                 */
                if (rst_opt == OPT_SYSTEM_RESET) {
-                       rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
+                       rc = request_firmware(&fw_entry, fw_name[init_step], &priv->udev->dev);
                        if (rc < 0) {
                                RT_TRACE(COMP_ERR, "request firmware fail!\n");
                                goto download_firmware_fail;
@@ -254,12 +255,12 @@ bool init_firmware(struct net_device *dev)
                        }
 
                        if (init_step != FW_INIT_STEP1_MAIN) {
-                               memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
+                               memcpy(pfirmware->firmware_buf, fw_entry->data, fw_entry->size);
                                mapped_file = pfirmware->firmware_buf;
                                file_length = fw_entry->size;
                        } else {
                                memset(pfirmware->firmware_buf, 0, 128);
-                               memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
+                               memcpy(&pfirmware->firmware_buf[128], fw_entry->data, fw_entry->size);
                                mapped_file = pfirmware->firmware_buf;
                                file_length = fw_entry->size + 128;
                        }
@@ -319,7 +320,7 @@ bool init_firmware(struct net_device *dev)
 
                        rt_status = CPUcheck_firmware_ready(dev);
                        if (!rt_status) {
-                               RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status);
+                               RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n", rt_status);
                                goto download_firmware_fail;
                        }
 
index 66cbe3f9cafd9116e42ea7a47be0fc16637288f0..e672126330f3dfa9c1e02bf6aa7fd30166b9ca3a 100644 (file)
@@ -57,36 +57,35 @@ typedef enum _RF90_RADIO_PATH {
 #define bMaskLWord                0x0000ffff
 #define bMaskDWord                0xffffffff
 
-extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
-extern void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr,
-       u32 bitmask, u32 data);
-extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr,
-       u32 bitmask);
-extern void rtl8192_phy_SetRFReg(struct net_device *dev,
-       RF90_RADIO_PATH_E eRFPath, u32 reg_addr, u32 bitmask, u32 data);
-extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
-       RF90_RADIO_PATH_E eRFPath, u32 reg_addr, u32 bitmask);
-extern void rtl8192_phy_configmac(struct net_device *dev);
-extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
-extern u8 rtl8192_phy_checkBBAndRF(struct net_device *dev,
-       HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
-extern void rtl8192_BBConfig(struct net_device *dev);
-extern void rtl8192_phy_getTxPower(struct net_device *dev);
-extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
-extern void rtl8192_phy_RFConfig(struct net_device *dev);
-extern void rtl8192_phy_updateInitGain(struct net_device *dev);
-extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
-       RF90_RADIO_PATH_E eRFPath);
+u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
+void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr,
+                     u32 bitmask, u32 data);
+u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr, u32 bitmask);
+void rtl8192_phy_SetRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
+                         u32 reg_addr, u32 bitmask, u32 data);
+u32 rtl8192_phy_QueryRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
+                          u32 reg_addr, u32 bitmask);
+void rtl8192_phy_configmac(struct net_device *dev);
+void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
+u8 rtl8192_phy_checkBBAndRF(struct net_device *dev,
+                           HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
+void rtl8192_BBConfig(struct net_device *dev);
+void rtl8192_phy_getTxPower(struct net_device *dev);
+void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
+void rtl8192_phy_RFConfig(struct net_device *dev);
+void rtl8192_phy_updateInitGain(struct net_device *dev);
+u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+                                     RF90_RADIO_PATH_E eRFPath);
 
-extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
-extern void rtl8192_SetBWMode(struct net_device *dev,
-       HT_CHANNEL_WIDTH bandwidth, HT_EXTCHNL_OFFSET offset);
-extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
+u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
+void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH bandwidth,
+                      HT_EXTCHNL_OFFSET offset);
+void rtl8192_SwChnl_WorkItem(struct net_device *dev);
 void rtl8192_SetBWModeWorkItem(struct net_device *dev);
-extern bool rtl8192_SetRFPowerState(struct net_device *dev,
-       RT_RF_POWER_STATE eRFPowerState);
-extern void InitialGain819xUsb(struct net_device *dev, u8 Operation);
+bool rtl8192_SetRFPowerState(struct net_device *dev,
+                            RT_RF_POWER_STATE eRFPowerState);
+void InitialGain819xUsb(struct net_device *dev, u8 Operation);
 
-extern void InitialGainOperateWorkItemCallBack(struct work_struct *work);
+void InitialGainOperateWorkItemCallBack(struct work_struct *work);
 
 #endif
index 57868085ce58c45c85aa8a5a37bbb034675f83cc..c5527c1ccaa6d7103e52f18eba0375d0e5051ba7 100644 (file)
@@ -134,22 +134,20 @@ u8 *r8712_get_ie(u8 *pbuf, sint index, sint *len, sint limit)
        return NULL;
 }
 
-static void set_supported_rate(u8 *SupportedRates, uint mode)
+static void set_supported_rate(u8 *rates, uint mode)
 {
-       memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+       memset(rates, 0, NDIS_802_11_LENGTH_RATES_EX);
        switch (mode) {
        case WIRELESS_11B:
-               memcpy(SupportedRates, WIFI_CCKRATES,
-                       IEEE80211_CCK_RATE_LEN);
+               memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
                break;
        case WIRELESS_11G:
        case WIRELESS_11A:
-               memcpy(SupportedRates, WIFI_OFDMRATES,
-                       IEEE80211_NUM_OFDM_RATESLEN);
+               memcpy(rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
                break;
        case WIRELESS_11BG:
-               memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
-               memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
+               memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+               memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
                        IEEE80211_NUM_OFDM_RATESLEN);
                break;
        }
@@ -195,17 +193,16 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv)
        ie = r8712_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength,
                    pdev_network->Ssid.Ssid, &sz);
        /*supported rates*/
-       set_supported_rate(pdev_network->SupportedRates,
-                          pregistrypriv->wireless_mode);
-       rateLen = r8712_get_rateset_len(pdev_network->SupportedRates);
+       set_supported_rate(pdev_network->rates, pregistrypriv->wireless_mode);
+       rateLen = r8712_get_rateset_len(pdev_network->rates);
        if (rateLen > 8) {
                ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, 8,
-                           pdev_network->SupportedRates, &sz);
+                           pdev_network->rates, &sz);
                ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8),
-                           (pdev_network->SupportedRates + 8), &sz);
+                           (pdev_network->rates + 8), &sz);
        } else
                ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_,
-                           rateLen, pdev_network->SupportedRates, &sz);
+                           rateLen, pdev_network->rates, &sz);
        /*DS parameter set*/
        ie = r8712_set_ie(ie, _DSSET_IE_, 1,
                    (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
index fcb8c61b28844fa78eb4c5637a11f7fa102865bc..4fa2540a6c3470c29cb364ef89372f1d583ab083 100644 (file)
@@ -58,8 +58,8 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter)
 
        /*init recv_buf*/
        _init_queue(&precvpriv->free_recv_buf_queue);
-       precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4,
-                                                GFP_ATOMIC);
+       precvpriv->pallocated_recv_buf =
+               kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC);
        if (precvpriv->pallocated_recv_buf == NULL)
                return _FAIL;
        precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
index e35854d28f90ed96aa3ff149f39175c9e46b1373..ef7182961002e8c45394a6a208cfe9bf850023e3 100644 (file)
@@ -456,9 +456,7 @@ u8 r8712_createbss_cmd(struct _adapter *padapter)
        INIT_LIST_HEAD(&pcmd->list);
        pcmd->cmdcode = _CreateBss_CMD_;
        pcmd->parmbuf = (unsigned char *)pdev_network;
-       pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz((
-                       struct ndis_wlan_bssid_ex *)
-                       pdev_network);
+       pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network);
        pcmd->rsp = NULL;
        pcmd->rspsz = 0;
        /* notes: translate IELength & Length after assign to cmdsz; */
@@ -471,8 +469,7 @@ u8 r8712_createbss_cmd(struct _adapter *padapter)
 
 u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
 {
-       uint t_len = 0;
-       struct ndis_wlan_bssid_ex *psecnetwork;
+       struct wlan_bssid_ex *psecnetwork;
        struct cmd_obj          *pcmd;
        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
@@ -486,14 +483,6 @@ u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
        if (pcmd == NULL)
                return _FAIL;
-       t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 +
-                       sizeof(struct ndis_802_11_ssid) + sizeof(u32) +
-                       sizeof(s32) +
-                       sizeof(enum NDIS_802_11_NETWORK_TYPE) +
-                       sizeof(struct NDIS_802_11_CONFIGURATION) +
-                       sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) +
-                       sizeof(NDIS_802_11_RATES_EX) +
-                       sizeof(u32) + MAX_IE_SZ;
 
        /* for hidden ap to set fw_state here */
        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) !=
@@ -511,12 +500,12 @@ u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
                        break;
                }
        }
-       psecnetwork = (struct ndis_wlan_bssid_ex *)&psecuritypriv->sec_bss;
+       psecnetwork = &psecuritypriv->sec_bss;
        if (psecnetwork == NULL) {
                kfree(pcmd);
                return _FAIL;
        }
-       memcpy(psecnetwork, &pnetwork->network, t_len);
+       memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
        psecuritypriv->authenticator_ie[0] = (unsigned char)
                                             psecnetwork->IELength;
        if ((psecnetwork->IELength-12) < (256 - 1))
@@ -575,7 +564,7 @@ u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
                        255);
        /* get cmdsz before endian conversion */
-       pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork);
+       pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
 #ifdef __BIG_ENDIAN
        /* wlan_network endian conversion */
        psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
@@ -903,8 +892,7 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
        struct sta_info *psta = NULL;
        struct wlan_network *pwlan = NULL;
        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
-       struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *)
-                                             pcmd->parmbuf;
+       struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
        struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 
        if (pcmd->res != H2C_SUCCESS)
@@ -958,11 +946,11 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter,
                } else
                        list_add_tail(&(pwlan->list),
                                         &pmlmepriv->scanned_queue.queue);
-               pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
+               pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
                memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
                pwlan->fixed = true;
                memcpy(&tgt_network->network, pnetwork,
-                       (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork)));
+                       (r8712_get_wlan_bssid_ex_sz(pnetwork)));
                if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
                        pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
                /* we will set _FW_LINKED when there is one more sat to
index cb8225b94cf10bdeaf71ae3468dd38a79ed934bf..818cd8807a380a45a111d889f8b43560a3014a52 100644 (file)
@@ -122,15 +122,6 @@ struct usb_suspend_parm {
        u32 action; /* 1: sleep, 0:resume */
 };
 
-/*
- * Caller Mode: Infra, Ad-Hoc
- * Notes: To join the specified bss
- * Command Event Mode
- */
-struct joinbss_parm {
-       struct ndis_wlan_bssid_ex network;
-};
-
 /*
  * Caller Mode: Infra, Ad-HoC(C)
  * Notes: To disconnect the current associated BSS
@@ -140,15 +131,6 @@ struct disconnect_parm {
        u32 rsvd;
 };
 
-/*
- * Caller Mode: AP, Ad-HoC(M)
- * Notes: To create a BSS
- * Command Mode
- */
-struct createbss_parm {
-       struct ndis_wlan_bssid_ex network;
-};
-
 /*
  * Caller Mode: AP, Ad-HoC, Infra
  * Notes: To set the NIC mode of RTL8711
index e03ee90d2870888c732f846b4d6567cace7ed8f9..697c8d735150eac0bf1dd9877038b314c541b797 100644 (file)
@@ -36,7 +36,7 @@
  * Used to report a bss has been scanned
 */
 struct survey_event    {
-       struct ndis_wlan_bssid_ex bss;
+       struct wlan_bssid_ex bss;
 };
 
 /*
index 8e6ef5d49fbf54cb9d3856124b39f88a8d35c851..c9218be5bb4ffe2f2372d7f60f5e92ebcdbcccf4 100644 (file)
@@ -76,22 +76,18 @@ uint oid_null_function(struct oid_par_priv *poid_par_priv);
 
 extern struct iw_handler_def  r871x_handlers_def;
 
-extern uint drv_query_info(
-       struct  net_device *MiniportAdapterContext,
-       uint Oid,
-       void *InformationBuffer,
-       u32 InformationBufferLength,
-       u32 *BytesWritten,
-       u32 *BytesNeeded
-);
+uint drv_query_info(struct net_device *MiniportAdapterContext,
+                   uint Oid,
+                   void *InformationBuffer,
+                   u32 InformationBufferLength,
+                   u32 *BytesWritten,
+                   u32 *BytesNeeded);
 
-extern uint drv_set_info(
-       struct  net_device *MiniportAdapterContext,
-       uint Oid,
-       void *InformationBuffer,
-       u32 InformationBufferLength,
-       u32 *BytesRead,
-       u32 *BytesNeeded
-);
+uint drv_set_info(struct net_device *MiniportAdapterContext,
+                 uint Oid,
+                 void *InformationBuffer,
+                 u32 InformationBufferLength,
+                 u32 *BytesRead,
+                 u32 *BytesNeeded);
 
 #endif
index 3388f971fb486ca766db532a4035ecac5600f814..143be0fdc578ead8afcf361d9d0a7ebeabc995ec 100644 (file)
@@ -203,14 +203,12 @@ static inline char *translate_scan(struct _adapter *padapter,
        }
        /* Add the protocol name */
        iwe.cmd = SIOCGIWNAME;
-       if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
-            SupportedRates)) == true) {
+       if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
                if (ht_cap == true)
                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
                else
                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
-       } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
-                   SupportedRates)) == true) {
+       } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
                if (ht_cap == true)
                        snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
                else
@@ -270,9 +268,9 @@ static inline char *translate_scan(struct _adapter *padapter,
        iwe.u.bitrate.disabled = 0;
        iwe.u.bitrate.value = 0;
        i = 0;
-       while (pnetwork->network.SupportedRates[i] != 0) {
+       while (pnetwork->network.rates[i] != 0) {
                /* Bit rate given in 500 kb/s units */
-               iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
+               iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
                                      0x7F) * 500000;
                current_val = iwe_stream_add_value(info, start, current_val,
                              stop, &iwe, IW_EV_PARAM_LEN);
@@ -634,8 +632,8 @@ static int r8711_wx_get_name(struct net_device *dev,
        char *p;
        u8 ht_cap = false;
        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
-       struct ndis_wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
-       NDIS_802_11_RATES_EX *prates = NULL;
+       struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+       u8 *prates;
 
        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
            true) {
@@ -644,15 +642,15 @@ static int r8711_wx_get_name(struct net_device *dev,
                                 &ht_ielen, pcur_bss->IELength - 12);
                if (p && ht_ielen > 0)
                        ht_cap = true;
-               prates = &pcur_bss->SupportedRates;
-               if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
+               prates = pcur_bss->rates;
+               if (r8712_is_cckratesonly_included(prates) == true) {
                        if (ht_cap == true)
                                snprintf(wrqu->name, IFNAMSIZ,
                                         "IEEE 802.11bn");
                        else
                                snprintf(wrqu->name, IFNAMSIZ,
                                         "IEEE 802.11b");
-               } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
+               } else if ((r8712_is_cckrates_included(prates)) == true) {
                        if (ht_cap == true)
                                snprintf(wrqu->name, IFNAMSIZ,
                                         "IEEE 802.11bgn");
@@ -723,7 +721,7 @@ static int r8711_wx_get_freq(struct net_device *dev,
 {
        struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-       struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+       struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
 
        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
                wrqu->freq.m = ieee80211_wlan_frequencies[
@@ -1111,7 +1109,7 @@ static int r8711_wx_get_wap(struct net_device *dev,
 {
        struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-       struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+       struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
 
        wrqu->ap_addr.sa_family = ARPHRD_ETHER;
        if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
@@ -1327,7 +1325,7 @@ static int r8711_wx_get_essid(struct net_device *dev,
 {
        struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-       struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+       struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
        u32 len, ret = 0;
 
        if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
@@ -1419,7 +1417,7 @@ static int r8711_wx_get_rate(struct net_device *dev,
 {
        struct _adapter *padapter = netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-       struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+       struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
        struct ieee80211_ht_cap *pht_capie;
        unsigned char rf_type = padapter->registrypriv.rf_config;
        int i;
@@ -1444,9 +1442,9 @@ static int r8711_wx_get_rate(struct net_device *dev,
                                    (IEEE80211_HT_CAP_SGI_20 |
                                    IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
                }
-               while ((pcur_bss->SupportedRates[i] != 0) &&
-                       (pcur_bss->SupportedRates[i] != 0xFF)) {
-                       rate = pcur_bss->SupportedRates[i] & 0x7F;
+               while ((pcur_bss->rates[i] != 0) &&
+                       (pcur_bss->rates[i] != 0xFF)) {
+                       rate = pcur_bss->rates[i] & 0x7F;
                        if (rate > max_rate)
                                max_rate = rate;
                        wrqu->bitrate.fixed = 0;        /* no auto select */
index c044b0e55ba93d0c989031d52ce99f4008ae0630..fc5dbea08cb490d53cda38f81c3e3404fac09b6a 100644 (file)
@@ -208,19 +208,9 @@ void r8712_generate_random_ibss(u8 *pibss)
        pibss[5] = (u8)((curtime>>16) & 0xff);
 }
 
-uint r8712_get_ndis_wlan_bssid_ex_sz(struct ndis_wlan_bssid_ex *bss)
+uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
 {
-       uint t_len;
-
-       t_len = sizeof(u32) + 6 * sizeof(unsigned long) + 2 +
-                       sizeof(struct ndis_802_11_ssid) + sizeof(u32) +
-                       sizeof(s32) +
-                       sizeof(enum NDIS_802_11_NETWORK_TYPE) +
-                       sizeof(struct NDIS_802_11_CONFIGURATION) +
-                       sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) +
-                       sizeof(NDIS_802_11_RATES_EX) +
-                       sizeof(u32) + bss->IELength;
-       return t_len;
+       return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
 }
 
 u8 *r8712_get_capability_from_ie(u8 *ie)
@@ -286,8 +276,8 @@ int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
 
 }
 
-static int is_same_network(struct ndis_wlan_bssid_ex *src,
-                          struct ndis_wlan_bssid_ex *dst)
+static int is_same_network(struct wlan_bssid_ex *src,
+                          struct wlan_bssid_ex *dst)
 {
         u16 s_cap, d_cap;
 
@@ -332,8 +322,8 @@ struct      wlan_network *r8712_get_oldest_wlan_network(
        return oldest;
 }
 
-static void update_network(struct ndis_wlan_bssid_ex *dst,
-                          struct ndis_wlan_bssid_ex *src,
+static void update_network(struct wlan_bssid_ex *dst,
+                          struct wlan_bssid_ex *src,
                           struct _adapter *padapter)
 {
        u32 last_evm = 0, tmpVal;
@@ -366,11 +356,11 @@ static void update_network(struct ndis_wlan_bssid_ex *dst,
                src->Rssi = padapter->recvpriv.signal;
        } else
                src->Rssi = (src->Rssi + dst->Rssi) / 2;
-       memcpy((u8 *)dst, (u8 *)src, r8712_get_ndis_wlan_bssid_ex_sz(src));
+       memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
 }
 
 static void update_current_network(struct _adapter *adapter,
-                                  struct ndis_wlan_bssid_ex *pnetwork)
+                                  struct wlan_bssid_ex *pnetwork)
 {
        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
@@ -388,7 +378,7 @@ static void update_current_network(struct _adapter *adapter,
 Caller must hold pmlmepriv->lock first.
 */
 static void update_scanned_network(struct _adapter *adapter,
-                           struct ndis_wlan_bssid_ex *target)
+                           struct wlan_bssid_ex *target)
 {
        struct list_head *plist, *phead;
 
@@ -426,7 +416,7 @@ static void update_scanned_network(struct _adapter *adapter,
                        target->Rssi = (pnetwork->network.Rssi +
                                        target->Rssi) / 2;
                        memcpy(&pnetwork->network, target,
-                               r8712_get_ndis_wlan_bssid_ex_sz(target));
+                               r8712_get_wlan_bssid_ex_sz(target));
                        pnetwork->last_scanned = jiffies;
                } else {
                        /* Otherwise just pull from the free list */
@@ -434,7 +424,7 @@ static void update_scanned_network(struct _adapter *adapter,
                        pnetwork = alloc_network(pmlmepriv);
                        if (pnetwork == NULL)
                                return;
-                       bssid_ex_sz = r8712_get_ndis_wlan_bssid_ex_sz(target);
+                       bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
                        target->Length = bssid_ex_sz;
                        memcpy(&pnetwork->network, target, bssid_ex_sz);
                        list_add_tail(&pnetwork->list, &queue->queue);
@@ -451,7 +441,7 @@ static void update_scanned_network(struct _adapter *adapter,
 }
 
 static void rtl8711_add_network(struct _adapter *adapter,
-                        struct ndis_wlan_bssid_ex *pnetwork)
+                        struct wlan_bssid_ex *pnetwork)
 {
        unsigned long irqL;
        struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
@@ -507,10 +497,10 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
 {
        unsigned long flags;
        u32 len;
-       struct ndis_wlan_bssid_ex *pnetwork;
+       struct wlan_bssid_ex *pnetwork;
        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 
-       pnetwork = (struct ndis_wlan_bssid_ex *)pbuf;
+       pnetwork = (struct wlan_bssid_ex *)pbuf;
 #ifdef __BIG_ENDIAN
        /* endian_convert */
        pnetwork->Length = le32_to_cpu(pnetwork->Length);
@@ -538,7 +528,7 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
                 le32_to_cpu(pnetwork->InfrastructureMode);
        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 #endif
-       len = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
+       len = r8712_get_wlan_bssid_ex_sz(pnetwork);
        if (len > sizeof(struct wlan_bssid_ex))
                return;
        spin_lock_irqsave(&pmlmepriv->lock2, flags);
@@ -769,7 +759,7 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
        the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
                                   cur_network->network.MacAddress, ETH_ALEN);
        pnetwork->network.Length =
-                r8712_get_ndis_wlan_bssid_ex_sz(&pnetwork->network);
+                r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
        spin_lock_irqsave(&pmlmepriv->lock, irqL);
        if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
                goto ignore_joinbss_callback;
@@ -1001,7 +991,7 @@ void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
                        pdev_network = &(adapter->registrypriv.dev_network);
                        pibss = adapter->registrypriv.dev_network.MacAddress;
                        memcpy(pdev_network, &tgt_network->network,
-                               r8712_get_ndis_wlan_bssid_ex_sz(&tgt_network->
+                               r8712_get_wlan_bssid_ex_sz(&tgt_network->
                                                        network));
                        memcpy(&pdev_network->Ssid,
                                &pmlmepriv->assoc_ssid,
@@ -1668,8 +1658,7 @@ void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
         */
        sz = r8712_generate_ie(pregistrypriv);
        pdev_network->IELength = sz;
-       pdev_network->Length = r8712_get_ndis_wlan_bssid_ex_sz(
-                             (struct ndis_wlan_bssid_ex *)pdev_network);
+       pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
 }
 
 /*the function is at passive_level*/
index 42bd0bf8a8168b30d181eff560c6f86e5d522498..08d6c986c11e26f5afe8f3eaab963ab31b54f949 100644 (file)
@@ -202,7 +202,7 @@ sint r8712_set_key(struct _adapter *adapter,
                   struct security_priv *psecuritypriv, sint keyid);
 sint r8712_set_auth(struct _adapter *adapter,
                    struct security_priv *psecuritypriv);
-uint r8712_get_ndis_wlan_bssid_ex_sz(struct ndis_wlan_bssid_ex *bss);
+uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss);
 void r8712_generate_random_ibss(u8 *pibss);
 u8 *r8712_get_capability_from_ie(u8 *ie);
 struct wlan_network *r8712_get_oldest_wlan_network(
index 0b5461208eb902637c2179d0a9782ccb5eb8b75f..77f01bf1ca3c023e04653e7c1e5290ad4efb398d 100644 (file)
@@ -160,13 +160,13 @@ static int mp_start_test(struct _adapter *padapter)
        struct mp_priv *pmppriv = &padapter->mppriv;
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-       struct ndis_wlan_bssid_ex bssid;
+       struct wlan_bssid_ex bssid;
        struct sta_info *psta;
        unsigned long length;
        unsigned long irqL;
        int res = _SUCCESS;
 
-       /* 3 1. initialize a new struct ndis_wlan_bssid_ex */
+       /* 3 1. initialize a new struct wlan_bssid_ex */
        memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
        bssid.Ssid.SsidLength = 16;
        memcpy(bssid.Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc",
@@ -174,7 +174,7 @@ static int mp_start_test(struct _adapter *padapter)
        bssid.InfrastructureMode = Ndis802_11IBSS;
        bssid.NetworkTypeInUse = Ndis802_11DS;
        bssid.IELength = 0;
-       length = r8712_get_ndis_wlan_bssid_ex_sz(&bssid);
+       length = r8712_get_wlan_bssid_ex_sz(&bssid);
        if (length % 4) {
                /*round up to multiple of 4 bytes.*/
                bssid.Length = ((length >> 2) + 1) << 2;
index bcd1a51288689d1043d069b3d96829baa87b8408..862792826dc5f73839eb28a6f8dd35742cd1a6b8 100644 (file)
@@ -124,28 +124,25 @@ static u8 crc32_reverseBit(u8 data)
 
 static void crc32_init(void)
 {
+       sint i, j;
+       u32 c;
+       u8 *p = (u8 *)&c, *p1;
+       u8 k;
+
        if (bcrc32initialized == 1)
                return;
-       else {
-               sint i, j;
-               u32 c;
-               u8 *p = (u8 *)&c, *p1;
-               u8 k;
-
-               c = 0x12340000;
-               for (i = 0; i < 256; ++i) {
-                       k = crc32_reverseBit((u8)i);
-                       for (c = ((u32)k) << 24, j = 8; j > 0; --j)
-                               c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY :
-                                   (c << 1);
-                       p1 = (u8 *)&crc32_table[i];
-                       p1[0] = crc32_reverseBit(p[3]);
-                       p1[1] = crc32_reverseBit(p[2]);
-                       p1[2] = crc32_reverseBit(p[1]);
-                       p1[3] = crc32_reverseBit(p[0]);
-               }
-               bcrc32initialized = 1;
+
+       for (i = 0; i < 256; ++i) {
+               k = crc32_reverseBit((u8)i);
+               for (c = ((u32)k) << 24, j = 8; j > 0; --j)
+                       c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
+               p1 = (u8 *)&crc32_table[i];
+               p1[0] = crc32_reverseBit(p[3]);
+               p1[1] = crc32_reverseBit(p[2]);
+               p1[2] = crc32_reverseBit(p[1]);
+               p1[3] = crc32_reverseBit(p[0]);
        }
+       bcrc32initialized = 1;
 }
 
 static u32 getcrc32(u8 *buf, u32 len)
index 2ea8a3d6b705587a715127650d4c69792d422d31..fda5707c4acda0f383fccc9b29f1c70cfa6e058d 100644 (file)
 #define NDIS_802_11_LENGTH_RATES        8
 #define NDIS_802_11_LENGTH_RATES_EX     16
 
-/* Set of 8 data rates*/
-typedef unsigned char   NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];
-/* Set of 16 data rates */
-typedef unsigned char   NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
-
 struct ndis_802_11_ssid {
        u32 SsidLength;
        u8  Ssid[32];
@@ -83,18 +78,7 @@ struct NDIS_802_11_FIXED_IEs {
        u16 Capabilities;
 };
 
-/*
- * Length is the 4 bytes multiples of the sume of
- * 6 * sizeof (unsigned char) + 2 + sizeof (ndis_802_11_ssid) + sizeof (u32)
- * + sizeof (s32) + sizeof (NDIS_802_11_NETWORK_TYPE)
- * + sizeof (struct NDIS_802_11_CONFIGURATION)
- * + sizeof (NDIS_802_11_RATES_EX) + IELength
-
- * Except the IELength, all other fields are fixed length. Therefore, we can
- * define a macro to present the partial sum.
- */
-
-struct ndis_wlan_bssid_ex {
+struct wlan_bssid_ex {
        u32 Length;
        unsigned char  MacAddress[6];
        u8  Reserved[2];
@@ -104,7 +88,8 @@ struct ndis_wlan_bssid_ex {
        enum NDIS_802_11_NETWORK_TYPE  NetworkTypeInUse;
        struct NDIS_802_11_CONFIGURATION  Configuration;
        enum NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
-       NDIS_802_11_RATES_EX  SupportedRates;
+       u8 rates[NDIS_802_11_LENGTH_RATES_EX];
+       /* number of content bytes in EIs, which varies */
        u32 IELength;
        /*(timestamp, beacon interval, and capability information) */
        u8 IEs[MAX_IE_SZ];
@@ -213,7 +198,7 @@ struct      wlan_network {
        unsigned int    last_scanned; /*timestamp for the network */
        int     aid;            /*will only be valid when a BSS is joined. */
        int     join_res;
-       struct ndis_wlan_bssid_ex network; /*must be the last item */
+       struct wlan_bssid_ex network; /*must be the last item */
 };
 
 enum VRTL_CARRIER_SENSE {
@@ -244,24 +229,5 @@ enum UAPSD_MAX_SP {
 #define NUM_PRE_AUTH_KEY 16
 #define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
 
-/*
- *     WPA2
- */
-struct wlan_bssid_ex {
-       u32 Length;
-       unsigned char  MacAddress[6];
-       u8  Reserved[2];
-       struct ndis_802_11_ssid  Ssid;
-       u32 Privacy;
-       s32 Rssi;
-       enum NDIS_802_11_NETWORK_TYPE  NetworkTypeInUse;
-       struct NDIS_802_11_CONFIGURATION  Configuration;
-       enum NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
-       NDIS_802_11_RATES_EX  SupportedRates;
-       u32 IELength;
-       u8  IEs[MAX_IE_SZ];     /* (timestamp, beacon interval, and capability
-                                * information) */
-};
-
 #endif /* #ifndef WLAN_BSSDEF_H_ */
 
index 274a4b65c0226d33581f3cfde71e7ca04ad940ba..ad0549c66529057dac8fe4ed5264df7666c95e39 100644 (file)
@@ -1554,8 +1554,7 @@ static int wlanhdr_to_ethhdr (struct recv_frame *precvframe)
        ether_addr_copy(ptr + ETH_ALEN, pattrib->src);
 
        if (!bsnaphdr) {
-               len = htons(len);
-               memcpy(ptr + 12, &len, 2);
+               put_unaligned_be16(len, ptr + 12);
        }
 
 
index af53c92fc3a29063c6e0ee9ddaf9a6db9f606d41..3d40bab1d9c8f1d934f0e49cbdd14bdf632a6e26 100644 (file)
@@ -148,7 +148,7 @@ void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
                     struct xmit_frame *pxmitframe)
 {
        /*  exclude ICV */
-       unsigned char crc[4];
+       __le32 crc;
        struct arc4context mycontext;
        int curfragnum, length, index;
        u32 keylength;
@@ -186,18 +186,20 @@ void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
                        length = pattrib->last_txcmdsz - pattrib->hdrlen -
                                pattrib->iv_len - pattrib->icv_len;
 
-                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+                       crc = cpu_to_le32(getcrc32(payload, length));
 
                        arcfour_init(&mycontext, wepkey, 3 + keylength);
                        arcfour_encrypt(&mycontext, payload, payload, length);
-                       arcfour_encrypt(&mycontext, payload + length, crc, 4);
+                       arcfour_encrypt(&mycontext, payload + length,
+                                       (char *)&crc, 4);
                } else {
                        length = pxmitpriv->frag_len - pattrib->hdrlen -
                                pattrib->iv_len - pattrib->icv_len;
-                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+                       crc = cpu_to_le32(getcrc32(payload, length));
                        arcfour_init(&mycontext, wepkey, 3 + keylength);
                        arcfour_encrypt(&mycontext, payload, payload, length);
-                       arcfour_encrypt(&mycontext, payload + length, crc, 4);
+                       arcfour_encrypt(&mycontext, payload + length,
+                                       (char *)&crc, 4);
 
                        pframe += pxmitpriv->frag_len;
                        pframe = PTR_ALIGN(pframe, 4);
@@ -602,7 +604,7 @@ int rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
        u32 pnh;
        u8 rc4key[16];
        u8 ttkey[16];
-       u8 crc[4];
+       __le32 crc;
        u8 hw_hdr_offset = 0;
        struct arc4context mycontext;
        int curfragnum, length;
@@ -679,11 +681,12 @@ int rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
                                 "pattrib->iv_len =%x, pattrib->icv_len =%x\n",
                                 pattrib->iv_len,
                                 pattrib->icv_len);
-                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+                       crc = cpu_to_le32(getcrc32(payload, length));
 
                        arcfour_init(&mycontext, rc4key, 16);
                        arcfour_encrypt(&mycontext, payload, payload, length);
-                       arcfour_encrypt(&mycontext, payload + length, crc, 4);
+                       arcfour_encrypt(&mycontext, payload + length,
+                                       (char *)&crc, 4);
 
                } else {
                        length = (pxmitpriv->frag_len -
@@ -691,10 +694,11 @@ int rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
                                  pattrib->iv_len -
                                  pattrib->icv_len);
 
-                       *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+                       crc = cpu_to_le32(getcrc32(payload, length));
                        arcfour_init(&mycontext, rc4key, 16);
                        arcfour_encrypt(&mycontext, payload, payload, length);
-                       arcfour_encrypt(&mycontext, payload + length, crc, 4);
+                       arcfour_encrypt(&mycontext, payload + length,
+                                       (char *)&crc, 4);
 
                        pframe += pxmitpriv->frag_len;
                        pframe  = PTR_ALIGN(pframe, 4);
index f354f5e11a3028d1463535d358401ce440d003f6..6b9dbeffafcbd029ce1311540125b428553f4b21 100644 (file)
@@ -985,7 +985,7 @@ void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal)
                        val32 = rtl8723au_read32(adapter, 0x874);
                        val32 |= pDM_PSTable->Reg874;
                        rtl8723au_write32(adapter, 0x874, val32);
-               
+
                        val32 = rtl8723au_read32(adapter, 0xc70);
                        val32 |= pDM_PSTable->RegC70;
                        rtl8723au_write32(adapter, 0xc70, val32);
index 342dec3e939f325eae79d2b31766047c0802cdca..a63c6cb88bc9eff4f1ab951e186057164165de84 100644 (file)
@@ -21,7 +21,7 @@ odm_ConfigRFReg_8723A(
        struct dm_odm_t *pDM_Odm,
        u32                                     Addr,
        u32                                     Data,
-  enum RF_RADIO_PATH     RF_PATH,
+       enum RF_RADIO_PATH     RF_PATH,
        u32                                 RegAddr
        )
 {
index cb5076abda8bc14c20554f42f88fd7678011f66f..cf2388f4f6e75b9d047aaac669e8d8f6cbb0632a 100644 (file)
@@ -1838,7 +1838,7 @@ Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter,
 
 static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
 {
-       u16 *usPtr = (u16 *) ptxdesc;
+       __le16 *usPtr = (__le16 *)ptxdesc;
        u32 count = 16;         /*  (32 bytes / 2 bytes per XOR) => 16 times */
        u32 index;
        u16 checksum = 0;
@@ -1847,7 +1847,7 @@ static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
        ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
 
        for (index = 0; index < count; index++)
-               checksum ^= le16_to_cpu(*(usPtr + index));
+               checksum ^= le16_to_cpu(usPtr[index]);
 
        ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
 }
index ee818b0dc4011f7aab19db049e7fb6f82958f197..cdaa1aba50edeb1b428e83069b1565fa7e523d82 100644 (file)
@@ -1121,11 +1121,10 @@ static int ms_read_attribute_info(struct rtsx_chip *chip)
 
 #ifdef SUPPORT_MSXC
                if ((buf[cur_addr_off + 8] == 0x10) ||
-                       (buf[cur_addr_off + 8] == 0x13))
+                       (buf[cur_addr_off + 8] == 0x13)) {
 #else
-               if (buf[cur_addr_off + 8] == 0x10)
+               if (buf[cur_addr_off + 8] == 0x10) {
 #endif
-               {
                        sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) |
                                ((u32)buf[cur_addr_off + 1] << 16) |
                                ((u32)buf[cur_addr_off + 2] << 8) |
index a8d657bb5c1bca8f99be1ea050a952ff9d337afa..d6c498209b2c6a4020a864a3b2e752881d4db1f1 100644 (file)
@@ -246,11 +246,10 @@ RTY_SEND_CMD:
                                }
                        }
 #ifdef SUPPORT_SD_LOCK
-                       if (ptr[1] & 0x7D)
+                       if (ptr[1] & 0x7D) {
 #else
-                       if (ptr[1] & 0x7F)
+                       if (ptr[1] & 0x7F) {
 #endif
-                       {
                                dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n",
                                        ptr[1]);
                                rtsx_trace(chip);
@@ -3520,12 +3519,11 @@ int reset_sd_card(struct rtsx_chip *chip)
                        if (chip->sd_io) {
                                rtsx_trace(chip);
                                return STATUS_FAIL;
-                       } else {
-                               retval = reset_mmc(chip);
-                               if (retval != STATUS_SUCCESS) {
-                                       rtsx_trace(chip);
-                                       return STATUS_FAIL;
-                               }
+                       }
+                       retval = reset_mmc(chip);
+                       if (retval != STATUS_SUCCESS) {
+                               rtsx_trace(chip);
+                               return STATUS_FAIL;
                        }
                }
        }
@@ -4149,11 +4147,10 @@ RTY_SEND_CMD:
                        }
                }
 #ifdef SUPPORT_SD_LOCK
-               if (ptr[1] & 0x7D)
+               if (ptr[1] & 0x7D) {
 #else
-               if (ptr[1] & 0x7F)
+               if (ptr[1] & 0x7F) {
 #endif
-               {
                        rtsx_trace(chip);
                        return STATUS_FAIL;
                }
index a609f3e67256aba12dbfda1fb9e1e2d3958c2f67..858597087ba7d0bf809984dfb0dca9a0a2d9a811 100644 (file)
@@ -2329,6 +2329,7 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags)
 
        if (!adapter->isp_initialized) {
                unsigned long flags;
+
                pshmem = (struct slic_shmem *)(unsigned long)
                         adapter->phys_shmem;
 
index f4975d2d97ad5a282ce4f2bc13a56bb154f4345c..5e6798ea9468af13a15bdbf366a6b61387c9144e 100644 (file)
@@ -268,7 +268,7 @@ int ddk750_initHw(initchip_param_t *pInitParam)
 #endif
 
 
-       if (pInitParam->powerMode != 0 )
+       if (pInitParam->powerMode != 0)
                pInitParam->powerMode = 0;
        setPowerMode(pInitParam->powerMode);
 
@@ -464,17 +464,18 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
                RN = N * request;
                quo = RN / input;
                rem = RN % input;/* rem always small than 14318181 */
-               fl_quo = (rem * 10000 /input);
+               fl_quo = (rem * 10000 / input);
 
                for (d = xcnt - 1; d >= 0; d--) {
                        X = xparm[d].value;
                        M = quo*X;
                        M += fl_quo * X / 10000;
                        /* round step */
-                       M += (fl_quo*X % 10000)>5000?1:0;
+                       M += (fl_quo*X % 10000) > 5000?1:0;
                        if (M < 256 && M > 0) {
                                unsigned int diff;
-                               tmpClock = pll->inputFreq *M / N / X;
+
+                               tmpClock = pll->inputFreq * M / N / X;
                                diff = absDiff(tmpClock, request_orig);
                                if (diff < miniDiff) {
                                        pll->M = M;
@@ -599,9 +600,9 @@ unsigned int formatPllReg(pll_value_t *pPLL)
        On returning a 32 bit number, the value can be applied to any PLL in the calling function.
     */
        ulPllReg =
-       FIELD_SET(  0, PANEL_PLL_CTRL, BYPASS, OFF)
-       | FIELD_SET(  0, PANEL_PLL_CTRL, POWER,  ON)
-       | FIELD_SET(  0, PANEL_PLL_CTRL, INPUT,  OSC)
+       FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF)
+       | FIELD_SET(0, PANEL_PLL_CTRL, POWER,  ON)
+       | FIELD_SET(0, PANEL_PLL_CTRL, INPUT,  OSC)
 #ifndef VALIDATION_CHIP
        | FIELD_VALUE(0, PANEL_PLL_CTRL, POD,    pPLL->POD)
 #endif
index 4e030e820cf328db9636a0254e953950ea249a1e..6ff043608fe95c8be833fabd7f8cc972990ff220 100644 (file)
@@ -8,8 +8,7 @@
 #include <linux/io.h>
 
 /* This is all the chips recognized by this library */
-typedef enum _logical_chip_type_t
-{
+typedef enum _logical_chip_type_t {
        SM_UNKNOWN,
        SM718,
        SM750,
@@ -18,8 +17,7 @@ typedef enum _logical_chip_type_t
 logical_chip_type_t;
 
 
-typedef enum _clock_type_t
-{
+typedef enum _clock_type_t {
        MXCLK_PLL,
        PRIMARY_PLL,
        SECONDARY_PLL,
@@ -28,8 +26,7 @@ typedef enum _clock_type_t
 }
 clock_type_t;
 
-typedef struct _pll_value_t
-{
+typedef struct _pll_value_t {
        clock_type_t clockType;
        unsigned long inputFreq; /* Input clock frequency to the PLL */
 
@@ -42,8 +39,7 @@ typedef struct _pll_value_t
 pll_value_t;
 
 /* input struct to initChipParam() function */
-typedef struct _initchip_param_t
-{
+typedef struct _initchip_param_t {
        unsigned short powerMode;    /* Use power mode 0 or 1 */
        unsigned short chipClock;    /**
                                      * Speed of main chip clock in MHz unit
index a3e672056ef8b99794e08085ed6cb20ca27decd4..8348113482d998754218d859d6b618a7a32a949c 100644 (file)
@@ -15,16 +15,14 @@ static void setDisplayControl(int ctrl, int dispState)
        cnt = 0;
 
        /* Set the primary display control */
-       if (!ctrl)
-       {
+       if (!ctrl) {
                ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
                /* Turn on/off the Panel display control */
-               if (dispState)
-               {
+               if (dispState) {
                        /* Timing should be enabled first before enabling the plane
                         * because changing at the same time does not guarantee that
                         * the plane will also enabled or disabled.
-            */
+                        */
                        ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
                                                                PANEL_DISPLAY_CTRL, TIMING, ENABLE);
                        POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
@@ -45,16 +43,13 @@ static void setDisplayControl(int ctrl, int dispState)
                         * until a few delay. Need to write
                         * and read it a couple times
                         */
-                       do
-                       {
+                       do {
                                cnt++;
                                POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
-                       } while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
+                       } while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
                                        (ulDisplayCtrlReg & ~ulReservedBits));
                        printk("Set Panel Plane enbit:after tried %d times\n", cnt);
-               }
-               else
-               {
+               } else {
                        /* When turning off, there is no rule on the programming
                         * sequence since whenever the clock is off, then it does not
                         * matter whether the plane is enabled or disabled.
@@ -71,14 +66,11 @@ static void setDisplayControl(int ctrl, int dispState)
                        POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
                }
 
-       }
-       /* Set the secondary display control */
-       else
-       {
+       } else {
+               /* Set the secondary display control */
                ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
 
-               if (dispState)
-               {
+               if (dispState) {
                        /* Timing should be enabled first before enabling the plane because changing at the
                           same time does not guarantee that the plane will also enabled or disabled.
                           */
@@ -100,16 +92,13 @@ static void setDisplayControl(int ctrl, int dispState)
                                FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
                                FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
 
-                       do
-                       {
+                       do {
                                cnt++;
                                POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
-                       } while((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
+                       } while ((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
                                        (ulDisplayCtrlReg & ~ulReservedBits));
                                printk("Set Crt Plane enbit:after tried %d times\n", cnt);
-               }
-               else
-               {
+               } else {
                        /* When turning off, there is no rule on the programming
                         * sequence since whenever the clock is off, then it does not
                         * matter whether the plane is enabled or disabled.
@@ -132,71 +121,60 @@ static void setDisplayControl(int ctrl, int dispState)
 static void waitNextVerticalSync(int ctrl, int delay)
 {
        unsigned int status;
-       if(!ctrl){
+
+       if (!ctrl) {
                /* primary controller */
 
-        /* Do not wait when the Primary PLL is off or display control is already off.
-                  This will prevent the software to wait forever. */
+               /* Do not wait when the Primary PLL is off or display control is already off.
+                  This will prevent the software to wait forever. */
                if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
                         PANEL_PLL_CTRL_POWER_OFF) ||
                        (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
-                        PANEL_DISPLAY_CTRL_TIMING_DISABLE))
-               {
+                        PANEL_DISPLAY_CTRL_TIMING_DISABLE)) {
                        return;
                }
 
-        while (delay-- > 0)
-        {
-            /* Wait for end of vsync. */
-            do
-            {
-                status = FIELD_GET(PEEK32(SYSTEM_CTRL),
-                                   SYSTEM_CTRL,
-                                   PANEL_VSYNC);
-            }
-            while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
-
-            /* Wait for start of vsync. */
-            do
-            {
-                status = FIELD_GET(PEEK32(SYSTEM_CTRL),
-                                   SYSTEM_CTRL,
-                                   PANEL_VSYNC);
-            }
-            while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
-        }
-
-       }else{
+               while (delay-- > 0) {
+                       /* Wait for end of vsync. */
+                       do {
+                               status = FIELD_GET(PEEK32(SYSTEM_CTRL),
+                                                  SYSTEM_CTRL,
+                                                  PANEL_VSYNC);
+                       } while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
+
+                       /* Wait for start of vsync. */
+                       do {
+                               status = FIELD_GET(PEEK32(SYSTEM_CTRL),
+                                                  SYSTEM_CTRL,
+                                                  PANEL_VSYNC);
+                       } while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
+               }
+
+       } else {
 
                /* Do not wait when the Primary PLL is off or display control is already off.
                           This will prevent the software to wait forever. */
                if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
                         CRT_PLL_CTRL_POWER_OFF) ||
                        (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
-                        CRT_DISPLAY_CTRL_TIMING_DISABLE))
-               {
+                        CRT_DISPLAY_CTRL_TIMING_DISABLE)) {
                        return;
                }
 
-               while (delay-- > 0)
-               {
+               while (delay-- > 0) {
                        /* Wait for end of vsync. */
-                       do
-                       {
+                       do {
                                status = FIELD_GET(PEEK32(SYSTEM_CTRL),
                                                                   SYSTEM_CTRL,
                                                                   CRT_VSYNC);
-                       }
-                       while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
+                       } while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
 
                        /* Wait for start of vsync. */
-                       do
-                       {
+                       do {
                                status = FIELD_GET(PEEK32(SYSTEM_CTRL),
                                                                   SYSTEM_CTRL,
                                                                   CRT_VSYNC);
-                       }
-                       while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
+                       } while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
                }
        }
 }
@@ -233,14 +211,15 @@ static void swPanelPowerSequence(int disp, int delay)
 void ddk750_setLogicalDispOut(disp_output_t output)
 {
        unsigned int reg;
-       if(output & PNL_2_USAGE){
+
+       if (output & PNL_2_USAGE) {
                /* set panel path controller select */
                reg = PEEK32(PANEL_DISPLAY_CTRL);
                reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, SELECT, (output & PNL_2_MASK)>>PNL_2_OFFSET);
                POKE32(PANEL_DISPLAY_CTRL, reg);
        }
 
-       if(output & CRT_2_USAGE){
+       if (output & CRT_2_USAGE) {
                /* set crt path controller select */
                reg = PEEK32(CRT_DISPLAY_CTRL);
                reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET);
@@ -250,58 +229,57 @@ void ddk750_setLogicalDispOut(disp_output_t output)
 
        }
 
-       if(output & PRI_TP_USAGE){
+       if (output & PRI_TP_USAGE) {
                /* set primary timing and plane en_bit */
                setDisplayControl(0, (output&PRI_TP_MASK)>>PRI_TP_OFFSET);
        }
 
-       if(output & SEC_TP_USAGE){
+       if (output & SEC_TP_USAGE) {
                /* set secondary timing and plane en_bit*/
                setDisplayControl(1, (output&SEC_TP_MASK)>>SEC_TP_OFFSET);
        }
 
-       if(output & PNL_SEQ_USAGE){
+       if (output & PNL_SEQ_USAGE) {
                /* set  panel sequence */
                swPanelPowerSequence((output&PNL_SEQ_MASK)>>PNL_SEQ_OFFSET, 4);
        }
 
-       if(output & DAC_USAGE)
+       if (output & DAC_USAGE)
                setDAC((output & DAC_MASK)>>DAC_OFFSET);
 
-       if(output & DPMS_USAGE)
+       if (output & DPMS_USAGE)
                ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
 }
 
 
 int ddk750_initDVIDisp(void)
 {
-    /* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
-       not zeroed, then set the failure flag. If it is zeroe, it might mean
-       that the system is in Dual CRT Monitor configuration. */
-
-    /* De-skew enabled with default 111b value.
-       This will fix some artifacts problem in some mode on board 2.2.
-       Somehow this fix does not affect board 2.1.
-     */
-    if ((dviInit(1,  /* Select Rising Edge */
-                1,  /* Select 24-bit bus */
-                0,  /* Select Single Edge clock */
-                1,  /* Enable HSync as is */
-                1,  /* Enable VSync as is */
-                1,  /* Enable De-skew */
-                7,  /* Set the de-skew setting to maximum setup */
-                1,  /* Enable continuous Sync */
-                1,  /* Enable PLL Filter */
-                4   /* Use the recommended value for PLL Filter value */
-        ) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000))
-    {
-        return (-1);
-    }
-
-    /* TODO: Initialize other display component */
-
-    /* Success */
-    return 0;
+       /* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
+          not zeroed, then set the failure flag. If it is zeroe, it might mean
+          that the system is in Dual CRT Monitor configuration. */
+
+       /* De-skew enabled with default 111b value.
+          This will fix some artifacts problem in some mode on board 2.2.
+          Somehow this fix does not affect board 2.1.
+        */
+       if ((dviInit(1,  /* Select Rising Edge */
+                    1,  /* Select 24-bit bus */
+                    0,  /* Select Single Edge clock */
+                    1,  /* Enable HSync as is */
+                    1,  /* Enable VSync as is */
+                    1,  /* Enable De-skew */
+                    7,  /* Set the de-skew setting to maximum setup */
+                    1,  /* Enable continuous Sync */
+                    1,  /* Enable PLL Filter */
+                    4   /* Use the recommended value for PLL Filter value */
+                    ) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000)) {
+               return (-1);
+       }
+
+       /* TODO: Initialize other display component */
+
+       /* Success */
+       return 0;
 
 }
 
index ae0f84c68de5b670c3560ed9e92c8dada854af46..abccf84a8c9a752f4d6ae663171890853e85bc93 100644 (file)
@@ -8,7 +8,7 @@
 #define PNL_2_OFFSET 0
 #define PNL_2_MASK (3 << PNL_2_OFFSET)
 #define PNL_2_USAGE    (PNL_2_MASK << 16)
-#define PNL_2_PRI      ((0 << PNL_2_OFFSET)|PNL_2_USAGE)
+#define PNL_2_PRI      ((0 << PNL_2_OFFSET)|PNL_2_USAGE)
 #define PNL_2_SEC      ((2 << PNL_2_OFFSET)|PNL_2_USAGE)
 
 
@@ -46,7 +46,7 @@
        0: both off
 */
 #define SEC_TP_OFFSET 5
-#define SEC_TP_MASK (1<< SEC_TP_OFFSET)
+#define SEC_TP_MASK (1 << SEC_TP_OFFSET)
 #define SEC_TP_USAGE (SEC_TP_MASK << 16)
 #define SEC_TP_ON  ((0x1 << SEC_TP_OFFSET)|SEC_TP_USAGE)
 #define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET)|SEC_TP_USAGE)
@@ -67,7 +67,7 @@
 #define DAC_OFFSET 7
 #define DAC_MASK (1 << DAC_OFFSET)
 #define DAC_USAGE (DAC_MASK << 16)
-#define DAC_ON ((0x0<< DAC_OFFSET)|DAC_USAGE)
+#define DAC_ON ((0x0 << DAC_OFFSET)|DAC_USAGE)
 #define DAC_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE)
 
 /* DPMS only affect D-SUB head
@@ -86,8 +86,7 @@
        CRT means crt path DSUB
 */
 #if 0
-typedef enum _disp_output_t
-{
+typedef enum _disp_output_t {
        NO_DISPLAY = DPMS_OFF,
 
        LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
@@ -129,7 +128,7 @@ typedef enum _disp_output_t
 }
 disp_output_t;
 #else
-typedef enum _disp_output_t{
+typedef enum _disp_output_t {
        do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON,
        do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON,
 #if 0
index b2bf7e66d5cb5104674e19e04b34140752bd15f2..a7a23514ac3900b31e20844b676c8d22e3cfb925 100644 (file)
@@ -1,4 +1,4 @@
-#define USE_DVICHIP 
+#define USE_DVICHIP
 #ifdef USE_DVICHIP
 #include "ddk750_help.h"
 #include "ddk750_reg.h"
@@ -9,47 +9,46 @@
 /* This global variable contains all the supported driver and its corresponding
    function API. Please set the function pointer to NULL whenever the function
    is not supported. */
-static dvi_ctrl_device_t g_dcftSupportedDviController[] =
-{
+static dvi_ctrl_device_t g_dcftSupportedDviController[] = {
 #ifdef DVI_CTRL_SII164
-    {
-        .pfnInit = sii164InitChip,
-        .pfnGetVendorId = sii164GetVendorID,
-        .pfnGetDeviceId = sii164GetDeviceID,
+       {
+               .pfnInit = sii164InitChip,
+               .pfnGetVendorId = sii164GetVendorID,
+               .pfnGetDeviceId = sii164GetDeviceID,
 #ifdef SII164_FULL_FUNCTIONS
-        .pfnResetChip = sii164ResetChip,
-        .pfnGetChipString = sii164GetChipString,
-        .pfnSetPower = sii164SetPower,
-        .pfnEnableHotPlugDetection = sii164EnableHotPlugDetection,
-        .pfnIsConnected = sii164IsConnected,
-        .pfnCheckInterrupt = sii164CheckInterrupt,
-        .pfnClearInterrupt = sii164ClearInterrupt,
+               .pfnResetChip = sii164ResetChip,
+               .pfnGetChipString = sii164GetChipString,
+               .pfnSetPower = sii164SetPower,
+               .pfnEnableHotPlugDetection = sii164EnableHotPlugDetection,
+               .pfnIsConnected = sii164IsConnected,
+               .pfnCheckInterrupt = sii164CheckInterrupt,
+               .pfnClearInterrupt = sii164ClearInterrupt,
 #endif
-    },
+       },
 #endif
 };
 
 
 int dviInit(
-    unsigned char edgeSelect,
-    unsigned char busSelect,
-    unsigned char dualEdgeClkSelect,
-    unsigned char hsyncEnable,
-    unsigned char vsyncEnable,
-    unsigned char deskewEnable,
-    unsigned char deskewSetting,
-    unsigned char continuousSyncEnable,
-    unsigned char pllFilterEnable,
-    unsigned char pllFilterValue
+       unsigned char edgeSelect,
+       unsigned char busSelect,
+       unsigned char dualEdgeClkSelect,
+       unsigned char hsyncEnable,
+       unsigned char vsyncEnable,
+       unsigned char deskewEnable,
+       unsigned char deskewSetting,
+       unsigned char continuousSyncEnable,
+       unsigned char pllFilterEnable,
+       unsigned char pllFilterValue
                        )
 {
        dvi_ctrl_device_t *pCurrentDviCtrl;
+
        pCurrentDviCtrl = g_dcftSupportedDviController;
-       if(pCurrentDviCtrl->pfnInit != NULL)
-       {
+       if (pCurrentDviCtrl->pfnInit != NULL) {
                return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, dualEdgeClkSelect, hsyncEnable,
-                              vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
-                              pllFilterEnable, pllFilterValue);
+                                               vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
+                                               pllFilterEnable, pllFilterValue);
        }
        return -1; /* error */
 }
@@ -64,13 +63,13 @@ int dviInit(
  */
 unsigned short dviGetVendorID(void)
 {
-    dvi_ctrl_device_t *pCurrentDviCtrl;
+       dvi_ctrl_device_t *pCurrentDviCtrl;
 
-    pCurrentDviCtrl = g_dcftSupportedDviController;
-    if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
-        return pCurrentDviCtrl->pfnGetVendorId();
+       pCurrentDviCtrl = g_dcftSupportedDviController;
+       if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
+               return pCurrentDviCtrl->pfnGetVendorId();
 
-    return 0x0000;
+       return 0x0000;
 }
 
 
@@ -83,13 +82,13 @@ unsigned short dviGetVendorID(void)
  */
 unsigned short dviGetDeviceID(void)
 {
-    dvi_ctrl_device_t *pCurrentDviCtrl;
+       dvi_ctrl_device_t *pCurrentDviCtrl;
 
        pCurrentDviCtrl = g_dcftSupportedDviController;
-    if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
-        return pCurrentDviCtrl->pfnGetDeviceId();
+       if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
+               return pCurrentDviCtrl->pfnGetDeviceId();
 
-    return 0x0000;
+       return 0x0000;
 }
 
 #endif
index 83bbd6d62061b1f58c99d43866b570cce37f48eb..e1d4c9a2d50a2461e685960cd97271079c152b4f 100644 (file)
@@ -26,8 +26,7 @@ typedef unsigned char (*PFN_DVICTRL_CHECKINTERRUPT)(void);
 typedef void (*PFN_DVICTRL_CLEARINTERRUPT)(void);
 
 /* Structure to hold all the function pointer to the DVI Controller. */
-typedef struct _dvi_ctrl_device_t
-{
+typedef struct _dvi_ctrl_device_t {
        PFN_DVICTRL_INIT                pfnInit;
        PFN_DVICTRL_RESETCHIP           pfnResetChip;
        PFN_DVICTRL_GETCHIPSTRING       pfnGetChipString;
index 1adcafcc51336b7bcdcd30a8b1bbc552611ab5b3..9637dd30d037918325391f84758ea3505657a418 100644 (file)
@@ -1,8 +1,8 @@
 #include "ddk750_help.h"
 
-void __iomem *mmio750 = NULL;
-char revId750 = 0;
-unsigned short devId750 = 0;
+void __iomem *mmio750;
+char revId750;
+unsigned short devId750;
 
 /* after driver mapped io registers, use this function first */
 void ddk750_set_mmio(void __iomem *addr, unsigned short devId, char revId)
@@ -10,7 +10,7 @@ void ddk750_set_mmio(void __iomem *addr, unsigned short devId, char revId)
        mmio750 = addr;
        devId750 = devId;
        revId750 = revId;
-       if(revId == 0xfe)
+       if (revId == 0xfe)
                printk("found sm750le\n");
 }
 
index 4285b056585aaed3883a80482c1fae6a10236f0a..3b06aed431bd23b24746492002107f80c92e890b 100644 (file)
@@ -12,8 +12,8 @@
 #if 0
 /* if 718 big endian turned on,be aware that don't use this driver for general use,only for ppc big-endian */
 #warning "big endian on target cpu and enable nature big endian support of 718 capability !"
-#define PEEK32(addr)                   __raw_readl(mmio750 + addr)
-#define POKE32(addr, data)             __raw_writel(data, mmio750 + addr)
+#define PEEK32(addr)                   __raw_readl(mmio750 + addr)
+#define POKE32(addr, data)             __raw_writel(data, mmio750 + addr)
 #else /* software control endianness */
 #define PEEK32(addr) readl(addr + mmio750)
 #define POKE32(addr, data) writel(data, addr + mmio750)
index 7826376ed705d587c9e214a6e71177359b4a9286..5ddac430aea2ef321d8a5c2bf189f7535b8299b6 100644 (file)
 
 
 int hwI2CInit(
-    unsigned char busSpeedMode
+unsigned char busSpeedMode
 )
 {
-    unsigned int value;
+       unsigned int value;
 
-    /* Enable GPIO 30 & 31 as IIC clock & data */
+       /* Enable GPIO 30 & 31 as IIC clock & data */
        value = PEEK32(GPIO_MUX);
 
-    value = FIELD_SET(value, GPIO_MUX, 30, I2C) |
-                       FIELD_SET(0, GPIO_MUX, 31, I2C);
+       value = FIELD_SET(value, GPIO_MUX, 30, I2C) |
+                         FIELD_SET(0, GPIO_MUX, 31, I2C);
        POKE32(GPIO_MUX, value);
 
-    /* Enable Hardware I2C power.
-       TODO: Check if we need to enable GPIO power?
-     */
-    enableI2C(1);
-
-    /* Enable the I2C Controller and set the bus speed mode */
-    value = PEEK32(I2C_CTRL);
-    if (busSpeedMode == 0)
-        value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD);
-    else
-        value = FIELD_SET(value, I2C_CTRL, MODE, FAST);
-    value = FIELD_SET(value, I2C_CTRL, EN, ENABLE);
-    POKE32(I2C_CTRL, value);
-
-    return 0;
+       /* Enable Hardware I2C power.
+        TODO: Check if we need to enable GPIO power?
+        */
+       enableI2C(1);
+
+       /* Enable the I2C Controller and set the bus speed mode */
+       value = PEEK32(I2C_CTRL);
+       if (busSpeedMode == 0)
+               value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD);
+       else
+               value = FIELD_SET(value, I2C_CTRL, MODE, FAST);
+       value = FIELD_SET(value, I2C_CTRL, EN, ENABLE);
+       POKE32(I2C_CTRL, value);
+
+       return 0;
 }
 
 
 void hwI2CClose(void)
 {
-    unsigned int value;
+       unsigned int value;
 
-    /* Disable I2C controller */
-    value = PEEK32(I2C_CTRL);
-    value = FIELD_SET(value, I2C_CTRL, EN, DISABLE);
-    POKE32(I2C_CTRL, value);
+       /* Disable I2C controller */
+       value = PEEK32(I2C_CTRL);
+       value = FIELD_SET(value, I2C_CTRL, EN, DISABLE);
+       POKE32(I2C_CTRL, value);
 
-    /* Disable I2C Power */
-    enableI2C(0);
+       /* Disable I2C Power */
+       enableI2C(0);
 
-    /* Set GPIO 30 & 31 back as GPIO pins */
-    value = PEEK32(GPIO_MUX);
-    value = FIELD_SET(value, GPIO_MUX, 30, GPIO);
-    value = FIELD_SET(value, GPIO_MUX, 31, GPIO);
-    POKE32(GPIO_MUX, value);
+       /* Set GPIO 30 & 31 back as GPIO pins */
+       value = PEEK32(GPIO_MUX);
+       value = FIELD_SET(value, GPIO_MUX, 30, GPIO);
+       value = FIELD_SET(value, GPIO_MUX, 31, GPIO);
+       POKE32(GPIO_MUX, value);
 }
 
 
 static long hwI2CWaitTXDone(void)
 {
-    unsigned int timeout;
+       unsigned int timeout;
 
-    /* Wait until the transfer is completed. */
-    timeout = HWI2C_WAIT_TIMEOUT;
+       /* Wait until the transfer is completed. */
+       timeout = HWI2C_WAIT_TIMEOUT;
        while ((FIELD_GET(PEEK32(I2C_STATUS), I2C_STATUS, TX) != I2C_STATUS_TX_COMPLETED) &&
-           (timeout != 0))
+              (timeout != 0))
                timeout--;
 
        if (timeout == 0)
-           return (-1);
+               return (-1);
 
-    return 0;
+       return 0;
 }
 
 
@@ -91,53 +91,52 @@ static long hwI2CWaitTXDone(void)
  *      Total number of bytes those are actually written.
  */
 static unsigned int hwI2CWriteData(
-    unsigned char deviceAddress,
-    unsigned int length,
-    unsigned char *pBuffer
+       unsigned char deviceAddress,
+       unsigned int length,
+       unsigned char *pBuffer
 )
 {
-    unsigned char count, i;
-    unsigned int totalBytes = 0;
+       unsigned char count, i;
+       unsigned int totalBytes = 0;
 
-    /* Set the Device Address */
-    POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01);
+       /* Set the Device Address */
+       POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01);
 
-    /* Write data.
-     * Note:
-     *      Only 16 byte can be accessed per i2c start instruction.
-     */
-    do
-    {
-        /* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */
-        POKE32(I2C_RESET, 0);
+       /* Write data.
+        * Note:
+        *      Only 16 byte can be accessed per i2c start instruction.
+        */
+       do {
+               /* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */
+               POKE32(I2C_RESET, 0);
 
-        /* Set the number of bytes to be written */
-        if (length < MAX_HWI2C_FIFO)
-            count = length - 1;
-        else
-            count = MAX_HWI2C_FIFO - 1;
-        POKE32(I2C_BYTE_COUNT, count);
+               /* Set the number of bytes to be written */
+               if (length < MAX_HWI2C_FIFO)
+                       count = length - 1;
+               else
+                       count = MAX_HWI2C_FIFO - 1;
+               POKE32(I2C_BYTE_COUNT, count);
 
-        /* Move the data to the I2C data register */
-           for (i = 0; i <= count; i++)
-            POKE32(I2C_DATA0 + i, *pBuffer++);
+               /* Move the data to the I2C data register */
+               for (i = 0; i <= count; i++)
+                       POKE32(I2C_DATA0 + i, *pBuffer++);
 
-        /* Start the I2C */
-        POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
+               /* Start the I2C */
+               POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
 
-        /* Wait until the transfer is completed. */
-        if (hwI2CWaitTXDone() != 0)
-            break;
+               /* Wait until the transfer is completed. */
+               if (hwI2CWaitTXDone() != 0)
+                       break;
 
-        /* Substract length */
-        length -= (count + 1);
+               /* Substract length */
+               length -= (count + 1);
 
-        /* Total byte written */
-        totalBytes += (count + 1);
+               /* Total byte written */
+               totalBytes += (count + 1);
 
-    } while (length > 0);
+       } while (length > 0);
 
-    return totalBytes;
+       return totalBytes;
 }
 
 
@@ -158,53 +157,52 @@ static unsigned int hwI2CWriteData(
  *      Total number of actual bytes read from the slave device
  */
 static unsigned int hwI2CReadData(
-    unsigned char deviceAddress,
-    unsigned int length,
-    unsigned char *pBuffer
+       unsigned char deviceAddress,
+       unsigned int length,
+       unsigned char *pBuffer
 )
 {
-    unsigned char count, i;
-    unsigned int totalBytes = 0;
+       unsigned char count, i;
+       unsigned int totalBytes = 0;
 
-    /* Set the Device Address */
-    POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01);
+       /* Set the Device Address */
+       POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01);
 
-    /* Read data and save them to the buffer.
-     * Note:
-     *      Only 16 byte can be accessed per i2c start instruction.
-     */
-    do
-    {
-        /* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */
-        POKE32(I2C_RESET, 0);
+       /* Read data and save them to the buffer.
+        * Note:
+        *      Only 16 byte can be accessed per i2c start instruction.
+        */
+       do {
+               /* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */
+               POKE32(I2C_RESET, 0);
 
-        /* Set the number of bytes to be read */
-        if (length <= MAX_HWI2C_FIFO)
-            count = length - 1;
-        else
-            count = MAX_HWI2C_FIFO - 1;
-        POKE32(I2C_BYTE_COUNT, count);
+               /* Set the number of bytes to be read */
+               if (length <= MAX_HWI2C_FIFO)
+                       count = length - 1;
+               else
+                       count = MAX_HWI2C_FIFO - 1;
+               POKE32(I2C_BYTE_COUNT, count);
 
-        /* Start the I2C */
-        POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
+               /* Start the I2C */
+               POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
 
-        /* Wait until transaction done. */
-        if (hwI2CWaitTXDone() != 0)
-            break;
+               /* Wait until transaction done. */
+               if (hwI2CWaitTXDone() != 0)
+                       break;
 
-        /* Save the data to the given buffer */
-        for (i = 0; i <= count; i++)
-                   *pBuffer++ = PEEK32(I2C_DATA0 + i);
+               /* Save the data to the given buffer */
+               for (i = 0; i <= count; i++)
+                       *pBuffer++ = PEEK32(I2C_DATA0 + i);
 
-        /* Substract length by 16 */
-        length -= (count + 1);
+               /* Substract length by 16 */
+               length -= (count + 1);
 
-        /* Number of bytes read. */
-        totalBytes += (count + 1);
+               /* Number of bytes read. */
+               totalBytes += (count + 1);
 
-    } while (length > 0);
+       } while (length > 0);
 
-    return totalBytes;
+       return totalBytes;
 }
 
 
@@ -222,16 +220,16 @@ static unsigned int hwI2CReadData(
  *      Register value
  */
 unsigned char hwI2CReadReg(
-    unsigned char deviceAddress,
-    unsigned char registerIndex
+       unsigned char deviceAddress,
+       unsigned char registerIndex
 )
 {
-    unsigned char value = (0xFF);
+       unsigned char value = (0xFF);
 
-    if (hwI2CWriteData(deviceAddress, 1, &registerIndex) == 1)
-        hwI2CReadData(deviceAddress, 1, &value);
+       if (hwI2CWriteData(deviceAddress, 1, &registerIndex) == 1)
+               hwI2CReadData(deviceAddress, 1, &value);
 
-    return value;
+       return value;
 }
 
 
@@ -252,19 +250,19 @@ unsigned char hwI2CReadReg(
  *         -1   - Fail
  */
 int hwI2CWriteReg(
-    unsigned char deviceAddress,
-    unsigned char registerIndex,
-    unsigned char data
+       unsigned char deviceAddress,
+       unsigned char registerIndex,
+       unsigned char data
 )
 {
-    unsigned char value[2];
+       unsigned char value[2];
 
-    value[0] = registerIndex;
-    value[1] = data;
-    if (hwI2CWriteData(deviceAddress, 2, value) == 2)
-        return 0;
+       value[0] = registerIndex;
+       value[1] = data;
+       if (hwI2CWriteData(deviceAddress, 2, value) == 2)
+               return 0;
 
-    return (-1);
+       return (-1);
 }
 
 
index 74313ff84e456879854b4cb7d07067ca62dbea68..2399b175ade0f222757a1485ffdde2d09c72e4be 100644 (file)
@@ -20,54 +20,54 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam,
        x = pModeParam->horizontal_display_end;
        y = pModeParam->vertical_display_end;
 
-    /* SM750LE has to set up the top-left and bottom-right
-       registers as well.
-       Note that normal SM750/SM718 only use those two register for
-       auto-centering mode.
-    */
-    POKE32(CRT_AUTO_CENTERING_TL,
-      FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
-    | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
-
-    POKE32(CRT_AUTO_CENTERING_BR,
-      FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
-    | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));
-
-    /* Assume common fields in dispControl have been properly set before
-       calling this function.
-       This function only sets the extra fields in dispControl.
-    */
+       /* SM750LE has to set up the top-left and bottom-right
+          registers as well.
+          Note that normal SM750/SM718 only use those two register for
+          auto-centering mode.
+        */
+       POKE32(CRT_AUTO_CENTERING_TL,
+       FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
+       | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
+
+       POKE32(CRT_AUTO_CENTERING_BR,
+       FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
+       | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));
+
+       /* Assume common fields in dispControl have been properly set before
+          calling this function.
+          This function only sets the extra fields in dispControl.
+        */
 
        /* Clear bit 29:27 of display control register */
-    dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
+       dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
 
        /* Set bit 29:27 of display control register for the right clock */
        /* Note that SM750LE only need to supported 7 resoluitons. */
-       if ( x == 800 && y == 600 )
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
+       if (x == 800 && y == 600)
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
        else if (x == 1024 && y == 768)
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
        else if (x == 1152 && y == 864)
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
        else if (x == 1280 && y == 768)
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
        else if (x == 1280 && y == 720)
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
        else if (x == 1280 && y == 960)
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
        else if (x == 1280 && y == 1024)
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
+               dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
        else /* default to VGA clock */
-       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
 
        /* Set bit 25:24 of display controller */
-    dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
-    dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
 
-    /* Set bit 14 of display controller */
-    dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
+       /* Set bit 14 of display controller */
+       dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
 
-    POKE32(CRT_DISPLAY_CTRL, dispControl);
+       POKE32(CRT_DISPLAY_CTRL, dispControl);
 
        return dispControl;
 }
@@ -80,25 +80,25 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
        int ret = 0;
        int cnt = 0;
        unsigned int ulTmpValue, ulReg;
-       if(pll->clockType == SECONDARY_PLL)
-       {
+
+       if (pll->clockType == SECONDARY_PLL) {
                /* programe secondary pixel clock */
                POKE32(CRT_PLL_CTRL, formatPllReg(pll));
-        POKE32(CRT_HORIZONTAL_TOTAL,
-              FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
-            | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
+               POKE32(CRT_HORIZONTAL_TOTAL,
+               FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
+               | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
 
-        POKE32(CRT_HORIZONTAL_SYNC,
-              FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
-            | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
+               POKE32(CRT_HORIZONTAL_SYNC,
+               FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
+               | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
 
-        POKE32(CRT_VERTICAL_TOTAL,
-              FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
-            | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
+               POKE32(CRT_VERTICAL_TOTAL,
+               FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
+               | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
 
-        POKE32(CRT_VERTICAL_SYNC,
-              FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
-            | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
+               POKE32(CRT_VERTICAL_SYNC,
+               FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
+               | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
 
 
                ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
@@ -107,9 +107,9 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
                                          FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE);
 
 
-               if(getChipType() == SM750LE){
+               if (getChipType() == SM750LE) {
                        displayControlAdjust_SM750LE(pModeParam, ulTmpValue);
-               }else{
+               } else {
                        ulReg = PEEK32(CRT_DISPLAY_CTRL)
                                        & FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE)
                                        & FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE)
@@ -119,45 +119,44 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
                         POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg);
                }
 
-       }
-       else if(pll->clockType == PRIMARY_PLL)
-       {
+       } else if (pll->clockType == PRIMARY_PLL) {
                unsigned int ulReservedBits;
+
                POKE32(PANEL_PLL_CTRL, formatPllReg(pll));
 
-        POKE32(PANEL_HORIZONTAL_TOTAL,
-              FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
-            | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
+               POKE32(PANEL_HORIZONTAL_TOTAL,
+               FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
+               | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
 
-        POKE32(PANEL_HORIZONTAL_SYNC,
-              FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
-            | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
+               POKE32(PANEL_HORIZONTAL_SYNC,
+               FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
+               | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
 
-        POKE32(PANEL_VERTICAL_TOTAL,
-              FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
-            | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
+               POKE32(PANEL_VERTICAL_TOTAL,
+               FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
+                       | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
 
-        POKE32(PANEL_VERTICAL_SYNC,
-              FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
-            | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
+               POKE32(PANEL_VERTICAL_SYNC,
+               FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
+               | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
 
                ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
-                                       FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
-                                       FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)|
-                                       FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)|
-                                       FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE);
+                            FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
+                            FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)|
+                            FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)|
+                            FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE);
 
-        ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
-                         FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
-                         FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
-                         FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW);
+               ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
+                                FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
+                                FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
+                                FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW);
 
-        ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
-              & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
-              & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
-              & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
-              & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
-              & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
+               ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
+                       & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
+                       & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
+                       & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
+                       & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
+                       & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
 
 
                /* May a hardware bug or just my test chip (not confirmed).
@@ -170,16 +169,14 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll)
 
                POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
 #if 1
-               while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg))
-               {
+               while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
                        cnt++;
-                       if(cnt > 1000)
+                       if (cnt > 1000)
                                break;
                        POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
                }
 #endif
-       }
-       else{
+       } else {
                ret = -1;
        }
        return ret;
@@ -189,11 +186,12 @@ int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock)
 {
        pll_value_t pll;
        unsigned int uiActualPixelClk;
+
        pll.inputFreq = DEFAULT_INPUT_CLOCK;
        pll.clockType = clock;
 
        uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll);
-       if(getChipType() == SM750LE){
+       if (getChipType() == SM750LE) {
                /* set graphic mode via IO method */
                outb_p(0x88, 0x3d4);
                outb_p(0x06, 0x3d5);
index 4e8fab3f17e468d0aa3133ee066b499c92830196..e846dc2c3d5cc6f347eedbfa76a1e4791ed60556 100644 (file)
@@ -3,37 +3,35 @@
 
 #include "ddk750_chip.h"
 
-typedef enum _spolarity_t
-{
-    POS = 0, /* positive */
-    NEG, /* negative */
+typedef enum _spolarity_t {
+       POS = 0, /* positive */
+       NEG, /* negative */
 }
 spolarity_t;
 
 
-typedef struct _mode_parameter_t
-{
-    /* Horizontal timing. */
-    unsigned long horizontal_total;
-    unsigned long horizontal_display_end;
-    unsigned long horizontal_sync_start;
-    unsigned long horizontal_sync_width;
-    spolarity_t horizontal_sync_polarity;
-
-    /* Vertical timing. */
-    unsigned long vertical_total;
-    unsigned long vertical_display_end;
-    unsigned long vertical_sync_start;
-    unsigned long vertical_sync_height;
-    spolarity_t vertical_sync_polarity;
-
-    /* Refresh timing. */
-    unsigned long pixel_clock;
-    unsigned long horizontal_frequency;
-    unsigned long vertical_frequency;
-
-    /* Clock Phase. This clock phase only applies to Panel. */
-    spolarity_t clock_phase_polarity;
+typedef struct _mode_parameter_t {
+       /* Horizontal timing. */
+       unsigned long horizontal_total;
+       unsigned long horizontal_display_end;
+       unsigned long horizontal_sync_start;
+       unsigned long horizontal_sync_width;
+       spolarity_t horizontal_sync_polarity;
+
+       /* Vertical timing. */
+       unsigned long vertical_total;
+       unsigned long vertical_display_end;
+       unsigned long vertical_sync_start;
+       unsigned long vertical_sync_height;
+       spolarity_t vertical_sync_polarity;
+
+       /* Refresh timing. */
+       unsigned long pixel_clock;
+       unsigned long horizontal_frequency;
+       unsigned long vertical_frequency;
+
+       /* Clock Phase. This clock phase only applies to Panel. */
+       spolarity_t clock_phase_polarity;
 }
 mode_parameter_t;
 
index 1e5f398aed1001d12fd6dc9f00cc07334429fad4..e580dab2b625d128ee10b6959387c62b30213f7a 100644 (file)
@@ -5,21 +5,23 @@
 void ddk750_setDPMS(DPMS_t state)
 {
        unsigned int value;
-       if(getChipType() == SM750LE){
+
+       if (getChipType() == SM750LE) {
                value = PEEK32(CRT_DISPLAY_CTRL);
-               POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL, DPMS, state));
-       }else{
+               POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL,
+                                                    DPMS, state));
+       } else {
                value = PEEK32(SYSTEM_CTRL);
-               value= FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state);
+               value = FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state);
                POKE32(SYSTEM_CTRL, value);
        }
 }
 
 unsigned int getPowerMode(void)
 {
-       if(getChipType() == SM750LE)
+       if (getChipType() == SM750LE)
                return 0;
-    return (FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE));
+       return FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE);
 }
 
 
@@ -29,76 +31,74 @@ unsigned int getPowerMode(void)
  */
 void setPowerMode(unsigned int powerMode)
 {
-    unsigned int control_value = 0;
+       unsigned int control_value = 0;
 
-    control_value = PEEK32(POWER_MODE_CTRL);
+       control_value = PEEK32(POWER_MODE_CTRL);
 
-       if(getChipType() == SM750LE)
+       if (getChipType() == SM750LE)
                return;
 
-    switch (powerMode)
-    {
-        case POWER_MODE_CTRL_MODE_MODE0:
-            control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0);
-            break;
+       switch (powerMode) {
+       case POWER_MODE_CTRL_MODE_MODE0:
+               control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
+                                         MODE0);
+               break;
 
-        case POWER_MODE_CTRL_MODE_MODE1:
-            control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE1);
-            break;
+       case POWER_MODE_CTRL_MODE_MODE1:
+               control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
+                                         MODE1);
+               break;
 
-        case POWER_MODE_CTRL_MODE_SLEEP:
-            control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, SLEEP);
-            break;
+       case POWER_MODE_CTRL_MODE_SLEEP:
+               control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
+                                         SLEEP);
+               break;
 
-        default:
-            break;
-    }
+       default:
+               break;
+       }
 
-    /* Set up other fields in Power Control Register */
-    if (powerMode == POWER_MODE_CTRL_MODE_SLEEP)
-    {
-        control_value =
+       /* Set up other fields in Power Control Register */
+       if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) {
+               control_value =
 #ifdef VALIDATION_CHIP
-            FIELD_SET(  control_value, POWER_MODE_CTRL, 336CLK, OFF) |
+               FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, OFF) |
 #endif
-            FIELD_SET(  control_value, POWER_MODE_CTRL, OSC_INPUT,  OFF);
-    }
-    else
-    {
-        control_value =
+               FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT,  OFF);
+       } else {
+               control_value =
 #ifdef VALIDATION_CHIP
-            FIELD_SET(  control_value, POWER_MODE_CTRL, 336CLK, ON) |
+               FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, ON) |
 #endif
-            FIELD_SET(  control_value, POWER_MODE_CTRL, OSC_INPUT,  ON);
-    }
+               FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT,  ON);
+       }
 
-    /* Program new power mode. */
-    POKE32(POWER_MODE_CTRL, control_value);
+       /* Program new power mode. */
+       POKE32(POWER_MODE_CTRL, control_value);
 }
 
 void setCurrentGate(unsigned int gate)
 {
-    unsigned int gate_reg;
-    unsigned int mode;
-
-    /* Get current power mode. */
-    mode = getPowerMode();
-
-    switch (mode)
-    {
-        case POWER_MODE_CTRL_MODE_MODE0:
-            gate_reg = MODE0_GATE;
-            break;
-
-        case POWER_MODE_CTRL_MODE_MODE1:
-            gate_reg = MODE1_GATE;
-            break;
-
-        default:
-            gate_reg = MODE0_GATE;
-            break;
-    }
-    POKE32(gate_reg, gate);
+       unsigned int gate_reg;
+       unsigned int mode;
+
+       /* Get current power mode. */
+       mode = getPowerMode();
+
+       switch (mode) {
+       case POWER_MODE_CTRL_MODE_MODE0:
+               gate_reg = MODE0_GATE;
+               break;
+
+       case POWER_MODE_CTRL_MODE_MODE1:
+               gate_reg = MODE1_GATE;
+               break;
+
+       default:
+               gate_reg = MODE0_GATE;
+               break;
+       }
+       POKE32(gate_reg, gate);
 }
 
 
@@ -108,21 +108,18 @@ void setCurrentGate(unsigned int gate)
  */
 void enable2DEngine(unsigned int enable)
 {
-    uint32_t gate;
-
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-    {
-        gate = FIELD_SET(gate, CURRENT_GATE, DE,  ON);
-        gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON);
-    }
-    else
-    {
-        gate = FIELD_SET(gate, CURRENT_GATE, DE,  OFF);
-        gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF);
-    }
-
-    setCurrentGate(gate);
+       uint32_t gate;
+
+       gate = PEEK32(CURRENT_GATE);
+       if (enable) {
+               gate = FIELD_SET(gate, CURRENT_GATE, DE,  ON);
+               gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON);
+       } else {
+               gate = FIELD_SET(gate, CURRENT_GATE, DE,  OFF);
+               gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF);
+       }
+
+       setCurrentGate(gate);
 }
 
 
@@ -131,58 +128,56 @@ void enable2DEngine(unsigned int enable)
  */
 void enableZVPort(unsigned int enable)
 {
-    uint32_t gate;
+       uint32_t gate;
 
-    /* Enable ZV Port Gate */
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-    {
-        gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, ON);
+       /* Enable ZV Port Gate */
+       gate = PEEK32(CURRENT_GATE);
+       if (enable) {
+               gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, ON);
 #if 1
-        /* Using Software I2C */
-        gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
+               /* Using Software I2C */
+               gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
 #else
-        /* Using Hardware I2C */
-        gate = FIELD_SET(gate, CURRENT_GATE, I2C,    ON);
+               /* Using Hardware I2C */
+               gate = FIELD_SET(gate, CURRENT_GATE, I2C,    ON);
 #endif
-    }
-    else
-    {
-        /* Disable ZV Port Gate. There is no way to know whether the GPIO pins are being used
-           or not. Therefore, do not disable the GPIO gate. */
-        gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF);
-    }
-
-    setCurrentGate(gate);
+       } else {
+               /* Disable ZV Port Gate. There is no way to know whether the
+               GPIO pins are being used or not. Therefore, do not disable the
+               GPIO gate. */
+               gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF);
+       }
+
+       setCurrentGate(gate);
 }
 
 
 void enableSSP(unsigned int enable)
 {
-    uint32_t gate;
+       uint32_t gate;
 
-    /* Enable SSP Gate */
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-        gate = FIELD_SET(gate, CURRENT_GATE, SSP, ON);
-    else
-        gate = FIELD_SET(gate, CURRENT_GATE, SSP, OFF);
+       /* Enable SSP Gate */
+       gate = PEEK32(CURRENT_GATE);
+       if (enable)
+               gate = FIELD_SET(gate, CURRENT_GATE, SSP, ON);
+       else
+               gate = FIELD_SET(gate, CURRENT_GATE, SSP, OFF);
 
-    setCurrentGate(gate);
+       setCurrentGate(gate);
 }
 
 void enableDMA(unsigned int enable)
 {
-    uint32_t gate;
+       uint32_t gate;
 
-    /* Enable DMA Gate */
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-        gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON);
-    else
-        gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF);
+       /* Enable DMA Gate */
+       gate = PEEK32(CURRENT_GATE);
+       if (enable)
+               gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON);
+       else
+               gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF);
 
-    setCurrentGate(gate);
+       setCurrentGate(gate);
 }
 
 /*
@@ -190,16 +185,16 @@ void enableDMA(unsigned int enable)
  */
 void enableGPIO(unsigned int enable)
 {
-    uint32_t gate;
+       uint32_t gate;
 
-    /* Enable GPIO Gate */
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-        gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
-    else
-        gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF);
+       /* Enable GPIO Gate */
+       gate = PEEK32(CURRENT_GATE);
+       if (enable)
+               gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
+       else
+               gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF);
 
-    setCurrentGate(gate);
+       setCurrentGate(gate);
 }
 
 /*
@@ -207,16 +202,16 @@ void enableGPIO(unsigned int enable)
  */
 void enablePWM(unsigned int enable)
 {
-    uint32_t gate;
+       uint32_t gate;
 
-    /* Enable PWM Gate */
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-        gate = FIELD_SET(gate, CURRENT_GATE, PWM, ON);
-    else
-        gate = FIELD_SET(gate, CURRENT_GATE, PWM, OFF);
+       /* Enable PWM Gate */
+       gate = PEEK32(CURRENT_GATE);
+       if (enable)
+               gate = FIELD_SET(gate, CURRENT_GATE, PWM, ON);
+       else
+               gate = FIELD_SET(gate, CURRENT_GATE, PWM, OFF);
 
-    setCurrentGate(gate);
+       setCurrentGate(gate);
 }
 
 /*
@@ -224,16 +219,16 @@ void enablePWM(unsigned int enable)
  */
 void enableI2C(unsigned int enable)
 {
-    uint32_t gate;
+       uint32_t gate;
 
-    /* Enable I2C Gate */
-    gate = PEEK32(CURRENT_GATE);
-    if (enable)
-        gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
-    else
-        gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF);
+       /* Enable I2C Gate */
+       gate = PEEK32(CURRENT_GATE);
+       if (enable)
+               gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
+       else
+       gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF);
 
-    setCurrentGate(gate);
+       setCurrentGate(gate);
 }
 
 
index 4e00955a07ddd08238d7fc7705e53496671d528d..b7cf6b281fb651fde508d3b177799d8e66084cde 100644 (file)
@@ -1,12 +1,11 @@
 #ifndef DDK750_POWER_H__
 #define DDK750_POWER_H__
 
-typedef enum _DPMS_t
-{
-    crtDPMS_ON = 0x0,
-    crtDPMS_STANDBY = 0x1,
-    crtDPMS_SUSPEND = 0x2,
-    crtDPMS_OFF = 0x3,
+typedef enum _DPMS_t {
+       crtDPMS_ON = 0x0,
+       crtDPMS_STANDBY = 0x1,
+       crtDPMS_SUSPEND = 0x2,
+       crtDPMS_OFF = 0x3,
 }
 DPMS_t;
 
index 1a40dc2a2f759ba383a70c1449cbd7f9c266bd98..2995625c3d62635b80938d1309158a99b30b7e22 100644 (file)
 /* CRT Graphics Control */
 
 #define CRT_DISPLAY_CTRL                              0x080200
-#define CRT_DISPLAY_CTRL_RESERVED_1_MASK                         31:27
-#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE                         0
-#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE                          0x1F
+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK             31:27
+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE      0
+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE       0x1F
 
 /* SM750LE definition */
 #define CRT_DISPLAY_CTRL_DPMS                         31:30
 #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_ENABLE         0
 
 
-#define CRT_DISPLAY_CTRL_RESERVED_2_MASK                         25:24
-#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE                          3
-#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE                         0
+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK             25:24
+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE              3
+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE      0
 
 /* SM750LE definition */
 #define CRT_DISPLAY_CTRL_CRTSELECT                    25:25
 #define CRT_DISPLAY_CTRL_RGBBIT_12BIT                 1
 
 
-#define CRT_DISPLAY_CTRL_RESERVED_3_MASK                         15:15
+#define CRT_DISPLAY_CTRL_RESERVED_3_MASK             15:15
 #define CRT_DISPLAY_CTRL_RESERVED_3_MASK_DISABLE      0
 #define CRT_DISPLAY_CTRL_RESERVED_3_MASK_ENABLE       1
 
-#define CRT_DISPLAY_CTRL_RESERVED_4_MASK                         9:9
+#define CRT_DISPLAY_CTRL_RESERVED_4_MASK             9:9
 #define CRT_DISPLAY_CTRL_RESERVED_4_MASK_DISABLE      0
 #define CRT_DISPLAY_CTRL_RESERVED_4_MASK_ENABLE       1
 
 #endif
 
 /* sm750le new register to control panel output */
-#define DISPLAY_CONTROL_750LE  0x80288
+#define DISPLAY_CONTROL_750LE                        0x80288
 /* Palette RAM */
 
 /* Panel Palette register starts at 0x080400 ~ 0x0807FC */
index b6395b87fc21d05bc839e81f72517f5b6b851d23..0bdf3db11df04af03186360a0232b2853bcdf693 100644 (file)
@@ -36,12 +36,12 @@ static char *gDviCtrlChipName = "Silicon Image SiI 164";
  */
 unsigned short sii164GetVendorID(void)
 {
-    unsigned short vendorID;
+       unsigned short vendorID;
 
-    vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
-                (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
+       vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
+                   (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
 
-    return vendorID;
+       return vendorID;
 }
 
 /*
@@ -53,12 +53,12 @@ unsigned short sii164GetVendorID(void)
  */
 unsigned short sii164GetDeviceID(void)
 {
-    unsigned short deviceID;
+       unsigned short deviceID;
 
-    deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
-                (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
+       deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
+                   (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
 
-    return deviceID;
+       return deviceID;
 }
 
 
@@ -113,132 +113,130 @@ unsigned short sii164GetDeviceID(void)
  *     -1   - Fail.
  */
 long sii164InitChip(
-    unsigned char edgeSelect,
-    unsigned char busSelect,
-    unsigned char dualEdgeClkSelect,
-    unsigned char hsyncEnable,
-    unsigned char vsyncEnable,
-    unsigned char deskewEnable,
-    unsigned char deskewSetting,
-    unsigned char continuousSyncEnable,
-    unsigned char pllFilterEnable,
-    unsigned char pllFilterValue
+       unsigned char edgeSelect,
+       unsigned char busSelect,
+       unsigned char dualEdgeClkSelect,
+       unsigned char hsyncEnable,
+       unsigned char vsyncEnable,
+       unsigned char deskewEnable,
+       unsigned char deskewSetting,
+       unsigned char continuousSyncEnable,
+       unsigned char pllFilterEnable,
+       unsigned char pllFilterValue
 )
 {
        unsigned char config;
 
-    /* Initialize the i2c bus */
+       /* Initialize the i2c bus */
 #ifdef USE_HW_I2C
-    /* Use fast mode. */
-    hwI2CInit(1);
+       /* Use fast mode. */
+       hwI2CInit(1);
 #else
-    swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
+       swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
 #endif
 
-    /* Check if SII164 Chip exists */
-    if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID))
-    {
-        /*
-         *  Initialize SII164 controller chip.
-         */
-
-        /* Select the edge */
-        if (edgeSelect == 0)
-            config = SII164_CONFIGURATION_LATCH_FALLING;
-        else
-            config = SII164_CONFIGURATION_LATCH_RISING;
-
-        /* Select bus wide */
-        if (busSelect == 0)
-            config |= SII164_CONFIGURATION_BUS_12BITS;
-        else
-            config |= SII164_CONFIGURATION_BUS_24BITS;
-
-        /* Select Dual/Single Edge Clock */
-        if (dualEdgeClkSelect == 0)
-            config |= SII164_CONFIGURATION_CLOCK_SINGLE;
-        else
-            config |= SII164_CONFIGURATION_CLOCK_DUAL;
-
-        /* Select HSync Enable */
-        if (hsyncEnable == 0)
-            config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
-        else
-            config |= SII164_CONFIGURATION_HSYNC_AS_IS;
-
-        /* Select VSync Enable */
-        if (vsyncEnable == 0)
-            config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
-        else
-            config |= SII164_CONFIGURATION_VSYNC_AS_IS;
-
-        i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
-
-        /* De-skew enabled with default 111b value.
-           This will fix some artifacts problem in some mode on board 2.2.
-           Somehow this fix does not affect board 2.1.
-         */
-        if (deskewEnable == 0)
-            config = SII164_DESKEW_DISABLE;
-        else
-            config = SII164_DESKEW_ENABLE;
-
-        switch (deskewSetting)
-        {
-            case 0:
-                config |= SII164_DESKEW_1_STEP;
-                break;
-            case 1:
-                config |= SII164_DESKEW_2_STEP;
-                break;
-            case 2:
-                config |= SII164_DESKEW_3_STEP;
-                break;
-            case 3:
-                config |= SII164_DESKEW_4_STEP;
-                break;
-            case 4:
-                config |= SII164_DESKEW_5_STEP;
-                break;
-            case 5:
-                config |= SII164_DESKEW_6_STEP;
-                break;
-            case 6:
-                config |= SII164_DESKEW_7_STEP;
-                break;
-            case 7:
-                config |= SII164_DESKEW_8_STEP;
-                break;
-        }
-        i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
-
-        /* Enable/Disable Continuous Sync. */
-        if (continuousSyncEnable == 0)
-            config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
-        else
-            config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
-
-        /* Enable/Disable PLL Filter */
-        if (pllFilterEnable == 0)
-            config |= SII164_PLL_FILTER_DISABLE;
-        else
-            config |= SII164_PLL_FILTER_ENABLE;
-
-        /* Set the PLL Filter value */
-        config |= ((pllFilterValue & 0x07) << 1);
-
-        i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
-
-        /* Recover from Power Down and enable output. */
-        config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
-        config |= SII164_CONFIGURATION_POWER_NORMAL;
-        i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
-
-        return 0;
-    }
-
-    /* Return -1 if initialization fails. */
-    return (-1);
+       /* Check if SII164 Chip exists */
+       if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
+               /*
+                *  Initialize SII164 controller chip.
+                */
+
+               /* Select the edge */
+               if (edgeSelect == 0)
+                       config = SII164_CONFIGURATION_LATCH_FALLING;
+               else
+                       config = SII164_CONFIGURATION_LATCH_RISING;
+
+               /* Select bus wide */
+               if (busSelect == 0)
+                       config |= SII164_CONFIGURATION_BUS_12BITS;
+               else
+                       config |= SII164_CONFIGURATION_BUS_24BITS;
+
+               /* Select Dual/Single Edge Clock */
+               if (dualEdgeClkSelect == 0)
+                       config |= SII164_CONFIGURATION_CLOCK_SINGLE;
+               else
+                       config |= SII164_CONFIGURATION_CLOCK_DUAL;
+
+               /* Select HSync Enable */
+               if (hsyncEnable == 0)
+                       config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
+               else
+                       config |= SII164_CONFIGURATION_HSYNC_AS_IS;
+
+               /* Select VSync Enable */
+               if (vsyncEnable == 0)
+                       config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
+               else
+                       config |= SII164_CONFIGURATION_VSYNC_AS_IS;
+
+               i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+
+               /* De-skew enabled with default 111b value.
+                  This will fix some artifacts problem in some mode on board 2.2.
+                  Somehow this fix does not affect board 2.1.
+                */
+               if (deskewEnable == 0)
+                       config = SII164_DESKEW_DISABLE;
+               else
+                       config = SII164_DESKEW_ENABLE;
+
+               switch (deskewSetting) {
+               case 0:
+                       config |= SII164_DESKEW_1_STEP;
+                       break;
+               case 1:
+                       config |= SII164_DESKEW_2_STEP;
+                       break;
+               case 2:
+                       config |= SII164_DESKEW_3_STEP;
+                       break;
+               case 3:
+                       config |= SII164_DESKEW_4_STEP;
+                       break;
+               case 4:
+                       config |= SII164_DESKEW_5_STEP;
+                       break;
+               case 5:
+                       config |= SII164_DESKEW_6_STEP;
+                       break;
+               case 6:
+                       config |= SII164_DESKEW_7_STEP;
+                       break;
+               case 7:
+                       config |= SII164_DESKEW_8_STEP;
+                       break;
+               }
+               i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
+
+               /* Enable/Disable Continuous Sync. */
+               if (continuousSyncEnable == 0)
+                       config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
+               else
+                       config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
+
+               /* Enable/Disable PLL Filter */
+               if (pllFilterEnable == 0)
+                       config |= SII164_PLL_FILTER_DISABLE;
+               else
+                       config |= SII164_PLL_FILTER_ENABLE;
+
+               /* Set the PLL Filter value */
+               config |= ((pllFilterValue & 0x07) << 1);
+
+               i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
+
+               /* Recover from Power Down and enable output. */
+               config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
+               config |= SII164_CONFIGURATION_POWER_NORMAL;
+               i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+
+               return 0;
+       }
+
+       /* Return -1 if initialization fails. */
+       return (-1);
 }
 
 
@@ -255,9 +253,9 @@ long sii164InitChip(
  */
 void sii164ResetChip(void)
 {
-    /* Power down */
-    sii164SetPower(0);
-    sii164SetPower(1);
+       /* Power down */
+       sii164SetPower(0);
+       sii164SetPower(1);
 }
 
 
@@ -268,7 +266,7 @@ void sii164ResetChip(void)
  */
 char *sii164GetChipString(void)
 {
-    return gDviCtrlChipName;
+       return gDviCtrlChipName;
 }
 
 
@@ -280,26 +278,23 @@ char *sii164GetChipString(void)
  *      powerUp - Flag to set the power down or up
  */
 void sii164SetPower(
-    unsigned char powerUp
+       unsigned char powerUp
 )
 {
-    unsigned char config;
-
-    config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
-    if (powerUp == 1)
-    {
-        /* Power up the chip */
-        config &= ~SII164_CONFIGURATION_POWER_MASK;
-        config |= SII164_CONFIGURATION_POWER_NORMAL;
-        i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
-    }
-    else
-    {
-        /* Power down the chip */
-        config &= ~SII164_CONFIGURATION_POWER_MASK;
-        config |= SII164_CONFIGURATION_POWER_DOWN;
-        i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
-    }
+       unsigned char config;
+
+       config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
+       if (powerUp == 1) {
+               /* Power up the chip */
+               config &= ~SII164_CONFIGURATION_POWER_MASK;
+               config |= SII164_CONFIGURATION_POWER_NORMAL;
+               i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+       } else {
+               /* Power down the chip */
+               config &= ~SII164_CONFIGURATION_POWER_MASK;
+               config |= SII164_CONFIGURATION_POWER_DOWN;
+               i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+       }
 }
 
 
@@ -308,31 +303,30 @@ void sii164SetPower(
  *      This function selects the mode of the hot plug detection.
  */
 static void sii164SelectHotPlugDetectionMode(
-    sii164_hot_plug_mode_t hotPlugMode
+       sii164_hot_plug_mode_t hotPlugMode
 )
 {
-    unsigned char detectReg;
-
-    detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
-    switch (hotPlugMode)
-    {
-        case SII164_HOTPLUG_DISABLE:
-            detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
-            break;
-        case SII164_HOTPLUG_USE_MDI:
-            detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
-            detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
-            detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
-            break;
-        case SII164_HOTPLUG_USE_RSEN:
-            detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
-            break;
-        case SII164_HOTPLUG_USE_HTPLG:
-            detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
-            break;
-    }
-
-    i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
+       unsigned char detectReg;
+
+       detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
+       switch (hotPlugMode) {
+       case SII164_HOTPLUG_DISABLE:
+               detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
+               break;
+       case SII164_HOTPLUG_USE_MDI:
+               detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
+               detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
+               detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
+               break;
+       case SII164_HOTPLUG_USE_RSEN:
+               detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
+               break;
+       case SII164_HOTPLUG_USE_HTPLG:
+               detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
+               break;
+       }
+
+       i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
 }
 
 /*
@@ -342,18 +336,19 @@ static void sii164SelectHotPlugDetectionMode(
  *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
  */
 void sii164EnableHotPlugDetection(
-    unsigned char enableHotPlug
+       unsigned char enableHotPlug
 )
 {
-    unsigned char detectReg;
-    detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
-
-    /* Depending on each DVI controller, need to enable the hot plug based on each
-       individual chip design. */
-    if (enableHotPlug != 0)
-        sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
-    else
-        sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
+       unsigned char detectReg;
+
+       detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
+
+       /* Depending on each DVI controller, need to enable the hot plug based on each
+          individual chip design. */
+       if (enableHotPlug != 0)
+               sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
+       else
+               sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
 }
 
 /*
@@ -366,13 +361,13 @@ void sii164EnableHotPlugDetection(
  */
 unsigned char sii164IsConnected(void)
 {
-    unsigned char hotPlugValue;
+       unsigned char hotPlugValue;
 
-    hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
-    if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
-        return 1;
-    else
-        return 0;
+       hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
+       if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
+               return 1;
+       else
+               return 0;
 }
 
 /*
@@ -385,13 +380,13 @@ unsigned char sii164IsConnected(void)
  */
 unsigned char sii164CheckInterrupt(void)
 {
-    unsigned char detectReg;
+       unsigned char detectReg;
 
-    detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
-    if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
-        return 1;
-    else
-        return 0;
+       detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
+       if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
+               return 1;
+       else
+               return 0;
 }
 
 /*
@@ -400,11 +395,11 @@ unsigned char sii164CheckInterrupt(void)
  */
 void sii164ClearInterrupt(void)
 {
-    unsigned char detectReg;
+       unsigned char detectReg;
 
-    /* Clear the MDI interrupt */
-    detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
-    i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
+       /* Clear the MDI interrupt */
+       detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
+       i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
 }
 
 #endif
index 2b4c7d3381dfd4773c484e74bac5be0f0e2e1bdf..f2610c90eeb4c2ead006ae01ba95eecb4f7fec1e 100644 (file)
@@ -4,27 +4,26 @@
 #define USE_DVICHIP
 
 /* Hot Plug detection mode structure */
-typedef enum _sii164_hot_plug_mode_t
-{
-    SII164_HOTPLUG_DISABLE = 0,         /* Disable Hot Plug output bit (always high). */
-    SII164_HOTPLUG_USE_MDI,             /* Use Monitor Detect Interrupt bit. */
-    SII164_HOTPLUG_USE_RSEN,            /* Use Receiver Sense detect bit. */
-    SII164_HOTPLUG_USE_HTPLG            /* Use Hot Plug detect bit. */
+typedef enum _sii164_hot_plug_mode_t {
+       SII164_HOTPLUG_DISABLE = 0,         /* Disable Hot Plug output bit (always high). */
+       SII164_HOTPLUG_USE_MDI,             /* Use Monitor Detect Interrupt bit. */
+       SII164_HOTPLUG_USE_RSEN,            /* Use Receiver Sense detect bit. */
+       SII164_HOTPLUG_USE_HTPLG            /* Use Hot Plug detect bit. */
 } sii164_hot_plug_mode_t;
 
 
 /* Silicon Image SiI164 chip prototype */
 long sii164InitChip(
-    unsigned char edgeSelect,
-    unsigned char busSelect,
-    unsigned char dualEdgeClkSelect,
-    unsigned char hsyncEnable,
-    unsigned char vsyncEnable,
-    unsigned char deskewEnable,
-    unsigned char deskewSetting,
-    unsigned char continuousSyncEnable,
-    unsigned char pllFilterEnable,
-    unsigned char pllFilterValue
+       unsigned char edgeSelect,
+       unsigned char busSelect,
+       unsigned char dualEdgeClkSelect,
+       unsigned char hsyncEnable,
+       unsigned char vsyncEnable,
+       unsigned char deskewEnable,
+       unsigned char deskewSetting,
+       unsigned char continuousSyncEnable,
+       unsigned char pllFilterEnable,
+       unsigned char pllFilterValue
 );
 
 unsigned short sii164GetVendorID(void);
index 8e201f19cc0d2b3862eba9ced37203e6598c27f7..07f8afd2defeb82da3b0f7fa502c2ffc661d666e 100644 (file)
@@ -24,8 +24,7 @@
 
 #include "modedb.h"
 
-int smi_indent = 0;
-
+int smi_indent;
 
 /*
  * #ifdef __BIG_ENDIAN
@@ -40,17 +39,15 @@ typedef void (*PROC_SPEC_SETUP)(struct lynx_share*, char *);
 typedef int (*PROC_SPEC_MAP)(struct lynx_share*, struct pci_dev*);
 typedef int (*PROC_SPEC_INITHW)(struct lynx_share*, struct pci_dev*);
 
-
 /* common var for all device */
 static int g_hwcursor = 1;
 static int g_noaccel;
 static int g_nomtrr;
 static const char *g_fbmode[] = {NULL, NULL};
 static const char *g_def_fbmode = "800x600-16@60";
-static char *g_settings = NULL;
+static char *g_settings;
 static int g_dualview;
-static char *g_option = NULL;
-
+static char *g_option;
 
 static const struct fb_videomode lynx750_ext[] = {
        /*      1024x600-60 VESA        [1.71:1] */
@@ -115,8 +112,6 @@ static const struct fb_videomode lynx750_ext[] = {
 };
 
 
-
-
 /* no hardware cursor supported under version 2.6.10, kernel bug */
 static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
 {
@@ -149,18 +144,17 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
                /* get the 16bit color of kernel means */
                u16 fg, bg;
 
-               fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800))|
-                     ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5)|
+               fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800)) |
+                     ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5) |
                      ((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11);
 
-               bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800))|
-                     ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5)|
+               bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800)) |
+                     ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5) |
                      ((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11);
 
                cursor->setColor(cursor, fg, bg);
        }
 
-
        if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
                cursor->setData(cursor,
                                fbcursor->rop,
@@ -188,14 +182,17 @@ static void lynxfb_ops_fillrect(struct fb_info *info,
        par = info->par;
        share = par->share;
 
-       /* each time 2d function begin to work,below three variable always need
-        * be set, seems we can put them together in some place  */
+       /*
+        * each time 2d function begin to work,below three variable always need
+        * be set, seems we can put them together in some place
+        */
        base = par->crtc.oScreen;
        pitch = info->fix.line_length;
        Bpp = info->var.bits_per_pixel >> 3;
 
-       color = (Bpp == 1)?region->color:((u32 *)info->pseudo_palette)[region->color];
-       rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR:HW_ROP2_COPY;
+       color = (Bpp == 1) ? region->color :
+               ((u32 *)info->pseudo_palette)[region->color];
+       rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR : HW_ROP2_COPY;
 
        /*
         * If not use spin_lock,system will die if user load driver
@@ -223,8 +220,10 @@ static void lynxfb_ops_copyarea(struct fb_info *info,
        par = info->par;
        share = par->share;
 
-       /* each time 2d function begin to work,below three variable always need
-        * be set, seems we can put them together in some place  */
+       /*
+        * each time 2d function begin to work,below three variable always need
+        * be set, seems we can put them together in some place
+        */
        base = par->crtc.oScreen;
        pitch = info->fix.line_length;
        Bpp = info->var.bits_per_pixel >> 3;
@@ -254,28 +253,29 @@ static void lynxfb_ops_imageblit(struct fb_info *info,
 
        par = info->par;
        share = par->share;
-       /* each time 2d function begin to work,below three variable always need
-        * be set, seems we can put them together in some place  */
+       /*
+        * each time 2d function begin to work,below three variable always need
+        * be set, seems we can put them together in some place
+        */
        base = par->crtc.oScreen;
        pitch = info->fix.line_length;
        Bpp = info->var.bits_per_pixel >> 3;
 
-       if (image->depth == 1) {
-               if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
-                   info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-                       fgcol = ((u32 *)info->pseudo_palette)[image->fg_color];
-                       bgcol = ((u32 *)info->pseudo_palette)[image->bg_color];
-               } else {
-                       fgcol = image->fg_color;
-                       bgcol = image->bg_color;
-               }
-               goto _do_work;
-       }
        /* TODO: Implement hardware acceleration for image->depth > 1 */
-       cfb_imageblit(info, image);
-       return;
+       if (image->depth != 1) {
+               cfb_imageblit(info, image);
+               return;
+       }
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+               fgcol = ((u32 *)info->pseudo_palette)[image->fg_color];
+               bgcol = ((u32 *)info->pseudo_palette)[image->bg_color];
+       } else {
+               fgcol = image->fg_color;
+               bgcol = image->bg_color;
+       }
 
-_do_work:
        /*
         * If not use spin_lock, system will die if user load driver
         * and immediately unload driver frequently (dual)
@@ -284,7 +284,7 @@ _do_work:
                spin_lock(&share->slock);
 
        share->accel.de_imageblit(&share->accel,
-                                 image->data, image->width>>3, 0,
+                                 image->data, image->width >> 3, 0,
                                  base, pitch, Bpp,
                                  image->dx, image->dy,
                                  image->width, image->height,
@@ -298,18 +298,13 @@ static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var,
 {
        struct lynxfb_par *par;
        struct lynxfb_crtc *crtc;
-       int ret;
-
 
        if (!info)
                return -EINVAL;
 
-       ret = 0;
        par = info->par;
        crtc = &par->crtc;
-       ret = crtc->proc_panDisplay(crtc, var, info);
-
-       return ret;
+       return crtc->proc_panDisplay(crtc, var, info);
 }
 
 static int lynxfb_ops_set_par(struct fb_info *info)
@@ -340,9 +335,10 @@ static int lynxfb_ops_set_par(struct fb_info *info)
        fix->line_length = line_length;
        pr_info("fix->line_length = %d\n", fix->line_length);
 
-       /* var->red,green,blue,transp are need to be set by driver
+       /*
+        * var->red,green,blue,transp are need to be set by driver
         * and these data should be set before setcolreg routine
-        * */
+        */
 
        switch (var->bits_per_pixel) {
        case 8:
@@ -466,7 +462,6 @@ static int lynxfb_resume(struct pci_dev *pdev)
 
        int ret;
 
-
        ret = 0;
        share = pci_get_drvdata(pdev);
 
@@ -478,7 +473,6 @@ static int lynxfb_resume(struct pci_dev *pdev)
                return ret;
        }
 
-
        if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) {
                pci_restore_state(pdev);
                ret = pci_enable_device(pdev);
@@ -493,7 +487,6 @@ static int lynxfb_resume(struct pci_dev *pdev)
 
        hw_sm750_inithw(share, pdev);
 
-
        info = share->fbinfo[0];
 
        if (info) {
@@ -518,7 +511,6 @@ static int lynxfb_resume(struct pci_dev *pdev)
                fb_set_suspend(info, 0);
        }
 
-
        console_unlock();
        return ret;
 }
@@ -534,7 +526,6 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
        int ret;
        resource_size_t request;
 
-
        par = info->par;
        crtc = &par->crtc;
        output = &par->output;
@@ -546,7 +537,6 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var,
                 var->yres,
                 var->bits_per_pixel);
 
-
        switch (var->bits_per_pixel) {
        case 8:
        case 16:
@@ -617,7 +607,6 @@ exit:
        return ret;
 }
 
-
 static int lynxfb_ops_setcolreg(unsigned regno,
                                unsigned red,
                                unsigned green,
@@ -652,7 +641,6 @@ static int lynxfb_ops_setcolreg(unsigned regno,
                goto exit;
        }
 
-
        if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 256) {
                u32 val;
 
@@ -699,7 +687,8 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
        output = &par->output;
        crtc = &par->crtc;
 
-       crtc->vidmem_size = (share->dual)?share->vidmem_size>>1:share->vidmem_size;
+       crtc->vidmem_size = (share->dual) ? share->vidmem_size >> 1 :
+                            share->vidmem_size;
        /* setup crtc and output member */
        spec_share->hwCursor = g_hwcursor;
 
@@ -716,10 +705,12 @@ static int sm750fb_set_drv(struct lynxfb_par *par)
        output->proc_setMode = hw_sm750_output_setMode;
        output->proc_checkMode = hw_sm750_output_checkMode;
 
-       output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID)?hw_sm750le_setBLANK:hw_sm750_setBLANK;
+       output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID) ?
+                                hw_sm750le_setBLANK : hw_sm750_setBLANK;
        output->clear = hw_sm750_output_clear;
        /* chip specific phase */
-       share->accel.de_wait = (share->revid == SM750LE_REVISION_ID)?hw_sm750le_deWait : hw_sm750_deWait;
+       share->accel.de_wait = (share->revid == SM750LE_REVISION_ID) ?
+                               hw_sm750le_deWait : hw_sm750_deWait;
        switch (spec_share->state.dataflow) {
        case sm750_simul_pri:
                output->paths = sm750_pnc;
@@ -782,7 +773,6 @@ static struct fb_ops lynxfb_ops = {
        .fb_cursor = lynxfb_ops_cursor,
 };
 
-
 static int lynxfb_set_fbinfo(struct fb_info *info, int index)
 {
        int i;
@@ -803,7 +793,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
                "kernel HELPERS prepared vesa_modes",
        };
 
-
        static const char *fixId[2] = {
                "sm750_fb1", "sm750_fb2",
        };
@@ -824,15 +813,16 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
        sm750fb_set_drv(par);
        lynxfb_ops.fb_pan_display = lynxfb_ops_pan_display;
 
-
-       /* set current cursor variable and proc pointer,
-        * must be set after crtc member initialized */
+       /*
+        * set current cursor variable and proc pointer,
+        * must be set after crtc member initialized
+        */
        crtc->cursor.offset = crtc->oScreen + crtc->vidmem_size - 1024;
        crtc->cursor.mmio = share->pvReg + 0x800f0 + (int)crtc->channel * 0x140;
 
        pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
        crtc->cursor.maxH = crtc->cursor.maxW = 64;
-       crtc->cursor.size = crtc->cursor.maxH*crtc->cursor.maxW*2/8;
+       crtc->cursor.size = crtc->cursor.maxH * crtc->cursor.maxW * 2 / 8;
        crtc->cursor.disable = hw_cursor_disable;
        crtc->cursor.enable = hw_cursor_enable;
        crtc->cursor.setColor = hw_cursor_setColor;
@@ -841,7 +831,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
        crtc->cursor.setData = hw_cursor_setData;
        crtc->cursor.vstart = share->pvMem + crtc->cursor.offset;
 
-
        crtc->cursor.share = share;
                memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
        if (!g_hwcursor) {
@@ -849,7 +838,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
                crtc->cursor.disable(&crtc->cursor);
        }
 
-
        /* set info->fbops, must be set before fb_find_mode */
        if (!share->accel_off) {
                /* use 2d acceleration */
@@ -865,7 +853,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
                        g_fbmode[index] = g_fbmode[0];
        }
 
-
        for (i = 0; i < 3; i++) {
 
                ret = fb_find_mode(var, info, g_fbmode[index],
@@ -917,13 +904,13 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
 
        /* set info */
        line_length = PADDING(crtc->line_pad,
-                             (var->xres_virtual * var->bits_per_pixel/8));
+                             (var->xres_virtual * var->bits_per_pixel / 8));
 
        info->pseudo_palette = &par->pseudo_palette[0];
        info->screen_base = crtc->vScreen;
        pr_debug("screen_base vaddr = %p\n", info->screen_base);
        info->screen_size = line_length * var->yres_virtual;
-       info->flags = FBINFO_FLAG_DEFAULT|0;
+       info->flags = FBINFO_FLAG_DEFAULT | 0;
 
        /* set info->fix */
        fix->type = FB_TYPE_PACKED_PIXELS;
@@ -935,15 +922,15 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
 
        strlcpy(fix->id, fixId[index], sizeof(fix->id));
 
-
        fix->smem_start = crtc->oScreen + share->vidmem_start;
        pr_info("fix->smem_start = %lx\n", fix->smem_start);
-       /* according to mmap experiment from user space application,
+       /*
+        * according to mmap experiment from user space application,
         * fix->mmio_len should not larger than virtual size
         * (xres_virtual x yres_virtual x ByPP)
         * Below line maybe buggy when user mmap fb dev node and write
         * data into the bound over virtual size
-        * */
+        */
        fix->smem_len = crtc->vidmem_size;
        pr_info("fix->smem_len = %x\n", fix->smem_len);
        info->screen_size = fix->smem_len;
@@ -967,7 +954,7 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index)
        var->accel_flags = 0;
        var->vmode = FB_VMODE_NONINTERLACED;
 
-       pr_debug("#1 show info->cmap : \nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
+       pr_debug("#1 show info->cmap :\nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
                 info->cmap.start, info->cmap.len,
                 info->cmap.red, info->cmap.green, info->cmap.blue,
                 info->cmap.transp);
@@ -998,7 +985,6 @@ static void sm750fb_setup(struct lynx_share *share, char *src)
 #endif
        int swap;
 
-
        spec_share = container_of(share, struct sm750_share, share);
 #ifdef CAP_EXPENSIION
        exp_res = NULL;
@@ -1096,15 +1082,16 @@ static int lynxfb_pci_probe(struct pci_dev *pdev,
        size_t spec_offset = 0;
        int fbidx;
 
-
        /* enable device */
        if (pci_enable_device(pdev)) {
                pr_err("can not enable device.\n");
                goto err_enable;
        }
 
-       /* though offset of share in sm750_share is 0,
-        * we use this marcro as the same */
+       /*
+        * though offset of share in sm750_share is 0,
+        * we use this marcro as the same
+        */
        spec_offset = offsetof(struct sm750_share, share);
 
        spec_share = kzalloc(sizeof(*spec_share), GFP_KERNEL);
@@ -1128,10 +1115,12 @@ static int lynxfb_pci_probe(struct pci_dev *pdev,
        spin_lock_init(&share->slock);
 
        if (!share->accel_off) {
-               /* hook deInit and 2d routines, notes that below hw_xxx
+               /*
+                * hook deInit and 2d routines, notes that below hw_xxx
                 * routine can work on most of lynx chips
                 * if some chip need specific function,
-                * please hook it in smXXX_set_drv routine */
+                * please hook it in smXXX_set_drv routine
+                */
                share->accel.de_init = hw_de_init;
                share->accel.de_fillrect = hw_fillrect;
                share->accel.de_copyarea = hw_copyarea;
@@ -1268,7 +1257,6 @@ static int __init lynxfb_setup(char *options)
        int len;
        char *opt, *tmp;
 
-
        if (!options || !*options) {
                pr_warn("no options.\n");
                return 0;
@@ -1283,14 +1271,15 @@ static int __init lynxfb_setup(char *options)
 
        tmp = g_settings;
 
-       /*      Notes:
-               char * strsep(char **s,const char * ct);
-               @s: the string to be searched
-               @ct :the characters to search for
-
-               strsep() updates @options to pointer after the first found token
-               it also returns the pointer ahead the token.
-               */
+       /*
+        * Notes:
+        * char * strsep(char **s,const char * ct);
+        * @s: the string to be searched
+        * @ct :the characters to search for
+        *
+        * strsep() updates @options to pointer after the first found token
+        * it also returns the pointer ahead the token.
+        */
        while ((opt = strsep(&options, ":")) != NULL) {
                /* options that mean for any lynx chips are configured here */
                if (!strncmp(opt, "noaccel", strlen("noaccel")))
@@ -1332,7 +1321,6 @@ static struct pci_driver lynxfb_driver = {
 #endif
 };
 
-
 static int __init lynxfb_init(void)
 {
        char *option;
index cc80580bc8233d8dbb98e196bc3cb1e1cfcf4131..5bc445571b48fe62c5933370daded21430d05934 100644 (file)
@@ -5,20 +5,20 @@
 
 #define FB_ACCEL_SMI 0xab
 /* please use revision id to distinguish sm750le and sm750*/
-#define SPC_SM750      0
+#define SPC_SM750 0
 
 #define MB(x) ((x)<<20)
 #define MHZ(x) ((x) * 1000000)
 /* align should be 2,4,8,16 */
-#define PADDING(align, data) (((data)+(align)-1)&(~((align) -1)))
+#define PADDING(align, data) (((data)+(align)-1)&(~((align) - 1)))
 extern int smi_indent;
 
 
-struct lynx_accel{
+struct lynx_accel {
        /* base virtual address of DPR registers */
-       volatile unsigned char __iomem * dprBase;
+       volatile unsigned char __iomem *dprBase;
        /* base virtual address of de data port */
-       volatile unsigned char __iomem * dpPortBase;
+       volatile unsigned char __iomem *dpPortBase;
 
        /* function fointers */
        void (*de_init)(struct lynx_accel *);
@@ -38,10 +38,10 @@ struct lynx_accel{
 
 };
 
-/*     lynx_share stands for a presentation of two frame buffer
-       that use one smi adaptor , it is similar to a basic class of C++
+/* lynx_share stands for a presentation of two frame buffer
+   that use one smi adaptor , it is similar to a basic class of C++
 */
-struct lynx_share{
+struct lynx_share {
        /* common members */
        u16 devid;
        u8 revid;
@@ -53,7 +53,7 @@ struct lynx_share{
                int mtrr_off;
                struct{
                        int vram;
-               }mtrr;
+               } mtrr;
        /* all smi graphic adaptor got below attributes */
        unsigned long vidmem_start;
        unsigned long vidreg_start;
@@ -64,11 +64,11 @@ struct lynx_share{
        /* locks*/
        spinlock_t slock;
        /* function pointers */
-       void (*suspend)(struct lynx_share*);
-       void (*resume)(struct lynx_share*);
+       void (*suspend)(struct lynx_share *);
+       void (*resume)(struct lynx_share *);
 };
 
-struct lynx_cursor{
+struct lynx_cursor {
        /* cursor width ,height and size */
        int w;
        int h;
@@ -80,7 +80,7 @@ struct lynx_cursor{
        char __iomem *vstart;
        int offset;
        /* mmio addr of hw cursor */
-       volatile char __iomem * mmio;
+       volatile char __iomem *mmio;
        /* the lynx_share of this adaptor */
        struct lynx_share *share;
        /* proc_routines */
@@ -92,7 +92,7 @@ struct lynx_cursor{
        void (*setData)(struct lynx_cursor *, u16, const u8*, const u8*);
 };
 
-struct lynxfb_crtc{
+struct lynxfb_crtc {
        unsigned char __iomem *vCursor; /* virtual address of cursor */
        unsigned char __iomem *vScreen; /* virtual address of on_screen */
        int oCursor; /* cursor address offset in vidmem */
@@ -108,14 +108,14 @@ struct lynxfb_crtc{
 
        void *priv;
 
-       int(*proc_setMode)(struct lynxfb_crtc*,
+       int (*proc_setMode)(struct lynxfb_crtc*,
                                                struct fb_var_screeninfo*,
                                                struct fb_fix_screeninfo*);
 
-       int(*proc_checkMode)(struct lynxfb_crtc*, struct fb_var_screeninfo*);
-       int(*proc_setColReg)(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
-       void (*clear)(struct lynxfb_crtc*);
-        /* pan display */
+       int (*proc_checkMode)(struct lynxfb_crtc*, struct fb_var_screeninfo*);
+       int (*proc_setColReg)(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
+       void (*clear)(struct lynxfb_crtc *);
+       /* pan display */
        int (*proc_panDisplay)(struct lynxfb_crtc *,
                               const struct fb_var_screeninfo *,
                               const struct fb_info *);
@@ -123,33 +123,33 @@ struct lynxfb_crtc{
        struct lynx_cursor cursor;
 };
 
-struct lynxfb_output{
+struct lynxfb_output {
        int dpms;
        int paths;
-       /*      which paths(s) this output stands for,for sm750:
-               paths=1:means output for panel paths
-               paths=2:means output for crt paths
-               paths=3:means output for both panel and crt paths
+       /* which paths(s) this output stands for,for sm750:
+          paths=1:means output for panel paths
+          paths=2:means output for crt paths
+          paths=3:means output for both panel and crt paths
        */
 
        int *channel;
-       /*      which channel these outputs linked with,for sm750:
-               *channel=0 means primary channel
-               *channel=1 means secondary channel
-               output->channel ==> &crtc->channel
+       /* which channel these outputs linked with,for sm750:
+          *channel=0 means primary channel
+          *channel=1 means secondary channel
+          output->channel ==> &crtc->channel
        */
        void *priv;
 
-       int(*proc_setMode)(struct lynxfb_output*,
+       int (*proc_setMode)(struct lynxfb_output*,
                                                struct fb_var_screeninfo*,
                                                struct fb_fix_screeninfo*);
 
-       int(*proc_checkMode)(struct lynxfb_output*, struct fb_var_screeninfo*);
-       int(*proc_setBLANK)(struct lynxfb_output*, int);
-       void  (*clear)(struct lynxfb_output*);
+       int (*proc_checkMode)(struct lynxfb_output*, struct fb_var_screeninfo*);
+       int (*proc_setBLANK)(struct lynxfb_output*, int);
+       void  (*clear)(struct lynxfb_output *);
 };
 
-struct lynxfb_par{
+struct lynxfb_par {
        /* either 0 or 1 for dual head adaptor,0 is the older one registered */
        int index;
        unsigned int pseudo_palette[256];
@@ -165,14 +165,14 @@ struct lynxfb_par{
 
 
 #define PS_TO_HZ(ps)   \
-                       ({      \
+                       ({ \
                        unsigned long long hz = 1000*1000*1000*1000ULL; \
                        do_div(hz, ps); \
-                       (unsigned long)hz;})
+                       (unsigned long)hz; })
 
 static inline unsigned long ps_to_hz(unsigned int psvalue)
 {
-       unsigned long long numerator=1000*1000*1000*1000ULL;
+       unsigned long long numerator = 1000*1000*1000*1000ULL;
        /* 10^12 / picosecond period gives frequency in Hz */
        do_div(numerator, psvalue);
        return (unsigned long)numerator;
index 6eee4cd582d1ba2e2c1cbdcb66e157600edc5835..1dd06a2e4edeb1a826278fd7df103a8a4bfe7c4d 100644 (file)
@@ -37,7 +37,7 @@ void hw_de_init(struct lynx_accel *accel)
 {
        /* setup 2d engine registers */
        u32 reg, clr;
-       
+
        write_dpr(accel, DE_MASKS, 0xFFFFFFFF);
 
        /* dpr1c */
@@ -82,7 +82,7 @@ void hw_de_init(struct lynx_accel *accel)
 void hw_set2dformat(struct lynx_accel *accel, int fmt)
 {
        u32 reg;
-       
+
        /* fmt=0,1,2 for 8,16,32,bpp on sm718/750/502 */
        reg = read_dpr(accel, DE_STRETCH_FORMAT);
        reg = FIELD_VALUE(reg, DE_STRETCH_FORMAT, PIXEL_FORMAT, fmt);
@@ -96,11 +96,10 @@ int hw_fillrect(struct lynx_accel *accel,
 {
        u32 deCtrl;
 
-       if(accel->de_wait() != 0)
-       {
+       if (accel->de_wait() != 0) {
                /* int time wait and always busy,seems hardware
                 * got something error */
-               pr_debug("%s:De engine always bussy\n", __func__);
+               pr_debug("De engine always busy\n");
                return -1;
        }
 
@@ -151,112 +150,102 @@ unsigned int width,
 unsigned int height, /* width and height of rectangle in pixel value */
 unsigned int rop2)   /* ROP value */
 {
-    unsigned int nDirection, de_ctrl;
-    int opSign;
-    nDirection = LEFT_TO_RIGHT;
+       unsigned int nDirection, de_ctrl;
+       int opSign;
+
+       nDirection = LEFT_TO_RIGHT;
        /* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
-    opSign = 1;
-    de_ctrl = 0;
-
-    /* If source and destination are the same surface, need to check for overlay cases */
-    if (sBase == dBase && sPitch == dPitch)
-    {
-        /* Determine direction of operation */
-        if (sy < dy)
-        {
-            /* +----------+
-               |S         |
-               |   +----------+
-               |   |      |   |
-               |   |      |   |
-               +---|------+   |
-                   |         D|
-                   +----------+ */
-
-            nDirection = BOTTOM_TO_TOP;
-        }
-        else if (sy > dy)
-        {
-            /* +----------+
-               |D         |
-               |   +----------+
-               |   |      |   |
-               |   |      |   |
-               +---|------+   |
-                   |         S|
-                   +----------+ */
-
-            nDirection = TOP_TO_BOTTOM;
-        }
-        else
-        {
-            /* sy == dy */
-
-            if (sx <= dx)
-            {
-                /* +------+---+------+
-                   |S     |   |     D|
-                   |      |   |      |
-                   |      |   |      |
-                   |      |   |      |
-                   +------+---+------+ */
-
-                nDirection = RIGHT_TO_LEFT;
-            }
-            else
-            {
-                /* sx > dx */
-
-                /* +------+---+------+
-                   |D     |   |     S|
-                   |      |   |      |
-                   |      |   |      |
-                   |      |   |      |
-                   +------+---+------+ */
-
-                nDirection = LEFT_TO_RIGHT;
-            }
-        }
-    }
-
-    if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT))
-    {
-        sx += width - 1;
-        sy += height - 1;
-        dx += width - 1;
-        dy += height - 1;
-        opSign = (-1);
-    }
-
-    /* Note:
-       DE_FOREGROUND are DE_BACKGROUND are don't care.
-       DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
-    */
+       opSign = 1;
+       de_ctrl = 0;
+
+       /* If source and destination are the same surface, need to check for overlay cases */
+       if (sBase == dBase && sPitch == dPitch) {
+               /* Determine direction of operation */
+               if (sy < dy) {
+                       /* +----------+
+                          |S         |
+                          |   +----------+
+                          |   |      |   |
+                          |   |      |   |
+                          +---|------+   |
+                          |         D|
+                          +----------+ */
+
+                       nDirection = BOTTOM_TO_TOP;
+               } else if (sy > dy) {
+                       /* +----------+
+                          |D         |
+                          |   +----------+
+                          |   |      |   |
+                          |   |      |   |
+                          +---|------+   |
+                          |         S|
+                          +----------+ */
+
+                       nDirection = TOP_TO_BOTTOM;
+               } else {
+                       /* sy == dy */
+
+                       if (sx <= dx) {
+                               /* +------+---+------+
+                                  |S     |   |     D|
+                                  |      |   |      |
+                                  |      |   |      |
+                                  |      |   |      |
+                                  +------+---+------+ */
+
+                               nDirection = RIGHT_TO_LEFT;
+                       } else {
+                       /* sx > dx */
+
+                               /* +------+---+------+
+                                  |D     |   |     S|
+                                  |      |   |      |
+                                  |      |   |      |
+                                  |      |   |      |
+                                  +------+---+------+ */
+
+                               nDirection = LEFT_TO_RIGHT;
+                       }
+               }
+       }
 
-    /* 2D Source Base.
-       It is an address offset (128 bit aligned) from the beginning of frame buffer.
-    */
-    write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
+       if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
+               sx += width - 1;
+               sy += height - 1;
+               dx += width - 1;
+               dy += height - 1;
+               opSign = (-1);
+       }
 
-    /* 2D Destination Base.
-       It is an address offset (128 bit aligned) from the beginning of frame buffer.
-    */
-    write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
+       /* Note:
+          DE_FOREGROUND are DE_BACKGROUND are don't care.
+         DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
+        */
+
+       /* 2D Source Base.
+        It is an address offset (128 bit aligned) from the beginning of frame buffer.
+        */
+       write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
+
+       /* 2D Destination Base.
+        It is an address offset (128 bit aligned) from the beginning of frame buffer.
+        */
+       write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
 
 #if 0
     /* Program pitch (distance between the 1st points of two adjacent lines).
        Note that input pitch is BYTE value, but the 2D Pitch register uses
        pixel values. Need Byte to pixel conversion.
     */
-       if(Bpp == 3){
+       if (Bpp == 3) {
                        sx *= 3;
                        dx *= 3;
                        width *= 3;
                write_dpr(accel, DE_PITCH,
                                FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
                                FIELD_VALUE(0, DE_PITCH, SOURCE,      sPitch)); /* dpr10 */
-       }
-       else
+       } else
 #endif
        {
                write_dpr(accel, DE_PITCH,
@@ -267,54 +256,53 @@ unsigned int rop2)   /* ROP value */
     /* Screen Window width in Pixels.
        2D engine uses this value to calculate the linear address in frame buffer for a given point.
     */
-    write_dpr(accel, DE_WINDOW_WIDTH,
-        FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
-        FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (sPitch/Bpp))); /* dpr3c */
+       write_dpr(accel, DE_WINDOW_WIDTH,
+       FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
+       FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (sPitch/Bpp))); /* dpr3c */
 
-       if (accel->de_wait() != 0){
+       if (accel->de_wait() != 0)
                return -1;
+
+       {
+
+       write_dpr(accel, DE_SOURCE,
+                 FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+                 FIELD_VALUE(0, DE_SOURCE, X_K1, sx)   |
+                 FIELD_VALUE(0, DE_SOURCE, Y_K2, sy)); /* dpr0 */
+       write_dpr(accel, DE_DESTINATION,
+                 FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                 FIELD_VALUE(0, DE_DESTINATION, X,    dx)  |
+                 FIELD_VALUE(0, DE_DESTINATION, Y,    dy)); /* dpr04 */
+       write_dpr(accel, DE_DIMENSION,
+                 FIELD_VALUE(0, DE_DIMENSION, X,    width) |
+                 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
+
+       de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
+                 FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+                 FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
+                 ((nDirection == RIGHT_TO_LEFT) ?
+                 FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT)
+                 : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) |
+                 FIELD_SET(0, DE_CONTROL, STATUS, START);
+       write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
+
        }
 
-    {
-
-        write_dpr(accel, DE_SOURCE,
-            FIELD_SET  (0, DE_SOURCE, WRAP, DISABLE) |
-            FIELD_VALUE(0, DE_SOURCE, X_K1, sx)   |
-            FIELD_VALUE(0, DE_SOURCE, Y_K2, sy)); /* dpr0 */
-        write_dpr(accel, DE_DESTINATION,
-            FIELD_SET  (0, DE_DESTINATION, WRAP, DISABLE) |
-            FIELD_VALUE(0, DE_DESTINATION, X,    dx)  |
-            FIELD_VALUE(0, DE_DESTINATION, Y,    dy)); /* dpr04 */
-        write_dpr(accel, DE_DIMENSION,
-            FIELD_VALUE(0, DE_DIMENSION, X,    width) |
-            FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
-
-        de_ctrl =
-            FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
-            FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
-            FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
-            ((nDirection == RIGHT_TO_LEFT) ?
-            FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT)
-            : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) |
-            FIELD_SET(0, DE_CONTROL, STATUS, START);
-               write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
-    }
-
-    return 0;
+       return 0;
 }
 
 static unsigned int deGetTransparency(struct lynx_accel *accel)
 {
-    unsigned int de_ctrl;
+       unsigned int de_ctrl;
 
-    de_ctrl = read_dpr(accel, DE_CONTROL);
+       de_ctrl = read_dpr(accel, DE_CONTROL);
 
-    de_ctrl &=
-        FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
-        FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
-        FIELD_MASK(DE_CONTROL_TRANSPARENCY);
+       de_ctrl &=
+                  FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
+                  FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
+                  FIELD_MASK(DE_CONTROL_TRANSPARENCY);
 
-    return de_ctrl;
+       return de_ctrl;
 }
 
 int hw_imageblit(struct lynx_accel *accel,
@@ -332,38 +320,36 @@ int hw_imageblit(struct lynx_accel *accel,
                 u32 bColor,   /* Background color (corresponding to a 0 in the monochrome data */
                 u32 rop2)     /* ROP value */
 {
-    unsigned int ulBytesPerScan;
-    unsigned int ul4BytesPerScan;
-    unsigned int ulBytesRemain;
-    unsigned int de_ctrl = 0;
-    unsigned char ajRemain[4];
-    int i, j;
-
-    startBit &= 7; /* Just make sure the start bit is within legal range */
-    ulBytesPerScan = (width + startBit + 7) / 8;
-    ul4BytesPerScan = ulBytesPerScan & ~3;
-    ulBytesRemain = ulBytesPerScan & 3;
-
-       if(accel->de_wait() != 0)
-    {
-        return -1;
-    }
-
-    /* 2D Source Base.
-       Use 0 for HOST Blt.
-    */
-    write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
+       unsigned int ulBytesPerScan;
+       unsigned int ul4BytesPerScan;
+       unsigned int ulBytesRemain;
+       unsigned int de_ctrl = 0;
+       unsigned char ajRemain[4];
+       int i, j;
+
+       startBit &= 7; /* Just make sure the start bit is within legal range */
+       ulBytesPerScan = (width + startBit + 7) / 8;
+       ul4BytesPerScan = ulBytesPerScan & ~3;
+       ulBytesRemain = ulBytesPerScan & 3;
+
+       if (accel->de_wait() != 0)
+               return -1;
 
-    /* 2D Destination Base.
-       It is an address offset (128 bit aligned) from the beginning of frame buffer.
-    */
-    write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
+       /* 2D Source Base.
+        Use 0 for HOST Blt.
+        */
+       write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
+
+       /* 2D Destination Base.
+        It is an address offset (128 bit aligned) from the beginning of frame buffer.
+        */
+       write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
 #if 0
     /* Program pitch (distance between the 1st points of two adjacent lines).
        Note that input pitch is BYTE value, but the 2D Pitch register uses
        pixel values. Need Byte to pixel conversion.
     */
-       if(bytePerPixel == 3 ){
+       if (bytePerPixel == 3) {
                dx *= 3;
                width *= 3;
                startBit *= 3;
@@ -371,8 +357,7 @@ int hw_imageblit(struct lynx_accel *accel,
                                FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
                                FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch)); /* dpr10 */
 
-       }
-       else
+       } else
 #endif
        {
                write_dpr(accel, DE_PITCH,
@@ -380,30 +365,30 @@ int hw_imageblit(struct lynx_accel *accel,
                                FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch/bytePerPixel)); /* dpr10 */
        }
 
-    /* Screen Window width in Pixels.
-       2D engine uses this value to calculate the linear address in frame buffer for a given point.
-    */
-    write_dpr(accel, DE_WINDOW_WIDTH,
-        FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
-        FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (dPitch/bytePerPixel)));
+       /* Screen Window width in Pixels.
+        2D engine uses this value to calculate the linear address in frame buffer for a given point.
+        */
+       write_dpr(accel, DE_WINDOW_WIDTH,
+                 FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
+                 FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (dPitch/bytePerPixel)));
 
-    /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
-             For mono bitmap, use startBit for X_K1. */
-    write_dpr(accel, DE_SOURCE,
-        FIELD_SET  (0, DE_SOURCE, WRAP, DISABLE)       |
-        FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit)); /* dpr00 */
+        /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
+           For mono bitmap, use startBit for X_K1. */
+       write_dpr(accel, DE_SOURCE,
+                 FIELD_SET(0, DE_SOURCE, WRAP, DISABLE)       |
+                 FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit)); /* dpr00 */
 
-    write_dpr(accel, DE_DESTINATION,
-        FIELD_SET  (0, DE_DESTINATION, WRAP, DISABLE) |
-        FIELD_VALUE(0, DE_DESTINATION, X,    dx)    |
-        FIELD_VALUE(0, DE_DESTINATION, Y,    dy)); /* dpr04 */
+       write_dpr(accel, DE_DESTINATION,
+                 FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+                 FIELD_VALUE(0, DE_DESTINATION, X,    dx)    |
+                 FIELD_VALUE(0, DE_DESTINATION, Y,    dy)); /* dpr04 */
 
-    write_dpr(accel, DE_DIMENSION,
-        FIELD_VALUE(0, DE_DIMENSION, X,    width) |
-        FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
+       write_dpr(accel, DE_DIMENSION,
+                 FIELD_VALUE(0, DE_DIMENSION, X,    width) |
+                 FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
 
-    write_dpr(accel, DE_FOREGROUND, fColor);
-    write_dpr(accel, DE_BACKGROUND, bColor);
+       write_dpr(accel, DE_FOREGROUND, fColor);
+       write_dpr(accel, DE_BACKGROUND, bColor);
 
        de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2)         |
                FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2)    |
@@ -413,24 +398,20 @@ int hw_imageblit(struct lynx_accel *accel,
 
        write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
 
-    /* Write MONO data (line by line) to 2D Engine data port */
-    for (i=0; i<height; i++)
-    {
-        /* For each line, send the data in chunks of 4 bytes */
-        for (j=0; j<(ul4BytesPerScan/4); j++)
-        {
-            write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
-        }
-
-        if (ulBytesRemain)
-        {
-            memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
-            write_dpPort(accel, *(unsigned int *)ajRemain);
-        }
-
-        pSrcbuf += srcDelta;
-    }
-
-    return 0;
+       /* Write MONO data (line by line) to 2D Engine data port */
+       for (i = 0; i < height; i++) {
+               /* For each line, send the data in chunks of 4 bytes */
+               for (j = 0; j < (ul4BytesPerScan/4); j++)
+                       write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
+
+               if (ulBytesRemain) {
+                       memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
+                       write_dpPort(accel, *(unsigned int *)ajRemain);
+               }
+
+               pSrcbuf += srcDelta;
+       }
+
+           return 0;
 }
 
index d3d256c21206b85b65d17401e9cac0d1e49973bc..f252e47d5ee9f9f713ae4c6abf09ecda03372c7a 100644 (file)
@@ -7,7 +7,7 @@
 /* notes: below address are the offset value from de_base_address (0x100000)*/
 
 /* for sm718/750/502 de_base is at mmreg_1mb*/
-#define DE_BASE_ADDR_TYPE1     0x100000
+#define DE_BASE_ADDR_TYPE1 0x100000
 /* for sm712,de_base is at mmreg_32kb */
 #define DE_BASE_ADDR_TYPE2  0x8000
 /* for sm722,de_base is at mmreg_0 */
@@ -26,7 +26,7 @@
 #define DE_SOURCE_WRAP_ENABLE                           1
 #define DE_SOURCE_X_K1                                  29:16
 #define DE_SOURCE_Y_K2                                  15:0
-#define DE_SOURCE_X_K1_MONO                                                    20:16
+#define DE_SOURCE_X_K1_MONO                            20:16
 
 #define DE_DESTINATION                                  0x4
 #define DE_DESTINATION_WRAP                             31:31
index 405e24b6768f8d709bbaec095a047ee1159a2bc9..a94a4bbff45096e24de516f3d5cc29f8bf49fe4d 100644 (file)
@@ -61,6 +61,7 @@ writel((data), cursor->mmio + (addr))
 void hw_cursor_enable(struct lynx_cursor *cursor)
 {
        u32 reg;
+
        reg = FIELD_VALUE(0, HWC_ADDRESS, ADDRESS, cursor->offset)|
                        FIELD_SET(0, HWC_ADDRESS, EXT, LOCAL)|
                        FIELD_SET(0, HWC_ADDRESS, ENABLE, ENABLE);
@@ -81,6 +82,7 @@ void hw_cursor_setPos(struct lynx_cursor *cursor,
                                                int x, int y)
 {
        u32 reg;
+
        reg = FIELD_VALUE(0, HWC_LOCATION, Y, y)|
                        FIELD_VALUE(0, HWC_LOCATION, X, x);
        POKE32(HWC_LOCATION, reg);
@@ -93,7 +95,7 @@ void hw_cursor_setColor(struct lynx_cursor *cursor,
 }
 
 void hw_cursor_setData(struct lynx_cursor *cursor,
-                       u16 rop, const u8* pcol, const u8* pmsk)
+                       u16 rop, const u8 *pcol, const u8 *pmsk)
 {
        int i, j, count, pitch, offset;
        u8 color, mask, opr;
@@ -122,8 +124,7 @@ void hw_cursor_setData(struct lynx_cursor *cursor,
                odd=0;
 */
 
-       for(i=0;i<count;i++)
-       {
+       for (i = 0; i < count; i++) {
                color = *pcol++;
                mask = *pmsk++;
                data = 0;
@@ -132,26 +133,25 @@ void hw_cursor_setData(struct lynx_cursor *cursor,
                 * but method 2 shows no lag
                 * and method 1 seems a bit wrong*/
 #if 0
-               if(rop == ROP_XOR)
+               if (rop == ROP_XOR)
                        opr = mask ^ color;
                else
                        opr = mask & color;
 
-               for(j=0;j<8;j++)
-               {
+               for (j = 0; j < 8; j++) {
 
-                       if(opr & (0x80 >> j))
-                       {       /* use fg color,id = 2 */
+                       if (opr & (0x80 >> j)) {
+                               /* use fg color,id = 2 */
                                data |= 2 << (j*2);
-                       }else{
+                       } else {
                                /* use bg color,id = 1 */
                                data |= 1 << (j*2);
                        }
                }
 #else
-               for(j=0;j<8;j++){
-                       if(mask & (0x80>>j)){
-                               if(rop == ROP_XOR)
+               for (j = 0; j < 8; j++) {
+                       if (mask & (0x80>>j)) {
+                               if (rop == ROP_XOR)
                                        opr = mask ^ color;
                                else
                                        opr = mask & color;
@@ -165,15 +165,15 @@ void hw_cursor_setData(struct lynx_cursor *cursor,
 
                /* assume pitch is 1,2,4,8,...*/
 #if 0
-               if(!((i+1)&(pitch-1)))   /* below line equal to is line */
+               if (!((i+1)&(pitch-1)))   /* below line equal to is line */
 #else
-               if((i+1) % pitch == 0)
+               if ((i+1) % pitch == 0)
 #endif
                {
                        /* need a return */
                        pstart += offset;
                        pbuffer = pstart;
-               }else{
+               } else {
                        pbuffer += sizeof(u16);
                }
 
@@ -184,7 +184,7 @@ void hw_cursor_setData(struct lynx_cursor *cursor,
 
 
 void hw_cursor_setData2(struct lynx_cursor *cursor,
-                       u16 rop, const u8* pcol, const u8* pmsk)
+                       u16 rop, const u8 *pcol, const u8 *pmsk)
 {
        int i, j, count, pitch, offset;
        u8 color, mask;
@@ -204,45 +204,42 @@ void hw_cursor_setData2(struct lynx_cursor *cursor,
        pstart = cursor->vstart;
        pbuffer = pstart;
 
-       for(i=0;i<count;i++)
-       {
+       for (i = 0; i < count; i++) {
                color = *pcol++;
                mask = *pmsk++;
                data = 0;
 
                /* either method below works well, but method 2 shows no lag */
 #if 0
-               if(rop == ROP_XOR)
+               if (rop == ROP_XOR)
                        opr = mask ^ color;
                else
                        opr = mask & color;
 
-               for(j=0;j<8;j++)
-               {
+               for (j = 0; j < 8; j++) {
 
-                       if(opr & (0x80 >> j))
-                       {       /* use fg color,id = 2 */
+                       if (opr & (0x80 >> j)) {
+                               /* use fg color,id = 2 */
                                data |= 2 << (j*2);
-                       }else{
+                       } else {
                                /* use bg color,id = 1 */
                                data |= 1 << (j*2);
                        }
                }
 #else
-               for(j=0;j<8;j++){
-                       if(mask & (1<<j))
+               for (j = 0; j < 8; j++) {
+                       if (mask & (1<<j))
                                data |= ((color & (1<<j))?1:2)<<(j*2);
                }
 #endif
                iowrite16(data, pbuffer);
 
                /* assume pitch is 1,2,4,8,...*/
-               if(!(i&(pitch-1)))
-               {
+               if (!(i&(pitch-1))) {
                        /* need a return */
                        pstart += offset;
                        pbuffer = pstart;
-               }else{
+               } else {
                        pbuffer += sizeof(u16);
                }
 
index e1716a600239662bb1a3119b8edcd4fbc824829f..6c4fc9b73489c2ba7892f7e30439c87fdb6fc2e4 100644 (file)
@@ -11,7 +11,7 @@ void hw_cursor_setPos(struct lynx_cursor *cursor,
 void hw_cursor_setColor(struct lynx_cursor *cursor,
                                                u32 fg, u32 bg);
 void hw_cursor_setData(struct lynx_cursor *cursor,
-                       u16 rop, const u8* data, const u8* mask);
+                       u16 rop, const u8 *data, const u8 *mask);
 void hw_cursor_setData2(struct lynx_cursor *cursor,
-                       u16 rop, const u8* data, const u8* mask);
+                       u16 rop, const u8 *data, const u8 *mask);
 #endif
index 05777f72c16627e9309a0a124e9b9f68db2a84a5..8dc6bd22f5db87e3a4349e1f67d56116b66d6311 100644 (file)
@@ -11,9 +11,9 @@
 #define GET_FIELD(d, f)     (((d) >> _LSB(f)) & RAW_MASK(f))
 #define TEST_FIELD(d, f, v) (GET_FIELD(d, f) == f ## _ ## v)
 #define SET_FIELD(d, f, v)  (((d) & ~GET_MASK(f)) | \
-                            (((f ## _ ## v) & RAW_MASK(f)) << _LSB(f)))
+                           (((f ## _ ## v) & RAW_MASK(f)) << _LSB(f)))
 #define SET_FIELDV(d, f, v) (((d) & ~GET_MASK(f)) | \
-                            (((v) & RAW_MASK(f)) << _LSB(f)))
+                           (((v) & RAW_MASK(f)) << _LSB(f)))
 
 /* Internal macros */
 #define _F_START(f)             (0 ? f)
 /* Global macros */
 #define FIELD_GET(x, reg, field) \
 ( \
-    _F_NORMALIZE((x), reg ## _ ## field) \
+       _F_NORMALIZE((x), reg ## _ ## field) \
 )
 
 #define FIELD_SET(x, reg, field, value) \
 ( \
-    (x & ~_F_MASK(reg ## _ ## field)) \
-    | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
+       (x & ~_F_MASK(reg ## _ ## field)) \
+       | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
 )
 
 #define FIELD_VALUE(x, reg, field, value) \
 ( \
-    (x & ~_F_MASK(reg ## _ ## field)) \
-    | _F_DENORMALIZE(value, reg ## _ ## field) \
+       (x & ~_F_MASK(reg ## _ ## field)) \
+       | _F_DENORMALIZE(value, reg ## _ ## field) \
 )
 
 #define FIELD_CLEAR(reg, field) \
 ( \
-    ~ _F_MASK(reg ## _ ## field) \
+       ~ _F_MASK(reg ## _ ## field) \
 )
 
 /* Field Macros */
 #define FIELD_DENORMALIZE(field, value) (((value) << FIELD_START(field)) & FIELD_MASK(field))
 
 #define FIELD_INIT(reg, field, value)   FIELD_DENORMALIZE(reg ## _ ## field, \
-                                                          reg ## _ ## field ## _ ## value)
+                                                         reg ## _ ## field ## _ ## value)
 #define FIELD_INIT_VAL(reg, field, value) \
-                                        (FIELD_DENORMALIZE(reg ## _ ## field, value))
+       (FIELD_DENORMALIZE(reg ## _ ## field, value))
 #define FIELD_VAL_SET(x, r, f, v)       x = x & ~FIELD_MASK(r ## _ ## f) \
-                                              | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v)
+                                       | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v)
 
 #define RGB(r, g, b) \
 ( \
-    (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \
+       (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \
 )
 
 #define RGB16(r, g, b) \
 ( \
-    (unsigned short) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3)) \
+       (unsigned short) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3)) \
 )
 
 static inline unsigned int absDiff(unsigned int a, unsigned int b)
 {
-       if(a<b)
+       if (a < b)
                return b-a;
        else
                return a-b;
index 84381bc414e79779be56fb4f97ff84c1ee6a3828..7317ba9b7fe5c1b289280c23a8cacd1586b9c8e6 100644 (file)
 #include "ddk750.h"
 #include "sm750_accel.h"
 
-int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev)
+int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev)
 {
        int ret;
        struct sm750_share *spec_share;
-       
+
 
        spec_share = container_of(share, struct sm750_share, share);
        ret = 0;
@@ -43,24 +43,23 @@ int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev)
         * in lynxfb_remove, or memory will not be mapped again
         * successfully
         * */
-
-       if((ret = pci_request_region(pdev, 1, "sm750fb")))
-       {
+       ret = pci_request_region(pdev, 1, "sm750fb");
+       if (ret) {
                pr_err("Can not request PCI regions.\n");
                goto exit;
        }
 
        /* now map mmio and vidmem*/
        share->pvReg = ioremap_nocache(share->vidreg_start, share->vidreg_size);
-       if(!share->pvReg){
+       if (!share->pvReg) {
                pr_err("mmio failed\n");
                ret = -EFAULT;
                goto exit;
-       }else{
+       } else {
                pr_info("mmio virtual addr = %p\n", share->pvReg);
        }
 
-       
+
        share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1;
        share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1;
 
@@ -78,8 +77,8 @@ int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev)
 
        /* reserve the vidmem space of smi adaptor */
 #if 0
-       if((ret = pci_request_region(pdev, 0, _moduleName_)))
-       {
+       ret = pci_request_region(pdev, 0, _moduleName_);
+       if (ret) {
                pr_err("Can not request PCI regions.\n");
                goto exit;
        }
@@ -87,11 +86,11 @@ int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev)
 
        share->pvMem = ioremap_wc(share->vidmem_start, share->vidmem_size);
 
-       if(!share->pvMem){
+       if (!share->pvMem) {
                pr_err("Map video memory failed\n");
                ret = -EFAULT;
                goto exit;
-       }else{
+       } else {
                pr_info("video memory vaddr = %p\n", share->pvMem);
        }
 exit:
@@ -104,22 +103,22 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
 {
        struct sm750_share *spec_share;
        struct init_status *parm;
-       
+
        spec_share = container_of(share, struct sm750_share, share);
        parm = &spec_share->state.initParm;
-       if(parm->chip_clk == 0)
-               parm->chip_clk = (getChipType() == SM750LE)?
+       if (parm->chip_clk == 0)
+               parm->chip_clk = (getChipType() == SM750LE) ?
                                                DEFAULT_SM750LE_CHIP_CLOCK :
                                                DEFAULT_SM750_CHIP_CLOCK;
 
-       if(parm->mem_clk == 0)
+       if (parm->mem_clk == 0)
                parm->mem_clk = parm->chip_clk;
-       if(parm->master_clk == 0)
+       if (parm->master_clk == 0)
                parm->master_clk = parm->chip_clk/3;
 
        ddk750_initHw((initchip_param_t *)&spec_share->state.initParm);
        /* for sm718,open pci burst */
-       if(share->devid == 0x718){
+       if (share->devid == 0x718) {
                POKE32(SYSTEM_CTRL,
                                FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
        }
@@ -130,10 +129,9 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
        ddk750_initDVIDisp();
 #endif
 
-       if(getChipType() != SM750LE)
-       {
+       if (getChipType() != SM750LE) {
                /* does user need CRT ?*/
-               if(spec_share->state.nocrt){
+               if (spec_share->state.nocrt) {
                        POKE32(MISC_CTRL,
                                        FIELD_SET(PEEK32(MISC_CTRL),
                                        MISC_CTRL,
@@ -143,7 +141,7 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
                                        FIELD_SET(PEEK32(SYSTEM_CTRL),
                                        SYSTEM_CTRL,
                                        DPMS, VNHN));
-               }else{
+               } else {
                        POKE32(MISC_CTRL,
                                        FIELD_SET(PEEK32(MISC_CTRL),
                                        MISC_CTRL,
@@ -155,45 +153,43 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
                                        DPMS, VPHP));
                }
 
-               switch (spec_share->state.pnltype){
-                       case sm750_doubleTFT:
-                       case sm750_24TFT:
-                       case sm750_dualTFT:
-                       POKE32(PANEL_DISPLAY_CTRL,
-                               FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
-                                                       PANEL_DISPLAY_CTRL,
-                                                       TFT_DISP,
-                                                       spec_share->state.pnltype));
-                       break;
+               switch (spec_share->state.pnltype) {
+               case sm750_doubleTFT:
+               case sm750_24TFT:
+               case sm750_dualTFT:
+               POKE32(PANEL_DISPLAY_CTRL,
+                       FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
+                                               PANEL_DISPLAY_CTRL,
+                                               TFT_DISP,
+                                               spec_share->state.pnltype));
+               break;
                }
-       }else{
+       } else {
                /* for 750LE ,no DVI chip initilization makes Monitor no signal */
                /* Set up GPIO for software I2C to program DVI chip in the
                   Xilinx SP605 board, in order to have video signal.
                 */
-        swI2CInit(0, 1);
+       swI2CInit(0, 1);
 
 
-        /* Customer may NOT use CH7301 DVI chip, which has to be
-           initialized differently.
-         */
-        if (swI2CReadReg(0xec, 0x4a) == 0x95)
-        {
-            /* The following register values for CH7301 are from
-               Chrontel app note and our experiment.
-             */
+       /* Customer may NOT use CH7301 DVI chip, which has to be
+          initialized differently.
+       */
+       if (swI2CReadReg(0xec, 0x4a) == 0x95) {
+               /* The following register values for CH7301 are from
+                  Chrontel app note and our experiment.
+               */
                        pr_info("yes,CH7301 DVI chip found\n");
-            swI2CWriteReg(0xec, 0x1d, 0x16);
-            swI2CWriteReg(0xec, 0x21, 0x9);
-            swI2CWriteReg(0xec, 0x49, 0xC0);
+               swI2CWriteReg(0xec, 0x1d, 0x16);
+               swI2CWriteReg(0xec, 0x21, 0x9);
+               swI2CWriteReg(0xec, 0x49, 0xC0);
                        pr_info("okay,CH7301 DVI chip setup done\n");
-        }
+       }
        }
 
        /* init 2d engine */
-       if(!share->accel_off){
+       if (!share->accel_off)
                hw_sm750_initAccel(share);
-       }
 
        return 0;
 }
@@ -202,86 +198,87 @@ int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
 resource_size_t hw_sm750_getVMSize(struct lynx_share *share)
 {
        resource_size_t ret;
-       
+
        ret = ddk750_getVMSize();
        return ret;
 }
 
 
 
-int hw_sm750_output_checkMode(struct lynxfb_output* output, struct fb_var_screeninfo* var)
+int hw_sm750_output_checkMode(struct lynxfb_output *output, struct fb_var_screeninfo *var)
 {
-       
+
        return 0;
 }
 
 
-int hw_sm750_output_setMode(struct lynxfb_outputoutput,
-                                                                       struct fb_var_screeninfo* var, struct fb_fix_screeninfo* fix)
+int hw_sm750_output_setMode(struct lynxfb_output *output,
+                                                                       struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
 {
        int ret;
        disp_output_t dispSet;
        int channel;
-       
+
        ret = 0;
        dispSet = 0;
        channel = *output->channel;
 
 
-       if(getChipType() != SM750LE){
-               if(channel == sm750_primary){
+       if (getChipType() != SM750LE) {
+               if (channel == sm750_primary) {
                        pr_info("primary channel\n");
-                       if(output->paths & sm750_panel)
+                       if (output->paths & sm750_panel)
                                dispSet |= do_LCD1_PRI;
-                       if(output->paths & sm750_crt)
+                       if (output->paths & sm750_crt)
                                dispSet |= do_CRT_PRI;
 
-               }else{
+               } else {
                        pr_info("secondary channel\n");
-                       if(output->paths & sm750_panel)
+                       if (output->paths & sm750_panel)
                                dispSet |= do_LCD1_SEC;
-                       if(output->paths & sm750_crt)
+                       if (output->paths & sm750_crt)
                                dispSet |= do_CRT_SEC;
 
                }
                ddk750_setLogicalDispOut(dispSet);
-       }else{
+       } else {
                /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
                u32 reg;
+
                reg = PEEK32(DISPLAY_CONTROL_750LE);
                reg |= 0xf;
                POKE32(DISPLAY_CONTROL_750LE, reg);
        }
 
-       pr_info("ddk setlogicdispout done \n");
+       pr_info("ddk setlogicdispout done\n");
        return ret;
 }
 
-void hw_sm750_output_clear(struct lynxfb_outputoutput)
+void hw_sm750_output_clear(struct lynxfb_output *output)
 {
-       
+
        return;
 }
 
-int hw_sm750_crtc_checkMode(struct lynxfb_crtc* crtc, struct fb_var_screeninfo* var)
+int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
 {
        struct lynx_share *share;
-       
+
 
        share = container_of(crtc, struct lynxfb_par, crtc)->share;
 
-       switch (var->bits_per_pixel){
-               case 8:
-               case 16:
-                       break;
-               case 32:
-                       if (share->revid == SM750LE_REVISION_ID) {
-                               pr_debug("750le do not support 32bpp\n");
-                               return -EINVAL;
-                       }
-                       break;
-               default:
+       switch (var->bits_per_pixel) {
+       case 8:
+       case 16:
+               break;
+       case 32:
+               if (share->revid == SM750LE_REVISION_ID) {
+                       pr_debug("750le do not support 32bpp\n");
                        return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
 
        }
 
@@ -292,9 +289,9 @@ int hw_sm750_crtc_checkMode(struct lynxfb_crtc* crtc, struct fb_var_screeninfo*
 /*
        set the controller's mode for @crtc charged with @var and @fix parameters
 */
-int hw_sm750_crtc_setMode(struct lynxfb_crtccrtc,
-                                                               struct fb_var_screeninfovar,
-                                                               struct fb_fix_screeninfofix)
+int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
+                                                               struct fb_var_screeninfo *var,
+                                                               struct fb_fix_screeninfo *fix)
 {
        int ret, fmt;
        u32 reg;
@@ -303,24 +300,24 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
        struct lynx_share *share;
        struct lynxfb_par *par;
 
-       
+
        ret = 0;
        par = container_of(crtc, struct lynxfb_par, crtc);
        share = par->share;
 #if 1
-       if(!share->accel_off){
+       if (!share->accel_off) {
                /* set 2d engine pixel format according to mode bpp */
-               switch(var->bits_per_pixel){
-                       case 8:
-                               fmt = 0;
-                               break;
-                       case 16:
-                               fmt = 1;
-                               break;
-                       case 32:
-                       default:
-                               fmt = 2;
-                               break;
+               switch (var->bits_per_pixel) {
+               case 8:
+                       fmt = 0;
+                       break;
+               case 16:
+                       fmt = 1;
+                       break;
+               case 32:
+               default:
+                       fmt = 2;
+                       break;
                }
                hw_set2dformat(&share->accel, fmt);
        }
@@ -330,7 +327,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
        modparm.pixel_clock = ps_to_hz(var->pixclock);
        modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG;
        modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG;
-       modparm.clock_phase_polarity = (var->sync& FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
+       modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
        modparm.horizontal_display_end = var->xres;
        modparm.horizontal_sync_width = var->hsync_len;
        modparm.horizontal_sync_start = var->xres + var->right_margin;
@@ -341,19 +338,19 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
        modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
 
        /* choose pll */
-       if(crtc->channel != sm750_secondary)
+       if (crtc->channel != sm750_secondary)
                clock = PRIMARY_PLL;
        else
                clock = SECONDARY_PLL;
 
        pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
        ret = ddk750_setModeTiming(&modparm, clock);
-       if(ret){
+       if (ret) {
                pr_err("Set mode timing failed\n");
                goto exit;
        }
 
-       if(crtc->channel != sm750_secondary){
+       if (crtc->channel != sm750_secondary) {
                /* set pitch, offset ,width,start address ,etc... */
                POKE32(PANEL_FB_ADDRESS,
                        FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
@@ -369,7 +366,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
                        FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length));
 
                POKE32(PANEL_WINDOW_WIDTH,
-                       FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres -1)|
+                       FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)|
                        FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset));
 
                POKE32(PANEL_WINDOW_HEIGHT,
@@ -389,7 +386,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
                        PANEL_DISPLAY_CTRL, FORMAT,
                        (var->bits_per_pixel >> 4)
                        ));
-       }else{
+       } else {
                /* not implemented now */
                POKE32(CRT_FB_ADDRESS, crtc->oScreen);
                reg = var->xres * (var->bits_per_pixel >> 3);
@@ -412,138 +409,137 @@ exit:
        return ret;
 }
 
-void hw_sm750_crtc_clear(struct lynxfb_crtccrtc)
+void hw_sm750_crtc_clear(struct lynxfb_crtc *crtc)
 {
-       
+
        return;
 }
 
-int hw_sm750_setColReg(struct lynxfb_crtccrtc, ushort index,
+int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
                                                                ushort red, ushort green, ushort blue)
 {
-       static unsigned int add[]={PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
+       static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
+
        POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
        return 0;
 }
 
-int hw_sm750le_setBLANK(struct lynxfb_output * output, int blank){
+int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
+{
        int dpms, crtdb;
-       
-       switch(blank)
-       {
+
+       switch (blank) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_UNBLANK:
+       case FB_BLANK_UNBLANK:
 #else
-               case VESA_NO_BLANKING:
+       case VESA_NO_BLANKING:
 #endif
-                       dpms = CRT_DISPLAY_CTRL_DPMS_0;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
-                       break;
+               dpms = CRT_DISPLAY_CTRL_DPMS_0;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
+               break;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_NORMAL:
-                       dpms = CRT_DISPLAY_CTRL_DPMS_0;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+       case FB_BLANK_NORMAL:
+               dpms = CRT_DISPLAY_CTRL_DPMS_0;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_VSYNC_SUSPEND:
 #else
-               case VESA_VSYNC_SUSPEND:
+       case VESA_VSYNC_SUSPEND:
 #endif
-                       dpms = CRT_DISPLAY_CTRL_DPMS_2;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+               dpms = CRT_DISPLAY_CTRL_DPMS_2;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
 #else
-               case VESA_HSYNC_SUSPEND:
+       case VESA_HSYNC_SUSPEND:
 #endif
-                       dpms = CRT_DISPLAY_CTRL_DPMS_1;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+               dpms = CRT_DISPLAY_CTRL_DPMS_1;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_POWERDOWN:
+       case FB_BLANK_POWERDOWN:
 #else
-               case VESA_POWERDOWN:
+       case VESA_POWERDOWN:
 #endif
-                       dpms = CRT_DISPLAY_CTRL_DPMS_3;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
-               default:
-                       return -EINVAL;
+               dpms = CRT_DISPLAY_CTRL_DPMS_3;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
+       default:
+               return -EINVAL;
        }
 
-       if(output->paths & sm750_crt){
+       if (output->paths & sm750_crt) {
                POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms));
                POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
        }
        return 0;
 }
 
-int hw_sm750_setBLANK(struct lynxfb_outputoutput, int blank)
+int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
 {
        unsigned int dpms, pps, crtdb;
-       
+
        dpms = pps = crtdb = 0;
 
-       switch (blank)
-       {
+       switch (blank) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_UNBLANK:
+       case FB_BLANK_UNBLANK:
 #else
-               case VESA_NO_BLANKING:
+       case VESA_NO_BLANKING:
 #endif
-                       pr_info("flag = FB_BLANK_UNBLANK \n");
-                       dpms = SYSTEM_CTRL_DPMS_VPHP;
-                       pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
-                       break;
+               pr_info("flag = FB_BLANK_UNBLANK\n");
+               dpms = SYSTEM_CTRL_DPMS_VPHP;
+               pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
+               break;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_NORMAL:
-                       pr_info("flag = FB_BLANK_NORMAL \n");
-                       dpms = SYSTEM_CTRL_DPMS_VPHP;
-                       pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+       case FB_BLANK_NORMAL:
+               pr_info("flag = FB_BLANK_NORMAL\n");
+               dpms = SYSTEM_CTRL_DPMS_VPHP;
+               pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_VSYNC_SUSPEND:
 #else
-               case VESA_VSYNC_SUSPEND:
+       case VESA_VSYNC_SUSPEND:
 #endif
-                       dpms = SYSTEM_CTRL_DPMS_VNHP;
-                       pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+               dpms = SYSTEM_CTRL_DPMS_VNHP;
+               pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
 #else
-               case VESA_HSYNC_SUSPEND:
+       case VESA_HSYNC_SUSPEND:
 #endif
-                       dpms = SYSTEM_CTRL_DPMS_VPHN;
-                       pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+               dpms = SYSTEM_CTRL_DPMS_VPHN;
+               pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
-               case FB_BLANK_POWERDOWN:
+       case FB_BLANK_POWERDOWN:
 #else
-               case VESA_POWERDOWN:
+       case VESA_POWERDOWN:
 #endif
-                       dpms = SYSTEM_CTRL_DPMS_VNHN;
-                       pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
-                       crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
-                       break;
+               dpms = SYSTEM_CTRL_DPMS_VNHN;
+               pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+               crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+               break;
        }
 
-       if(output->paths & sm750_crt){
+       if (output->paths & sm750_crt) {
 
                POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
                POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
        }
 
-       if(output->paths & sm750_panel){
+       if (output->paths & sm750_panel)
                POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
-       }
 
        return 0;
 }
@@ -552,9 +548,10 @@ int hw_sm750_setBLANK(struct lynxfb_output* output, int blank)
 void hw_sm750_initAccel(struct lynx_share *share)
 {
        u32 reg;
+
        enable2DEngine(1);
 
-       if(getChipType() == SM750LE){
+       if (getChipType() == SM750LE) {
                reg = PEEK32(DE_STATE1);
                reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
                POKE32(DE_STATE1, reg);
@@ -563,7 +560,7 @@ void hw_sm750_initAccel(struct lynx_share *share)
                reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
                POKE32(DE_STATE1, reg);
 
-       }else{
+       } else {
                /* engine reset */
                reg = PEEK32(SYSTEM_CTRL);
            reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
@@ -580,13 +577,14 @@ void hw_sm750_initAccel(struct lynx_share *share)
 
 int hw_sm750le_deWait(void)
 {
-       int i=0x10000000;
-       while(i--){
+       int i = 0x10000000;
+
+       while (i--) {
                unsigned int dwVal = PEEK32(DE_STATE2);
-               if((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
+
+               if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
                        (FIELD_GET(dwVal, DE_STATE2, DE_FIFO)  == DE_STATE2_DE_FIFO_EMPTY) &&
-                       (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY))
-               {
+                       (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
                        return 0;
                }
        }
@@ -597,13 +595,14 @@ int hw_sm750le_deWait(void)
 
 int hw_sm750_deWait(void)
 {
-       int i=0x10000000;
-       while(i--){
+       int i = 0x10000000;
+
+       while (i--) {
                unsigned int dwVal = PEEK32(SYSTEM_CTRL);
-               if((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
+
+               if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
                        (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO)  == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
-                       (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY))
-               {
+                       (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
                        return 0;
                }
        }
@@ -612,28 +611,27 @@ int hw_sm750_deWait(void)
 }
 
 int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
-        const struct fb_var_screeninfo *var,
-        const struct fb_info *info)
+       const struct fb_var_screeninfo *var,
+       const struct fb_info *info)
 {
-    uint32_t total;
-    /* check params */
-    if ((var->xoffset + var->xres > var->xres_virtual) ||
-            (var->yoffset + var->yres > var->yres_virtual)) {
-        return -EINVAL;
-    }
-
-    total = var->yoffset * info->fix.line_length +
-        ((var->xoffset * var->bits_per_pixel) >> 3);
-    total += crtc->oScreen;
-    if (crtc->channel == sm750_primary) {
-        POKE32(PANEL_FB_ADDRESS,
-                FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
-                    PANEL_FB_ADDRESS, ADDRESS, total));
-    } else {
-        POKE32(CRT_FB_ADDRESS,
-                FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
-                    CRT_FB_ADDRESS, ADDRESS, total));
-    }
-    return 0;
-}
+       uint32_t total;
+       /* check params */
+       if ((var->xoffset + var->xres > var->xres_virtual) ||
+           (var->yoffset + var->yres > var->yres_virtual)) {
+               return -EINVAL;
+       }
 
+       total = var->yoffset * info->fix.line_length +
+               ((var->xoffset * var->bits_per_pixel) >> 3);
+       total += crtc->oScreen;
+       if (crtc->channel == sm750_primary) {
+               POKE32(PANEL_FB_ADDRESS,
+                       FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
+                               PANEL_FB_ADDRESS, ADDRESS, total));
+       } else {
+               POKE32(CRT_FB_ADDRESS,
+                       FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
+                               CRT_FB_ADDRESS, ADDRESS, total));
+       }
+       return 0;
+}
index 93288b3a99d8914413522e74e6672684acd27ae2..3781a1a11c6832115d27ba827d0110508394bc2c 100644 (file)
@@ -2,14 +2,14 @@
 #define LYNX_HW750_H__
 
 
-#define DEFAULT_SM750_CHIP_CLOCK               290
-#define DEFAULT_SM750LE_CHIP_CLOCK     333
+#define DEFAULT_SM750_CHIP_CLOCK       290
+#define DEFAULT_SM750LE_CHIP_CLOCK     333
 #ifndef SM750LE_REVISION_ID
 #define SM750LE_REVISION_ID (unsigned char)0xfe
 #endif
 
 
-enum sm750_pnltype{
+enum sm750_pnltype {
 
        sm750_24TFT = 0,/* 24bit tft */
 
@@ -19,30 +19,30 @@ enum sm750_pnltype{
 };
 
 /* vga channel is not concerned  */
-enum sm750_dataflow{
+enum sm750_dataflow {
        sm750_simul_pri,/* primary => all head */
 
        sm750_simul_sec,/* secondary => all head */
 
-       sm750_dual_normal,/*    primary => panel head and secondary => crt */
+       sm750_dual_normal,/* primary => panel head and secondary => crt */
 
-       sm750_dual_swap,/*      primary => crt head and secondary => panel */
+       sm750_dual_swap,/* primary => crt head and secondary => panel */
 };
 
 
-enum sm750_channel{
+enum sm750_channel {
        sm750_primary = 0,
        /* enum value equal to the register filed data */
        sm750_secondary = 1,
 };
 
-enum sm750_path{
+enum sm750_path {
        sm750_panel = 1,
        sm750_crt = 2,
        sm750_pnc = 3,/* panel and crt */
 };
 
-struct init_status{
+struct init_status {
        ushort powerMode;
        /* below three clocks are in unit of MHZ*/
        ushort chip_clk;
@@ -52,7 +52,7 @@ struct init_status{
        ushort resetMemory;
 };
 
-struct sm750_state{
+struct sm750_state {
        struct init_status initParm;
        enum sm750_pnltype pnltype;
        enum sm750_dataflow dataflow;
@@ -61,24 +61,24 @@ struct sm750_state{
        int yLCD;
 };
 
-/*     sm750_share stands for a presentation of two frame buffer
-       that use one sm750 adaptor, it is similar to the super class of lynx_share
-       in C++
-*/
+/* sm750_share stands for a presentation of two frame buffer
+   that use one sm750 adaptor, it is similar to the super class of lynx_share
+   in C++
+ */
 
-struct sm750_share{
+struct sm750_share {
        /* it's better to put lynx_share struct to the first place of sm750_share */
        struct lynx_share share;
        struct sm750_state state;
        int hwCursor;
-       /*      0: no hardware cursor
-               1: primary crtc hw cursor enabled,
-               2: secondary crtc hw cursor enabled
-               3: both ctrc hw cursor enabled
+       /* 0: no hardware cursor
+          1: primary crtc hw cursor enabled,
+          2: secondary crtc hw cursor enabled
+          3: both ctrc hw cursor enabled
        */
 };
 
-int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev);
+int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev);
 int hw_sm750_inithw(struct lynx_share*, struct pci_dev *);
 void hw_sm750_initAccel(struct lynx_share *);
 int hw_sm750_deWait(void);
@@ -92,10 +92,10 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc*, struct fb_var_screeninfo*, struct
 int hw_sm750_setColReg(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
 int hw_sm750_setBLANK(struct lynxfb_output*, int);
 int hw_sm750le_setBLANK(struct lynxfb_output*, int);
-void hw_sm750_crtc_clear(struct lynxfb_crtc*);
-void hw_sm750_output_clear(struct lynxfb_output*);
+void hw_sm750_crtc_clear(struct lynxfb_crtc *);
+void hw_sm750_output_clear(struct lynxfb_output *);
 int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
-        const struct fb_var_screeninfo *var,
-        const struct fb_info *info);
+                        const struct fb_var_screeninfo *var,
+                        const struct fb_info *info);
 
 #endif
diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig
deleted file mode 100644 (file)
index e2922ae..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-config FB_SM7XX
-       tristate "Silicon Motion SM7XX framebuffer support"
-       depends on FB && PCI
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         Frame buffer driver for the Silicon Motion SM710, SM712, SM721
-         and SM722 chips.
-
-         This driver is also available as a module. The module will be
-         called sm7xxfb. If you want to compile it as a module, say M
-         here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile
deleted file mode 100644 (file)
index 48f471c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o
diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO
deleted file mode 100644 (file)
index 7cb0b24..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-TODO:
-- Dual head support
-- 2D acceleration support
-- use kernel coding style
-- refine the code and remove unused code
-- move it to drivers/video/fbdev/sm7xxfb.c
-
-Please send any patches to
-       Greg Kroah-Hartman <greg@kroah.com>
-       Sudip Mukherjee <sudipm.mukherjee@gmail.com>
-       Teddy Wang <teddy.wang@siliconmotion.com>
-       Sudip Mukherjee <sudip@vectorindia.org>
index d45c8afb041d8f894bd8ed212281d26f850e82fe..d4d45989b6050a33051fbf66c46866596bc97e28 100644 (file)
@@ -63,7 +63,8 @@ void synth_buffer_add(char ch)
 {
        if (!synth->alive) {
                /* This makes sure that we won't stop TTYs if there is no synth
-                * to restart them */
+                * to restart them
+                */
                return;
        }
        if (synth_buffer_free() <= 100) {
index 9ea16c5b4d6c6d008b0e8923423438377f43583c..f061747546a66d364980a06ba7759e0235f78cc8 100644 (file)
@@ -1,5 +1,6 @@
 /* Internationalization implementation.  Includes definitions of English
- * string arrays, and the i18n pointer. */
+ * string arrays, and the i18n pointer.
+ */
 
 #include <linux/slab.h>                /* For kmalloc. */
 #include <linux/ctype.h>
index 326d086f9d5a1e23e5da6a060e054f471887418d..8fcce566653f365e252aac9690269ffc4410bff4 100644 (file)
@@ -224,11 +224,11 @@ struct msg_group_t {
        enum msg_index_t end;
 };
 
-extern char *spk_msg_get(enum msg_index_t index);
-extern ssize_t spk_msg_set(enum msg_index_t index, char *text, size_t length);
-extern struct msg_group_t *spk_find_msg_group(const char *group_name);
-extern void spk_reset_msg_group(struct msg_group_t *group);
-extern void spk_initialize_msgs(void);
-extern void spk_free_user_msgs(void);
+char *spk_msg_get(enum msg_index_t index);
+ssize_t spk_msg_set(enum msg_index_t index, char *text, size_t length);
+struct msg_group_t *spk_find_msg_group(const char *group_name);
+void spk_reset_msg_group(struct msg_group_t *group);
+void spk_initialize_msgs(void);
+void spk_free_user_msgs(void);
 
 #endif
index 94756742136f93f50bbf8b655a165993edafd590..02d5c706aee7bc85ca3f29035fba67e59fdd087e 100644 (file)
@@ -165,7 +165,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key)
                        synth_printf("\n");
                        return 1;
                }
-       cur_item = letter_offsets[ch-'a'];
+               cur_item = letter_offsets[ch-'a'];
        } else if (type == KT_CUR) {
                if (ch == 0
                    && (MSG_FUNCNAMES_START + cur_item + 1) <=
index 0211df60004a6e267698b2171dd449a797258f2c..958add4839bc56be14fe261945b395374172751c 100644 (file)
@@ -240,7 +240,8 @@ static ssize_t keymap_show(struct kobject *kobj, struct kobj_attribute *attr,
        cp += sprintf(cp, "%d, %d, %d,\n", KEY_MAP_VER, num_keys, nstates);
        cp1 += 2; /* now pointing at shift states */
        /* dump num_keys+1 as first row is shift states + flags,
-        * each subsequent row is key + states */
+        * each subsequent row is key + states
+        */
        for (n = 0; n <= num_keys; n++) {
                for (i = 0; i <= nstates; i++) {
                        ch = *cp1++;
index 6c4f9a1ed07f933646eb7d4c770c23244fc2fa5a..63c59bc89b040fe68fcf01d364d5b636e8ac6707 100644 (file)
@@ -128,7 +128,8 @@ static char *phonetic[] = {
 
 /* array of 256 char pointers (one for each character description)
  * initialized to default_chars and user selectable via
- * /proc/speakup/characters */
+ * /proc/speakup/characters
+ */
 char *spk_characters[256];
 
 char *spk_default_chars[256] = {
@@ -194,7 +195,8 @@ char *spk_default_chars[256] = {
 
 /* array of 256 u_short (one for each character)
  * initialized to default_chartab and user selectable via
- * /sys/module/speakup/parameters/chartab */
+ * /sys/module/speakup/parameters/chartab
+ */
 u_short spk_chartab[256];
 
 static u_short default_chartab[256] = {
@@ -540,7 +542,8 @@ static void say_next_char(struct vc_data *vc)
  * see if there is a word starting on the next position to the right
  * and return that word if it exists.  If it does not exist it will
  * move left to the beginning of any previous word on the line or the
- * beginning off the line whichever comes first.. */
+ * beginning off the line whichever comes first..
+ */
 
 static u_long get_word(struct vc_data *vc)
 {
@@ -1113,7 +1116,8 @@ static void spkup_write(const char *in_buf, int count)
                         * suppress multiple to get rid of long pauses and
                         * clear repeat count
                         * so if someone has
-                        * repeats on you don't get nothing repeated count */
+                        * repeats on you don't get nothing repeated count
+                        */
                        if (ch != old_ch)
                                synth_printf("%c", ch);
                        else
@@ -1509,7 +1513,8 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
        if (spk_no_intr)
                spk_do_flush();
 /* the key press flushes if !no_inter but we want to flush on cursor
- * moves regardless of no_inter state */
+ * moves regardless of no_inter state
+ */
        is_cursor = value + 1;
        old_cursor_pos = vc->vc_pos;
        old_cursor_x = vc->vc_x;
index a0315701c7d96ec7ca506ab08400b66823cface1..98af3b1f2d2a13efea585a11429bc00a48451582 100644 (file)
@@ -114,7 +114,8 @@ int speakup_set_selection(struct tty_struct *tty)
                        obp = bp;
                if (!((i + 2) % vc->vc_size_row)) {
                        /* strip trailing blanks from line and add newline,
-                          unless non-space at end of line. */
+                        * unless non-space at end of line.
+                        */
                        if (obp != bp) {
                                bp = obp;
                                *bp++ = '\r';
index 1d9d51bdf5171b1be1e9bdbbc8bcd5444cbb1e9b..66ac999a032320791db2e307fabc98221920ca90 100644 (file)
@@ -51,7 +51,8 @@ const struct old_serial_port *spk_serial_init(int index)
        }
 
        /*      Disable UART interrupts, set DTR and RTS high
-        *      and set speed. */
+        *      and set speed.
+        */
        outb(cval | UART_LCR_DLAB, ser->port + UART_LCR);       /* set DLAB */
        outb(quot & 0xff, ser->port + UART_DLL);        /* LS of divisor */
        outb(quot >> 8, ser->port + UART_DLM);          /* MS of divisor */
@@ -145,7 +146,8 @@ int spk_wait_for_xmitr(void)
                synth->alive = 0;
                /* No synth any more, so nobody will restart TTYs, and we thus
                 * need to do it ourselves.  Now that there is no synth we can
-                * let application flood anyway */
+                * let application flood anyway
+                */
                speakup_start_ttys();
                timeouts = 0;
                return 0;
@@ -163,7 +165,8 @@ int spk_wait_for_xmitr(void)
                /* CTS */
                if (--tmout == 0) {
                        /* pr_warn("%s: timed out (cts)\n",
-                        * synth->long_name); */
+                        * synth->long_name);
+                        */
                        timeouts++;
                        return 0;
                }
@@ -217,4 +220,3 @@ void spk_serial_release(void)
        speakup_info.port_tts = 0;
 }
 EXPORT_SYMBOL_GPL(spk_serial_release);
-
index a7f4962427f36b98d54e98518e8259ff11f044c8..df74c912da7264859564e94a0153d73072019816 100644 (file)
 #define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type)
 #define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type)
 
-extern int speakup_thread(void *data);
-extern void spk_reset_default_chars(void);
-extern void spk_reset_default_chartab(void);
-extern void synth_start(void);
+int speakup_thread(void *data);
+void spk_reset_default_chars(void);
+void spk_reset_default_chartab(void);
+void synth_start(void);
 void synth_insert_next_index(int sent_num);
 void spk_reset_index_count(int sc);
 void spk_get_index_count(int *linecount, int *sentcount);
-extern int spk_set_key_info(const u_char *key_info, u_char *k_buffer);
-extern char *spk_strlwr(char *s);
-extern char *spk_s2uchar(char *start, char *dest);
-extern int speakup_kobj_init(void);
-extern void speakup_kobj_exit(void);
-extern int spk_chartab_get_value(char *keyword);
-extern void speakup_register_var(struct var_t *var);
-extern void speakup_unregister_var(enum var_id_t var_id);
-extern struct st_var_header *spk_get_var_header(enum var_id_t var_id);
-extern struct st_var_header *spk_var_header_by_name(const char *name);
-extern struct punc_var_t *spk_get_punc_var(enum var_id_t var_id);
-extern int spk_set_num_var(int val, struct st_var_header *var, int how);
-extern int spk_set_string_var(const char *page, struct st_var_header *var,
-                               int len);
-extern int spk_set_mask_bits(const char *input, const int which, const int how);
+int spk_set_key_info(const u_char *key_info, u_char *k_buffer);
+char *spk_strlwr(char *s);
+char *spk_s2uchar(char *start, char *dest);
+int speakup_kobj_init(void);
+void speakup_kobj_exit(void);
+int spk_chartab_get_value(char *keyword);
+void speakup_register_var(struct var_t *var);
+void speakup_unregister_var(enum var_id_t var_id);
+struct st_var_header *spk_get_var_header(enum var_id_t var_id);
+struct st_var_header *spk_var_header_by_name(const char *name);
+struct punc_var_t *spk_get_punc_var(enum var_id_t var_id);
+int spk_set_num_var(int val, struct st_var_header *var, int how);
+int spk_set_string_var(const char *page, struct st_var_header *var, int len);
+int spk_set_mask_bits(const char *input, const int which, const int how);
 extern special_func spk_special_handler;
-extern int spk_handle_help(struct vc_data *vc, u_char type, u_char ch,
-                               u_short key);
-extern int synth_init(char *name);
-extern void synth_release(void);
+int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key);
+int synth_init(char *name);
+void synth_release(void);
 
-extern void spk_do_flush(void);
-extern void speakup_start_ttys(void);
-extern void synth_buffer_add(char ch);
-extern void synth_buffer_clear(void);
-extern void speakup_clear_selection(void);
-extern int speakup_set_selection(struct tty_struct *tty);
-extern int speakup_paste_selection(struct tty_struct *tty);
-extern void speakup_cancel_paste(void);
-extern void speakup_register_devsynth(void);
-extern void speakup_unregister_devsynth(void);
-extern void synth_write(const char *buf, size_t count);
-extern int synth_supports_indexing(void);
+void spk_do_flush(void);
+void speakup_start_ttys(void);
+void synth_buffer_add(char ch);
+void synth_buffer_clear(void);
+void speakup_clear_selection(void);
+int speakup_set_selection(struct tty_struct *tty);
+int speakup_paste_selection(struct tty_struct *tty);
+void speakup_cancel_paste(void);
+void speakup_register_devsynth(void);
+void speakup_unregister_devsynth(void);
+void synth_write(const char *buf, size_t count);
+int synth_supports_indexing(void);
 
 extern struct vc_data *spk_sel_cons;
 extern unsigned short spk_xs, spk_ys, spk_xe, spk_ye; /* our region points */
index 6376fca9e0e1654e10c01ab69f1f60efc54d247f..107ec1155f51b6d5208615246408bdd7d5441297 100644 (file)
@@ -6,10 +6,12 @@
 
        /* Port Status Flags */
 #define SYNTH_READABLE 0x01    /* mask for bit which is nonzero if a
-                                  byte can be read from the data port */
+                                * byte can be read from the data port
+                                */
 #define SYNTH_WRITABLE 0x02    /* mask for RDY bit, which when set to
-                                  1, indicates the data port is ready
-                                  to accept a byte of data. */
+                                * 1, indicates the data port is ready
+                                *  to accept a byte of data.
+                                */
 #define SYNTH_QUIET    'S' /* synth is not speaking */
 #define SYNTH_FULL     'F' /* synth is full. */
 #define SYNTH_ALMOST_EMPTY 'M' /* synth has less than 2 seconds of text left */
index 437e13a85943dc00a0bbb7eb569eafe62589afb2..4893fef3f8949cd4bfbe9b50b5f7059c9c0da0ac 100644 (file)
@@ -88,8 +88,9 @@
 #define        CTRL_last_index         0x0b00  /*   get last index spoken */
 #define        CTRL_io_priority        0x0c00  /*   change i/o priority */
 #define        CTRL_free_mem           0x0d00  /*   get free paragraphs on module */
-#define        CTRL_get_lang           0x0e00  /*   return bit mask of loaded
-                                        *   languages */
+#define        CTRL_get_lang           0x0e00  /* return bit mask of loaded
+                                                * languages
+                                                */
 #define        CMD_test                        0x2000          /* self-test request */
 #define        TEST_mask               0x0F00  /* isolate test field */
 #define        TEST_null               0x0000  /* no test requested */
@@ -500,4 +501,3 @@ MODULE_AUTHOR("David Borowski");
 MODULE_DESCRIPTION("Speakup support for DECtalk PC synthesizers");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
-
index d951d18c57927116b0c12e332c77321903b4342c..46d885fcfb209016a7c00fd4ae965c387feb5407 100644 (file)
@@ -4,31 +4,37 @@
 #define SYNTH_CLEAR    0x18            /* stops speech */
        /* TTS Port Status Flags */
 #define TTS_READABLE   0x80    /* mask for bit which is nonzero if a
-                                        byte can be read from the TTS port */
+                                * byte can be read from the TTS port
+                                */
 #define TTS_SPEAKING   0x40    /* mask for SYNC bit, which is nonzero
-                                        while DoubleTalk is producing
-                                        output with TTS, PCM or CVSD
-                                        synthesizers or tone generators
-                                        (that is, all but LPC) */
+                                * while DoubleTalk is producing
+                                * output with TTS, PCM or CVSD
+                                * synthesizers or tone generators
+                                * (that is, all but LPC)
+                                */
 #define TTS_SPEAKING2  0x20    /* mask for SYNC2 bit,
-                                        which falls to zero up to 0.4 sec
-                                        before speech stops */
+                                * which falls to zero up to 0.4 sec
+                                * before speech stops
+                                */
 #define TTS_WRITABLE   0x10    /* mask for RDY bit, which when set to
-                                        1, indicates the TTS port is ready
-                                        to accept a byte of data.  The RDY
-                                        bit goes zero 2-3 usec after
-                                        writing, and goes 1 again 180-190
-                                        usec later. */
+                                * 1, indicates the TTS port is ready
+                                * to accept a byte of data.  The RDY
+                                * bit goes zero 2-3 usec after
+                                * writing, and goes 1 again 180-190
+                                * usec later.
+                                */
 #define TTS_ALMOST_FULL        0x08    /* mask for AF bit: When set to 1,
-                                        indicates that less than 300 bytes
-                                        are available in the TTS input
-                                        buffer. AF is always 0 in the PCM,
-                                        TGN and CVSD modes. */
+                                        * indicates that less than 300 bytes
+                                        * are available in the TTS input
+                                        * buffer. AF is always 0 in the PCM,
+                                        * TGN and CVSD modes.
+                                        */
 #define TTS_ALMOST_EMPTY 0x04  /* mask for AE bit: When set to 1,
-                                        indicates that less than 300 bytes
-                                        are remaining in DoubleTalk's input
-                                        (TTS or PCM) buffer. AE is always 1
-                                        in the TGN and CVSD modes. */
+                                * indicates that less than 300 bytes
+                                * are remaining in DoubleTalk's input
+                                * (TTS or PCM) buffer. AE is always 1
+                                * in the TGN and CVSD modes.
+                                */
 
                                /* data returned by Interrogate command */
 struct synth_settings {
@@ -45,10 +51,12 @@ struct synth_settings {
        u_char ext_dict_loaded; /* 1=exception dictionary loaded */
        u_char ext_dict_status; /* 1=exception dictionary enabled */
        u_char free_ram;        /* # pages (truncated) remaining for
-                                * text buffer */
+                                * text buffer
+                                */
        u_char articulation;    /* nA; 0-9 */
        u_char reverb;          /* nR; 0-9 */
        u_char eob;             /* 7Fh value indicating end of
-                                * parameter block */
+                                * parameter block
+                                */
        u_char has_indexing;    /* nonzero if indexing is implemented */
 };
index fb31bb95d83a1b591b47f34e571979cd2660228f..366358b600a17ce1575a214d9e8d3af3902b28ac 100644 (file)
@@ -356,4 +356,3 @@ MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
 MODULE_DESCRIPTION("Speakup userspace software synthesizer support");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
-
index d95efb702fe4eb51195ad5aa942ca1935419217a..90c383ee7c3f55fb6d8d04c56589f2d046c9cd76 100644 (file)
@@ -48,7 +48,8 @@ int speakup_thread(void *data)
                        kd_mksound(our_sound.freq, our_sound.jiffies);
                if (synth && synth->catch_up && synth->alive) {
                        /* It is up to the callee to take the lock, so that it
-                        * can sleep whenever it likes */
+                        * can sleep whenever it likes
+                        */
                        synth->catch_up(synth);
                }
 
index 1b0d1c08741f9a1d05dd0606f20c1f55f8069e7e..75bf40c14c793930bc8f8903ffff3a09f0647386 100644 (file)
@@ -269,7 +269,8 @@ int spk_set_string_var(const char *page, struct st_var_header *var, int len)
 /* spk_set_mask_bits sets or clears the punc/delim/repeat bits,
  * if input is null uses the defaults.
  * values for how: 0 clears bits of chars supplied,
- * 1 clears allk, 2 sets bits for chars */
+ * 1 clears allk, 2 sets bits for chars
+ */
 int spk_set_mask_bits(const char *input, const int which, const int how)
 {
        u_char *cp;
index 0f524bb7b41d5bfaba0e038e20846c63d24b7785..1f9ba8beb06173adad9041b823498c41313d79b1 100644 (file)
@@ -1126,7 +1126,6 @@ MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table);
 static struct i2c_driver synaptics_rmi4_driver = {
        .driver = {
                .name   =       DRIVER_NAME,
-               .owner  =       THIS_MODULE,
                .pm     =       &synaptics_rmi4_dev_pm_ops,
        },
        .probe          =       synaptics_rmi4_probe,
index 778f9d05f98a83646604cc98f618af37591af4d5..624abe66c20c25f9685f607273ec6b14c003ea50 100644 (file)
@@ -3,7 +3,7 @@
 #
 menuconfig UNISYSSPAR
        bool "Unisys SPAR driver support"
-       depends on X86_64
+       depends on X86_64 && !UML
        select PCI
        select ACPI
        ---help---
index 706363fc3e9a77af30bc6c19b0fbee36be2bd302..17cb499cb53c3e5949679531d3b49f2662038945 100644 (file)
  * CHANNEL Guids
  */
 
-/* Used in IOChannel
- * {414815ed-c58c-11da-95a9-00e08161165f}
- */
+/* {414815ed-c58c-11da-95a9-00e08161165f} */
 #define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \
                UUID_LE(0x414815ed, 0xc58c, 0x11da, \
                                0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
 static const uuid_le spar_vhba_channel_protocol_uuid =
        SPAR_VHBA_CHANNEL_PROTOCOL_UUID;
+#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \
+       "414815ed-c58c-11da-95a9-00e08161165f"
 
-/* Used in IOChannel
- * {8cd5994d-c58e-11da-95a9-00e08161165f}
- */
+/* {8cd5994d-c58e-11da-95a9-00e08161165f} */
 #define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \
                UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \
                                0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
 static const uuid_le spar_vnic_channel_protocol_uuid =
        SPAR_VNIC_CHANNEL_PROTOCOL_UUID;
+#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \
+       "8cd5994d-c58e-11da-95a9-00e08161165f"
 
-/* Used in IOChannel
- * {72120008-4AAB-11DC-8530-444553544200}
- */
+/* {72120008-4AAB-11DC-8530-444553544200} */
 #define SPAR_SIOVM_UUID \
                UUID_LE(0x72120008, 0x4AAB, 0x11DC, \
                                0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
 static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID;
 
-/* Used in visornoop/visornoop_main.c
- * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f}
- */
+/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */
 #define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID  \
                UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \
                                0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f)
@@ -53,9 +49,7 @@ static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID;
 static const uuid_le spar_controldirector_channel_protocol_uuid =
        SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID;
 
-/* Used in visorchipset/visorchipset_main.c
- * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C}
- */
+/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */
 #define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID                           \
                UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \
                                0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c)
index e4a21e42e868c2bfdd3c6f748883636956cb6e78..9235536fa75f76ee2ace83093dec44e80b59efee 100644 (file)
@@ -113,7 +113,8 @@ struct visor_driver {
        struct driver_attribute version_attr;
 };
 
-#define to_visor_driver(x) container_of(x, struct visor_driver, driver)
+#define to_visor_driver(x) ((x) ? \
+       (container_of(x, struct visor_driver, driver)) : (NULL))
 
 /** A device type for things "plugged" into the visorbus bus */
 
@@ -200,6 +201,8 @@ bool visorchannel_signalremove(struct visorchannel *channel, u32 queue,
                               void *msg);
 bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
                               void *msg);
+bool visorchannel_signalempty(struct visorchannel *channel, u32 queue);
+
 int visorchannel_signalqueue_slots_avail(struct visorchannel *channel,
                                         u32 queue);
 int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue);
index a50d9cf4bed740491423d5f1412a97e508700a37..ec25366b127c0fcc33e51093449baa126f5d52ea 100644 (file)
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index f74f5d8c282099d3a766d4c54c0e3f8c40a1007d..3c97ebac4f322fe493aeed4cf31ce06369c09519 100644 (file)
@@ -1,12 +1,11 @@
 /* controlvmcompletionstatus.c
  *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 57dd93e0cc83f9f32ea1e7d8405e69844f606f0a..b08b6ecc8d31e26e6b23d4b30f737c539178233f 100644 (file)
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 5e56088cf8555fce57cf410983236ca25f3afc98..a3631c3591f61cc088479ae90563e5e1f88752ff 100644 (file)
@@ -1,12 +1,11 @@
 /* periodic_work.c
  *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 5ed83a3f14281b92c90aaef87da20f4efec274e2..80e64477e547ef70d11729f0425704a49191d20c 100644 (file)
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 9b6d3e69355c77ded203a8eb6288ca3d8c3d7abb..f59fd8a523c4fa838d4b4f9f4d60166ec4d3f1f5 100644 (file)
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 6db47196c1899b9b7c9a587f0fd38ccb64492a42..2309f5f2b238e574db07c80e509d815a98c643c1 100644 (file)
@@ -1,12 +1,11 @@
 /* visorbus_main.c
  *
- * Copyright ï¿½ 2010 - 2013 UNISYS CORPORATION
+ * Copyright ï¿½ 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -70,6 +69,38 @@ static const struct attribute_group *visorbus_bus_groups[] = {
        NULL,
 };
 
+/*
+ * DEVICE type attributes
+ *
+ * The modalias file will contain the guid of the device.
+ */
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct visor_device *vdev;
+       uuid_le guid;
+
+       vdev = to_visor_device(dev);
+       guid = visorchannel_get_uuid(vdev->visorchannel);
+       return snprintf(buf, PAGE_SIZE, "visorbus:%pUl\n", &guid);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *visorbus_dev_attrs[] = {
+       &dev_attr_modalias.attr,
+       NULL,
+};
+
+/* sysfs example for bridge-only sysfs files using device_type's */
+static const struct attribute_group visorbus_dev_group = {
+       .attrs = visorbus_dev_attrs,
+};
+
+static const struct attribute_group *visorbus_dev_groups[] = {
+       &visorbus_dev_group,
+       NULL,
+};
+
 /** This describes the TYPE of bus.
  *  (Don't confuse this with an INSTANCE of the bus.)
  */
@@ -77,6 +108,7 @@ struct bus_type visorbus_type = {
        .name = "visorbus",
        .match = visorbus_match,
        .uevent = visorbus_uevent,
+       .dev_groups = visorbus_dev_groups,
        .bus_groups = visorbus_bus_groups,
 };
 
@@ -129,7 +161,13 @@ static LIST_HEAD(list_all_device_instances);
 static int
 visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env)
 {
-       if (add_uevent_var(env, "VERSION=%s", VERSION))
+       struct visor_device *dev;
+       uuid_le guid;
+
+       dev = to_visor_device(xdev);
+       guid = visorchannel_get_uuid(dev->visorchannel);
+
+       if (add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid))
                return -ENOMEM;
        return 0;
 }
@@ -218,9 +256,9 @@ visorbus_release_device(struct device *xdev)
 struct devmajorminor_attribute {
        struct attribute attr;
        int slot;
-        ssize_t (*show)(struct visor_device *, int slot, char *buf);
-        ssize_t (*store)(struct visor_device *, int slot, const char *buf,
-                         size_t count);
+       ssize_t (*show)(struct visor_device *, int slot, char *buf);
+       ssize_t (*store)(struct visor_device *, int slot, const char *buf,
+                        size_t count);
 };
 
 static ssize_t DEVMAJORMINOR_ATTR(struct visor_device *dev, int slot, char *buf)
@@ -281,12 +319,11 @@ devmajorminor_create_file(struct visor_device *dev, const char *name,
                rc = -ENOMEM;
                goto away;
        }
-       myattr = kmalloc(sizeof(*myattr), GFP_KERNEL);
+       myattr = kzalloc(sizeof(*myattr), GFP_KERNEL);
        if (!myattr) {
                rc = -ENOMEM;
                goto away;
        }
-       memset(myattr, 0, sizeof(struct devmajorminor_attribute));
        myattr->show = DEVMAJORMINOR_ATTR;
        myattr->store = NULL;
        myattr->slot = slot;
@@ -471,6 +508,7 @@ static struct attribute *channel_attrs[] = {
                &dev_attr_typeguid.attr,
                &dev_attr_zoneguid.attr,
                &dev_attr_typename.attr,
+               NULL
 };
 
 static struct attribute_group channel_attr_grp = {
@@ -478,7 +516,7 @@ static struct attribute_group channel_attr_grp = {
                .attrs = channel_attrs,
 };
 
-static const struct attribute_group *visorbus_dev_groups[] = {
+static const struct attribute_group *visorbus_channel_groups[] = {
                &channel_attr_grp,
                NULL
 };
@@ -678,7 +716,7 @@ unregister_driver_attributes(struct visor_driver *drv)
 static void
 dev_periodic_work(void *xdev)
 {
-       struct visor_device *dev = (struct visor_device *)xdev;
+       struct visor_device *dev = xdev;
        struct visor_driver *drv = to_visor_driver(dev->device.driver);
 
        down(&dev->visordriver_callback_lock);
@@ -937,7 +975,7 @@ create_visor_device(struct visor_device *dev)
 
        sema_init(&dev->visordriver_callback_lock, 1);  /* unlocked */
        dev->device.bus = &visorbus_type;
-       dev->device.groups = visorbus_dev_groups;
+       dev->device.groups = visorbus_channel_groups;
        device_initialize(&dev->device);
        dev->device.release = visorbus_release_device;
        /* keep a reference just for us (now 2) */
@@ -1043,10 +1081,10 @@ write_vbus_chp_info(struct visorchannel *chan,
        int off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
 
        if (hdr_info->chp_info_offset == 0)
-                       return -1;
+               return -1;
 
        if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
-                       return -1;
+               return -1;
        return 0;
 }
 
@@ -1061,10 +1099,10 @@ write_vbus_bus_info(struct visorchannel *chan,
        int off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
 
        if (hdr_info->bus_info_offset == 0)
-                       return -1;
+               return -1;
 
        if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
-                       return -1;
+               return -1;
        return 0;
 }
 
@@ -1081,10 +1119,10 @@ write_vbus_dev_info(struct visorchannel *chan,
            (hdr_info->device_info_struct_bytes * devix);
 
        if (hdr_info->dev_info_offset == 0)
-                       return -1;
+               return -1;
 
        if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
-                       return -1;
+               return -1;
        return 0;
 }
 
@@ -1106,7 +1144,7 @@ fix_vbus_dev_info(struct visor_device *visordev)
        struct spar_vbus_headerinfo *hdr_info;
 
        if (!visordev->device.driver)
-                       return;
+               return;
 
        hdr_info = (struct spar_vbus_headerinfo *)visordev->vbus_hdr_info;
        if (!hdr_info)
@@ -1319,11 +1357,11 @@ static void
 pause_state_change_complete(struct visor_device *dev, int status)
 {
        if (!dev->pausing)
-                       return;
+               return;
 
        dev->pausing = false;
        if (!chipset_responders.device_pause) /* this can never happen! */
-                       return;
+               return;
 
        /* Notify the chipset driver that the pause is complete, which
        * will presumably want to send some sort of response to the
@@ -1339,11 +1377,11 @@ static void
 resume_state_change_complete(struct visor_device *dev, int status)
 {
        if (!dev->resuming)
-                       return;
+               return;
 
        dev->resuming = false;
        if (!chipset_responders.device_resume) /* this can never happen! */
-                       return;
+               return;
 
        /* Notify the chipset driver that the resume is complete,
         * which will presumably want to send some sort of response to
@@ -1367,14 +1405,14 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
        else
                notify_func = chipset_responders.device_resume;
        if (!notify_func)
-                       goto away;
+               goto away;
 
        drv = to_visor_driver(dev->device.driver);
        if (!drv)
-                       goto away;
+               goto away;
 
        if (dev->pausing || dev->resuming)
-                       goto away;
+               goto away;
 
        /* Note that even though both drv->pause() and drv->resume
         * specify a callback function, it is NOT necessary for us to
@@ -1385,7 +1423,7 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
         */
        if (is_pause) {
                if (!drv->pause)
-                               goto away;
+                       goto away;
 
                dev->pausing = true;
                x = drv->pause(dev, pause_state_change_complete);
@@ -1397,7 +1435,7 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
                 * would never even get here in that case. */
                fix_vbus_dev_info(dev);
                if (!drv->resume)
-                               goto away;
+                       goto away;
 
                dev->resuming = true;
                x = drv->resume(dev, resume_state_change_complete);
@@ -1413,7 +1451,7 @@ initiate_chipset_device_pause_resume(struct visor_device *dev, bool is_pause)
 away:
        if (rc < 0) {
                if (notify_func)
-                               (*notify_func)(dev, rc);
+                       (*notify_func)(dev, rc);
        }
 }
 
@@ -1469,8 +1507,8 @@ visorbus_init(void)
 
 away:
        if (rc)
-                       POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
-                                        POSTCODE_SEVERITY_ERR);
+               POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
+                                POSTCODE_SEVERITY_ERR);
        return rc;
 }
 
@@ -1495,9 +1533,8 @@ visorbus_exit(void)
 
        list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
                struct visor_device *dev = list_entry(listentry,
-                                                             struct
-                                                             visor_device,
-                                                             list_all);
+                                                     struct visor_device,
+                                                     list_all);
                remove_bus_instance(dev);
        }
        remove_bus_type();
index 2f12483e38ab3f6007adcf40c2d034a057929e24..39edd20184531f89b4174f3abaaa12807e6dbb35 100644 (file)
@@ -1,12 +1,11 @@
 /* visorchipset.h
  *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 20b63496e9f215a51e6385fd0d2e4b96b8758e75..6da7e49a662758c7e673aea32705a86e2269cb2c 100644 (file)
@@ -1,12 +1,11 @@
 /* visorchannel_funcs.c
  *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -259,7 +258,8 @@ visorchannel_write(struct visorchannel *channel, ulong offset,
 
        if (offset < chdr_size) {
                copy_size = min(chdr_size - offset, nbytes);
-               memcpy(&channel->chan_hdr + offset, local, copy_size);
+               memcpy(((char *)(&channel->chan_hdr)) + offset,
+                      local, copy_size);
        }
 
        memcpy_toio(channel->mapped + offset, local, nbytes);
@@ -416,11 +416,12 @@ bool
 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
 {
        bool rc;
+       unsigned long flags;
 
        if (channel->needs_lock) {
-               spin_lock(&channel->remove_lock);
+               spin_lock_irqsave(&channel->remove_lock, flags);
                rc = signalremove_inner(channel, queue, msg);
-               spin_unlock(&channel->remove_lock);
+               spin_unlock_irqrestore(&channel->remove_lock, flags);
        } else {
                rc = signalremove_inner(channel, queue, msg);
        }
@@ -429,6 +430,27 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
 }
 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
 
+bool
+visorchannel_signalempty(struct visorchannel *channel, u32 queue)
+{
+       unsigned long flags = 0;
+       struct signal_queue_header sig_hdr;
+       bool rc = false;
+
+       if (channel->needs_lock)
+               spin_lock_irqsave(&channel->remove_lock, flags);
+
+       if (!sig_read_header(channel, queue, &sig_hdr))
+               rc = true;
+       if (sig_hdr.head == sig_hdr.tail)
+               rc = true;
+       if (channel->needs_lock)
+               spin_unlock_irqrestore(&channel->remove_lock, flags);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalempty);
+
 static bool
 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
 {
@@ -470,11 +492,12 @@ bool
 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
 {
        bool rc;
+       unsigned long flags;
 
        if (channel->needs_lock) {
-               spin_lock(&channel->insert_lock);
+               spin_lock_irqsave(&channel->insert_lock, flags);
                rc = signalinsert_inner(channel, queue, msg);
-               spin_unlock(&channel->insert_lock);
+               spin_unlock_irqrestore(&channel->insert_lock, flags);
        } else {
                rc = signalinsert_inner(channel, queue, msg);
        }
index bb8087e70127c800015fa0d4fae8675cbcb0e2bd..4b76cb441ed4eb683a1bffbc792a40aa8b2adebd 100644 (file)
@@ -1,12 +1,11 @@
 /* visorchipset_main.c
  *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -1247,10 +1246,11 @@ my_device_create(struct controlvm_message *inmsg)
        POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
                         POSTCODE_SEVERITY_INFO);
 
-       visorchannel = visorchannel_create(cmd->create_device.channel_addr,
-                                          cmd->create_device.channel_bytes,
-                                          GFP_KERNEL,
-                                          cmd->create_device.data_type_uuid);
+       visorchannel =
+              visorchannel_create_with_lock(cmd->create_device.channel_addr,
+                                            cmd->create_device.channel_bytes,
+                                            GFP_KERNEL,
+                                            cmd->create_device.data_type_uuid);
 
        if (!visorchannel) {
                POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
@@ -2047,6 +2047,7 @@ device_create_response(struct visor_device *dev_info, int response)
                         response);
 
        kfree(dev_info->pending_msg_hdr);
+       dev_info->pending_msg_hdr = NULL;
 }
 
 static void
@@ -2381,6 +2382,9 @@ static struct acpi_driver unisys_acpi_driver = {
                .remove = visorchipset_exit,
                },
 };
+
+MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
+
 static __init uint32_t visorutil_spar_detect(void)
 {
        unsigned int eax, ebx, ecx, edx;
index 7a53df00726a31be9ce3180cc0deef8e70cceef5..7abd27a618f8d12f97e646c5d1f7b7ca541c497d 100644 (file)
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
index 71007443773713ee5c5d58892ba4b299a6f3e555..8c9da7ea7845a1affc64931faf10d9dfcfe16452 100644 (file)
@@ -1,10 +1,9 @@
 /* Copyright (c) 2012 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * 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 that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  */
 
 #include <linux/debugfs.h>
-#include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/skbuff.h>
+#include <linux/netdevice.h>
 #include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
 
 #include "visorbus.h"
 #include "iochannel.h"
 
-#define VISORNIC_INFINITE_RESPONSE_WAIT 0
+#define VISORNIC_INFINITE_RSP_WAIT 0
 #define VISORNICSOPENMAX 32
 #define MAXDEVICES     16384
 
@@ -61,7 +61,6 @@ static const struct file_operations debugfs_enable_ints_fops = {
        .write = enable_ints_write,
 };
 
-static struct workqueue_struct *visornic_serverdown_workqueue;
 static struct workqueue_struct *visornic_timeout_reset_workqueue;
 
 /* GUIDS for director channel type supported by this driver.  */
@@ -72,6 +71,15 @@ static struct visor_channeltype_descriptor visornic_channel_types[] = {
        { SPAR_VNIC_CHANNEL_PROTOCOL_UUID, "ultravnic" },
        { NULL_UUID_LE, NULL }
 };
+MODULE_DEVICE_TABLE(visorbus, visornic_channel_types);
+/*
+ * FIXME XXX: This next line of code must be fixed and removed before
+ * acceptance into the 'normal' part of the kernel.  It is only here as a place
+ * holder to get module autoloading functionality working for visorbus.  Code
+ * must be added to scripts/mode/file2alias.c, etc., to get this working
+ * properly.
+ */
+MODULE_ALIAS("visorbus:" SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR);
 
 /* This is used to tell the visor bus driver which types of visor devices
  * we support, and what functions to call when a visor device that we support
@@ -90,12 +98,6 @@ static struct visor_driver visornic_driver = {
        .channel_interrupt = NULL,
 };
 
-struct visor_thread_info {
-       struct task_struct *task;
-       struct completion has_stopped;
-       int id;
-};
-
 struct chanstat {
        unsigned long got_rcv;
        unsigned long got_enbdisack;
@@ -104,6 +106,7 @@ struct chanstat {
        unsigned long sent_enbdis;
        unsigned long sent_promisc;
        unsigned long sent_post;
+       unsigned long sent_post_failed;
        unsigned long sent_xmit;
        unsigned long reject_count;
        unsigned long extra_rcvbufs_sent;
@@ -111,7 +114,6 @@ struct chanstat {
 
 struct visornic_devdata {
        int devnum;
-       int thread_wait_ms;
        unsigned short enabled;         /* 0 disabled 1 enabled to receive */
        unsigned short enab_dis_acked;  /* NET_RCV_ENABLE/DISABLE acked by
                                         * IOPART
@@ -119,7 +121,6 @@ struct visornic_devdata {
        struct visor_device *dev;
        char name[99];
        struct list_head list_all;   /* < link within list_all_devices list */
-       struct kref kref;
        struct net_device *netdev;
        struct net_device_stats net_stats;
        atomic_t interrupt_rcvd;
@@ -137,20 +138,21 @@ struct visornic_devdata {
        atomic_t num_rcvbuf_in_iovm;
        unsigned long alloc_failed_in_if_needed_cnt;
        unsigned long alloc_failed_in_repost_rtn_cnt;
-       int max_outstanding_net_xmits;   /* absolute max number of outstanding
-                                         * xmits - should never hit this
-                                         */
-       int upper_threshold_net_xmits;   /* high water mark for calling
-                                         * netif_stop_queue()
-                                         */
-       int lower_threshold_net_xmits;   /* high water mark for calling
-                                         * netif_wake_queue()
-                                         */
+       unsigned long max_outstanding_net_xmits; /* absolute max number of
+                                                 * outstanding xmits - should
+                                                 * never hit this
+                                                 */
+       unsigned long upper_threshold_net_xmits;  /* high water mark for
+                                                  * calling netif_stop_queue()
+                                                  */
+       unsigned long lower_threshold_net_xmits; /* high water mark for calling
+                                                 * netif_wake_queue()
+                                                 */
        struct sk_buff_head xmitbufhead; /* xmitbufhead is the head of the
                                          * xmit buffer list that have been
                                          * sent to the IOPART end
                                          */
-       struct work_struct serverdown_completion;
+       visorbus_state_complete_func server_down_complete_func;
        struct work_struct timeout_reset;
        struct uiscmdrsp *cmdrsp_rcv;    /* cmdrsp_rcv is used for
                                          * posting/unposting rcv buffers
@@ -161,8 +163,8 @@ struct visornic_devdata {
                                          */
        bool server_down;                /* IOPART is down */
        bool server_change_state;        /* Processing SERVER_CHANGESTATE msg */
+       bool going_away;                 /* device is being torn down */
        struct dentry *eth_debugfs_dir;
-       struct visor_thread_info threadinfo;
        u64 interrupts_rcvd;
        u64 interrupts_notme;
        u64 interrupts_disabled;
@@ -194,16 +196,19 @@ struct visornic_devdata {
 
        int queuefullmsg_logged;
        struct chanstat chstat;
+       struct timer_list irq_poll_timer;
+       struct napi_struct napi;
+       struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP];
 };
 
-/* array of open devices maintained by open() and close() */
-static struct net_device *num_visornic_open[VISORNICSOPENMAX];
 
 /* List of all visornic_devdata structs,
  * linked via the list_all member
  */
 static LIST_HEAD(list_all_devices);
 static DEFINE_SPINLOCK(lock_all_devices);
+static int visornic_poll(struct napi_struct *napi, int budget);
+static void poll_for_irq(unsigned long v);
 
 /**
  *     visor_copy_fragsinfo_from_skb(
@@ -223,9 +228,25 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen,
                              struct phys_info frags[])
 {
        unsigned int count = 0, ii, size, offset = 0, numfrags;
+       unsigned int total_count;
 
        numfrags = skb_shinfo(skb)->nr_frags;
 
+       /*
+        * Compute the number of fragments this skb has, and if its more than
+        * frag array can hold, linearize the skb
+        */
+       total_count = numfrags + (firstfraglen / PI_PAGE_SIZE);
+       if (firstfraglen % PI_PAGE_SIZE)
+               total_count++;
+
+       if (total_count > frags_max) {
+               if (skb_linearize(skb))
+                       return -EINVAL;
+               numfrags = skb_shinfo(skb)->nr_frags;
+               firstfraglen = 0;
+       }
+
        while (firstfraglen) {
                if (count == frags_max)
                        return -EINVAL;
@@ -256,8 +277,16 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen,
                                              page_offset,
                                              skb_shinfo(skb)->frags[ii].
                                              size, count, frags_max, frags);
-                       if (!count)
-                               return -EIO;
+                       /*
+                        * add_physinfo_entries only returns
+                        * zero if the frags array is out of room
+                        * That should never happen because we
+                        * fail above, if count+numfrags > frags_max.
+                        * Given that theres no recovery mechanism from putting
+                        * half a packet in the I/O channel, panic here as this
+                        * should never happen
+                        */
+                       BUG_ON(!count);
                }
        }
        if (skb_shinfo(skb)->frag_list) {
@@ -279,222 +308,15 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen,
        return count;
 }
 
-/**
- *     visort_thread_start - starts thread for the device
- *     @thrinfo: The thread to start
- *     @threadfn: Function the thread starts
- *     @thrcontext: Context to pass to the thread, i.e. devdata
- *     @name:  string describing name of thread
- *
- *     Starts a thread for the device, currently only thread is
- *     process_incoming_rsps
- *     Returns 0 on success;
- */
-static int visor_thread_start(struct visor_thread_info *thrinfo,
-                             int (*threadfn)(void *),
-                             void *thrcontext, char *name)
-{
-       /* used to stop the thread */
-       init_completion(&thrinfo->has_stopped);
-       thrinfo->task = kthread_run(threadfn, thrcontext, name);
-       if (IS_ERR(thrinfo->task)) {
-               thrinfo->id = 0;
-               return -EINVAL;
-       }
-       thrinfo->id = thrinfo->task->pid;
-       return 0;
-}
-
-/**
- *     visor_thread_stop - stop a thread for the device
- *     @thrinfo: The thread to stop
- *
- *     Stop the thread and wait for completion for a minute
- *     Returns void.
- */
-static void visor_thread_stop(struct visor_thread_info *thrinfo)
-{
-       if (!thrinfo->id)
-               return; /* thread not running */
-
-       kthread_stop(thrinfo->task);
-       /* give up if the thread has NOT died in 1 minute */
-       if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ))
-               thrinfo->id = 0;
-}
-
-/* DebugFS code */
-static ssize_t info_debugfs_read(struct file *file, char __user *buf,
-                                size_t len, loff_t *offset)
-{
-       int i;
-       ssize_t bytes_read = 0;
-       int str_pos = 0;
-       struct visornic_devdata *devdata;
-       char *vbuf;
-
-       if (len > MAX_BUF)
-               len = MAX_BUF;
-       vbuf = kzalloc(len, GFP_KERNEL);
-       if (!vbuf)
-               return -ENOMEM;
-
-       /* for each vnic channel
-        * dump out channel specific data
-        */
-       for (i = 0; i < VISORNICSOPENMAX; i++) {
-               if (!num_visornic_open[i])
-                       continue;
-
-               devdata = netdev_priv(num_visornic_open[i]);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    "Vnic i = %d\n", i);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    "netdev = %s (0x%p), MAC Addr %pM\n",
-                                    num_visornic_open[i]->name,
-                                    num_visornic_open[i],
-                                    num_visornic_open[i]->dev_addr);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    "VisorNic Dev Info = 0x%p\n", devdata);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " num_rcv_bufs = %d\n",
-                                    devdata->num_rcv_bufs);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " max_oustanding_next_xmits = %d\n",
-                                   devdata->max_outstanding_net_xmits);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " upper_threshold_net_xmits = %d\n",
-                                    devdata->upper_threshold_net_xmits);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " lower_threshold_net_xmits = %d\n",
-                                    devdata->lower_threshold_net_xmits);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " queuefullmsg_logged = %d\n",
-                                    devdata->queuefullmsg_logged);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.got_rcv = %lu\n",
-                                    devdata->chstat.got_rcv);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.got_enbdisack = %lu\n",
-                                    devdata->chstat.got_enbdisack);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.got_xmit_done = %lu\n",
-                                    devdata->chstat.got_xmit_done);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.xmit_fail = %lu\n",
-                                    devdata->chstat.xmit_fail);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.sent_enbdis = %lu\n",
-                                    devdata->chstat.sent_enbdis);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.sent_promisc = %lu\n",
-                                    devdata->chstat.sent_promisc);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.sent_post = %lu\n",
-                                    devdata->chstat.sent_post);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.sent_xmit = %lu\n",
-                                    devdata->chstat.sent_xmit);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.reject_count = %lu\n",
-                                    devdata->chstat.reject_count);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " chstat.extra_rcvbufs_sent = %lu\n",
-                                    devdata->chstat.extra_rcvbufs_sent);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " n_rcv0 = %lu\n", devdata->n_rcv0);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " n_rcv1 = %lu\n", devdata->n_rcv1);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " n_rcv2 = %lu\n", devdata->n_rcv2);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " n_rcvx = %lu\n", devdata->n_rcvx);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " num_rcvbuf_in_iovm = %d\n",
-                                    atomic_read(&devdata->num_rcvbuf_in_iovm));
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " alloc_failed_in_if_needed_cnt = %lu\n",
-                                    devdata->alloc_failed_in_if_needed_cnt);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " alloc_failed_in_repost_rtn_cnt = %lu\n",
-                                    devdata->alloc_failed_in_repost_rtn_cnt);
-               /* str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                *                   " inner_loop_limit_reached_cnt = %lu\n",
-                *                   devdata->inner_loop_limit_reached_cnt);
-                */
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " found_repost_rcvbuf_cnt = %lu\n",
-                                    devdata->found_repost_rcvbuf_cnt);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " repost_found_skb_cnt = %lu\n",
-                                    devdata->repost_found_skb_cnt);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " n_repost_deficit = %lu\n",
-                                    devdata->n_repost_deficit);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " bad_rcv_buf = %lu\n",
-                                    devdata->bad_rcv_buf);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " n_rcv_packets_not_accepted = %lu\n",
-                                    devdata->n_rcv_packets_not_accepted);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " interrupts_rcvd = %llu\n",
-                                    devdata->interrupts_rcvd);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " interrupts_notme = %llu\n",
-                                    devdata->interrupts_notme);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " interrupts_disabled = %llu\n",
-                                    devdata->interrupts_disabled);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " busy_cnt = %llu\n",
-                                    devdata->busy_cnt);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " flow_control_upper_hits = %llu\n",
-                                    devdata->flow_control_upper_hits);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " flow_control_lower_hits = %llu\n",
-                                    devdata->flow_control_lower_hits);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " thread_wait_ms = %d\n",
-                                    devdata->thread_wait_ms);
-               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
-                                    " netif_queue = %s\n",
-                                    netif_queue_stopped(devdata->netdev) ?
-                                    "stopped" : "running");
-       }
-       bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos);
-       kfree(vbuf);
-       return bytes_read;
-}
-
 static ssize_t enable_ints_write(struct file *file,
                                 const char __user *buffer,
                                 size_t count, loff_t *ppos)
 {
-       char buf[4];
-       int i, new_value;
-       struct visornic_devdata *devdata;
-
-       if (count >= ARRAY_SIZE(buf))
-               return -EINVAL;
-
-       buf[count] = '\0';
-       if (copy_from_user(buf, buffer, count))
-               return -EFAULT;
-
-       i = kstrtoint(buf, 10, &new_value);
-       if (i != 0)
-               return -EFAULT;
-
-       /* set all counts to new_value usually 0 */
-       for (i = 0; i < VISORNICSOPENMAX; i++) {
-               if (num_visornic_open[i]) {
-                       devdata = netdev_priv(num_visornic_open[i]);
-                       /* TODO update features bit in channel */
-               }
-       }
-
+       /*
+        * Don't want to break ABI here by having a debugfs
+        * file that no longer exists or is writable, so
+        * lets just make this a vestigual function
+        */
        return count;
 }
 
@@ -509,44 +331,29 @@ static ssize_t enable_ints_write(struct file *file,
  *     Returns void.
  */
 static void
-visornic_serverdown_complete(struct work_struct *work)
+visornic_serverdown_complete(struct visornic_devdata *devdata)
 {
-       struct visornic_devdata *devdata;
        struct net_device *netdev;
-       unsigned long flags;
-       int i = 0, count = 0;
 
-       devdata = container_of(work, struct visornic_devdata,
-                              serverdown_completion);
        netdev = devdata->netdev;
 
-       /* Stop using datachan */
-       visor_thread_stop(&devdata->threadinfo);
-
-       /* Inform Linux that the link is down */
-       netif_carrier_off(netdev);
-       netif_stop_queue(netdev);
+       /* Stop polling for interrupts */
+       del_timer_sync(&devdata->irq_poll_timer);
 
-       /* Free the skb for XMITs that haven't been serviced by the server
-        * We shouldn't have to inform Linux about these IOs because they
-        * are "lost in the ethernet"
-        */
-       skb_queue_purge(&devdata->xmitbufhead);
+       rtnl_lock();
+       dev_close(netdev);
+       rtnl_unlock();
 
-       spin_lock_irqsave(&devdata->priv_lock, flags);
-       /* free rcv buffers */
-       for (i = 0; i < devdata->num_rcv_bufs; i++) {
-               if (devdata->rcvbuf[i]) {
-                       kfree_skb(devdata->rcvbuf[i]);
-                       devdata->rcvbuf[i] = NULL;
-                       count++;
-               }
-       }
        atomic_set(&devdata->num_rcvbuf_in_iovm, 0);
-       spin_unlock_irqrestore(&devdata->priv_lock, flags);
+       devdata->chstat.sent_xmit = 0;
+       devdata->chstat.got_xmit_done = 0;
+
+       if (devdata->server_down_complete_func)
+               (*devdata->server_down_complete_func)(devdata->dev, 0);
 
        devdata->server_down = true;
        devdata->server_change_state = false;
+       devdata->server_down_complete_func = NULL;
 }
 
 /**
@@ -558,15 +365,31 @@ visornic_serverdown_complete(struct work_struct *work)
  *     Returns 0 if we scheduled the work, -EINVAL on error.
  */
 static int
-visornic_serverdown(struct visornic_devdata *devdata)
+visornic_serverdown(struct visornic_devdata *devdata,
+                   visorbus_state_complete_func complete_func)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&devdata->priv_lock, flags);
        if (!devdata->server_down && !devdata->server_change_state) {
+               if (devdata->going_away) {
+                       spin_unlock_irqrestore(&devdata->priv_lock, flags);
+                       dev_dbg(&devdata->dev->device,
+                               "%s aborting because device removal pending\n",
+                               __func__);
+                       return -ENODEV;
+               }
                devdata->server_change_state = true;
-               queue_work(visornic_serverdown_workqueue,
-                          &devdata->serverdown_completion);
+               devdata->server_down_complete_func = complete_func;
+               spin_unlock_irqrestore(&devdata->priv_lock, flags);
+               visornic_serverdown_complete(devdata);
        } else if (devdata->server_change_state) {
+               dev_dbg(&devdata->dev->device, "%s changing state\n",
+                       __func__);
+               spin_unlock_irqrestore(&devdata->priv_lock, flags);
                return -EINVAL;
-       }
+       } else
+               spin_unlock_irqrestore(&devdata->priv_lock, flags);
        return 0;
 }
 
@@ -625,11 +448,14 @@ post_skb(struct uiscmdrsp *cmdrsp,
        if ((cmdrsp->net.rcvpost.frag.pi_off + skb->len) <= PI_PAGE_SIZE) {
                cmdrsp->net.type = NET_RCV_POST;
                cmdrsp->cmdtype = CMD_NET_TYPE;
-               visorchannel_signalinsert(devdata->dev->visorchannel,
+               if (visorchannel_signalinsert(devdata->dev->visorchannel,
                                          IOCHAN_TO_IOPART,
-                                         cmdrsp);
-               atomic_inc(&devdata->num_rcvbuf_in_iovm);
-               devdata->chstat.sent_post++;
+                                         cmdrsp)) {
+                       atomic_inc(&devdata->num_rcvbuf_in_iovm);
+                       devdata->chstat.sent_post++;
+               } else {
+                       devdata->chstat.sent_post_failed++;
+               }
        }
 }
 
@@ -651,10 +477,10 @@ send_enbdis(struct net_device *netdev, int state,
        devdata->cmdrsp_rcv->net.enbdis.context = netdev;
        devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS;
        devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE;
-       visorchannel_signalinsert(devdata->dev->visorchannel,
+       if (visorchannel_signalinsert(devdata->dev->visorchannel,
                                  IOCHAN_TO_IOPART,
-                                 devdata->cmdrsp_rcv);
-       devdata->chstat.sent_enbdis++;
+                                 devdata->cmdrsp_rcv))
+               devdata->chstat.sent_enbdis++;
 }
 
 /**
@@ -676,9 +502,6 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout)
        unsigned long flags;
        int wait = 0;
 
-       /* stop the transmit queue so nothing more can be transmitted */
-       netif_stop_queue(netdev);
-
        /* send a msg telling the other end we are stopping incoming pkts */
        spin_lock_irqsave(&devdata->priv_lock, flags);
        devdata->enabled = 0;
@@ -695,12 +518,14 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout)
         * when it gets a disable.
         */
        spin_lock_irqsave(&devdata->priv_lock, flags);
-       while ((timeout == VISORNIC_INFINITE_RESPONSE_WAIT) ||
+       while ((timeout == VISORNIC_INFINITE_RSP_WAIT) ||
               (wait < timeout)) {
                if (devdata->enab_dis_acked)
                        break;
                if (devdata->server_down || devdata->server_change_state) {
                        spin_unlock_irqrestore(&devdata->priv_lock, flags);
+                       dev_dbg(&netdev->dev, "%s server went away\n",
+                               __func__);
                        return -EIO;
                }
                set_current_state(TASK_INTERRUPTIBLE);
@@ -722,10 +547,16 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout)
                                break;
                }
        }
-
        /* we've set enabled to 0, so we can give up the lock. */
        spin_unlock_irqrestore(&devdata->priv_lock, flags);
 
+       /* stop the transmit queue so nothing more can be transmitted */
+       netif_stop_queue(netdev);
+
+       napi_disable(&devdata->napi);
+
+       skb_queue_purge(&devdata->xmitbufhead);
+
        /* Free rcv buffers - other end has automatically unposed them on
         * disable
         */
@@ -736,13 +567,6 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout)
                }
        }
 
-       /* remove references from array */
-       for (i = 0; i < VISORNICSOPENMAX; i++)
-               if (num_visornic_open[i] == netdev) {
-                       num_visornic_open[i] = NULL;
-                       break;
-               }
-
        return 0;
 }
 
@@ -814,11 +638,15 @@ visornic_enable_with_timeout(struct net_device *netdev, const int timeout)
         * gets a disable.
         */
        i = init_rcv_bufs(netdev, devdata);
-       if (i < 0)
+       if (i < 0) {
+               dev_err(&netdev->dev,
+                       "%s failed to init rcv bufs (%d)\n", __func__, i);
                return i;
+       }
 
        spin_lock_irqsave(&devdata->priv_lock, flags);
        devdata->enabled = 1;
+       devdata->enab_dis_acked = 0;
 
        /* now we're ready, let's send an ENB to uisnic but until we get
         * an ACK back from uisnic, we'll drop the packets
@@ -829,15 +657,18 @@ visornic_enable_with_timeout(struct net_device *netdev, const int timeout)
        /* send enable and wait for ack -- don't hold lock when sending enable
         * because if the queue is full, insert might sleep.
         */
+       napi_enable(&devdata->napi);
        send_enbdis(netdev, 1, devdata);
 
        spin_lock_irqsave(&devdata->priv_lock, flags);
-       while ((timeout == VISORNIC_INFINITE_RESPONSE_WAIT) ||
+       while ((timeout == VISORNIC_INFINITE_RSP_WAIT) ||
               (wait < timeout)) {
                if (devdata->enab_dis_acked)
                        break;
                if (devdata->server_down || devdata->server_change_state) {
                        spin_unlock_irqrestore(&devdata->priv_lock, flags);
+                       dev_dbg(&netdev->dev, "%s server went away\n",
+                               __func__);
                        return -EIO;
                }
                set_current_state(TASK_INTERRUPTIBLE);
@@ -848,19 +679,13 @@ visornic_enable_with_timeout(struct net_device *netdev, const int timeout)
 
        spin_unlock_irqrestore(&devdata->priv_lock, flags);
 
-       if (!devdata->enab_dis_acked)
+       if (!devdata->enab_dis_acked) {
+               dev_err(&netdev->dev, "%s missing ACK\n", __func__);
                return -EIO;
-
-       /* find an open slot in the array to save off VisorNic references
-        * for debug
-        */
-       for (i = 0; i < VISORNICSOPENMAX; i++) {
-               if (!num_visornic_open[i]) {
-                       num_visornic_open[i] = netdev;
-                       break;
-               }
        }
 
+       netif_start_queue(netdev);
+
        return 0;
 }
 
@@ -882,20 +707,29 @@ visornic_timeout_reset(struct work_struct *work)
        devdata = container_of(work, struct visornic_devdata, timeout_reset);
        netdev = devdata->netdev;
 
-       netif_stop_queue(netdev);
-       response = visornic_disable_with_timeout(netdev, 100);
+       rtnl_lock();
+       if (!netif_running(netdev)) {
+               rtnl_unlock();
+               return;
+       }
+
+       response = visornic_disable_with_timeout(netdev,
+                                                VISORNIC_INFINITE_RSP_WAIT);
        if (response)
                goto call_serverdown;
 
-       response = visornic_enable_with_timeout(netdev, 100);
+       response = visornic_enable_with_timeout(netdev,
+                                               VISORNIC_INFINITE_RSP_WAIT);
        if (response)
                goto call_serverdown;
-       netif_wake_queue(netdev);
+
+       rtnl_unlock();
 
        return;
 
 call_serverdown:
-       visornic_serverdown(devdata);
+       visornic_serverdown(devdata, NULL);
+       rtnl_unlock();
 }
 
 /**
@@ -908,12 +742,7 @@ call_serverdown:
 static int
 visornic_open(struct net_device *netdev)
 {
-       visornic_enable_with_timeout(netdev, VISORNIC_INFINITE_RESPONSE_WAIT);
-
-       /* start the interface's transmit queue, allowing it to accept
-        * packets for transmission
-        */
-       netif_start_queue(netdev);
+       visornic_enable_with_timeout(netdev, VISORNIC_INFINITE_RSP_WAIT);
 
        return 0;
 }
@@ -928,12 +757,58 @@ visornic_open(struct net_device *netdev)
 static int
 visornic_close(struct net_device *netdev)
 {
-       netif_stop_queue(netdev);
-       visornic_disable_with_timeout(netdev, VISORNIC_INFINITE_RESPONSE_WAIT);
+       visornic_disable_with_timeout(netdev, VISORNIC_INFINITE_RSP_WAIT);
 
        return 0;
 }
 
+/**
+ *     devdata_xmits_outstanding - compute outstanding xmits
+ *     @devdata: visornic_devdata for device
+ *
+ *     Return value is the number of outstanding xmits.
+ */
+static unsigned long devdata_xmits_outstanding(struct visornic_devdata *devdata)
+{
+       if (devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done)
+               return devdata->chstat.sent_xmit -
+                       devdata->chstat.got_xmit_done;
+       else
+               return (ULONG_MAX - devdata->chstat.got_xmit_done
+                       + devdata->chstat.sent_xmit + 1);
+}
+
+/**
+ *     vnic_hit_high_watermark
+ *     @devdata: indicates visornic device we are checking
+ *     @high_watermark: max num of unacked xmits we will tolerate,
+ *                       before we will start throttling
+ *
+ *      Returns true iff the number of unacked xmits sent to
+ *      the IO partition is >= high_watermark.
+ */
+static inline bool vnic_hit_high_watermark(struct visornic_devdata *devdata,
+                                          ulong high_watermark)
+{
+       return (devdata_xmits_outstanding(devdata) >= high_watermark);
+}
+
+/**
+ *     vnic_hit_low_watermark
+ *     @devdata: indicates visornic device we are checking
+ *     @low_watermark: we will wait until the num of unacked xmits
+ *                      drops to this value or lower before we start
+ *                      transmitting again
+ *
+ *      Returns true iff the number of unacked xmits sent to
+ *      the IO partition is <= low_watermark.
+ */
+static inline bool vnic_hit_low_watermark(struct visornic_devdata *devdata,
+                                         ulong low_watermark)
+{
+       return (devdata_xmits_outstanding(devdata) <= low_watermark);
+}
+
 /**
  *     visornic_xmit - send a packet to the IO Partition
  *     @skb: Packet to be sent
@@ -944,7 +819,7 @@ visornic_close(struct net_device *netdev)
  *     function is protected from concurrent calls by a spinlock xmit_lock
  *     in the net_device struct, but as soon as the function returns it
  *     can be called again.
- *     Returns NETDEV_TX_OK for success, NETDEV_TX_BUSY for error.
+ *     Returns NETDEV_TX_OK.
  */
 static int
 visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
@@ -961,7 +836,10 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
            devdata->server_change_state) {
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                devdata->busy_cnt++;
-               return NETDEV_TX_BUSY;
+               dev_dbg(&netdev->dev,
+                       "%s busy - queue stopped\n", __func__);
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
 
        /* sk_buff struct is used to host network data throughout all the
@@ -979,7 +857,11 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
        if (firstfraglen < ETH_HEADER_SIZE) {
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                devdata->busy_cnt++;
-               return NETDEV_TX_BUSY;
+               dev_err(&netdev->dev,
+                       "%s busy - first frag too small (%d)\n",
+                       __func__, firstfraglen);
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
 
        if ((len < ETH_MIN_PACKET_SIZE) &&
@@ -1002,13 +884,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
        /* save the pointer to skb -- we'll need it for completion */
        cmdrsp->net.buf = skb;
 
-       if (((devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) &&
-            (devdata->chstat.sent_xmit - devdata->chstat.got_xmit_done >=
-            devdata->max_outstanding_net_xmits)) ||
-            ((devdata->chstat.sent_xmit < devdata->chstat.got_xmit_done) &&
-            (ULONG_MAX - devdata->chstat.got_xmit_done +
-             devdata->chstat.sent_xmit >=
-             devdata->max_outstanding_net_xmits))) {
+       if (vnic_hit_high_watermark(devdata,
+                                   devdata->max_outstanding_net_xmits)) {
                /* too many NET_XMITs queued over to IOVM - need to wait
                 */
                devdata->chstat.reject_count++;
@@ -1018,7 +895,11 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                devdata->busy_cnt++;
-               return NETDEV_TX_BUSY;
+               dev_dbg(&netdev->dev,
+                       "%s busy - waiting for iovm to catch up\n",
+                       __func__);
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
        if (devdata->queuefullmsg_logged)
                devdata->queuefullmsg_logged = 0;
@@ -1055,10 +936,13 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
                visor_copy_fragsinfo_from_skb(skb, firstfraglen,
                                              MAX_PHYS_INFO,
                                              cmdrsp->net.xmt.frags);
-       if (cmdrsp->net.xmt.num_frags == -1) {
+       if (cmdrsp->net.xmt.num_frags < 0) {
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                devdata->busy_cnt++;
-               return NETDEV_TX_BUSY;
+               dev_err(&netdev->dev,
+                       "%s busy - copy frags failed\n", __func__);
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
 
        if (!visorchannel_signalinsert(devdata->dev->visorchannel,
@@ -1066,18 +950,15 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                devdata->busy_cnt++;
-               return NETDEV_TX_BUSY;
+               dev_dbg(&netdev->dev,
+                       "%s busy - signalinsert failed\n", __func__);
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
 
        /* Track the skbs that have been sent to the IOVM for XMIT */
        skb_queue_head(&devdata->xmitbufhead, skb);
 
-       /* set the last transmission start time
-        * linux doc says: Do not forget to update netdev->trans_start to
-        * jiffies after each new tx packet is given to the hardware.
-        */
-       netdev->trans_start = jiffies;
-
        /* update xmt stats */
        devdata->net_stats.tx_packets++;
        devdata->net_stats.tx_bytes += skb->len;
@@ -1086,18 +967,16 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
        /* check to see if we have hit the high watermark for
         * netif_stop_queue()
         */
-       if (((devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) &&
-            (devdata->chstat.sent_xmit - devdata->chstat.got_xmit_done >=
-             devdata->upper_threshold_net_xmits)) ||
-           ((devdata->chstat.sent_xmit < devdata->chstat.got_xmit_done) &&
-            (ULONG_MAX - devdata->chstat.got_xmit_done +
-             devdata->chstat.sent_xmit >=
-             devdata->upper_threshold_net_xmits))) {
+       if (vnic_hit_high_watermark(devdata,
+                                   devdata->upper_threshold_net_xmits)) {
                /* too many NET_XMITs queued over to IOVM - need to wait */
                netif_stop_queue(netdev); /* calling stop queue - call
                                           * netif_wake_queue() after lower
                                           * threshold
                                           */
+               dev_dbg(&netdev->dev,
+                       "%s busy - invoking iovm flow control\n",
+                       __func__);
                devdata->flow_control_upper_hits++;
        }
        spin_unlock_irqrestore(&devdata->priv_lock, flags);
@@ -1112,27 +991,12 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
  *
  *     Returns the net_device_stats for the device
  */
-static struct net_device_stats *
-visornic_get_stats(struct net_device *netdev)
-{
-       struct visornic_devdata *devdata = netdev_priv(netdev);
-
-       return &devdata->net_stats;
-}
-
-/**
- *     visornic_ioctl - ioctl function for netdevice.
- *     @netdev: netdevice
- *     @ifr: ignored
- *     @cmd: ignored
- *
- *     Currently not supported.
- *     Returns EOPNOTSUPP
- */
-static int
-visornic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static struct net_device_stats *
+visornic_get_stats(struct net_device *netdev)
 {
-       return -EOPNOTSUPP;
+       struct visornic_devdata *devdata = netdev_priv(netdev);
+
+       return &devdata->net_stats;
 }
 
 /**
@@ -1201,15 +1065,24 @@ visornic_xmit_timeout(struct net_device *netdev)
        unsigned long flags;
 
        spin_lock_irqsave(&devdata->priv_lock, flags);
+       if (devdata->going_away) {
+               spin_unlock_irqrestore(&devdata->priv_lock, flags);
+               dev_dbg(&devdata->dev->device,
+                       "%s aborting because device removal pending\n",
+                       __func__);
+               return;
+       }
+
        /* Ensure that a ServerDown message hasn't been received */
        if (!devdata->enabled ||
            (devdata->server_down && !devdata->server_change_state)) {
+               dev_dbg(&netdev->dev, "%s no processing\n",
+                       __func__);
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                return;
        }
-       spin_unlock_irqrestore(&devdata->priv_lock, flags);
-
        queue_work(visornic_timeout_reset_workqueue, &devdata->timeout_reset);
+       spin_unlock_irqrestore(&devdata->priv_lock, flags);
 }
 
 /**
@@ -1281,7 +1154,6 @@ repost_return(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata,
                        devdata->bad_rcv_buf++;
                }
        }
-       atomic_dec(&devdata->usage);
        return status;
 }
 
@@ -1293,18 +1165,16 @@ repost_return(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata,
  *     it up the stack.
  *     Returns void
  */
-static void
+static int
 visornic_rx(struct uiscmdrsp *cmdrsp)
 {
        struct visornic_devdata *devdata;
        struct sk_buff *skb, *prev, *curr;
        struct net_device *netdev;
-       int cc, currsize, off, status;
+       int cc, currsize, off;
        struct ethhdr *eth;
        unsigned long flags;
-#ifdef DEBUG
-       struct phys_info testfrags[MAX_PHYS_INFO];
-#endif
+       int rx_count = 0;
 
        /* post new rcv buf to the other end using the cmdrsp we have at hand
         * post it without holding lock - but we'll use the signal lock to
@@ -1314,18 +1184,6 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
        skb = cmdrsp->net.buf;
        netdev = skb->dev;
 
-       if (!netdev) {
-               /* We must have previously downed this network device and
-                * this skb and device is no longer valid. This also means
-                * the skb reference was removed from devdata->rcvbuf so no
-                * need to search for it.
-                * All we can do is free the skb and return.
-                * Note: We crash if we try to log this here.
-                */
-               kfree_skb(skb);
-               return;
-       }
-
        devdata = netdev_priv(netdev);
 
        spin_lock_irqsave(&devdata->priv_lock, flags);
@@ -1335,10 +1193,6 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
        devdata->net_stats.rx_packets++;
        devdata->net_stats.rx_bytes = skb->len;
 
-       atomic_inc(&devdata->usage);    /* don't want a close to happen before
-                                        *  we're done here
-                                        */
-
        /* set length to how much was ACTUALLY received -
         * NOTE: rcv_done_len includes actual length of data rcvd
         * including ethhdr
@@ -1352,7 +1206,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
                 */
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
                repost_return(cmdrsp, devdata, skb, netdev);
-               return;
+               return rx_count;
        }
 
        spin_unlock_irqrestore(&devdata->priv_lock, flags);
@@ -1371,7 +1225,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
                        if (repost_return(cmdrsp, devdata, skb, netdev) < 0)
                                dev_err(&devdata->netdev->dev,
                                        "repost_return failed");
-                       return;
+                       return rx_count;
                }
                /* length rcvd is greater than firstfrag in this skb rcv buf  */
                skb->tail += RCVPOST_BUF_SIZE;  /* amount in skb->data */
@@ -1386,7 +1240,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
                        if (repost_return(cmdrsp, devdata, skb, netdev) < 0)
                                dev_err(&devdata->netdev->dev,
                                        "repost_return failed");
-                       return;
+                       return rx_count;
                }
                skb->tail += skb->len;
                skb->data_len = 0;      /* nothing rcvd in frag_list */
@@ -1405,7 +1259,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
        if (cmdrsp->net.rcv.rcvbuf[0] != skb) {
                if (repost_return(cmdrsp, devdata, skb, netdev) < 0)
                        dev_err(&devdata->netdev->dev, "repost_return failed");
-               return;
+               return rx_count;
        }
 
        if (cmdrsp->net.rcv.numrcvbufs > 1) {
@@ -1431,29 +1285,12 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
                        curr->data_len = 0;
                        off += currsize;
                }
-#ifdef DEBUG
                /* assert skb->len == off */
                if (skb->len != off) {
-                       dev_err(&devdata->netdev->dev,
-                               "%s something wrong; skb->len:%d != off:%d\n",
-                               netdev->name, skb->len, off);
-               }
-               /* test code */
-               cc = util_copy_fragsinfo_from_skb("rcvchaintest", skb,
-                                                 RCVPOST_BUF_SIZE,
-                                                 MAX_PHYS_INFO, testfrags);
-               if (cc != cmdrsp->net.rcv.numrcvbufs) {
-                       dev_err(&devdata->netdev->dev,
-                               "**** %s Something wrong; rcvd chain length %d different from one we calculated %d\n",
-                               netdev->name, cmdrsp->net.rcv.numrcvbufs, cc);
+                       netdev_err(devdata->netdev,
+                                  "something wrong; skb->len:%d != off:%d\n",
+                                  skb->len, off);
                }
-               for (i = 0; i < cc; i++) {
-                       dev_inf(&devdata->netdev->dev,
-                               "test:RCVPOST_BUF_SIZE:%d[%d] pfn:%llu off:0x%x len:%d\n",
-                               RCVPOST_BUF_SIZE, i, testfrags[i].pi_pfn,
-                               testfrags[i].pi_off, testfrags[i].pi_len);
-               }
-#endif
        }
 
        /* set up packet's protocl type using ethernet header - this
@@ -1505,10 +1342,11 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
                /* drop packet - don't forward it up to OS */
                devdata->n_rcv_packets_not_accepted++;
                repost_return(cmdrsp, devdata, skb, netdev);
-               return;
+               return rx_count;
        } while (0);
 
-       status = netif_rx(skb);
+       rx_count++;
+       netif_receive_skb(skb);
        /* netif_rx returns various values, but "in practice most drivers
         * ignore the return value
         */
@@ -1520,6 +1358,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
         * new rcv buffer.
         */
        repost_return(cmdrsp, devdata, skb, netdev);
+       return rx_count;
 }
 
 /**
@@ -1545,14 +1384,11 @@ devdata_initialize(struct visornic_devdata *devdata, struct visor_device *dev)
        spin_unlock(&dev_num_pool_lock);
        if (devnum == MAXDEVICES)
                devnum = -1;
-       if (devnum < 0) {
-               kfree(devdata);
+       if (devnum < 0)
                return NULL;
-       }
        devdata->devnum = devnum;
        devdata->dev = dev;
        strncpy(devdata->name, dev_name(&dev->device), sizeof(devdata->name));
-       kref_init(&devdata->kref);
        spin_lock(&lock_all_devices);
        list_add_tail(&devdata->list_all, &list_all_devices);
        spin_unlock(&lock_all_devices);
@@ -1560,24 +1396,23 @@ devdata_initialize(struct visornic_devdata *devdata, struct visor_device *dev)
 }
 
 /**
- *     devdata_release - Frees up a devdata
- *     @mykref: kref to the devdata
+ *     devdata_release - Frees up references in devdata
+ *     @devdata: struct to clean up
  *
- *     Frees up a devdata.
+ *     Frees up references in devdata.
  *     Returns void
  */
-static void devdata_release(struct kref *mykref)
+static void devdata_release(struct visornic_devdata *devdata)
 {
-       struct visornic_devdata *devdata =
-               container_of(mykref, struct visornic_devdata, kref);
-
        spin_lock(&dev_num_pool_lock);
        clear_bit(devdata->devnum, dev_num_pool);
        spin_unlock(&dev_num_pool_lock);
        spin_lock(&lock_all_devices);
        list_del(&devdata->list_all);
        spin_unlock(&lock_all_devices);
-       kfree(devdata);
+       kfree(devdata->rcvbuf);
+       kfree(devdata->cmdrsp_rcv);
+       kfree(devdata->xmit_cmdrsp);
 }
 
 static const struct net_device_ops visornic_dev_ops = {
@@ -1585,12 +1420,163 @@ static const struct net_device_ops visornic_dev_ops = {
        .ndo_stop = visornic_close,
        .ndo_start_xmit = visornic_xmit,
        .ndo_get_stats = visornic_get_stats,
-       .ndo_do_ioctl = visornic_ioctl,
        .ndo_change_mtu = visornic_change_mtu,
        .ndo_tx_timeout = visornic_xmit_timeout,
        .ndo_set_rx_mode = visornic_set_multi,
 };
 
+/* DebugFS code */
+static ssize_t info_debugfs_read(struct file *file, char __user *buf,
+                                size_t len, loff_t *offset)
+{
+       ssize_t bytes_read = 0;
+       int str_pos = 0;
+       struct visornic_devdata *devdata;
+       struct net_device *dev;
+       char *vbuf;
+
+       if (len > MAX_BUF)
+               len = MAX_BUF;
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+       /* for each vnic channel
+        * dump out channel specific data
+        */
+       rcu_read_lock();
+       for_each_netdev_rcu(current->nsproxy->net_ns, dev) {
+               /*
+                * Only consider netdevs that are visornic, and are open
+                */
+               if ((dev->netdev_ops != &visornic_dev_ops) ||
+                   (!netif_queue_stopped(dev)))
+                       continue;
+
+               devdata = netdev_priv(dev);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    "netdev = %s (0x%p), MAC Addr %pM\n",
+                                    dev->name,
+                                    dev,
+                                    dev->dev_addr);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    "VisorNic Dev Info = 0x%p\n", devdata);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " num_rcv_bufs = %d\n",
+                                    devdata->num_rcv_bufs);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " max_oustanding_next_xmits = %lu\n",
+                                   devdata->max_outstanding_net_xmits);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " upper_threshold_net_xmits = %lu\n",
+                                    devdata->upper_threshold_net_xmits);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " lower_threshold_net_xmits = %lu\n",
+                                    devdata->lower_threshold_net_xmits);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " queuefullmsg_logged = %d\n",
+                                    devdata->queuefullmsg_logged);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.got_rcv = %lu\n",
+                                    devdata->chstat.got_rcv);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.got_enbdisack = %lu\n",
+                                    devdata->chstat.got_enbdisack);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.got_xmit_done = %lu\n",
+                                    devdata->chstat.got_xmit_done);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.xmit_fail = %lu\n",
+                                    devdata->chstat.xmit_fail);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.sent_enbdis = %lu\n",
+                                    devdata->chstat.sent_enbdis);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.sent_promisc = %lu\n",
+                                    devdata->chstat.sent_promisc);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.sent_post = %lu\n",
+                                    devdata->chstat.sent_post);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.sent_post_failed = %lu\n",
+                                    devdata->chstat.sent_post_failed);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.sent_xmit = %lu\n",
+                                    devdata->chstat.sent_xmit);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.reject_count = %lu\n",
+                                    devdata->chstat.reject_count);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " chstat.extra_rcvbufs_sent = %lu\n",
+                                    devdata->chstat.extra_rcvbufs_sent);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " n_rcv0 = %lu\n", devdata->n_rcv0);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " n_rcv1 = %lu\n", devdata->n_rcv1);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " n_rcv2 = %lu\n", devdata->n_rcv2);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " n_rcvx = %lu\n", devdata->n_rcvx);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " num_rcvbuf_in_iovm = %d\n",
+                                    atomic_read(&devdata->num_rcvbuf_in_iovm));
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " alloc_failed_in_if_needed_cnt = %lu\n",
+                                    devdata->alloc_failed_in_if_needed_cnt);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " alloc_failed_in_repost_rtn_cnt = %lu\n",
+                                    devdata->alloc_failed_in_repost_rtn_cnt);
+               /* str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                *                   " inner_loop_limit_reached_cnt = %lu\n",
+                *                   devdata->inner_loop_limit_reached_cnt);
+                */
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " found_repost_rcvbuf_cnt = %lu\n",
+                                    devdata->found_repost_rcvbuf_cnt);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " repost_found_skb_cnt = %lu\n",
+                                    devdata->repost_found_skb_cnt);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " n_repost_deficit = %lu\n",
+                                    devdata->n_repost_deficit);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " bad_rcv_buf = %lu\n",
+                                    devdata->bad_rcv_buf);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " n_rcv_packets_not_accepted = %lu\n",
+                                    devdata->n_rcv_packets_not_accepted);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " interrupts_rcvd = %llu\n",
+                                    devdata->interrupts_rcvd);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " interrupts_notme = %llu\n",
+                                    devdata->interrupts_notme);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " interrupts_disabled = %llu\n",
+                                    devdata->interrupts_disabled);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " busy_cnt = %llu\n",
+                                    devdata->busy_cnt);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " flow_control_upper_hits = %llu\n",
+                                    devdata->flow_control_upper_hits);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " flow_control_lower_hits = %llu\n",
+                                    devdata->flow_control_lower_hits);
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " netif_queue = %s\n",
+                                    netif_queue_stopped(devdata->netdev) ?
+                                    "stopped" : "running");
+               str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+                                    " xmits_outstanding = %lu\n",
+                                    devdata_xmits_outstanding(devdata));
+       }
+       rcu_read_unlock();
+       bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos);
+       kfree(vbuf);
+       return bytes_read;
+}
+
 /**
  *     send_rcv_posts_if_needed
  *     @devdata: visornic device
@@ -1644,15 +1630,15 @@ send_rcv_posts_if_needed(struct visornic_devdata *devdata)
  *     Returns when response queue is empty or when the threadd stops.
  */
 static void
-drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata)
+service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata,
+                  int *rx_work_done)
 {
        unsigned long flags;
        struct net_device *netdev;
 
-       /* drain queue */
-       while (1) {
-               /* TODO: CLIENT ACQUIRE -- Don't really need this at the
-                * moment */
+       /* TODO: CLIENT ACQUIRE -- Don't really need this at the
+        * moment */
+       for (;;) {
                if (!visorchannel_signalremove(devdata->dev->visorchannel,
                                               IOCHAN_FROM_IOPART,
                                               cmdrsp))
@@ -1662,7 +1648,7 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata)
                case NET_RCV:
                        devdata->chstat.got_rcv++;
                        /* process incoming packet */
-                       visornic_rx(cmdrsp);
+                       *rx_work_done += visornic_rx(cmdrsp);
                        break;
                case NET_XMIT_DONE:
                        spin_lock_irqsave(&devdata->priv_lock, flags);
@@ -1678,16 +1664,8 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata)
                                 * the lower watermark for
                                 * netif_wake_queue()
                                 */
-                               if (((devdata->chstat.sent_xmit >=
-                                   devdata->chstat.got_xmit_done) &&
-                                   (devdata->chstat.sent_xmit -
-                                   devdata->chstat.got_xmit_done <=
-                                   devdata->lower_threshold_net_xmits)) ||
-                                   ((devdata->chstat.sent_xmit <
-                                   devdata->chstat.got_xmit_done) &&
-                                   (ULONG_MAX - devdata->chstat.got_xmit_done
-                                   + devdata->chstat.sent_xmit <=
-                                   devdata->lower_threshold_net_xmits))) {
+                               if (vnic_hit_low_watermark(devdata,
+                                       devdata->lower_threshold_net_xmits)) {
                                        /* enough NET_XMITs completed
                                         * so can restart netif queue
                                         */
@@ -1738,50 +1716,51 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata)
                        break;
                }
                /* cmdrsp is now available for reuse  */
-
-               if (kthread_should_stop())
-                       break;
        }
 }
 
+static int visornic_poll(struct napi_struct *napi, int budget)
+{
+       struct visornic_devdata *devdata = container_of(napi,
+                                                       struct visornic_devdata,
+                                                       napi);
+       int rx_count = 0;
+
+       send_rcv_posts_if_needed(devdata);
+       service_resp_queue(devdata->cmdrsp, devdata, &rx_count);
+
+       /*
+        * If there aren't any more packets to receive
+        * stop the poll
+        */
+       if (rx_count < budget)
+               napi_complete(napi);
+
+       return rx_count;
+}
+
 /**
- *     process_incoming_rsps   - Checks the status of the response queue.
+ *     poll_for_irq    - Checks the status of the response queue.
  *     @v: void pointer to the visronic devdata
  *
  *     Main function of the vnic_incoming thread. Peridocially check the
  *     response queue and drain it if needed.
  *     Returns when thread has stopped.
  */
-static int
-process_incoming_rsps(void *v)
+static void
+poll_for_irq(unsigned long v)
 {
-       struct visornic_devdata *devdata = v;
-       struct uiscmdrsp *cmdrsp = NULL;
-       const int SZ = SIZEOF_CMDRSP;
+       struct visornic_devdata *devdata = (struct visornic_devdata *)v;
 
-       cmdrsp = kmalloc(SZ, GFP_ATOMIC);
-       if (!cmdrsp)
-               complete_and_exit(&devdata->threadinfo.has_stopped, 0);
+       if (!visorchannel_signalempty(
+                                  devdata->dev->visorchannel,
+                                  IOCHAN_FROM_IOPART))
+               napi_schedule(&devdata->napi);
 
-       while (1) {
-               wait_event_interruptible_timeout(
-                       devdata->rsp_queue, (atomic_read(
-                                            &devdata->interrupt_rcvd) == 1),
-                               msecs_to_jiffies(devdata->thread_wait_ms));
+       atomic_set(&devdata->interrupt_rcvd, 0);
 
-               /* periodically check to see if there are any rcf bufs which
-                * need to get sent to the IOSP. This can only happen if
-                * we run out of memory when trying to allocate skbs.
-                */
-               atomic_set(&devdata->interrupt_rcvd, 0);
-               send_rcv_posts_if_needed(devdata);
-               drain_queue(cmdrsp, devdata);
-               if (kthread_should_stop())
-                       break;
-       }
+       mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
 
-       kfree(cmdrsp);
-       complete_and_exit(&devdata->threadinfo.has_stopped, 0);
 }
 
 /**
@@ -1801,12 +1780,15 @@ static int visornic_probe(struct visor_device *dev)
        u64 features;
 
        netdev = alloc_etherdev(sizeof(struct visornic_devdata));
-       if (!netdev)
+       if (!netdev) {
+               dev_err(&dev->device,
+                       "%s alloc_etherdev failed\n", __func__);
                return -ENOMEM;
+       }
 
        netdev->netdev_ops = &visornic_dev_ops;
        netdev->watchdog_timeo = (5 * HZ);
-       netdev->dev.parent = &dev->device;
+       SET_NETDEV_DEV(netdev, &dev->device);
 
        /* Get MAC adddress from channel and read it into the device. */
        netdev->addr_len = ETH_ALEN;
@@ -1814,16 +1796,23 @@ static int visornic_probe(struct visor_device *dev)
                                  vnic.macaddr);
        err = visorbus_read_channel(dev, channel_offset, netdev->dev_addr,
                                    ETH_ALEN);
-       if (err < 0)
+       if (err < 0) {
+               dev_err(&dev->device,
+                       "%s failed to get mac addr from chan (%d)\n",
+                       __func__, err);
                goto cleanup_netdev;
+       }
 
        devdata = devdata_initialize(netdev_priv(netdev), dev);
        if (!devdata) {
+               dev_err(&dev->device,
+                       "%s devdata_initialize failed\n", __func__);
                err = -ENOMEM;
                goto cleanup_netdev;
        }
 
        devdata->netdev = netdev;
+       dev_set_drvdata(&dev->device, devdata);
        init_waitqueue_head(&devdata->rsp_queue);
        spin_lock_init(&devdata->priv_lock);
        devdata->enabled = 0; /* not yet */
@@ -1834,10 +1823,14 @@ static int visornic_probe(struct visor_device *dev)
                                  vnic.num_rcv_bufs);
        err = visorbus_read_channel(dev, channel_offset,
                                    &devdata->num_rcv_bufs, 4);
-       if (err)
+       if (err) {
+               dev_err(&dev->device,
+                       "%s failed to get #rcv bufs from chan (%d)\n",
+                       __func__, err);
                goto cleanup_netdev;
+       }
 
-       devdata->rcvbuf = kmalloc(sizeof(struct sk_buff *) *
+       devdata->rcvbuf = kzalloc(sizeof(struct sk_buff *) *
                                  devdata->num_rcv_bufs, GFP_KERNEL);
        if (!devdata->rcvbuf) {
                err = -ENOMEM;
@@ -1846,12 +1839,15 @@ static int visornic_probe(struct visor_device *dev)
 
        /* set the net_xmit outstanding threshold */
        /* always leave two slots open but you should have 3 at a minimum */
+       /* note that max_outstanding_net_xmits must be > 0 */
        devdata->max_outstanding_net_xmits =
-               max(3, ((devdata->num_rcv_bufs / 3) - 2));
+               max_t(unsigned long, 3, ((devdata->num_rcv_bufs / 3) - 2));
        devdata->upper_threshold_net_xmits =
-               max(2, devdata->max_outstanding_net_xmits - 1);
+               max_t(unsigned long,
+                     2, (devdata->max_outstanding_net_xmits - 1));
        devdata->lower_threshold_net_xmits =
-               max(1, devdata->max_outstanding_net_xmits / 2);
+               max_t(unsigned long,
+                     1, (devdata->max_outstanding_net_xmits / 2));
 
        skb_queue_head_init(&devdata->xmitbufhead);
 
@@ -1866,8 +1862,6 @@ static int visornic_probe(struct visor_device *dev)
                err = -ENOMEM;
                goto cleanup_xmit_cmdrsp;
        }
-       INIT_WORK(&devdata->serverdown_completion,
-                 visornic_serverdown_complete);
        INIT_WORK(&devdata->timeout_reset, visornic_timeout_reset);
        devdata->server_down = false;
        devdata->server_change_state = false;
@@ -1876,42 +1870,70 @@ static int visornic_probe(struct visor_device *dev)
        channel_offset = offsetof(struct spar_io_channel_protocol,
                                  vnic.mtu);
        err = visorbus_read_channel(dev, channel_offset, &netdev->mtu, 4);
-       if (err)
+       if (err) {
+               dev_err(&dev->device,
+                       "%s failed to get mtu from chan (%d)\n",
+                       __func__, err);
                goto cleanup_xmit_cmdrsp;
+       }
 
        /* TODO: Setup Interrupt information */
        /* Let's start our threads to get responses */
+       netif_napi_add(netdev, &devdata->napi, visornic_poll, 64);
+
+       setup_timer(&devdata->irq_poll_timer, poll_for_irq,
+                   (unsigned long)devdata);
+       /*
+        * Note: This time has to start running before the while
+        * loop below because the napi routine is responsible for
+        * setting enab_dis_acked
+        */
+       mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
+
        channel_offset = offsetof(struct spar_io_channel_protocol,
                                  channel_header.features);
        err = visorbus_read_channel(dev, channel_offset, &features, 8);
-       if (err)
-               goto cleanup_xmit_cmdrsp;
+       if (err) {
+               dev_err(&dev->device,
+                       "%s failed to get features from chan (%d)\n",
+                       __func__, err);
+               goto cleanup_napi_add;
+       }
 
        features |= ULTRA_IO_CHANNEL_IS_POLLING;
        err = visorbus_write_channel(dev, channel_offset, &features, 8);
-       if (err)
-               goto cleanup_xmit_cmdrsp;
-
-       devdata->thread_wait_ms = 2;
-       visor_thread_start(&devdata->threadinfo, process_incoming_rsps,
-                          devdata, "vnic_incoming");
+       if (err) {
+               dev_err(&dev->device,
+                       "%s failed to set features in chan (%d)\n",
+                       __func__, err);
+               goto cleanup_napi_add;
+       }
 
        err = register_netdev(netdev);
-       if (err)
-               goto cleanup_thread_stop;
+       if (err) {
+               dev_err(&dev->device,
+                       "%s register_netdev failed (%d)\n", __func__, err);
+               goto cleanup_napi_add;
+       }
 
        /* create debgug/sysfs directories */
        devdata->eth_debugfs_dir = debugfs_create_dir(netdev->name,
                                                      visornic_debugfs_dir);
        if (!devdata->eth_debugfs_dir) {
+               dev_err(&dev->device,
+                       "%s debugfs_create_dir %s failed\n",
+                       __func__, netdev->name);
                err = -ENOMEM;
-               goto cleanup_thread_stop;
+               goto cleanup_xmit_cmdrsp;
        }
 
+       dev_info(&dev->device, "%s success netdev=%s\n",
+                __func__, netdev->name);
        return 0;
 
-cleanup_thread_stop:
-       visor_thread_stop(&devdata->threadinfo);
+cleanup_napi_add:
+       del_timer_sync(&devdata->irq_poll_timer);
+       netif_napi_del(&devdata->napi);
 
 cleanup_xmit_cmdrsp:
        kfree(devdata->xmit_cmdrsp);
@@ -1954,12 +1976,41 @@ static void host_side_disappeared(struct visornic_devdata *devdata)
 static void visornic_remove(struct visor_device *dev)
 {
        struct visornic_devdata *devdata = dev_get_drvdata(&dev->device);
+       struct net_device *netdev;
+       unsigned long flags;
 
-       if (!devdata)
+       if (!devdata) {
+               dev_err(&dev->device, "%s no devdata\n", __func__);
+               return;
+       }
+       spin_lock_irqsave(&devdata->priv_lock, flags);
+       if (devdata->going_away) {
+               spin_unlock_irqrestore(&devdata->priv_lock, flags);
+               dev_err(&dev->device, "%s already being removed\n", __func__);
                return;
+       }
+       devdata->going_away = true;
+       spin_unlock_irqrestore(&devdata->priv_lock, flags);
+       netdev = devdata->netdev;
+       if (!netdev) {
+               dev_err(&dev->device, "%s not net device\n", __func__);
+               return;
+       }
+
+       /* going_away prevents new items being added to the workqueues */
+       flush_workqueue(visornic_timeout_reset_workqueue);
+
+       debugfs_remove_recursive(devdata->eth_debugfs_dir);
+
+       unregister_netdev(netdev);  /* this will call visornic_close() */
+
+       del_timer_sync(&devdata->irq_poll_timer);
+       netif_napi_del(&devdata->napi);
+
        dev_set_drvdata(&dev->device, NULL);
        host_side_disappeared(devdata);
-       kref_put(&devdata->kref, devdata_release);
+       devdata_release(devdata);
+       free_netdev(netdev);
 }
 
 /**
@@ -1980,8 +2031,7 @@ static int visornic_pause(struct visor_device *dev,
 {
        struct visornic_devdata *devdata = dev_get_drvdata(&dev->device);
 
-       visornic_serverdown(devdata);
-       complete_func(dev, 0);
+       visornic_serverdown(devdata, complete_func);
        return 0;
 }
 
@@ -2003,37 +2053,40 @@ static int visornic_resume(struct visor_device *dev,
        unsigned long flags;
 
        devdata = dev_get_drvdata(&dev->device);
-       if (!devdata)
+       if (!devdata) {
+               dev_err(&dev->device, "%s no devdata\n", __func__);
                return -EINVAL;
+       }
 
        netdev = devdata->netdev;
 
-       if (devdata->server_down && !devdata->server_change_state) {
-               devdata->server_change_state = true;
-               /* Must transition channel to ATTACHED state BEFORE
-                * we can start using the device again.
-                * TODO: State transitions
-                */
-               visor_thread_start(&devdata->threadinfo, process_incoming_rsps,
-                                  devdata, "vnic_incoming");
-               init_rcv_bufs(netdev, devdata);
-               spin_lock_irqsave(&devdata->priv_lock, flags);
-               devdata->enabled = 1;
-
-               /* Now we're ready, let's send an ENB to uisnic but until
-                * we get an ACK back from uisnic, we'll drop the packets
-                */
-               devdata->enab_dis_acked = 0;
+       spin_lock_irqsave(&devdata->priv_lock, flags);
+       if (devdata->server_change_state) {
                spin_unlock_irqrestore(&devdata->priv_lock, flags);
-
-               /* send enable and wait for ack - don't hold lock when
-                * sending enable because if the queue if sull, insert
-                * might sleep.
-                */
-               send_enbdis(netdev, 1, devdata);
-       } else if (devdata->server_change_state) {
-               return -EIO;
+               dev_err(&dev->device, "%s server already changing state\n",
+                       __func__);
+               return -EINVAL;
+       }
+       if (!devdata->server_down) {
+               spin_unlock_irqrestore(&devdata->priv_lock, flags);
+               dev_err(&dev->device, "%s server not down\n", __func__);
+               complete_func(dev, 0);
+               return 0;
        }
+       devdata->server_change_state = true;
+       spin_unlock_irqrestore(&devdata->priv_lock, flags);
+
+       /* Must transition channel to ATTACHED state BEFORE
+        * we can start using the device again.
+        * TODO: State transitions
+        */
+       mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
+
+       init_rcv_bufs(netdev, devdata);
+
+       rtnl_lock();
+       dev_open(netdev);
+       rtnl_unlock();
 
        complete_func(dev, 0);
        return 0;
@@ -2051,18 +2104,6 @@ static int visornic_init(void)
        struct dentry *ret;
        int err = -ENOMEM;
 
-       /* create workqueue for serverdown completion */
-       visornic_serverdown_workqueue =
-               create_singlethread_workqueue("visornic_serverdown");
-       if (!visornic_serverdown_workqueue)
-               return -ENOMEM;
-
-       /* create workqueue for tx timeout reset */
-       visornic_timeout_reset_workqueue =
-               create_singlethread_workqueue("visornic_timeout_reset");
-       if (!visornic_timeout_reset_workqueue)
-               return -ENOMEM;
-
        visornic_debugfs_dir = debugfs_create_dir("visornic", NULL);
        if (!visornic_debugfs_dir)
                return err;
@@ -2076,12 +2117,6 @@ static int visornic_init(void)
        if (!ret)
                goto cleanup_debugfs;
 
-       /* create workqueue for serverdown completion */
-       visornic_serverdown_workqueue =
-               create_singlethread_workqueue("visornic_serverdown");
-       if (!visornic_serverdown_workqueue)
-               goto cleanup_debugfs;
-
        /* create workqueue for tx timeout reset */
        visornic_timeout_reset_workqueue =
                create_singlethread_workqueue("visornic_timeout_reset");
@@ -2097,8 +2132,6 @@ static int visornic_init(void)
        return 0;
 
 cleanup_workqueue:
-       flush_workqueue(visornic_serverdown_workqueue);
-       destroy_workqueue(visornic_serverdown_workqueue);
        if (visornic_timeout_reset_workqueue) {
                flush_workqueue(visornic_timeout_reset_workqueue);
                destroy_workqueue(visornic_timeout_reset_workqueue);
@@ -2116,17 +2149,14 @@ cleanup_debugfs:
  */
 static void visornic_cleanup(void)
 {
-       if (visornic_serverdown_workqueue) {
-               flush_workqueue(visornic_serverdown_workqueue);
-               destroy_workqueue(visornic_serverdown_workqueue);
-       }
+       visorbus_unregister_visor_driver(&visornic_driver);
+
        if (visornic_timeout_reset_workqueue) {
                flush_workqueue(visornic_timeout_reset_workqueue);
                destroy_workqueue(visornic_timeout_reset_workqueue);
        }
        debugfs_remove_recursive(visornic_debugfs_dir);
 
-       visorbus_unregister_visor_driver(&visornic_driver);
        kfree(dev_num_pool);
        dev_num_pool = NULL;
 }
index eabbcc710a2024d68d9e2c69c9bb88b9d3b5b179..35c6ce5047de752bae7086ba92aaf8d8abdbb089 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "vme_pio2.h"
 
-
 static const char driver_name[] = "pio2";
 
 static int bus[PIO2_CARDS_MAX];
@@ -118,7 +117,6 @@ static void pio2_int(int level, int vector, void *ptr)
        }
 }
 
-
 /*
  * We return whether this has been successful - this is used in the probe to
  * ensure we have a valid card.
@@ -158,7 +156,6 @@ static struct vme_driver pio2_driver = {
        .remove = pio2_remove,
 };
 
-
 static int __init pio2_init(void)
 {
        if (bus_num == 0) {
@@ -178,7 +175,6 @@ static int __init pio2_init(void)
 
 static int pio2_match(struct vme_dev *vdev)
 {
-
        if (vdev->num >= bus_num) {
                dev_err(&vdev->dev,
                        "The enumeration of the VMEbus to which the board is connected must be specified\n");
@@ -220,7 +216,7 @@ static int pio2_probe(struct vme_dev *vdev)
        int vec;
 
        card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL);
-       if (card == NULL) {
+       if (!card) {
                retval = -ENOMEM;
                goto err_struct;
        }
@@ -234,7 +230,6 @@ static int pio2_probe(struct vme_dev *vdev)
        card->vdev = vdev;
 
        for (i = 0; i < PIO2_VARIANT_LENGTH; i++) {
-
                if (isdigit(card->variant[i]) == 0) {
                        dev_err(&card->vdev->dev, "Variant invalid\n");
                        retval = -EINVAL;
@@ -264,29 +259,29 @@ static int pio2_probe(struct vme_dev *vdev)
        for (i = 1; i < PIO2_VARIANT_LENGTH; i++) {
                switch (card->variant[i]) {
                case '0':
-                       card->bank[i-1].config = NOFIT;
+                       card->bank[i - 1].config = NOFIT;
                        break;
                case '1':
                case '2':
                case '3':
                case '4':
-                       card->bank[i-1].config = INPUT;
+                       card->bank[i - 1].config = INPUT;
                        break;
                case '5':
-                       card->bank[i-1].config = OUTPUT;
+                       card->bank[i - 1].config = OUTPUT;
                        break;
                case '6':
                case '7':
                case '8':
                case '9':
-                       card->bank[i-1].config = BOTH;
+                       card->bank[i - 1].config = BOTH;
                        break;
                }
        }
 
        /* Get a master window and position over regs */
        card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16);
-       if (card->window == NULL) {
+       if (!card->window) {
                dev_err(&card->vdev->dev,
                        "Unable to assign VME master resource\n");
                retval = -EIO;
@@ -481,7 +476,6 @@ static void __exit pio2_exit(void)
        vme_unregister_driver(&pio2_driver);
 }
 
-
 /* These are required for each board */
 MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected");
 module_param_array(bus, int, &bus_num, S_IRUGO);
index 9cca97af304449c10616751e87800ebd2713b862..8e61a3b3e7e4771d445a7bbd5be9d87b5152fd1e 100644 (file)
@@ -101,13 +101,13 @@ struct image_desc {
        struct vme_resource *resource;  /* VME resource */
        int mmap_count;         /* Number of current mmap's */
 };
+
 static struct image_desc image[VME_DEVS];
 
 static struct cdev *vme_user_cdev;             /* Character device */
 static struct class *vme_user_sysfs_class;     /* Sysfs class */
 static struct vme_dev *vme_user_bridge;                /* Pointer to user device */
 
-
 static const int type[VME_DEVS] = {    MASTER_MINOR,   MASTER_MINOR,
                                        MASTER_MINOR,   MASTER_MINOR,
                                        SLAVE_MINOR,    SLAVE_MINOR,
@@ -120,125 +120,68 @@ struct vme_user_vma_priv {
        atomic_t refcnt;
 };
 
-
-/*
- * We are going ot alloc a page during init per window for small transfers.
- * Small transfers will go VME -> buffer -> user space. Larger (more than a
- * page) transfers will lock the user space buffer into memory and then
- * transfer the data directly into the user space buffers.
- */
 static ssize_t resource_to_user(int minor, char __user *buf, size_t count,
-       loff_t *ppos)
+                               loff_t *ppos)
 {
-       ssize_t retval;
        ssize_t copied = 0;
 
-       if (count <= image[minor].size_buf) {
-               /* We copy to kernel buffer */
-               copied = vme_master_read(image[minor].resource,
-                       image[minor].kern_buf, count, *ppos);
-               if (copied < 0)
-                       return (int)copied;
-
-               retval = __copy_to_user(buf, image[minor].kern_buf,
-                       (unsigned long)copied);
-               if (retval != 0) {
-                       copied = (copied - retval);
-                       pr_info("User copy failed\n");
-                       return -EINVAL;
-               }
+       if (count > image[minor].size_buf)
+               count = image[minor].size_buf;
 
-       } else {
-               /* XXX Need to write this */
-               pr_info("Currently don't support large transfers\n");
-               /* Map in pages from userspace */
+       copied = vme_master_read(image[minor].resource, image[minor].kern_buf,
+                                count, *ppos);
+       if (copied < 0)
+               return (int)copied;
 
-               /* Call vme_master_read to do the transfer */
-               return -EINVAL;
-       }
+       if (__copy_to_user(buf, image[minor].kern_buf, (unsigned long)copied))
+               return -EFAULT;
 
        return copied;
 }
 
-/*
- * We are going to alloc a page during init per window for small transfers.
- * Small transfers will go user space -> buffer -> VME. Larger (more than a
- * page) transfers will lock the user space buffer into memory and then
- * transfer the data directly from the user space buffers out to VME.
- */
 static ssize_t resource_from_user(unsigned int minor, const char __user *buf,
-       size_t count, loff_t *ppos)
+                                 size_t count, loff_t *ppos)
 {
-       ssize_t retval;
-       ssize_t copied = 0;
+       if (count > image[minor].size_buf)
+               count = image[minor].size_buf;
 
-       if (count <= image[minor].size_buf) {
-               retval = __copy_from_user(image[minor].kern_buf, buf,
-                       (unsigned long)count);
-               if (retval != 0)
-                       copied = (copied - retval);
-               else
-                       copied = count;
-
-               copied = vme_master_write(image[minor].resource,
-                       image[minor].kern_buf, copied, *ppos);
-       } else {
-               /* XXX Need to write this */
-               pr_info("Currently don't support large transfers\n");
-               /* Map in pages from userspace */
-
-               /* Call vme_master_write to do the transfer */
-               return -EINVAL;
-       }
+       if (__copy_from_user(image[minor].kern_buf, buf, (unsigned long)count))
+               return -EFAULT;
 
-       return copied;
+       return vme_master_write(image[minor].resource, image[minor].kern_buf,
+                               count, *ppos);
 }
 
 static ssize_t buffer_to_user(unsigned int minor, char __user *buf,
-       size_t count, loff_t *ppos)
+                             size_t count, loff_t *ppos)
 {
        void *image_ptr;
-       ssize_t retval;
 
        image_ptr = image[minor].kern_buf + *ppos;
+       if (__copy_to_user(buf, image_ptr, (unsigned long)count))
+               return -EFAULT;
 
-       retval = __copy_to_user(buf, image_ptr, (unsigned long)count);
-       if (retval != 0) {
-               retval = (count - retval);
-               pr_warn("Partial copy to userspace\n");
-       } else
-               retval = count;
-
-       /* Return number of bytes successfully read */
-       return retval;
+       return count;
 }
 
 static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
-       size_t count, loff_t *ppos)
+                               size_t count, loff_t *ppos)
 {
        void *image_ptr;
-       size_t retval;
 
        image_ptr = image[minor].kern_buf + *ppos;
+       if (__copy_from_user(image_ptr, buf, (unsigned long)count))
+               return -EFAULT;
 
-       retval = __copy_from_user(image_ptr, buf, (unsigned long)count);
-       if (retval != 0) {
-               retval = (count - retval);
-               pr_warn("Partial copy to userspace\n");
-       } else
-               retval = count;
-
-       /* Return number of bytes successfully read */
-       return retval;
+       return count;
 }
 
 static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
-                       loff_t *ppos)
+                            loff_t *ppos)
 {
        unsigned int minor = MINOR(file_inode(file)->i_rdev);
        ssize_t retval;
        size_t image_size;
-       size_t okcount;
 
        if (minor == CONTROL_MINOR)
                return 0;
@@ -256,16 +199,14 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
 
        /* Ensure not reading past end of the image */
        if (*ppos + count > image_size)
-               okcount = image_size - *ppos;
-       else
-               okcount = count;
+               count = image_size - *ppos;
 
        switch (type[minor]) {
        case MASTER_MINOR:
-               retval = resource_to_user(minor, buf, okcount, ppos);
+               retval = resource_to_user(minor, buf, count, ppos);
                break;
        case SLAVE_MINOR:
-               retval = buffer_to_user(minor, buf, okcount, ppos);
+               retval = buffer_to_user(minor, buf, count, ppos);
                break;
        default:
                retval = -EINVAL;
@@ -279,12 +220,11 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
 }
 
 static ssize_t vme_user_write(struct file *file, const char __user *buf,
-                       size_t count, loff_t *ppos)
+                             size_t count, loff_t *ppos)
 {
        unsigned int minor = MINOR(file_inode(file)->i_rdev);
        ssize_t retval;
        size_t image_size;
-       size_t okcount;
 
        if (minor == CONTROL_MINOR)
                return 0;
@@ -301,16 +241,14 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
 
        /* Ensure not reading past end of the image */
        if (*ppos + count > image_size)
-               okcount = image_size - *ppos;
-       else
-               okcount = count;
+               count = image_size - *ppos;
 
        switch (type[minor]) {
        case MASTER_MINOR:
-               retval = resource_from_user(minor, buf, okcount, ppos);
+               retval = resource_from_user(minor, buf, count, ppos);
                break;
        case SLAVE_MINOR:
-               retval = buffer_from_user(minor, buf, okcount, ppos);
+               retval = buffer_from_user(minor, buf, count, ppos);
                break;
        default:
                retval = -EINVAL;
@@ -354,7 +292,7 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
  * already been defined.
  */
 static int vme_user_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
+                         unsigned int cmd, unsigned long arg)
 {
        struct vme_master master;
        struct vme_slave slave;
@@ -390,12 +328,13 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
                         *      to userspace as they are
                         */
                        retval = vme_master_get(image[minor].resource,
-                               &master.enable, &master.vme_addr,
-                               &master.size, &master.aspace,
-                               &master.cycle, &master.dwidth);
+                                               &master.enable,
+                                               &master.vme_addr,
+                                               &master.size, &master.aspace,
+                                               &master.cycle, &master.dwidth);
 
                        copied = copy_to_user(argp, &master,
-                               sizeof(struct vme_master));
+                                             sizeof(struct vme_master));
                        if (copied != 0) {
                                pr_warn("Partial copy to userspace\n");
                                return -EFAULT;
@@ -435,12 +374,12 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
                         *      to userspace as they are
                         */
                        retval = vme_slave_get(image[minor].resource,
-                               &slave.enable, &slave.vme_addr,
-                               &slave.size, &pci_addr, &slave.aspace,
-                               &slave.cycle);
+                                              &slave.enable, &slave.vme_addr,
+                                              &slave.size, &pci_addr,
+                                              &slave.aspace, &slave.cycle);
 
                        copied = copy_to_user(argp, &slave,
-                               sizeof(struct vme_slave));
+                                             sizeof(struct vme_slave));
                        if (copied != 0) {
                                pr_warn("Partial copy to userspace\n");
                                return -EFAULT;
@@ -526,8 +465,8 @@ static int vme_user_master_mmap(unsigned int minor, struct vm_area_struct *vma)
                return err;
        }
 
-       vma_priv = kmalloc(sizeof(struct vme_user_vma_priv), GFP_KERNEL);
-       if (vma_priv == NULL) {
+       vma_priv = kmalloc(sizeof(*vma_priv), GFP_KERNEL);
+       if (!vma_priv) {
                mutex_unlock(&image[minor].mutex);
                return -ENOMEM;
        }
@@ -588,7 +527,7 @@ static int vme_user_probe(struct vme_dev *vdev)
        char *name;
 
        /* Save pointer to the bridge device */
-       if (vme_user_bridge != NULL) {
+       if (vme_user_bridge) {
                dev_err(&vdev->dev, "Driver can only be loaded for 1 device\n");
                err = -EINVAL;
                goto err_dev;
@@ -606,7 +545,7 @@ static int vme_user_probe(struct vme_dev *vdev)
 
        /* Assign major and minor numbers for the driver */
        err = register_chrdev_region(MKDEV(VME_MAJOR, 0), VME_DEVS,
-               driver_name);
+                                    driver_name);
        if (err) {
                dev_warn(&vdev->dev, "Error getting Major Number %d for driver.\n",
                         VME_MAJOR);
@@ -622,10 +561,8 @@ static int vme_user_probe(struct vme_dev *vdev)
        vme_user_cdev->ops = &vme_user_fops;
        vme_user_cdev->owner = THIS_MODULE;
        err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS);
-       if (err) {
-               dev_warn(&vdev->dev, "cdev_all failed\n");
+       if (err)
                goto err_char;
-       }
 
        /* Request slave resources and allocate buffers (128kB wide) */
        for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
@@ -636,7 +573,7 @@ static int vme_user_probe(struct vme_dev *vdev)
                 */
                image[i].resource = vme_slave_request(vme_user_bridge,
                        VME_A24, VME_SCT);
-               if (image[i].resource == NULL) {
+               if (!image[i].resource) {
                        dev_warn(&vdev->dev,
                                 "Unable to allocate slave resource\n");
                        err = -ENOMEM;
@@ -645,7 +582,7 @@ static int vme_user_probe(struct vme_dev *vdev)
                image[i].size_buf = PCI_BUF_SIZE;
                image[i].kern_buf = vme_alloc_consistent(image[i].resource,
                        image[i].size_buf, &image[i].pci_buf);
-               if (image[i].kern_buf == NULL) {
+               if (!image[i].kern_buf) {
                        dev_warn(&vdev->dev,
                                 "Unable to allocate memory for buffer\n");
                        image[i].pci_buf = 0;
@@ -663,7 +600,7 @@ static int vme_user_probe(struct vme_dev *vdev)
                /* XXX Need to properly request attributes */
                image[i].resource = vme_master_request(vme_user_bridge,
                        VME_A32, VME_SCT, VME_D32);
-               if (image[i].resource == NULL) {
+               if (!image[i].resource) {
                        dev_warn(&vdev->dev,
                                 "Unable to allocate master resource\n");
                        err = -ENOMEM;
@@ -671,7 +608,7 @@ static int vme_user_probe(struct vme_dev *vdev)
                }
                image[i].size_buf = PCI_BUF_SIZE;
                image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
-               if (image[i].kern_buf == NULL) {
+               if (!image[i].kern_buf) {
                        err = -ENOMEM;
                        vme_master_free(image[i].resource);
                        goto err_master;
@@ -835,7 +772,6 @@ static void __exit vme_user_exit(void)
        vme_unregister_driver(&vme_user_driver);
 }
 
-
 MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the driver is connected");
 module_param_array(bus, int, &bus_num, 0);
 
index b0ea38f1911c1bdca61a95b25208126d141645d7..9e61f2df3a00a283d8de53371ef91c3b23e3b4d1 100644 (file)
@@ -1728,10 +1728,8 @@ BBuGetFrameTime(
        unsigned int uRateIdx = (unsigned int) wRate;
        unsigned int uRate = 0;
 
-       if (uRateIdx > RATE_54M) {
-               ASSERT(0);
+       if (uRateIdx > RATE_54M)
                return 0;
-       }
 
        uRate = (unsigned int)awcFrameTime[uRateIdx];
 
@@ -1945,7 +1943,6 @@ bool BBbReadEmbedded(struct vnt_private *priv,
        VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData);
 
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x30);
                pr_debug(" DBG_PORT80(0x30)\n");
                return false;
        }
@@ -1988,7 +1985,6 @@ bool BBbWriteEmbedded(struct vnt_private *priv,
        }
 
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x31);
                pr_debug(" DBG_PORT80(0x31)\n");
                return false;
        }
index e00c0605d1541556492c8ab46d5d4db8156a30f6..c7b75dfc2d5f27cc9c2c882ac1becdf9b6b0c487 100644 (file)
@@ -514,7 +514,7 @@ CARDvSafeResetTx(
 )
 {
        unsigned int uu;
-       PSTxDesc    pCurrTD;
+       struct vnt_tx_desc *pCurrTD;
 
        /* initialize TD index */
        pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
@@ -525,12 +525,12 @@ CARDvSafeResetTx(
 
        for (uu = 0; uu < pDevice->sOpts.nTxDescs[0]; uu++) {
                pCurrTD = &(pDevice->apTD0Rings[uu]);
-               pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
+               pCurrTD->td0.owner = OWNED_BY_HOST;
                /* init all Tx Packet pointer to NULL */
        }
        for (uu = 0; uu < pDevice->sOpts.nTxDescs[1]; uu++) {
                pCurrTD = &(pDevice->apTD1Rings[uu]);
-               pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
+               pCurrTD->td0.owner = OWNED_BY_HOST;
                /* init all Tx Packet pointer to NULL */
        }
 
@@ -573,17 +573,17 @@ CARDvSafeResetRx(
        /* init state, all RD is chip's */
        for (uu = 0; uu < pDevice->sOpts.nRxDescs0; uu++) {
                pDesc = &(pDevice->aRD0Ring[uu]);
-               pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
+               pDesc->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
                pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC;
-               pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
+               pDesc->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
        }
 
        /* init state, all RD is chip's */
        for (uu = 0; uu < pDevice->sOpts.nRxDescs1; uu++) {
                pDesc = &(pDevice->aRD1Ring[uu]);
-               pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
+               pDesc->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
                pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC;
-               pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
+               pDesc->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
        }
 
        /* set perPkt mode */
@@ -847,7 +847,6 @@ void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode
        case CARD_LB_PHY:
                break;
        default:
-               ASSERT(false);
                break;
        }
        /* set MAC loopback */
index 758eeb2afd512a5e2d0e2928fdcbe3acf3f37145..3c9007e34c0ff30c644d923a2a040bcf146f456b 100644 (file)
 typedef struct tagDEVICE_RD_INFO {
        struct sk_buff *skb;
        dma_addr_t  skb_dma;
-       dma_addr_t  curr_desc;
 } DEVICE_RD_INFO,   *PDEVICE_RD_INFO;
 
 #ifdef __BIG_ENDIAN
 
 typedef struct tagRDES0 {
-       volatile unsigned short wResCount;
+       volatile __le16 wResCount;
        union {
                volatile u16    f15Reserved;
                struct {
@@ -191,7 +190,7 @@ SRDES0, *PSRDES0;
 #else
 
 typedef struct tagRDES0 {
-       unsigned short wResCount;
+       __le16         wResCount;
        unsigned short f15Reserved:15;
        unsigned short f1Owner:1;
 } __attribute__ ((__packed__))
@@ -200,7 +199,7 @@ SRDES0;
 #endif
 
 typedef struct tagRDES1 {
-       unsigned short wReqCount;
+       __le16         wReqCount;
        unsigned short wReserved;
 } __attribute__ ((__packed__))
 SRDES1;
@@ -209,93 +208,56 @@ SRDES1;
 typedef struct tagSRxDesc {
        volatile SRDES0 m_rd0RD0;
        volatile SRDES1 m_rd1RD1;
-       volatile u32    buff_addr;
-       volatile u32    next_desc;
+       volatile __le32 buff_addr;
+       volatile __le32 next_desc;
        struct tagSRxDesc *next __aligned(8);
        volatile PDEVICE_RD_INFO pRDInfo __aligned(8);
 } __attribute__ ((__packed__))
 SRxDesc, *PSRxDesc;
 typedef const SRxDesc *PCSRxDesc;
 
+struct vnt_tdes0 {
+       volatile u8 tsr0;
+       volatile u8 tsr1;
 #ifdef __BIG_ENDIAN
-
-typedef struct tagTDES0 {
-       volatile    unsigned char byTSR0;
-       volatile    unsigned char byTSR1;
        union {
-               volatile u16    f15Txtime;
+               volatile u16 f15_txtime;
                struct {
-                       volatile u8 f8Reserved1;
-                       volatile u8 f1Owner:1;
-                       volatile u8 f7Reserved:7;
-               } __attribute__ ((__packed__));
-       } __attribute__ ((__packed__));
-} __attribute__ ((__packed__))
-STDES0, PSTDES0;
-
+                       volatile u8 f8_reserved;
+                       volatile u8 owner:1;
+                       volatile u8 f7_reserved:7;
+               } __packed;
+       } __packed;
 #else
-
-typedef struct tagTDES0 {
-       volatile    unsigned char byTSR0;
-       volatile    unsigned char byTSR1;
-       volatile    unsigned short f15Txtime:15;
-       volatile    unsigned short f1Owner:1;
-} __attribute__ ((__packed__))
-STDES0;
-
+       volatile u16 f15_txtime:15;
+       volatile u16 owner:1;
 #endif
+} __packed;
 
-typedef struct tagTDES1 {
-       volatile    unsigned short wReqCount;
-       volatile    unsigned char byTCR;
-       volatile    unsigned char byReserved;
-} __attribute__ ((__packed__))
-STDES1;
+struct vnt_tdes1 {
+       volatile __le16 req_count;
+       volatile u8 tcr;
+       volatile u8 reserved;
+} __packed;
 
-typedef struct tagDEVICE_TD_INFO {
+struct vnt_td_info {
        void *mic_hdr;
        struct sk_buff *skb;
        unsigned char *buf;
-       dma_addr_t          skb_dma;
-       dma_addr_t          buf_dma;
-       dma_addr_t          curr_desc;
-       unsigned long dwReqCount;
-       unsigned long dwHeaderLength;
-       unsigned char byFlags;
-} DEVICE_TD_INFO,    *PDEVICE_TD_INFO;
+       dma_addr_t buf_dma;
+       u16 req_count;
+       u8 flags;
+};
 
 /* transmit descriptor */
-typedef struct tagSTxDesc {
-       volatile    STDES0  m_td0TD0;
-       volatile    STDES1  m_td1TD1;
-       volatile    u32    buff_addr;
-       volatile    u32    next_desc;
-       struct tagSTxDesc *next __aligned(8);
-       volatile    PDEVICE_TD_INFO pTDInfo __aligned(8);
-} __attribute__ ((__packed__))
-STxDesc, *PSTxDesc;
-typedef const STxDesc *PCSTxDesc;
-
-typedef struct tagSTxSyncDesc {
-       volatile    STDES0  m_td0TD0;
-       volatile    STDES1  m_td1TD1;
-       volatile    u32 buff_addr; /* pointer to logical buffer */
-       volatile    u32 next_desc; /* pointer to next logical descriptor */
-       volatile    unsigned short m_wFIFOCtl;
-       volatile    unsigned short m_wTimeStamp;
-       struct tagSTxSyncDesc *next __aligned(8);
-       volatile    PDEVICE_TD_INFO pTDInfo __aligned(8);
-} __attribute__ ((__packed__))
-STxSyncDesc, *PSTxSyncDesc;
-typedef const STxSyncDesc *PCSTxSyncDesc;
-
-/* RsvTime buffer header */
-typedef struct tagSRrvTime_atim {
-       unsigned short wCTSTxRrvTime_ba;
-       unsigned short wTxRrvTime_a;
-} __attribute__ ((__packed__))
-SRrvTime_atim, *PSRrvTime_atim;
-typedef const SRrvTime_atim *PCSRrvTime_atim;
+struct vnt_tx_desc {
+       volatile struct vnt_tdes0 td0;
+       volatile struct vnt_tdes1 td1;
+       volatile __le32 buff_addr;
+       volatile __le32 next_desc;
+       struct vnt_tx_desc *next __aligned(8);
+       struct vnt_td_info *td_info __aligned(8);
+} __packed;
 
 /* Length, Service, and Signal fields of Phy for Tx */
 struct vnt_phy_field {
@@ -310,42 +272,4 @@ union vnt_phy_field_swap {
        u32 field_write;
 };
 
-/* Tx FIFO header */
-typedef struct tagSTxBufHead {
-       u32 adwTxKey[4];
-       unsigned short wFIFOCtl;
-       unsigned short wTimeStamp;
-       unsigned short wFragCtl;
-       unsigned char byTxPower;
-       unsigned char wReserved;
-} __attribute__ ((__packed__))
-STxBufHead, *PSTxBufHead;
-typedef const STxBufHead *PCSTxBufHead;
-
-typedef struct tagSBEACONCtl {
-       u32 BufReady:1;
-       u32 TSF:15;
-       u32 BufLen:11;
-       u32 Reserved:5;
-} __attribute__ ((__packed__))
-SBEACONCtl;
-
-typedef struct tagSSecretKey {
-       u32 dwLowDword;
-       unsigned char byHighByte;
-} __attribute__ ((__packed__))
-SSecretKey;
-
-typedef struct tagSKeyEntry {
-       unsigned char abyAddrHi[2];
-       unsigned short wKCTL;
-       unsigned char abyAddrLo[4];
-       u32 dwKey0[4];
-       u32 dwKey1[4];
-       u32 dwKey2[4];
-       u32 dwKey3[4];
-       u32 dwKey4[4];
-} __attribute__ ((__packed__))
-SKeyEntry;
-
 #endif /* __DESC_H__ */
index 5cf1b337cba7e6beb5de410a99c9c658a2166ab8..c9fa6ef42d340d6cb5e48343e503cbdaec43e7c4 100644 (file)
@@ -252,11 +252,11 @@ struct vnt_private {
        int                         nTxQueues;
        volatile int                iTDUsed[TYPE_MAXTD];
 
-       volatile PSTxDesc           apCurrTD[TYPE_MAXTD];
-       volatile PSTxDesc           apTailTD[TYPE_MAXTD];
+       struct vnt_tx_desc *apCurrTD[TYPE_MAXTD];
+       struct vnt_tx_desc *apTailTD[TYPE_MAXTD];
 
-       volatile PSTxDesc           apTD0Rings;
-       volatile PSTxDesc           apTD1Rings;
+       struct vnt_tx_desc *apTD0Rings;
+       struct vnt_tx_desc *apTD1Rings;
 
        volatile PSRxDesc           aRD0Ring;
        volatile PSRxDesc           aRD1Ring;
@@ -403,6 +403,7 @@ struct vnt_private {
        unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */
 
        unsigned short wBeaconInterval;
+       u16 wake_up_count;
 
        struct work_struct interrupt_work;
 
@@ -414,8 +415,8 @@ static inline PDEVICE_RD_INFO alloc_rd_info(void)
        return kzalloc(sizeof(DEVICE_RD_INFO), GFP_ATOMIC);
 }
 
-static inline PDEVICE_TD_INFO alloc_td_info(void)
+static inline struct vnt_td_info *alloc_td_info(void)
 {
-       return kzalloc(sizeof(DEVICE_TD_INFO), GFP_ATOMIC);
+       return kzalloc(sizeof(struct vnt_td_info), GFP_ATOMIC);
 }
 #endif
index a4a8a8489e0befe93488c80130c53f92422ce98e..b4c9547d3138b49e7b5550b1a95410c7aa7f538a 100644 (file)
@@ -69,19 +69,4 @@ typedef enum  _chip_type {
        VT3253 = 1
 } CHIP_TYPE, *PCHIP_TYPE;
 
-#ifdef VIAWET_DEBUG
-#define ASSERT(x)                                                      \
-do {                                                                   \
-       if (!(x)) {                                                     \
-               pr_err("assertion %s failed: file %s line %d\n", \
-                      #x, __func__, __LINE__);                         \
-               *(int *)0 = 0;                                          \
-       }                                                               \
-} while (0)
-#define DBG_PORT80(value)                   outb(value, 0x80)
-#else
-#define ASSERT(x)
-#define DBG_PORT80(value)
-#endif
-
 #endif
index 69bdc8f29b59f4c1e1cbacabf7563a7ca1d66817..0d8f123c57fe22cebe800d7c282e6808bb046b3c 100644 (file)
@@ -157,7 +157,7 @@ static int  device_rx_srv(struct vnt_private *pDevice, unsigned int uIdx);
 static int  device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx);
 static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pDesc);
 static void device_init_registers(struct vnt_private *pDevice);
-static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc);
+static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *);
 static void device_free_td0_ring(struct vnt_private *pDevice);
 static void device_free_td1_ring(struct vnt_private *pDevice);
 static void device_free_rd0_ring(struct vnt_private *pDevice);
@@ -522,8 +522,8 @@ static bool device_init_rings(struct vnt_private *pDevice)
        vir_pool = dma_zalloc_coherent(&pDevice->pcid->dev,
                                         pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
                                         pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-                                        pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-                                        pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
+                                        pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc) +
+                                        pDevice->sOpts.nTxDescs[1] * sizeof(struct vnt_tx_desc),
                                         &pDevice->pool_dma, GFP_ATOMIC);
        if (vir_pool == NULL) {
                dev_err(&pDevice->pcid->dev, "allocate desc dma memory failed\n");
@@ -551,8 +551,8 @@ static bool device_init_rings(struct vnt_private *pDevice)
                dma_free_coherent(&pDevice->pcid->dev,
                                    pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
                                    pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-                                   pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-                                   pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
+                                   pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc) +
+                                   pDevice->sOpts.nTxDescs[1] * sizeof(struct vnt_tx_desc),
                                    vir_pool, pDevice->pool_dma
                        );
                return false;
@@ -562,7 +562,7 @@ static bool device_init_rings(struct vnt_private *pDevice)
                pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
 
        pDevice->td1_pool_dma = pDevice->td0_pool_dma +
-               pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
+               pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc);
 
        /* vir_pool: pvoid type */
        pDevice->apTD0Rings = vir_pool
@@ -572,7 +572,7 @@ static bool device_init_rings(struct vnt_private *pDevice)
        pDevice->apTD1Rings = vir_pool
                + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
                + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
-               + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
+               + pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc);
 
        pDevice->tx1_bufs = pDevice->tx0_bufs +
                pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
@@ -597,8 +597,8 @@ static void device_free_rings(struct vnt_private *pDevice)
        dma_free_coherent(&pDevice->pcid->dev,
                            pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
                            pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
-                           pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
-                           pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
+                           pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc) +
+                           pDevice->sOpts.nTxDescs[1] * sizeof(struct vnt_tx_desc)
                            ,
                            pDevice->aRD0Ring, pDevice->pool_dma
                );
@@ -623,12 +623,11 @@ static void device_init_rd0_ring(struct vnt_private *pDevice)
        for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
                pDesc = &(pDevice->aRD0Ring[i]);
                pDesc->pRDInfo = alloc_rd_info();
-               ASSERT(pDesc->pRDInfo);
+
                if (!device_alloc_rx_buf(pDevice, pDesc))
                        dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n");
 
                pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
-               pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
                pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
        }
 
@@ -647,12 +646,11 @@ static void device_init_rd1_ring(struct vnt_private *pDevice)
        for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
                pDesc = &(pDevice->aRD1Ring[i]);
                pDesc->pRDInfo = alloc_rd_info();
-               ASSERT(pDesc->pRDInfo);
+
                if (!device_alloc_rx_buf(pDevice, pDesc))
                        dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n");
 
                pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
-               pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
                pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
        }
 
@@ -699,20 +697,20 @@ static void device_init_td0_ring(struct vnt_private *pDevice)
 {
        int i;
        dma_addr_t  curr;
-       PSTxDesc        pDesc;
+       struct vnt_tx_desc *pDesc;
 
        curr = pDevice->td0_pool_dma;
-       for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
+       for (i = 0; i < pDevice->sOpts.nTxDescs[0];
+            i++, curr += sizeof(struct vnt_tx_desc)) {
                pDesc = &(pDevice->apTD0Rings[i]);
-               pDesc->pTDInfo = alloc_td_info();
-               ASSERT(pDesc->pTDInfo);
+               pDesc->td_info = alloc_td_info();
+
                if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
-                       pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
-                       pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
+                       pDesc->td_info->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
+                       pDesc->td_info->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
                }
                pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
-               pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
-               pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
+               pDesc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
        }
 
        if (i > 0)
@@ -724,21 +722,21 @@ static void device_init_td1_ring(struct vnt_private *pDevice)
 {
        int i;
        dma_addr_t  curr;
-       PSTxDesc    pDesc;
+       struct vnt_tx_desc *pDesc;
 
        /* Init the TD ring entries */
        curr = pDevice->td1_pool_dma;
-       for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) {
+       for (i = 0; i < pDevice->sOpts.nTxDescs[1];
+            i++, curr += sizeof(struct vnt_tx_desc)) {
                pDesc = &(pDevice->apTD1Rings[i]);
-               pDesc->pTDInfo = alloc_td_info();
-               ASSERT(pDesc->pTDInfo);
+               pDesc->td_info = alloc_td_info();
+
                if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
-                       pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
-                       pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
+                       pDesc->td_info->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
+                       pDesc->td_info->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
                }
                pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]);
-               pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
-               pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
+               pDesc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
        }
 
        if (i > 0)
@@ -751,17 +749,11 @@ static void device_free_td0_ring(struct vnt_private *pDevice)
        int i;
 
        for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
-               PSTxDesc        pDesc = &(pDevice->apTD0Rings[i]);
-               PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
+               struct vnt_tx_desc *pDesc = &pDevice->apTD0Rings[i];
+               struct vnt_td_info *pTDInfo = pDesc->td_info;
 
-               if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
-                       dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
-                                        pTDInfo->skb->len, DMA_TO_DEVICE);
-
-               if (pTDInfo->skb)
-                       dev_kfree_skb(pTDInfo->skb);
-
-               kfree(pDesc->pTDInfo);
+               dev_kfree_skb(pTDInfo->skb);
+               kfree(pDesc->td_info);
        }
 }
 
@@ -770,17 +762,11 @@ static void device_free_td1_ring(struct vnt_private *pDevice)
        int i;
 
        for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
-               PSTxDesc        pDesc = &(pDevice->apTD1Rings[i]);
-               PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
-
-               if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
-                       dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
-                                        pTDInfo->skb->len, DMA_TO_DEVICE);
-
-               if (pTDInfo->skb)
-                       dev_kfree_skb(pTDInfo->skb);
+               struct vnt_tx_desc *pDesc = &pDevice->apTD1Rings[i];
+               struct vnt_td_info *pTDInfo = pDesc->td_info;
 
-               kfree(pDesc->pTDInfo);
+               dev_kfree_skb(pTDInfo->skb);
+               kfree(pDesc->td_info);
        }
 }
 
@@ -822,7 +808,6 @@ static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pRD)
        pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
        if (pRDInfo->skb == NULL)
                return false;
-       ASSERT(pRDInfo->skb);
 
        pRDInfo->skb_dma =
                dma_map_single(&pDevice->pcid->dev,
@@ -856,7 +841,7 @@ static const u8 fallback_rate1[5][5] = {
 };
 
 static int vnt_int_report_rate(struct vnt_private *priv,
-                              PDEVICE_TD_INFO context, u8 tsr0, u8 tsr1)
+                              struct vnt_td_info *context, u8 tsr0, u8 tsr1)
 {
        struct vnt_tx_fifo_head *fifo_head;
        struct ieee80211_tx_info *info;
@@ -917,23 +902,23 @@ static int vnt_int_report_rate(struct vnt_private *priv,
 
 static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx)
 {
-       PSTxDesc                 pTD;
+       struct vnt_tx_desc *pTD;
        int                      works = 0;
        unsigned char byTsr0;
        unsigned char byTsr1;
 
        for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) {
-               if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
+               if (pTD->td0.owner == OWNED_BY_NIC)
                        break;
                if (works++ > 15)
                        break;
 
-               byTsr0 = pTD->m_td0TD0.byTSR0;
-               byTsr1 = pTD->m_td0TD0.byTSR1;
+               byTsr0 = pTD->td0.tsr0;
+               byTsr1 = pTD->td0.tsr1;
 
                /* Only the status of first TD in the chain is correct */
-               if (pTD->m_td1TD1.byTCR & TCR_STP) {
-                       if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
+               if (pTD->td1.tcr & TCR_STP) {
+                       if ((pTD->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) {
                                if (!(byTsr1 & TSR1_TERR)) {
                                        if (byTsr0 != 0) {
                                                pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
@@ -947,13 +932,13 @@ static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx)
                        }
 
                        if (byTsr1 & TSR1_TERR) {
-                               if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
+                               if ((pTD->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) {
                                        pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n",
                                                 (int)uIdx, byTsr1, byTsr0);
                                }
                        }
 
-                       vnt_int_report_rate(pDevice, pTD->pTDInfo, byTsr0, byTsr1);
+                       vnt_int_report_rate(pDevice, pTD->td_info, byTsr0, byTsr1);
 
                        device_free_tx_buf(pDevice, pTD);
                        pDevice->iTDUsed[uIdx]--;
@@ -975,23 +960,17 @@ static void device_error(struct vnt_private *pDevice, unsigned short status)
        }
 }
 
-static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc)
+static void device_free_tx_buf(struct vnt_private *pDevice,
+                              struct vnt_tx_desc *pDesc)
 {
-       PDEVICE_TD_INFO  pTDInfo = pDesc->pTDInfo;
+       struct vnt_td_info *pTDInfo = pDesc->td_info;
        struct sk_buff *skb = pTDInfo->skb;
 
-       /* pre-allocated buf_dma can't be unmapped. */
-       if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
-               dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
-                                skb->len, DMA_TO_DEVICE);
-       }
-
        if (skb)
                ieee80211_tx_status_irqsafe(pDevice->hw, skb);
 
-       pTDInfo->skb_dma = 0;
        pTDInfo->skb = NULL;
-       pTDInfo->byFlags = 0;
+       pTDInfo->flags = 0;
 }
 
 static void vnt_check_bb_vga(struct vnt_private *priv)
@@ -1180,7 +1159,7 @@ static irqreturn_t vnt_interrupt(int irq,  void *arg)
 static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       PSTxDesc head_td;
+       struct vnt_tx_desc *head_td;
        u32 dma_idx;
        unsigned long flags;
 
@@ -1198,12 +1177,12 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 
        head_td = priv->apCurrTD[dma_idx];
 
-       head_td->m_td1TD1.byTCR = 0;
+       head_td->td1.tcr = 0;
 
-       head_td->pTDInfo->skb = skb;
+       head_td->td_info->skb = skb;
 
        if (dma_idx == TYPE_AC0DMA)
-               head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;
+               head_td->td_info->flags = TD_FLAGS_NETIF_SKB;
 
        priv->apCurrTD[dma_idx] = head_td->next;
 
@@ -1211,26 +1190,22 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 
        vnt_generate_fifo_header(priv, dma_idx, head_td, skb);
 
-       if (MACbIsRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
-               MACbPSWakeup(priv->PortOffset);
-
        spin_lock_irqsave(&priv->lock, flags);
 
        priv->bPWBitOn = false;
 
        /* Set TSR1 & ReqCount in TxDescHead */
-       head_td->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
-       head_td->m_td1TD1.wReqCount =
-                       cpu_to_le16((u16)head_td->pTDInfo->dwReqCount);
+       head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU);
+       head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count);
 
-       head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma);
+       head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma);
 
        /* Poll Transmit the adapter */
        wmb();
-       head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
+       head_td->td0.owner = OWNED_BY_NIC;
        wmb(); /* second memory barrier */
 
-       if (head_td->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
+       if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB)
                MACvTransmitAC0(priv->PortOffset);
        else
                MACvTransmit0(priv->PortOffset);
@@ -1775,6 +1750,12 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
+       if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) {
+               dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n");
+               device_free_info(priv);
+               return -ENODEV;
+       }
+
        INIT_WORK(&priv->interrupt_work, vnt_interrupt_work);
 
        /* do reset */
@@ -1812,6 +1793,7 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
        ieee80211_hw_set(priv->hw, SIGNAL_DBM);
        ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
        ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
+       ieee80211_hw_set(priv->hw, SUPPORTS_PS);
 
        priv->hw->max_signal = 100;
 
index b25ee962558d786776df34cedcbefe5ee9999b7a..e14eed160a191fd5405ea900ea720bcbbeda230e 100644 (file)
@@ -144,7 +144,7 @@ bool vnt_receive_frame(struct vnt_private *priv, PSRxDesc curr_rd)
                         priv->rx_buf_sz, DMA_FROM_DEVICE);
 
        frame_size = le16_to_cpu(curr_rd->m_rd1RD1.wReqCount)
-                       - cpu_to_le16(curr_rd->m_rd0RD0.wResCount);
+                       - le16_to_cpu(curr_rd->m_rd0RD0.wResCount);
 
        if ((frame_size > 2364) || (frame_size < 33)) {
                /* Frame Size error drop this packet.*/
index aed530f022b8cf817f3cf703dac8e4d61d21ddf5..3dfd333475c020718359f6fe832349ba9aeea70d 100644 (file)
@@ -186,7 +186,6 @@ void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode)
 {
        unsigned char byOrgValue;
 
-       ASSERT(byLoopbackMode < 3);
        byLoopbackMode <<= 6;
        /* set TCR */
        VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
@@ -374,7 +373,6 @@ bool MACbSafeRxOff(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x10);
                pr_debug(" DBG_PORT80(0x10)\n");
                return false;
        }
@@ -384,7 +382,6 @@ bool MACbSafeRxOff(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x11);
                pr_debug(" DBG_PORT80(0x11)\n");
                return false;
        }
@@ -398,7 +395,6 @@ bool MACbSafeRxOff(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x12);
                pr_debug(" DBG_PORT80(0x12)\n");
                return false;
        }
@@ -436,7 +432,6 @@ bool MACbSafeTxOff(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x20);
                pr_debug(" DBG_PORT80(0x20)\n");
                return false;
        }
@@ -446,7 +441,6 @@ bool MACbSafeTxOff(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x21);
                pr_debug(" DBG_PORT80(0x21)\n");
                return false;
        }
@@ -461,7 +455,6 @@ bool MACbSafeTxOff(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x24);
                pr_debug(" DBG_PORT80(0x24)\n");
                return false;
        }
@@ -486,13 +479,11 @@ bool MACbSafeStop(void __iomem *dwIoBase)
        MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX);
 
        if (!MACbSafeRxOff(dwIoBase)) {
-               DBG_PORT80(0xA1);
                pr_debug(" MACbSafeRxOff == false)\n");
                MACbSafeSoftwareReset(dwIoBase);
                return false;
        }
        if (!MACbSafeTxOff(dwIoBase)) {
-               DBG_PORT80(0xA2);
                pr_debug(" MACbSafeTxOff == false)\n");
                MACbSafeSoftwareReset(dwIoBase);
                return false;
@@ -590,9 +581,6 @@ void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr
                        break;
        }
 
-       if (ww == W_MAX_TIMEOUT)
-               DBG_PORT80(0x13);
-
        VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, dwCurrDescAddr);
        if (byOrgDMACtl & DMACTL_RUN)
                VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN);
@@ -627,8 +615,6 @@ void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr
                if (!(byData & DMACTL_RUN))
                        break;
        }
-       if (ww == W_MAX_TIMEOUT)
-               DBG_PORT80(0x14);
 
        VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, dwCurrDescAddr);
        if (byOrgDMACtl & DMACTL_RUN)
@@ -666,8 +652,6 @@ void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase,
                if (!(byData & DMACTL_RUN))
                        break;
        }
-       if (ww == W_MAX_TIMEOUT)
-               DBG_PORT80(0x25);
 
        VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, dwCurrDescAddr);
        if (byOrgDMACtl & DMACTL_RUN)
@@ -706,7 +690,6 @@ void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase,
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x26);
                pr_debug(" DBG_PORT80(0x26)\n");
        }
        VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, dwCurrDescAddr);
@@ -807,7 +790,6 @@ bool MACbPSWakeup(void __iomem *dwIoBase)
                        break;
        }
        if (ww == W_MAX_TIMEOUT) {
-               DBG_PORT80(0x36);
                pr_debug(" DBG_PORT80(0x33)\n");
                return false;
        }
index be3c4e949b6a315dc7ac80880654eb413c089224..06e6b9d871c44a7f4806331fed92b611cc86f3ed 100644 (file)
@@ -157,10 +157,18 @@ PSbIsNextTBTTWakeUp(
        struct ieee80211_conf *conf = &hw->conf;
        bool bWakeUp = false;
 
-       if (conf->listen_interval == 1) {
-               /* Turn on wake up to listen next beacon */
-               MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
-               bWakeUp = true;
+       if (conf->listen_interval > 1) {
+               if (!pDevice->wake_up_count)
+                       pDevice->wake_up_count = conf->listen_interval;
+
+               --pDevice->wake_up_count;
+
+               if (pDevice->wake_up_count == 1) {
+                       /* Turn on wake up to listen next beacon */
+                       MACvRegBitsOn(pDevice->PortOffset,
+                                     MAC_REG_PSCTL, PSCTL_LNBCN);
+                       bWakeUp = true;
+               }
        }
 
        return bWakeUp;
index 7626f635f160799f581b50d3e1e50bbcc7fd8da0..c537321444be1ba5dde589127b9e3450827af65b 100644 (file)
 #include "rf.h"
 #include "baseband.h"
 
-#define BY_AL2230_REG_LEN     23 //24bit
+#define BY_AL2230_REG_LEN     23 /* 24bit */
 #define CB_AL2230_INIT_SEQ    15
-#define SWITCH_CHANNEL_DELAY_AL2230 200 //us
+#define SWITCH_CHANNEL_DELAY_AL2230 200 /* us */
 #define AL2230_PWR_IDX_LEN    64
 
-#define BY_AL7230_REG_LEN     23 //24bit
+#define BY_AL7230_REG_LEN     23 /* 24bit */
 #define CB_AL7230_INIT_SEQ    16
-#define SWITCH_CHANNEL_DELAY_AL7230 200 //us
+#define SWITCH_CHANNEL_DELAY_AL7230 200 /* us */
 #define AL7230_PWR_IDX_LEN    64
 
 static const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = {
-       0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
-       0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+       0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+       0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
        0x0BDFFC00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
        0x00000D00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
        0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
 };
 
 static const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = {
-       0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
-       0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
-       0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
-       0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
-       0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
-       0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
-       0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
-       0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
-       0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
-       0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-       0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-       0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-       0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-       0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
+       0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+       0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+       0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+       0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+       0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+       0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+       0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+       0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
+       0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
+       0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+       0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+       0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+       0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+       0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  /* channel = 14, Tf = 2412M */
 };
 
 static const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = {
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
-       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
-       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
-       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
-       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
-       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-       0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
+       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+       0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+       0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+       0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  /* channel = 14, Tf = 2412M */
 };
 
 static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
@@ -168,240 +168,240 @@ static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
        0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
 };
 
-// 40MHz reference frequency
-// Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.
+/* 40MHz reference frequency
+ * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.*/
 static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = {
-       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
-       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
-       0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2
-       0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 5FDFA3
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11b/g    // Need modify for 11a
-       // RoberYu:20050113, Rev0.47 Regsiter Setting Guide
-       0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B55
+       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */
+       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */
+       0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 451FE2 */
+       0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 5FDFA3 */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* 11b/g    // Need modify for 11a */
+       /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */
+       0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 8D1B55 */
        0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-       0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 860207
+       0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 860207 */
        0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
        0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-       0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: E0600A
-       0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
-       // RoberYu:20050113, Rev0.47 Regsiter Setting Guide
-       0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C
+       0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: E0600A */
+       0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */
+       /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */
+       0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 00143C */
        0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
        0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-       0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11a: 12BACF
+       0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  /* Need modify for 11a: 12BACF */
 };
 
 static const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = {
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
-       0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-       0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-       0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11a    // Need modify for 11b/g
-       0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g, RoberYu:20050113
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */
+       0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
+       0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
+       0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* 11a    // Need modify for 11b/g */
+       0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g, RoberYu:20050113 */
        0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-       0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+       0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
        0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
        0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-       0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
-       0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
-       0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+       0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
+       0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */
+       0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
        0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
        0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
-       0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11b/g
+       0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  /* Need modify for 11b/g */
 };
 
 static const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = {
-       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
-       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
-       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
-       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
-       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
-       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
-       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
-       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49
-       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49
-       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49
-       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49
-       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49
-       0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49
-       0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
-
-       // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
-       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
-       0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
-       0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
-
-       // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
-       // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
-
-       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
-       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
-       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
-       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
-       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
-       0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
-       0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
-       0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
-       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49
-       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
-       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
-       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
-       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
-       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
-       0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
-       0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
-       0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
-       0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
-
-       0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
-       0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
-       0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
-       0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
-       0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
-       0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
-       0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
-       0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
-       0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
-       0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
-       0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
-       0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
-       0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
-       0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
-       0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
-       0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
+       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  1, Tf = 2412MHz */
+       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  2, Tf = 2417MHz */
+       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  3, Tf = 2422MHz */
+       0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  4, Tf = 2427MHz */
+       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  5, Tf = 2432MHz */
+       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  6, Tf = 2437MHz */
+       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  7, Tf = 2442MHz */
+       0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 */
+       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 */
+       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 */
+       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 */
+       0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 */
+       0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 */
+       0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */
+
+       /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22) */
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */
+       0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */
+       0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */
+       0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */
+
+       /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+        * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56) */
+
+       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   7, Tf = 5035MHz (23) */
+       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   8, Tf = 5040MHz (24) */
+       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   9, Tf = 5045MHz (25) */
+       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  11, Tf = 5055MHz (26) */
+       0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  12, Tf = 5060MHz (27) */
+       0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  16, Tf = 5080MHz (28) */
+       0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  34, Tf = 5170MHz (29) */
+       0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  36, Tf = 5180MHz (30) */
+       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 */
+       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  40, Tf = 5200MHz (32) */
+       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  42, Tf = 5210MHz (33) */
+       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  44, Tf = 5220MHz (34) */
+       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  46, Tf = 5230MHz (35) */
+       0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  48, Tf = 5240MHz (36) */
+       0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  52, Tf = 5260MHz (37) */
+       0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  56, Tf = 5280MHz (38) */
+       0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  60, Tf = 5300MHz (39) */
+       0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  64, Tf = 5320MHz (40) */
+
+       0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */
+       0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */
+       0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */
+       0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */
+       0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */
+       0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */
+       0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */
+       0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */
+       0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */
+       0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */
+       0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */
+       0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */
+       0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */
+       0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */
+       0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */
+       0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  /* channel = 165, Tf = 5825MHz (56) */
 };
 
 static const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = {
-       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
-       0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
-       0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
-       0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
-       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
-       0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
-       0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
-       0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz
-       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz
-       0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-       0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-       0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-       0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
-
-       // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
-       0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
-       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
-       0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
-       0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
-
-       // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
-       // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
-       0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
-       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
-       0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
-       0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
-       0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
-       0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
-       0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
-       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
-       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
-       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
-       0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
-       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
-       0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
-       0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
-       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
+       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  1, Tf = 2412MHz */
+       0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  2, Tf = 2417MHz */
+       0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  3, Tf = 2422MHz */
+       0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  4, Tf = 2427MHz */
+       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  5, Tf = 2432MHz */
+       0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  6, Tf = 2437MHz */
+       0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  7, Tf = 2442MHz */
+       0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  8, Tf = 2447MHz */
+       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  9, Tf = 2452MHz */
+       0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+       0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+       0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+       0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+       0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */
+
+       /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22) */
+       0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */
+       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */
+       0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */
+       0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */
+
+       /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+        * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56) */
+       0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   7, Tf = 5035MHz (23) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   8, Tf = 5040MHz (24) */
+       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   9, Tf = 5045MHz (25) */
+       0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  11, Tf = 5055MHz (26) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  12, Tf = 5060MHz (27) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  16, Tf = 5080MHz (28) */
+       0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  34, Tf = 5170MHz (29) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  36, Tf = 5180MHz (30) */
+       0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  38, Tf = 5190MHz (31) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  40, Tf = 5200MHz (32) */
+       0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  42, Tf = 5210MHz (33) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  44, Tf = 5220MHz (34) */
+       0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  46, Tf = 5230MHz (35) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  48, Tf = 5240MHz (36) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  52, Tf = 5260MHz (37) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  56, Tf = 5280MHz (38) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  60, Tf = 5300MHz (39) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  64, Tf = 5320MHz (40) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */
+       0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */
+       0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */
+       0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */
+       0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */
+       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */
+       0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */
+       0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */
+       0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  /* channel = 165, Tf = 5825MHz (56) */
 };
 
 static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = {
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  4, Tf = 2427MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  5, Tf = 2432MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  6, Tf = 2437MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  7, Tf = 2442MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  8, Tf = 2447MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  9, Tf = 2452MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
-       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
-
-       // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
-
-       // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
-       // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   7, Tf = 5035MHz (23)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   8, Tf = 5040MHz (24)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =   9, Tf = 5045MHz (25)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  11, Tf = 5055MHz (26)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  12, Tf = 5060MHz (27)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  16, Tf = 5080MHz (28)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  34, Tf = 5170MHz (29)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  36, Tf = 5180MHz (30)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  38, Tf = 5190MHz (31)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  40, Tf = 5200MHz (32)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  42, Tf = 5210MHz (33)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  44, Tf = 5220MHz (34)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  46, Tf = 5230MHz (35)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  48, Tf = 5240MHz (36)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  52, Tf = 5260MHz (37)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  56, Tf = 5280MHz (38)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  60, Tf = 5300MHz (39)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  64, Tf = 5320MHz (40)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
-       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
-       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  1, Tf = 2412MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  2, Tf = 2417MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  3, Tf = 2422MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  4, Tf = 2427MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  5, Tf = 2432MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  6, Tf = 2437MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  7, Tf = 2442MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  8, Tf = 2447MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  9, Tf = 2452MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+       0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */
+
+       /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196  (Value:15 ~ 22) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */
+
+       /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+        * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165  (Value 23 ~ 56) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   7, Tf = 5035MHz (23) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   8, Tf = 5040MHz (24) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =   9, Tf = 5045MHz (25) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  11, Tf = 5055MHz (26) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  12, Tf = 5060MHz (27) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  16, Tf = 5080MHz (28) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  34, Tf = 5170MHz (29) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  36, Tf = 5180MHz (30) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  38, Tf = 5190MHz (31) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  40, Tf = 5200MHz (32) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  42, Tf = 5210MHz (33) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  44, Tf = 5220MHz (34) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  46, Tf = 5230MHz (35) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  48, Tf = 5240MHz (36) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  52, Tf = 5260MHz (37) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  56, Tf = 5280MHz (38) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  60, Tf = 5300MHz (39) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel =  64, Tf = 5320MHz (40) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */
+       0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */
+       0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  /* channel = 165, Tf = 5825MHz (56) */
 };
 
 /*
@@ -438,13 +438,13 @@ static bool s_bAL7230Init(struct vnt_private *priv)
        MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
        /* Calibration */
-       MACvTimer0MicroSDelay(dwIoBase, 150);//150us
+       MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */
        /* TXDCOC:active, RCK:disable */
        bResult &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
-       MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+       MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
        /* TXDCOC:disable, RCK:active */
        bResult &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
-       MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+       MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
        /* TXDCOC:disable, RCK:disable */
        bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]);
 
@@ -457,7 +457,7 @@ static bool s_bAL7230Init(struct vnt_private *priv)
 
        /* PE1: TX_ON, PE2: RX_ON, PE3: PLLON */
        /* 3-wire control for power saving mode */
-       VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
+       VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */
 
        return bResult;
 }
@@ -557,16 +557,16 @@ static bool RFbAL2230Init(struct vnt_private *priv)
 
        for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
                bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]);
-       MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us
+       MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */
 
        /* PLL On */
        MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
 
-       MACvTimer0MicroSDelay(dwIoBase, 150);//150us
+       MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */
        bResult &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
-       MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+       MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
        bResult &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
-       MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+       MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
        bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
 
        MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3    |
@@ -575,7 +575,7 @@ static bool RFbAL2230Init(struct vnt_private *priv)
                                                         SOFTPWRCTL_TXPEINV));
 
        /* 3-wire control for power saving mode */
-       VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
+       VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */
 
        return bResult;
 }
@@ -661,11 +661,11 @@ bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType,
        case RF_AL2230S:
                bResult = RFbAL2230SelectChannel(priv, byChannel);
                break;
-               //{{ RobertYu: 20050104
+               /*{{ RobertYu: 20050104 */
        case RF_AIROHA7230:
                bResult = s_bAL7230SelectChannel(priv, byChannel);
                break;
-               //}} RobertYu
+               /*}} RobertYu */
        case RF_NOTHING:
                bResult = true;
                break;
index 2ea21e2b00f2ce93aff6123925f2f6e0a1c09936..b5fc3eed06fb71e7b7dd8f294f4b1c8c392d67e1 100644 (file)
 #include "device.h"
 
 /*---------------------  Export Definitions -------------------------*/
-//
-// Baseband RF pair definition in eeprom (Bits 6..0)
-//
+/*
+ * Baseband RF pair definition in eeprom (Bits 6..0)
+*/
 #define RF_RFMD2959             0x01
 #define RF_MAXIMAG              0x02
 #define RF_AIROHA               0x03
 
 #define RF_UW2451               0x05
 #define RF_MAXIMG               0x06
-#define RF_MAXIM2829            0x07 // RobertYu: 20041118
-#define RF_UW2452               0x08 // RobertYu: 20041210
-#define RF_AIROHA7230           0x0a // RobertYu: 20050104
+#define RF_MAXIM2829            0x07 /* RobertYu: 20041118 */
+#define RF_UW2452               0x08 /* RobertYu: 20041210 */
+#define RF_AIROHA7230           0x0a /* RobertYu: 20050104 */
 #define RF_UW2453               0x0b
 
 #define RF_VT3226               0x09
@@ -63,9 +63,9 @@
 #define ZONE_MKK                6
 #define ZONE_ISRAEL             7
 
-//[20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41
-#define CB_MAXIM2829_CHANNEL_5G_HIGH    41 //Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1
-#define CB_UW2452_CHANNEL_5G_HIGH       41 //[20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3
+/* [20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 */
+#define CB_MAXIM2829_CHANNEL_5G_HIGH    41 /* Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 */
+#define CB_UW2452_CHANNEL_5G_HIGH       41 /* [20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 */
 
 /*---------------------  Export Classes  ----------------------------*/
 
@@ -93,8 +93,8 @@ RFvRSSITodBm(
        long    *pldBm
 );
 
-//{{ RobertYu: 20050104
+/* {{ RobertYu: 20050104 */
 bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, u16, u16);
-//}} RobertYu
+/* }} RobertYu */
 
-#endif // __RF_H__
+#endif /* __RF_H__ */
index 534338c466197013a5b66a8b3f0e7fe74982e490..5875d655dd5545af326ab776ce5bc394f2580ea4 100644 (file)
@@ -130,7 +130,7 @@ s_vGenerateTxParameter(
 static unsigned int
 s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                  unsigned char *pbyTxBufferAddr,
-                 unsigned int uDMAIdx, PSTxDesc pHeadTD,
+                 unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
                  unsigned int uNodeIndex);
 
 static
@@ -387,7 +387,6 @@ s_uGetDataDuration(
                break;
        }
 
-       ASSERT(false);
        return 0;
 }
 
@@ -1028,10 +1027,10 @@ s_vGenerateTxParameter(
 static unsigned int
 s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
                  unsigned char *pbyTxBufferAddr,
-                 unsigned int uDMAIdx, PSTxDesc pHeadTD,
+                 unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
                  unsigned int is_pspoll)
 {
-       PDEVICE_TD_INFO td_info = pHeadTD->pTDInfo;
+       struct vnt_td_info *td_info = pHeadTD->td_info;
        struct sk_buff *skb = td_info->skb;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -1048,7 +1047,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
        unsigned int cbReqCount = 0;
        bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK);
        bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS);
-       PSTxDesc       ptdCurr;
+       struct vnt_tx_desc *ptdCurr;
        unsigned int cbHeaderLength = 0;
        void *pvRrvTime;
        struct vnt_mic_hdr *pMICHDR;
@@ -1089,7 +1088,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
 
 
        /* Set RrvTime/RTS/CTS Buffer */
-       wTxBufSize = sizeof(STxBufHead);
+       wTxBufSize = sizeof(struct vnt_tx_fifo_head);
        if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */
 
                if (byFBOption == AUTO_FB_NONE) {
@@ -1193,17 +1192,15 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
        hdr->duration_id = uDuration;
 
        cbReqCount = cbHeaderLength + uPadding + skb->len;
-       pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
+       pbyBuffer = (unsigned char *)pHeadTD->td_info->buf;
        uLength = cbHeaderLength + uPadding;
 
        /* Copy the Packet into a tx Buffer */
        memcpy((pbyBuffer + uLength), skb->data, skb->len);
 
-       ptdCurr = (PSTxDesc)pHeadTD;
+       ptdCurr = pHeadTD;
 
-       ptdCurr->pTDInfo->dwReqCount = cbReqCount;
-       ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
-       ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
+       ptdCurr->td_info->req_count = (u16)cbReqCount;
 
        return cbHeaderLength;
 }
@@ -1276,9 +1273,9 @@ static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
 }
 
 int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
-                            PSTxDesc head_td, struct sk_buff *skb)
+                            struct vnt_tx_desc *head_td, struct sk_buff *skb)
 {
-       PDEVICE_TD_INFO td_info = head_td->pTDInfo;
+       struct vnt_td_info *td_info = head_td->td_info;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
        struct ieee80211_rate *rate;
index b9bd1639b13eab216ed013cd5995d5463d67581c..1e30ecb5c63c08b6a3ab1b06658203a32c5bdf8d 100644 (file)
@@ -192,9 +192,9 @@ struct vnt_tx_short_buf_head {
 } __packed;
 
 int vnt_generate_fifo_header(struct vnt_private *, u32,
-                            PSTxDesc head_td, struct sk_buff *);
+                            struct vnt_tx_desc *head_td, struct sk_buff *);
 int vnt_beacon_make(struct vnt_private *, struct ieee80211_vif *);
 int vnt_beacon_enable(struct vnt_private *, struct ieee80211_vif *,
                      struct ieee80211_bss_conf *);
 
-#endif // __RXTX_H__
+#endif /* __RXTX_H__ */
index cc63dc8d47f713a46e8dbb041991cc7b7f1a7f12..85fe0464cfb3a20a44dfab6cb3020d2d4b87f6da 100644 (file)
 /* For memory mapped IO */
 
 
-#define VNSvInPortB(dwIOAddress, pbyData)                              \
-do {                                                                   \
-       *(pbyData) = ioread8(dwIOAddress);                              \
-} while (0)
+#define VNSvInPortB(dwIOAddress, pbyData) \
+       (*(pbyData) = ioread8(dwIOAddress))
 
-#define VNSvInPortW(dwIOAddress, pwData)                               \
-do {                                                                   \
-       *(pwData) = ioread16(dwIOAddress);                              \
-} while (0)
+#define VNSvInPortW(dwIOAddress, pwData) \
+       (*(pwData) = ioread16(dwIOAddress))
 
-#define VNSvInPortD(dwIOAddress, pdwData)                              \
-do {                                                                   \
-       *(pdwData) = ioread32(dwIOAddress);                             \
-} while (0)
+#define VNSvInPortD(dwIOAddress, pdwData) \
+       (*(pdwData) = ioread32(dwIOAddress))
 
-#define VNSvOutPortB(dwIOAddress, byData)                              \
-do {                                                                   \
-       iowrite8((u8)byData, dwIOAddress);                              \
-} while (0)
+#define VNSvOutPortB(dwIOAddress, byData) \
+       iowrite8((u8)(byData), dwIOAddress)
 
-#define VNSvOutPortW(dwIOAddress, wData)                               \
-do {                                                                   \
-       iowrite16((u16)wData, dwIOAddress);                             \
-} while (0)
+#define VNSvOutPortW(dwIOAddress, wData) \
+       iowrite16((u16)(wData), dwIOAddress)
 
-#define VNSvOutPortD(dwIOAddress, dwData)                              \
-do {                                                                   \
-       iowrite32((u32)dwData, dwIOAddress);                            \
-} while (0)
+#define VNSvOutPortD(dwIOAddress, dwData) \
+       iowrite32((u32)(dwData), dwIOAddress)
 
 #define PCAvDelayByIO(uDelayUnit)                              \
 do {                                                           \
index 8116791f4f068e38a05986fb5a76c9e88fb8ff87..da075f4852989840568e9cca434a975822dc8efd 100644 (file)
 #include "usbpipe.h"
 
 static const u16 vnt_time_stampoff[2][MAX_RATE] = {
-       {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},/* Long Preamble */
-       {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},/* Short Preamble */
+       /* Long Preamble */
+       {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},
+
+       /* Short Preamble */
+       {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},
 };
 
 static const u16 vnt_fb_opt0[2][5] = {
index 062d9c5ca4bdc953e452e865672db190914fb7e4..51bbf468fe45aa17679f7401bf1e02c4be0d1b52 100644 (file)
@@ -37,17 +37,26 @@ choice
        bool "SDIO support"
        depends on MMC
        ---help---
-         This module adds support for the SDIO interface
-         of adapters using WILC chipset. Select this if
-         your platform is using the SDIO bus.
+         This module adds support for the SDIO interface of adapters using
+         WILC1000 chipset. The Atmel WILC1000 SDIO is a full speed interface.
+         It meets SDIO card specification version 2.0. The interface supports
+         the 1-bit/4-bit SD transfer mode at the clock range of 0-50 MHz.
+         The host can use this interface to read and write from any register
+         within the chip as well as configure the WILC1000 for data DMA.
+         To use this interface, pin9 (SDIO_SPI_CFG) must be grounded. Select
+         this if your platform is using the SDIO bus.
 
        config WILC1000_SPI
        depends on SPI
        bool "SPI support"
        ---help---
-         This module adds support for the SPI interface
-         of adapters using WILC chipset. Select this if
-         your platform is using the SPI bus.
+         This module adds support for the SPI interface of adapters using
+         WILC1000 chipset. The Atmel WILC1000 has a Serial Peripheral
+         Interface (SPI) that operates as a SPI slave. This SPI interface can
+         be used for control and for serial I/O of 802.11 data. The SPI is a
+         full-duplex slave synchronous serial interface that is available
+         immediately following reset when pin 9 (SDIO_SPI_CFG) is tied to
+         VDDIO. Select this if your platform is using the SPI bus.
 endchoice
 
 config WILC1000_HW_OOB_INTR
@@ -55,5 +64,8 @@ config WILC1000_HW_OOB_INTR
        depends on WILC1000 && WILC1000_SDIO
        default n
        ---help---
-         If your platform don't recognize SDIO IRQ, connect chipset external IRQ pin
-         and check this option. Or, Use this to get all interrupts including SDIO interrupts.
+         This option enables out-of-band interrupt support for the WILC1000
+         chipset. This OOB interrupt is intended to provide a faster interrupt
+         mechanism for SDIO host controllers that don't support SDIO interrupt.
+         Select this option If the SDIO host controller in your platform
+         doesn't support SDIO time devision interrupt.
index a78c4d529a58af7e741040bbffcd17ffa67bfa8e..6be8a920706a1065534d1d0bca1cc1472618c10e 100644 (file)
@@ -25,10 +25,10 @@ ccflags-$(CONFIG_WILC1000_PREALLOCATE_AT_LOADING_DRIVER) += -DMEMORY_STATIC \
 ccflags-$(CONFIG_WILC1000_DYNAMICALLY_ALLOCATE_MEMROY) += -DWILC_NORMAL_ALLOC
 
 
-wilc1000-objs := wilc_wfi_netdevice.o wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
-                       wilc_memory.o wilc_msgqueue.o wilc_sleep.o wilc_strutils.o \
-                       wilc_timer.o coreconfigurator.o host_interface.o \
-                       fifo_buffer.o wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o
+wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
+                       wilc_memory.o wilc_msgqueue.o \
+                       coreconfigurator.o host_interface.o \
+                       wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o
 
 wilc1000-$(CONFIG_WILC1000_SDIO) += linux_wlan_sdio.o
 wilc1000-$(CONFIG_WILC1000_SPI) += linux_wlan_spi.o
diff --git a/drivers/staging/wilc1000/coreconfigsimulator.h b/drivers/staging/wilc1000/coreconfigsimulator.h
deleted file mode 100644 (file)
index 5e01f8e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/*!
- *  @file      coreconfigsimulator.h
- *  @brief
- *  @author
- *  @sa                coreconfigsimulator.c
- *  @date      1 Mar 2012
- *  @version   1.0
- */
-
-#ifndef CORECONFIGSIMULATOR_H
-#define CORECONFIGSIMULATOR_H
-
-extern s32 CoreConfigSimulatorInit(void);
-extern s32 CoreConfigSimulatorDeInit(void);
-
-#endif
index ed6ac45c0385714ac6208b26ca55991428eed431..16a0abc970c001d5a3f26ce1f2bf81e86df90f85 100644 (file)
@@ -167,7 +167,6 @@ extern void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length);
 static struct semaphore SemHandleSendPkt;
 static struct semaphore SemHandlePktResp;
 
-static s8 *gps8ConfigPacket;
 
 static tstrConfigPktInfo gstrConfigPktInfo;
 
@@ -544,21 +543,21 @@ INLINE u8 get_from_ds(u8 *header)
 /* header and updates the MAC Address in the allocated 'addr' variable.      */
 INLINE void get_address1(u8 *pu8msa, u8 *addr)
 {
-       WILC_memcpy(addr, pu8msa + 4, 6);
+       memcpy(addr, pu8msa + 4, 6);
 }
 
 /* This function extracts the MAC Address in 'address2' field of the MAC     */
 /* header and updates the MAC Address in the allocated 'addr' variable.      */
 INLINE void get_address2(u8 *pu8msa, u8 *addr)
 {
-       WILC_memcpy(addr, pu8msa + 10, 6);
+       memcpy(addr, pu8msa + 10, 6);
 }
 
 /* This function extracts the MAC Address in 'address3' field of the MAC     */
 /* header and updates the MAC Address in the allocated 'addr' variable.      */
 INLINE void get_address3(u8 *pu8msa, u8 *addr)
 {
-       WILC_memcpy(addr, pu8msa + 16, 6);
+       memcpy(addr, pu8msa + 16, 6);
 }
 
 /* This function extracts the BSSID from the incoming WLAN packet based on   */
@@ -605,7 +604,7 @@ INLINE u16 get_cap_info(u8 *data)
 {
        u16 cap_info = 0;
        u16 index    = MAC_HDR_LEN;
-       tenuFrmSubtype st = BEACON;
+       tenuFrmSubtype st;
 
        st = get_sub_type(data);
 
@@ -674,17 +673,8 @@ s32 CoreConfiguratorInit(void)
        sema_init(&SemHandleSendPkt, 1);
        sema_init(&SemHandlePktResp, 0);
 
-       gps8ConfigPacket = (s8 *)WILC_MALLOC(MAX_PACKET_BUFF_SIZE);
-       if (gps8ConfigPacket == NULL) {
-               PRINT_ER("failed in gps8ConfigPacket allocation\n");
-               s32Error = WILC_NO_MEM;
-               goto _fail_;
-       }
-
-       WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE);
 
-       WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
-_fail_:
+       memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
        return s32Error;
 }
 
@@ -706,11 +696,10 @@ u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset)
 
        /* Search for the TIM Element Field and return if the element is found */
        while (u16index < (u16RxLen - FCS_LEN)) {
-               if (pu8msa[u16index] == ITIM) {
+               if (pu8msa[u16index] == ITIM)
                        return &pu8msa[u16index];
-               } else {
+               else
                        u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
-               }
        }
 
        return 0;
@@ -811,8 +800,11 @@ s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
                u32 u32Tsf_Lo;
                u32 u32Tsf_Hi;
 
-               pstrNetworkInfo = (tstrNetworkInfo *)WILC_MALLOC(sizeof(tstrNetworkInfo));
-               WILC_memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo));
+               pstrNetworkInfo = kmalloc(sizeof(tstrNetworkInfo), GFP_KERNEL);
+               if (!pstrNetworkInfo)
+                       return -ENOMEM;
+
+               memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo));
 
                pstrNetworkInfo->s8rssi = pu8WidVal[0];
 
@@ -855,17 +847,19 @@ s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
 
                /* Get DTIM Period */
                pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index);
-               if (pu8TimElm != 0) {
+               if (pu8TimElm != 0)
                        pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
-               }
                pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
                u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN);
 
                if (u16IEsLen > 0) {
-                       pstrNetworkInfo->pu8IEs = (u8 *)WILC_MALLOC(u16IEsLen);
-                       WILC_memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen);
+                       pstrNetworkInfo->pu8IEs = kmalloc(u16IEsLen, GFP_KERNEL);
+                       if (!pstrNetworkInfo->pu8IEs)
+                               return -ENOMEM;
 
-                       WILC_memcpy(pstrNetworkInfo->pu8IEs, pu8IEs, u16IEsLen);
+                       memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen);
+
+                       memcpy(pstrNetworkInfo->pu8IEs, pu8IEs, u16IEsLen);
                }
                pstrNetworkInfo->u16IEsLen = u16IEsLen;
 
@@ -893,13 +887,13 @@ s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo)
 
        if (pstrNetworkInfo != NULL) {
                if (pstrNetworkInfo->pu8IEs != NULL) {
-                       WILC_FREE(pstrNetworkInfo->pu8IEs);
+                       kfree(pstrNetworkInfo->pu8IEs);
                        pstrNetworkInfo->pu8IEs = NULL;
                } else {
                        s32Error = WILC_FAIL;
                }
 
-               WILC_FREE(pstrNetworkInfo);
+               kfree(pstrNetworkInfo);
                pstrNetworkInfo = NULL;
 
        } else {
@@ -929,8 +923,11 @@ s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
        u8 *pu8IEs = 0;
        u16 u16IEsLen = 0;
 
-       pstrConnectRespInfo = (tstrConnectRespInfo *)WILC_MALLOC(sizeof(tstrConnectRespInfo));
-       WILC_memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo));
+       pstrConnectRespInfo = kmalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL);
+       if (!pstrConnectRespInfo)
+               return -ENOMEM;
+
+       memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo));
 
        /* u16AssocRespLen = pu8Buffer[0]; */
        u16AssocRespLen = (u16)u32BufferLen;
@@ -949,10 +946,13 @@ s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
                pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
                u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
 
-               pstrConnectRespInfo->pu8RespIEs = (u8 *)WILC_MALLOC(u16IEsLen);
-               WILC_memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen);
+               pstrConnectRespInfo->pu8RespIEs = kmalloc(u16IEsLen, GFP_KERNEL);
+               if (!pstrConnectRespInfo->pu8RespIEs)
+                       return -ENOMEM;
 
-               WILC_memcpy(pstrConnectRespInfo->pu8RespIEs, pu8IEs, u16IEsLen);
+               memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen);
+
+               memcpy(pstrConnectRespInfo->pu8RespIEs, pu8IEs, u16IEsLen);
                pstrConnectRespInfo->u16RespIEsLen = u16IEsLen;
        }
 
@@ -978,13 +978,13 @@ s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo)
 
        if (pstrConnectRespInfo != NULL) {
                if (pstrConnectRespInfo->pu8RespIEs != NULL) {
-                       WILC_FREE(pstrConnectRespInfo->pu8RespIEs);
+                       kfree(pstrConnectRespInfo->pu8RespIEs);
                        pstrConnectRespInfo->pu8RespIEs = NULL;
                } else {
                        s32Error = WILC_FAIL;
                }
 
-               WILC_FREE(pstrConnectRespInfo);
+               kfree(pstrConnectRespInfo);
                pstrConnectRespInfo = NULL;
 
        } else {
@@ -1018,13 +1018,12 @@ s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZ
                }
        }
 
-       pstrSurveyResults = (wid_site_survey_reslts_s *)WILC_MALLOC(u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
-       if (pstrSurveyResults == NULL) {
-               u32SurveyResultsCount = 0;
-               WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
+       pstrSurveyResults = kmalloc_array(u32SurveyResultsCount,
+                               sizeof(wid_site_survey_reslts_s), GFP_KERNEL);
+       if (!pstrSurveyResults)
+               return -ENOMEM;
 
-       WILC_memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
+       memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
 
        u32SurveyResultsCount = 0;
 
@@ -1039,7 +1038,7 @@ s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZ
                pu8BufferPtr += 2;
 
                for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
-                       WILC_memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH);
+                       memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH);
                        pu8BufferPtr += SURVEY_RESULT_LENGTH;
                        u32SurveyResultsCount++;
                }
@@ -1058,7 +1057,7 @@ s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults)
        s32 s32Error = WILC_SUCCESS;
 
        if (pstrSurveyResults != NULL) {
-               WILC_FREE(pstrSurveyResults);
+               kfree(pstrSurveyResults);
        }
 
        return s32Error;
@@ -1334,7 +1333,6 @@ void ProcessStrWid(char *pcPacket, s32 *ps32PktLen,
 
        if (g_oper_mode == SET_CFG) {
                /* Message Length */
-               /* u16MsgLen = WILC_strlen(pu8val); */
                u16MsgLen = (u16)s32ValueSize;
 
                /* Length */
@@ -1441,8 +1439,6 @@ void ProcessAdrWid(char *pcPacket, s32 *ps32PktLen,
 void ProcessBinWid(char *pcPacket, s32 *ps32PktLen,
                   tstrWID *pstrWID, u8 *pu8val, s32 s32ValueSize)
 {
-       /* WILC_ERROR("processing Binary WIDs is not supported\n"); */
-
        u16 u16MsgLen = 0;
        u16 idx    = 0;
        s32 s32PktLen = *ps32PktLen;
@@ -1528,11 +1524,10 @@ s32 further_process_response(u8 *resp,
        u8 cfg_str[256] = {0};
        tenuWIDtype enuWIDtype = WID_UNDEF;
 
-       if (process_wid_num) {
+       if (process_wid_num)
                enuWIDtype = get_wid_type(g_wid_num);
-       } else {
+       else
                enuWIDtype = gastrWIDs[cnt].enuWIDtype;
-       }
 
 
        switch (enuWIDtype) {
@@ -1566,18 +1561,10 @@ s32 further_process_response(u8 *resp,
        }
 
        case WID_STR:
-               WILC_memcpy(cfg_str, resp + idx, cfg_len);
+               memcpy(cfg_str, resp + idx, cfg_len);
                /* cfg_str[cfg_len] = '\0'; //mostafa: no need currently for NULL termination */
-               if (process_wid_num) {
-                       /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num,
-                        *                              cfg_str);*/
-               } else {
-                       /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch,
-                        *                           cfg_str);*/
-               }
-
                if (pstrWIDresult->s32ValueSize >= cfg_len) {
-                       WILC_memcpy(pstrWIDresult->ps8WidVal, cfg_str, cfg_len); /* mostafa: no need currently for the extra NULL byte */
+                       memcpy(pstrWIDresult->ps8WidVal, cfg_str, cfg_len); /* mostafa: no need currently for the extra NULL byte */
                        pstrWIDresult->s32ValueSize = cfg_len;
                } else {
                        PRINT_ER("allocated WID buffer length is smaller than the received WID Length\n");
@@ -1589,15 +1576,8 @@ s32 further_process_response(u8 *resp,
        case WID_ADR:
                create_mac_addr(cfg_str, resp + idx);
 
-               WILC_strncpy(pstrWIDresult->ps8WidVal, cfg_str, WILC_strlen(cfg_str));
-               pstrWIDresult->ps8WidVal[WILC_strlen(cfg_str)] = '\0';
-               if (process_wid_num) {
-                       /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num,
-                        *                              cfg_str);*/
-               } else {
-                       /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch,
-                        *                           cfg_str);*/
-               }
+               strncpy(pstrWIDresult->ps8WidVal, cfg_str, strlen(cfg_str));
+               pstrWIDresult->ps8WidVal[strlen(cfg_str)] = '\0';
                break;
 
        case WID_IP:
@@ -1606,18 +1586,11 @@ s32 further_process_response(u8 *resp,
                                MAKE_WORD16(resp[idx + 2], resp[idx + 3])
                                );
                conv_int_to_ip(cfg_str, cfg_int);
-               if (process_wid_num) {
-                       /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num,
-                        *                              cfg_str);*/
-               } else {
-                       /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch,
-                        *                           cfg_str);*/
-               }
                break;
 
        case WID_BIN_DATA:
                if (pstrWIDresult->s32ValueSize >= cfg_len) {
-                       WILC_memcpy(pstrWIDresult->ps8WidVal, resp + idx, cfg_len);
+                       memcpy(pstrWIDresult->ps8WidVal, resp + idx, cfg_len);
                        pstrWIDresult->s32ValueSize = cfg_len;
                } else {
                        PRINT_ER("Allocated WID buffer length is smaller than the received WID Length Err(%d)\n", retval);
@@ -1739,7 +1712,6 @@ s32 ParseResponse(u8 *resp, tstrWID *pstrWIDcfgResult)
 s32 ParseWriteResponse(u8 *pu8RespBuffer)
 {
        s32 s32Error = WILC_FAIL;
-       u16 u16RespLen   = 0;
        u16 u16WIDtype = (u16)WID_NIL;
 
        /* Check whether the received frame is a valid response */
@@ -1748,9 +1720,6 @@ s32 ParseWriteResponse(u8 *pu8RespBuffer)
                return WILC_FAIL;
        }
 
-       /* Extract Response Length */
-       u16RespLen = MAKE_WORD16(pu8RespBuffer[2], pu8RespBuffer[3]);
-
        u16WIDtype = MAKE_WORD16(pu8RespBuffer[4], pu8RespBuffer[5]);
 
        /* Check for WID_STATUS ID and then check the length and status value */
@@ -1898,104 +1867,21 @@ s32 ConfigWaitResponse(char *pcRespBuffer, s32 s32MaxRespBuffLen, s32 *ps32Bytes
                *ps32BytesRead = gstrConfigPktInfo.s32BytesRead;
        }
 
-       WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
+       memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
 
        return s32Error;
 }
 
-/**
- *  @brief              sends certain Configuration Packet based on the input WIDs pstrWIDs
- *                      and retrieves the packet response pu8RxResp
- *  @details
- *  @param[in]  pstrWIDs WIDs to be sent in the configuration packet
- *  @param[in]  u32WIDsCount number of WIDs to be sent in the configuration packet
- *  @param[out]         pu8RxResp The received Packet Response
- *  @param[out]         ps32RxRespLen Length of the received Packet Response
- *  @return     Error code indicating success/failure
- *  @note
- *  @author    mabubakr
- *  @date              1 Mar 2012
- *  @version   1.0
- */
-#ifdef SIMULATION
-s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
-                         u32 u32WIDsCount, bool bRespRequired, u32 drvHandler)
-{
-       s32 s32Error = WILC_SUCCESS;
-       s32 err = WILC_SUCCESS;
-       s32 s32ConfigPacketLen = 0;
-       s32 s32RcvdRespLen = 0;
-
-       down(&SemHandleSendPkt);
-
-       /*set the packet mode*/
-       g_oper_mode = u8Mode;
-
-       WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE);
-
-       if (CreateConfigPacket(gps8ConfigPacket, &s32ConfigPacketLen, pstrWIDs, u32WIDsCount) != WILC_SUCCESS) {
-               s32Error = WILC_FAIL;
-               goto End_ConfigPkt;
-       }
-       /*bug 3878*/
-       gstrConfigPktInfo.pcRespBuffer = gps8ConfigPacket;
-       gstrConfigPktInfo.s32MaxRespBuffLen = MAX_PACKET_BUFF_SIZE;
-       PRINT_INFO(CORECONFIG_DBG, "GLOBAL =bRespRequired =%d\n", bRespRequired);
-       gstrConfigPktInfo.bRespRequired = bRespRequired;
-
-       s32Error = SendRawPacket(gps8ConfigPacket, s32ConfigPacketLen);
-       if (s32Error != WILC_SUCCESS) {
-               goto End_ConfigPkt;
-       }
-
-       WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE);
-
-       ConfigWaitResponse(gps8ConfigPacket, MAX_PACKET_BUFF_SIZE, &s32RcvdRespLen, bRespRequired);
-
-
-       if (bRespRequired)      {
-               /* If the operating Mode is GET, then we expect a response frame from */
-               /* the driver. Hence start listening to the port for response         */
-               if (g_oper_mode == GET_CFG) {
-                       #if 1
-                       err = ParseResponse(gps8ConfigPacket, pstrWIDs);
-                       if (err != 0) {
-                               s32Error = WILC_FAIL;
-                               goto End_ConfigPkt;
-                       } else {
-                               s32Error = WILC_SUCCESS;
-                       }
-                       #endif
-               } else {
-                       err = ParseWriteResponse(gps8ConfigPacket);
-                       if (err != WRITE_RESP_SUCCESS) {
-                               s32Error = WILC_FAIL;
-                               goto End_ConfigPkt;
-                       } else {
-                               s32Error = WILC_SUCCESS;
-                       }
-               }
-
-
-       }
-
-
-End_ConfigPkt:
-       up(&SemHandleSendPkt);
-
-       return s32Error;
-}
-#endif
 s32 ConfigProvideResponse(char *pcRespBuffer, s32 s32RespLen)
 {
        s32 s32Error = WILC_SUCCESS;
 
        if (gstrConfigPktInfo.bRespRequired) {
                if (s32RespLen <= gstrConfigPktInfo.s32MaxRespBuffLen) {
-                       WILC_memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen);
+                       memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen);
                        gstrConfigPktInfo.s32BytesRead = s32RespLen;
                } else {
-                       WILC_memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen);
+                       memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen);
                        gstrConfigPktInfo.s32BytesRead = gstrConfigPktInfo.s32MaxRespBuffLen;
                        PRINT_ER("BusProvideResponse() Response greater than the prepared Buffer Size\n");
                }
@@ -2069,17 +1955,10 @@ s32 CoreConfiguratorDeInit(void)
 
        PRINT_D(CORECONFIG_DBG, "CoreConfiguratorDeInit()\n");
 
-       if (gps8ConfigPacket != NULL) {
-
-               WILC_FREE(gps8ConfigPacket);
-               gps8ConfigPacket = NULL;
-       }
 
        return s32Error;
 }
 
-
-#ifndef SIMULATION
 /*Using the global handle of the driver*/
 extern wilc_wlan_oup_t *gpstrWlanOps;
 /**
@@ -2129,7 +2008,6 @@ s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
                /**
                 *      get the value
                 **/
-               /* WILC_Sleep(1000); */
                counter = 0;
                for (counter = 0; counter < u32WIDsCount; counter++) {
                        pstrWIDs[counter].s32ValueSize = gpstrWlanOps->wlan_cfg_get_value(
@@ -2153,4 +2031,3 @@ s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
 
        return ret;
 }
-#endif
index 9059c8df7ce54d83a5854a2f09d702627de567ad..3af193543cdbae0f1775a867c0eddbfda71ca7bd 100644 (file)
@@ -8,7 +8,6 @@
  *  @version   1.0
  */
 
-
 #ifndef CORECONFIGURATOR_H
 #define CORECONFIGURATOR_H
 
@@ -42,7 +41,6 @@ extern u16 g_num_total_switches;
 #define AID_LEN                 2
 #define IE_HDR_LEN              2
 
-
 /* Operating Mode: SET */
 #define SET_CFG              0
 /* Operating Mode: GET */
@@ -59,15 +57,12 @@ extern u16 g_num_total_switches;
 #define MAC_CONNECTED                1
 #define MAC_DISCONNECTED             0
 
-
-
 /*****************************************************************************/
 /* Function Macros                                                           */
 /*****************************************************************************/
 #define MAKE_WORD16(lsb, msb) ((((u16)(msb) << 8) & 0xFF00) | (lsb))
 #define MAKE_WORD32(lsw, msw) ((((u32)(msw) << 16) & 0xFFFF0000) | (lsw))
 
-
 /*****************************************************************************/
 /* Type Definitions                                                                                                                       */
 /*****************************************************************************/
@@ -140,7 +135,6 @@ typedef struct {
        u16 u16RespIEsLen;
 } tstrConnectRespInfo;
 
-
 typedef struct {
        u8 au8bssid[6];
        u8 *pu8ReqIEs;
@@ -150,8 +144,6 @@ typedef struct {
        u16 u16ConnectStatus;
 } tstrConnectInfo;
 
-
-
 typedef struct {
        u16 u16reason;
        u8 *ie;
@@ -171,26 +163,27 @@ typedef struct wid_site_survey_reslts {
 } wid_site_survey_reslts_s;
 #endif
 
-extern s32 CoreConfiguratorInit(void);
-extern s32 CoreConfiguratorDeInit(void);
+s32 CoreConfiguratorInit(void);
+s32 CoreConfiguratorDeInit(void);
 
-extern s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
-                                u32 u32WIDsCount, bool bRespRequired, u32 drvHandler);
-extern s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo);
-extern s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo);
+s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
+                 u32 u32WIDsCount, bool bRespRequired, u32 drvHandler);
+s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo);
+s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo);
 
-extern s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
-                                     tstrConnectRespInfo **ppstrConnectRespInfo);
-extern s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo);
+s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
+                      tstrConnectRespInfo **ppstrConnectRespInfo);
+s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo);
 
 #ifndef CONNECT_DIRECT
-extern s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
-                                     wid_site_survey_reslts_s **ppstrSurveyResults, u32 *pu32SurveyResultsCount);
-extern s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults);
+s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
+                      wid_site_survey_reslts_s **ppstrSurveyResults,
+                      u32 *pu32SurveyResultsCount);
+s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults);
 #endif
 
-extern s32 SendRawPacket(s8 *pspacket, s32 s32PacketLen);
-extern void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
+s32 SendRawPacket(s8 *pspacket, s32 s32PacketLen);
+void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
 void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length);
 void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length);
 
diff --git a/drivers/staging/wilc1000/fifo_buffer.c b/drivers/staging/wilc1000/fifo_buffer.c
deleted file mode 100644 (file)
index b6c07cf..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-#include "fifo_buffer.h"
-
-
-
-u32 FIFO_InitBuffer(tHANDLE *hBuffer, u32 u32BufferLength)
-{
-       u32 u32Error = 0;
-       tstrFifoHandler *pstrFifoHandler = WILC_MALLOC (sizeof (tstrFifoHandler));
-       if (pstrFifoHandler) {
-               WILC_memset (pstrFifoHandler, 0, sizeof (tstrFifoHandler));
-               pstrFifoHandler->pu8Buffer = WILC_MALLOC (u32BufferLength);
-               if (pstrFifoHandler->pu8Buffer) {
-                       pstrFifoHandler->u32BufferLength = u32BufferLength;
-                       WILC_memset (pstrFifoHandler->pu8Buffer, 0, u32BufferLength);
-                       /* create semaphore */
-                       sema_init(&pstrFifoHandler->SemBuffer, 1);
-                       *hBuffer = pstrFifoHandler;
-               } else {
-                       *hBuffer = NULL;
-                       u32Error = 1;
-               }
-       } else {
-               u32Error = 1;
-       }
-       return u32Error;
-}
-u32 FIFO_DeInit(tHANDLE hFifo)
-{
-       u32 u32Error = 0;
-       tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
-       if (pstrFifoHandler) {
-               if (pstrFifoHandler->pu8Buffer) {
-                       WILC_FREE (pstrFifoHandler->pu8Buffer);
-               } else {
-                       u32Error = 1;
-               }
-
-               WILC_FREE (pstrFifoHandler);
-       } else {
-               u32Error = 1;
-       }
-       return u32Error;
-}
-
-u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToRead, u32 *pu32BytesRead)
-{
-       u32 u32Error = 0;
-       tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
-       if (pstrFifoHandler && pu32BytesRead) {
-               if (pstrFifoHandler->u32TotalBytes) {
-                       down(&pstrFifoHandler->SemBuffer);
-
-                       if (u32BytesToRead > pstrFifoHandler->u32TotalBytes) {
-                               *pu32BytesRead = pstrFifoHandler->u32TotalBytes;
-                       } else {
-                               *pu32BytesRead = u32BytesToRead;
-                       }
-                       if ((pstrFifoHandler->u32ReadOffset + u32BytesToRead) <= pstrFifoHandler->u32BufferLength) {
-                               WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset,
-                                           *pu32BytesRead);
-                               /* update read offset and total bytes */
-                               pstrFifoHandler->u32ReadOffset += u32BytesToRead;
-                               pstrFifoHandler->u32TotalBytes -= u32BytesToRead;
-
-                       } else {
-                               u32 u32FirstPart =
-                                       pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32ReadOffset;
-                               WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset,
-                                           u32FirstPart);
-                               WILC_memcpy(pu8Buffer + u32FirstPart, pstrFifoHandler->pu8Buffer,
-                                           u32BytesToRead - u32FirstPart);
-                               /* update read offset and total bytes */
-                               pstrFifoHandler->u32ReadOffset = u32BytesToRead - u32FirstPart;
-                               pstrFifoHandler->u32TotalBytes -= u32BytesToRead;
-                       }
-                       up(&pstrFifoHandler->SemBuffer);
-               } else {
-                       u32Error = 1;
-               }
-       } else {
-               u32Error = 1;
-       }
-       return u32Error;
-}
-
-u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToWrite, bool bForceOverWrite)
-{
-       u32 u32Error = 0;
-       tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
-       if (pstrFifoHandler) {
-               if (u32BytesToWrite < pstrFifoHandler->u32BufferLength) {
-                       if ((pstrFifoHandler->u32TotalBytes + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength ||
-                           bForceOverWrite) {
-                               down(&pstrFifoHandler->SemBuffer);
-                               if ((pstrFifoHandler->u32WriteOffset + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength) {
-                                       WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer,
-                                                   u32BytesToWrite);
-                                       /* update read offset and total bytes */
-                                       pstrFifoHandler->u32WriteOffset += u32BytesToWrite;
-                                       pstrFifoHandler->u32TotalBytes  += u32BytesToWrite;
-
-                               } else {
-                                       u32 u32FirstPart =
-                                               pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32WriteOffset;
-                                       WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer,
-                                                   u32FirstPart);
-                                       WILC_memcpy(pstrFifoHandler->pu8Buffer, pu8Buffer + u32FirstPart,
-                                                   u32BytesToWrite - u32FirstPart);
-                                       /* update read offset and total bytes */
-                                       pstrFifoHandler->u32WriteOffset = u32BytesToWrite - u32FirstPart;
-                                       pstrFifoHandler->u32TotalBytes += u32BytesToWrite;
-                               }
-                               /* if data overwriten */
-                               if (pstrFifoHandler->u32TotalBytes > pstrFifoHandler->u32BufferLength) {
-                                       /* adjust read offset to the oldest data available */
-                                       pstrFifoHandler->u32ReadOffset = pstrFifoHandler->u32WriteOffset;
-                                       /* data availabe is the buffer length */
-                                       pstrFifoHandler->u32TotalBytes = pstrFifoHandler->u32BufferLength;
-                               }
-                               up(&pstrFifoHandler->SemBuffer);
-                       } else {
-                               u32Error = 1;
-                       }
-               } else {
-                       u32Error = 1;
-               }
-       } else {
-               u32Error = 1;
-       }
-       return u32Error;
-}
diff --git a/drivers/staging/wilc1000/fifo_buffer.h b/drivers/staging/wilc1000/fifo_buffer.h
deleted file mode 100644 (file)
index 7b76998..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include <linux/types.h>
-#include <linux/semaphore.h>
-#include "wilc_memory.h"
-#include "wilc_strutils.h"
-
-
-#define tHANDLE        void *
-
-typedef struct {
-       u8              *pu8Buffer;
-       u32 u32BufferLength;
-       u32 u32WriteOffset;
-       u32 u32ReadOffset;
-       u32 u32TotalBytes;
-       struct semaphore SemBuffer;
-} tstrFifoHandler;
-
-
-extern u32 FIFO_InitBuffer(tHANDLE *hBuffer,
-                                                                  u32 u32BufferLength);
-extern u32 FIFO_DeInit(tHANDLE hFifo);
-extern u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer,
-                               u32 u32BytesToRead, u32 *pu32BytesRead);
-extern u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer,
-                               u32 u32BytesToWrite, bool bForceOverWrite);
index 6b10bbbe6ab26abfafa25950071b353960cce61e..66fa677015db43e5224eef679b60a690708a7297 100644 (file)
@@ -6,10 +6,9 @@ extern s32 TransportDeInit(void);
 extern u8 connecting;
 
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-extern WILC_TimerHandle hDuringIpTimer;
+extern struct timer_list hDuringIpTimer;
 #endif
 
-extern bool bEnablePS;
 /*BugID_5137*/
 extern u8 g_wilc_initialized;
 /*****************************************************************************/
@@ -467,7 +466,7 @@ typedef union _tuniHostIFmsgBody {
 typedef struct _tstrHostIFmsg {
        u16 u16MsgId;                                           /*!< Message ID */
        tuniHostIFmsgBody uniHostIFmsgBody;             /*!< Message body */
-       void *drvHandler;
+       tstrWILC_WFIDrv *drvHandler;
 } tstrHostIFmsg;
 
 #ifdef CONNECT_DIRECT
@@ -534,8 +533,8 @@ typedef enum {
 /*****************************************************************************/
 
 
-tstrWILC_WFIDrv *terminated_handle = NULL;
-tstrWILC_WFIDrv *gWFiDrvHandle = NULL;
+tstrWILC_WFIDrv *terminated_handle;
+tstrWILC_WFIDrv *gWFiDrvHandle;
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 bool g_obtainingIP = false;
 #endif
@@ -547,7 +546,7 @@ static struct semaphore hSemHostIFthrdEnd;
 struct semaphore hSemDeinitDrvHandle;
 static struct semaphore hWaitResponse;
 struct semaphore hSemHostIntDeinit;
-WILC_TimerHandle g_hPeriodicRSSI;
+struct timer_list g_hPeriodicRSSI;
 
 
 
@@ -570,9 +569,7 @@ static u8 gs8GetIP[2][4];
 static u32 gu32InactiveTime;
 static u8 gu8DelBcn;
 #endif
-#ifndef SIMULATION
 static u32 gu32WidConnRstHack;
-#endif
 
 /*BugID_5137*/
 u8 *gu8FlushedJoinReq;
@@ -604,7 +601,7 @@ extern int linux_wlan_get_num_conn_ifcs(void);
  *  @date
  *  @version   1.0
  */
-static s32 Handle_SetChannel(void *drvHandler, tstrHostIFSetChan *pstrHostIFSetChan)
+static s32 Handle_SetChannel(tstrWILC_WFIDrv *drvHandler, tstrHostIFSetChan *pstrHostIFSetChan)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -659,9 +656,8 @@ static s32 Handle_SetWfiDrvHandler(tstrHostIfSetDrvHandler *pstrHostIfSetDrvHand
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
 
-       if ((pstrHostIfSetDrvHandler->u32Address) == (u32)NULL) {
+       if ((pstrHostIfSetDrvHandler->u32Address) == (u32)NULL)
                up(&hSemDeinitDrvHandle);
-       }
 
 
        if (s32Error) {
@@ -685,7 +681,7 @@ static s32 Handle_SetWfiDrvHandler(tstrHostIfSetDrvHandler *pstrHostIfSetDrvHand
  *  @date
  *  @version   1.0
  */
-static s32 Handle_SetOperationMode(void *drvHandler, tstrHostIfSetOperationMode *pstrHostIfSetOperationMode)
+static s32 Handle_SetOperationMode(tstrWILC_WFIDrv *drvHandler, tstrHostIfSetOperationMode *pstrHostIfSetOperationMode)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -700,14 +696,13 @@ static s32 Handle_SetOperationMode(void *drvHandler, tstrHostIfSetOperationMode
        strWID.s32ValueSize = sizeof(u32);
 
        /*Sending Cfg*/
-       PRINT_INFO(HOSTINF_DBG, "pstrWFIDrv= %p \n", pstrWFIDrv);
+       PRINT_INFO(HOSTINF_DBG, "pstrWFIDrv= %p\n", pstrWFIDrv);
 
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
 
-       if ((pstrHostIfSetOperationMode->u32Mode) == (u32)NULL) {
+       if ((pstrHostIfSetOperationMode->u32Mode) == (u32)NULL)
                up(&hSemDeinitDrvHandle);
-       }
 
 
        if (s32Error) {
@@ -731,7 +726,7 @@ static s32 Handle_SetOperationMode(void *drvHandler, tstrHostIfSetOperationMode
  *  @date
  *  @version   1.0
  */
-s32 Handle_set_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
+s32 Handle_set_IPAddress(tstrWILC_WFIDrv *drvHandler, u8 *pu8IPAddr, u8 idx)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -742,9 +737,9 @@ s32 Handle_set_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
        if (pu8IPAddr[0] < 192)
                pu8IPAddr[0] = 0;
 
-       PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set  IP = %d.%d.%d.%d \n", idx, pu8IPAddr[0], pu8IPAddr[1], pu8IPAddr[2], pu8IPAddr[3]);
+       PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set  IP = %pI4\n", idx, pu8IPAddr);
 
-       WILC_memcpy(gs8SetIP[idx], pu8IPAddr, IP_ALEN);
+       memcpy(gs8SetIP[idx], pu8IPAddr, IP_ALEN);
 
        /*prepare configuration packet*/
        strWID.u16WIDid = (u16)WID_IP_ADDRESS;
@@ -756,7 +751,7 @@ s32 Handle_set_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
 
 
 
-       host_int_get_ipaddress((WILC_WFIDrvHandle)drvHandler, firmwareIPAddress, idx);
+       host_int_get_ipaddress(drvHandler, firmwareIPAddress, idx);
 
        if (s32Error) {
                PRINT_D(HOSTINF_DBG, "Failed to set IP address\n");
@@ -783,7 +778,7 @@ s32 Handle_set_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
  *  @date
  *  @version   1.0
  */
-s32 Handle_get_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
+s32 Handle_get_IPAddress(tstrWILC_WFIDrv *drvHandler, u8 *pu8IPAddr, u8 idx)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -793,27 +788,27 @@ s32 Handle_get_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
        /*prepare configuration packet*/
        strWID.u16WIDid = (u16)WID_IP_ADDRESS;
        strWID.enuWIDtype = WID_STR;
-       strWID.ps8WidVal = (u8 *)WILC_MALLOC(IP_ALEN);
+       strWID.ps8WidVal = WILC_MALLOC(IP_ALEN);
        strWID.s32ValueSize = IP_ALEN;
 
        s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
-       PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", (u8)(strWID.ps8WidVal[0]), (u8)(strWID.ps8WidVal[1]), (u8)(strWID.ps8WidVal[2]), (u8)(strWID.ps8WidVal[3]));
+       PRINT_INFO(HOSTINF_DBG, "%pI4\n", strWID.ps8WidVal);
 
-       WILC_memcpy(gs8GetIP[idx], strWID.ps8WidVal, IP_ALEN);
+       memcpy(gs8GetIP[idx], strWID.ps8WidVal, IP_ALEN);
 
        /*get the value by searching the local copy*/
-       WILC_FREE(strWID.ps8WidVal);
+       kfree(strWID.ps8WidVal);
 
-       if (WILC_memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0)
-               host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, gs8SetIP[idx], idx);
+       if (memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0)
+               host_int_setup_ipaddress(pstrWFIDrv, gs8SetIP[idx], idx);
 
        if (s32Error != WILC_SUCCESS) {
                PRINT_ER("Failed to get IP address\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE);
        } else {
-               PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d \n", idx);
-               PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", gs8GetIP[idx][0], gs8GetIP[idx][1], gs8GetIP[idx][2], gs8GetIP[idx][3]);
+               PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d\n", idx);
+               PRINT_INFO(HOSTINF_DBG, "%pI4\n", gs8GetIP[idx]);
                PRINT_INFO(HOSTINF_DBG, "\n");
        }
 
@@ -836,18 +831,19 @@ s32 Handle_get_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
  *  @date              November 2013
  *  @version   7.0
  */
-static s32 Handle_SetMacAddress(void *drvHandler, tstrHostIfSetMacAddress *pstrHostIfSetMacAddress)
+static s32 Handle_SetMacAddress(tstrWILC_WFIDrv *drvHandler, tstrHostIfSetMacAddress *pstrHostIfSetMacAddress)
 {
 
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
-       u8 *mac_buf = (u8 *)WILC_MALLOC(ETH_ALEN);
+       u8 *mac_buf = WILC_MALLOC(ETH_ALEN);
+
        if (mac_buf == NULL) {
                PRINT_ER("No buffer to send mac address\n");
                return WILC_FAIL;
        }
-       WILC_memcpy(mac_buf, pstrHostIfSetMacAddress->u8MacAddress, ETH_ALEN);
+       memcpy(mac_buf, pstrHostIfSetMacAddress->u8MacAddress, ETH_ALEN);
 
        /*prepare configuration packet*/
        strWID.u16WIDid = (u16)WID_MAC_ADDR;
@@ -866,7 +862,7 @@ static s32 Handle_SetMacAddress(void *drvHandler, tstrHostIfSetMacAddress *pstrH
        {
 
        }
-       WILC_FREE(mac_buf);
+       kfree(mac_buf);
        return s32Error;
 }
 
@@ -881,7 +877,7 @@ static s32 Handle_SetMacAddress(void *drvHandler, tstrHostIfSetMacAddress *pstrH
  *  @date              JAN 2013
  *  @version   8.0
  */
-static s32 Handle_GetMacAddress(void *drvHandler, tstrHostIfGetMacAddress *pstrHostIfGetMacAddress)
+static s32 Handle_GetMacAddress(tstrWILC_WFIDrv *drvHandler, tstrHostIfGetMacAddress *pstrHostIfGetMacAddress)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -918,7 +914,7 @@ static s32 Handle_GetMacAddress(void *drvHandler, tstrHostIfGetMacAddress *pstrH
  *  @date
  *  @version   1.0
  */
-static s32 Handle_CfgParam(void *drvHandler, tstrHostIFCfgParamAttr *strHostIFCfgParamAttr)
+static s32 Handle_CfgParam(tstrWILC_WFIDrv *drvHandler, tstrHostIFCfgParamAttr *strHostIFCfgParamAttr)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWIDList[32];
@@ -1204,10 +1200,9 @@ static s32 Handle_CfgParam(void *drvHandler, tstrHostIFCfgParamAttr *strHostIFCf
        }
        s32Error = SendConfigPkt(SET_CFG, strWIDList, u8WidCnt, false, (u32)pstrWFIDrv);
 
-       if (s32Error) {
+       if (s32Error)
                PRINT_ER("Error in setting CFG params\n");
 
-       }
        WILC_CATCH(s32Error)
        {
        }
@@ -1228,6 +1223,7 @@ static s32 Handle_CfgParam(void *drvHandler, tstrHostIFCfgParamAttr *strHostIFCf
 static s32 Handle_wait_msg_q_empty(void)
 {
        s32 s32Error = WILC_SUCCESS;
+
        g_wilc_initialized = 0;
        up(&hWaitResponse);
        return s32Error;
@@ -1242,7 +1238,7 @@ static s32 Handle_wait_msg_q_empty(void)
  *  @date
  *  @version   1.0
  */
-static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
+static s32 Handle_Scan(tstrWILC_WFIDrv *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWIDList[5];
@@ -1254,7 +1250,7 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
 
        PRINT_D(HOSTINF_DBG, "Setting SCAN params\n");
-       PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state \n", pstrWFIDrv->enuHostIFstate);
+       PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", pstrWFIDrv->enuHostIFstate);
 
        pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = pstrHostIFscanAttr->pfScanResult;
        pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid = pstrHostIFscanAttr->pvUserArg;
@@ -1284,9 +1280,8 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
        strWIDList[u32WidsCount].u16WIDid = (u16)WID_SSID_PROBE_REQ;
        strWIDList[u32WidsCount].enuWIDtype = WID_STR;
 
-       for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++) {
+       for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++)
                valuesize += ((pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen) + 1);
-       }
        pu8HdnNtwrksWidVal = WILC_MALLOC(valuesize + 1);
        strWIDList[u32WidsCount].ps8WidVal = pu8HdnNtwrksWidVal;
        if (strWIDList[u32WidsCount].ps8WidVal != NULL) {
@@ -1298,7 +1293,7 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
 
                for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++) {
                        *pu8Buffer++ = pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen;
-                       WILC_memcpy(pu8Buffer, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen);
+                       memcpy(pu8Buffer, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen);
                        pu8Buffer += pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen;
                }
 
@@ -1336,9 +1331,8 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
                int i;
 
                for (i = 0; i < pstrHostIFscanAttr->u8ChnlListLen; i++) {
-                       if (pstrHostIFscanAttr->pu8ChnlFreqList[i] > 0) {
+                       if (pstrHostIFscanAttr->pu8ChnlFreqList[i] > 0)
                                pstrHostIFscanAttr->pu8ChnlFreqList[i] = pstrHostIFscanAttr->pu8ChnlFreqList[i] - 1;
-                       }
                }
        }
 
@@ -1356,11 +1350,10 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
        /*keep the state as is , no need to change it*/
        /* gWFiDrvHandle->enuHostIFstate = HOST_IF_SCANNING; */
 
-       if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) {
+       if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED)
                gbScanWhileConnected = true;
-       } else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE)    {
+       else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE)
                gbScanWhileConnected = false;
-       }
 
        s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)pstrWFIDrv);
 
@@ -1373,36 +1366,35 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
 
        WILC_CATCH(s32Error)
        {
-               WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+               del_timer(&pstrWFIDrv->hScanTimer);
                /*if there is an ongoing scan request*/
                Handle_ScanDone(drvHandler, SCAN_EVENT_ABORTED);
        }
 
        /* Deallocate pstrHostIFscanAttr->u8ChnlListLen which was prevoisuly allocated by the sending thread */
        if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL) {
-               WILC_FREE(pstrHostIFscanAttr->pu8ChnlFreqList);
+               kfree(pstrHostIFscanAttr->pu8ChnlFreqList);
                pstrHostIFscanAttr->pu8ChnlFreqList = NULL;
        }
 
        /* Deallocate pstrHostIFscanAttr->pu8IEs which was previously allocated by the sending thread */
        if (pstrHostIFscanAttr->pu8IEs != NULL) {
-               WILC_FREE(pstrHostIFscanAttr->pu8IEs);
+               kfree(pstrHostIFscanAttr->pu8IEs);
                pstrHostIFscanAttr->pu8IEs = NULL;
        }
        if (pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo != NULL) {
-               WILC_FREE(pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo);
+               kfree(pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo);
                pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo = NULL;
        }
 
        /* Deallocate pstrHostIFscanAttr->u8ChnlListLen which was prevoisuly allocated by the sending thread */
        if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL) {
-               WILC_FREE(pstrHostIFscanAttr->pu8ChnlFreqList);
+               kfree(pstrHostIFscanAttr->pu8ChnlFreqList);
                pstrHostIFscanAttr->pu8ChnlFreqList = NULL;
        }
 
-       if (pu8HdnNtwrksWidVal != NULL) {
-               WILC_FREE(pu8HdnNtwrksWidVal);
-       }
+       if (pu8HdnNtwrksWidVal != NULL)
+               kfree(pu8HdnNtwrksWidVal);
 
        return s32Error;
 }
@@ -1416,7 +1408,7 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
  *  @date
  *  @version   1.0
  */
-static s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent)
+static s32 Handle_ScanDone(tstrWILC_WFIDrv *drvHandler, tenuScanEvent enuEvent)
 {
        s32 s32Error = WILC_SUCCESS;
 
@@ -1476,7 +1468,7 @@ static s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent)
  *  @version   1.0
  */
 u8 u8ConnectedSSID[6] = {0};
-static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFconnectAttr)
+static s32 Handle_Connect(tstrWILC_WFIDrv *drvHandler, tstrHostIFconnectAttr *pstrHostIFconnectAttr)
 {
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
        s32 s32Error = WILC_SUCCESS;
@@ -1500,12 +1492,12 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        PRINT_D(GENERIC_DBG, "Handling connect request\n");
 
        #ifndef CONNECT_DIRECT
-       WILC_memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
-       WILC_memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
+       memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
+       memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
 
 
        PRINT_D(HOSTINF_DBG, "Getting site survey results\n");
-       s32Err = host_int_get_site_survey_results((WILC_WFIDrvHandle)pstrWFIDrv,
+       s32Err = host_int_get_site_survey_results(pstrWFIDrv,
                                                  gapu8RcvdSurveyResults,
                                                  MAX_SURVEY_RESULT_FRAG_SIZE);
        if (s32Err) {
@@ -1521,19 +1513,19 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
                /* use the parsed info in pstrSurveyResults, then deallocate it */
                PRINT_D(HOSTINF_DBG, "Copying site survey results in global structure, then deallocate\n");
                for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) {
-                       WILC_memcpy(&pstrWFIDrv->astrSurveyResults[i], &pstrSurveyResults[i],
+                       memcpy(&pstrWFIDrv->astrSurveyResults[i], &pstrSurveyResults[i],
                                    sizeof(wid_site_survey_reslts_s));
                }
 
                DeallocateSurveyResults(pstrSurveyResults);
        } else {
                WILC_ERRORREPORT(s32Error, WILC_FAIL);
-               PRINT_ER("ParseSurveyResults() Error(%d) \n", s32Err);
+               PRINT_ER("ParseSurveyResults() Error(%d)\n", s32Err);
        }
 
 
        for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) {
-               if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].SSID,
+               if (memcmp(pstrWFIDrv->astrSurveyResults[i].SSID,
                                pstrHostIFconnectAttr->pu8ssid,
                                pstrHostIFconnectAttr->ssidLen) == 0) {
                        PRINT_INFO(HOSTINF_DBG, "Network with required SSID is found %s\n", pstrHostIFconnectAttr->pu8ssid);
@@ -1546,7 +1538,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
                                /* BSSID is also passed from the user, so decision of matching
                                 * should consider also this passed BSSID */
 
-                               if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID,
+                               if (memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID,
                                                pstrHostIFconnectAttr->pu8bssid,
                                                6) == 0) {
                                        PRINT_INFO(HOSTINF_DBG, "BSSID is passed from the user and matched\n");
@@ -1559,29 +1551,29 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        if (i < pstrWFIDrv->u32SurveyResultsCount) {
                u8bssDscListIndex = i;
 
-               PRINT_INFO(HOSTINF_DBG, "Connecting to network of Bss Idx %d and SSID %s and channel %d \n",
+               PRINT_INFO(HOSTINF_DBG, "Connecting to network of Bss Idx%d and SSID %s and channel%d\n",
                           u8bssDscListIndex, pstrWFIDrv->astrSurveyResults[u8bssDscListIndex].SSID,
                           pstrWFIDrv->astrSurveyResults[u8bssDscListIndex].Channel);
 
                PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n");
 
                if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-                       pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (u8 *)WILC_MALLOC(6);
-                       WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
+                       pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = WILC_MALLOC(6);
+                       memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
                }
 
                pstrWFIDrv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssidLen;
                if (pstrHostIFconnectAttr->pu8ssid != NULL) {
-                       pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
-                       WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
+                       pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
+                       memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
                                    pstrHostIFconnectAttr->ssidLen);
                        pstrWFIDrv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssidLen] = '\0';
                }
 
                pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->IEsLen;
                if (pstrHostIFconnectAttr->pu8IEs != NULL) {
-                       pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
-                       WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
+                       pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
+                       memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
                                    pstrHostIFconnectAttr->IEsLen);
                }
 
@@ -1630,14 +1622,12 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
                strWIDList[u32WidsCount].ps8WidVal = (s8 *)&u8bssDscListIndex;
                u32WidsCount++;
 
-               #ifndef SIMULATION
                /* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the
                 *   firmware at chip reset when processing the WIDs of the Connect Request.
                 *   (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */
                /* ////////////////////// */
                gu32WidConnRstHack = 0;
                /* ////////////////////// */
-               #endif
 
                s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)pstrWFIDrv);
                if (s32Error) {
@@ -1656,7 +1646,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
 
        /* if we try to connect to an already connected AP then discard the request */
 
-       if (WILC_memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) {
+       if (memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) {
 
                s32Error = WILC_SUCCESS;
                PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n");
@@ -1675,22 +1665,22 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        #endif /*WILC_PARSE_SCAN_IN_HOST*/
 
        if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-               pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (u8 *)WILC_MALLOC(6);
-               WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
+               pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = WILC_MALLOC(6);
+               memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
        }
 
        pstrWFIDrv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssidLen;
        if (pstrHostIFconnectAttr->pu8ssid != NULL) {
-               pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
-               WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
+               pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
+               memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
                            pstrHostIFconnectAttr->ssidLen);
                pstrWFIDrv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssidLen] = '\0';
        }
 
        pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->IEsLen;
        if (pstrHostIFconnectAttr->pu8IEs != NULL) {
-               pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
-               WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
+               pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
+               memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
                            pstrHostIFconnectAttr->IEsLen);
        }
 
@@ -1728,7 +1718,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
                u32WidsCount++;
 
                /*BugID_5137*/
-               if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
+               if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
 
                        gu32FlushedInfoElemAsocSize = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen;
                        gu8FlushedInfoElemAsoc =  WILC_MALLOC(gu32FlushedInfoElemAsocSize);
@@ -1743,7 +1733,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        u32WidsCount++;
 
        /*BugID_5137*/
-       if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
+       if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
                gu8Flushed11iMode = pstrWFIDrv->strWILC_UsrConnReq.u8security;
 
        PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", pstrWFIDrv->strWILC_UsrConnReq.u8security);
@@ -1756,7 +1746,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        u32WidsCount++;
 
        /*BugID_5137*/
-       if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
+       if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
                gu8FlushedAuthType = (u8)pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type;
 
        PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type);
@@ -1778,14 +1768,13 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        strWIDList[u32WidsCount].s32ValueSize = MAX_SSID_LEN + 7;
        strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize);
 
-       if (strWIDList[u32WidsCount].ps8WidVal == NULL) {
+       if (strWIDList[u32WidsCount].ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal;
 
        if (pstrHostIFconnectAttr->pu8ssid != NULL) {
-               WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
+               memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
                pu8CurrByte[pstrHostIFconnectAttr->ssidLen] = '\0';
        }
        pu8CurrByte += MAX_SSID_LEN;
@@ -1795,9 +1784,8 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
                PRINT_ER("Channel out of range\n");
                *(pu8CurrByte++) = 0xFF;
        }
-       if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-               WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
-       }
+       if (pstrHostIFconnectAttr->pu8bssid != NULL)
+               memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
        pu8CurrByte += 6;
 
        /* keep the buffer at the start of the allocated pointer to use it with the free*/
@@ -1813,19 +1801,18 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize);
 
        /*BugID_5137*/
-       if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
+       if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
                gu32FlushedJoinReqSize = strWIDList[u32WidsCount].s32ValueSize;
                gu8FlushedJoinReq = WILC_MALLOC(gu32FlushedJoinReqSize);
        }
-       if (strWIDList[u32WidsCount].ps8WidVal == NULL) {
+       if (strWIDList[u32WidsCount].ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal;
 
 
        if (pstrHostIFconnectAttr->pu8ssid != NULL) {
-               WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
+               memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
                pu8CurrByte[pstrHostIFconnectAttr->ssidLen] = '\0';
        }
        pu8CurrByte += MAX_SSID_LEN;
@@ -1845,15 +1832,13 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8)));
 
        /* sa*/
-       if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-               WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
-       }
+       if (pstrHostIFconnectAttr->pu8bssid != NULL)
+               memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
        pu8CurrByte += 6;
 
        /* bssid*/
-       if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-               WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
-       }
+       if (pstrHostIFconnectAttr->pu8bssid != NULL)
+               memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
        pu8CurrByte += 6;
 
        /* Beacon Period*/
@@ -1864,7 +1849,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        *(pu8CurrByte++)  =  ptstrJoinBssParam->dtim_period;
        PRINT_D(HOSTINF_DBG, "* DTIM Period %d*\n", (*(pu8CurrByte - 1)));
        /* Supported rates*/
-       WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1);
+       memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1);
        pu8CurrByte += (MAX_RATES_SUPPORTED + 1);
 
        /* wmm cap*/
@@ -1888,15 +1873,15 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        *(pu8CurrByte++) =  ptstrJoinBssParam->mode_802_11i;
        PRINT_D(HOSTINF_DBG, "* mode_802_11i %d*\n", (*(pu8CurrByte - 1)));
        /* rsn pcip policy*/
-       WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy));
+       memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy));
        pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy);
 
        /* rsn auth policy*/
-       WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_auth_policy, sizeof(ptstrJoinBssParam->rsn_auth_policy));
+       memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_auth_policy, sizeof(ptstrJoinBssParam->rsn_auth_policy));
        pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_auth_policy);
 
        /* rsn auth policy*/
-       WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_cap, sizeof(ptstrJoinBssParam->rsn_cap));
+       memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_cap, sizeof(ptstrJoinBssParam->rsn_cap));
        pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_cap);
 
        /*BugID_5137*/
@@ -1921,15 +1906,15 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
 
                *(pu8CurrByte++) = ptstrJoinBssParam->u8Count;
 
-               WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8Duration, sizeof(ptstrJoinBssParam->au8Duration));
+               memcpy(pu8CurrByte, ptstrJoinBssParam->au8Duration, sizeof(ptstrJoinBssParam->au8Duration));
 
                pu8CurrByte += sizeof(ptstrJoinBssParam->au8Duration);
 
-               WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8Interval, sizeof(ptstrJoinBssParam->au8Interval));
+               memcpy(pu8CurrByte, ptstrJoinBssParam->au8Interval, sizeof(ptstrJoinBssParam->au8Interval));
 
                pu8CurrByte += sizeof(ptstrJoinBssParam->au8Interval);
 
-               WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8StartTime, sizeof(ptstrJoinBssParam->au8StartTime));
+               memcpy(pu8CurrByte, ptstrJoinBssParam->au8StartTime, sizeof(ptstrJoinBssParam->au8StartTime));
 
                pu8CurrByte += sizeof(ptstrJoinBssParam->au8StartTime);
 
@@ -1945,17 +1930,15 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        #endif /* #ifdef WILC_PARSE_SCAN_IN_HOST*/
        u32WidsCount++;
 
-       #ifndef SIMULATION
        /* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the
         *   firmware at chip reset when processing the WIDs of the Connect Request.
         *   (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */
        /* ////////////////////// */
        gu32WidConnRstHack = 0;
        /* ////////////////////// */
-       #endif
 
        /*BugID_5137*/
-       if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
+       if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
                memcpy(gu8FlushedJoinReq, pu8CurrByte, gu32FlushedJoinReqSize);
                gu8FlushedJoinReqDrvHandler = (u32)pstrWFIDrv;
        }
@@ -1963,7 +1946,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n");
 
        if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-               WILC_memcpy(u8ConnectedSSID, pstrHostIFconnectAttr->pu8bssid, ETH_ALEN);
+               memcpy(u8ConnectedSSID, pstrHostIFconnectAttr->pu8bssid, ETH_ALEN);
 
                PRINT_D(GENERIC_DBG, "save Bssid = %x:%x:%x:%x:%x:%x\n", (pstrHostIFconnectAttr->pu8bssid[0]), (pstrHostIFconnectAttr->pu8bssid[1]), (pstrHostIFconnectAttr->pu8bssid[2]), (pstrHostIFconnectAttr->pu8bssid[3]), (pstrHostIFconnectAttr->pu8bssid[4]), (pstrHostIFconnectAttr->pu8bssid[5]));
                PRINT_D(GENERIC_DBG, "save bssid = %x:%x:%x:%x:%x:%x\n", (u8ConnectedSSID[0]), (u8ConnectedSSID[1]), (u8ConnectedSSID[2]), (u8ConnectedSSID[3]), (u8ConnectedSSID[4]), (u8ConnectedSSID[5]));
@@ -1983,21 +1966,20 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
        {
                tstrConnectInfo strConnectInfo;
 
-               WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), NULL);
+               del_timer(&pstrWFIDrv->hConnectTimer);
 
                PRINT_D(HOSTINF_DBG, "could not start connecting to the required network\n");
 
-               WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
+               memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
 
                if (pstrHostIFconnectAttr->pfConnectResult != NULL) {
-                       if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-                               WILC_memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
-                       }
+                       if (pstrHostIFconnectAttr->pu8bssid != NULL)
+                               memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
 
                        if (pstrHostIFconnectAttr->pu8IEs != NULL) {
                                strConnectInfo.ReqIEsLen = pstrHostIFconnectAttr->IEsLen;
-                               strConnectInfo.pu8ReqIEs = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
-                               WILC_memcpy(strConnectInfo.pu8ReqIEs,
+                               strConnectInfo.pu8ReqIEs = WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
+                               memcpy(strConnectInfo.pu8ReqIEs,
                                            pstrHostIFconnectAttr->pu8IEs,
                                            pstrHostIFconnectAttr->IEsLen);
                        }
@@ -2011,37 +1993,36 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
                        pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
                        /* Deallocation */
                        if (strConnectInfo.pu8ReqIEs != NULL) {
-                               WILC_FREE(strConnectInfo.pu8ReqIEs);
+                               kfree(strConnectInfo.pu8ReqIEs);
                                strConnectInfo.pu8ReqIEs = NULL;
                        }
 
                } else {
-                       PRINT_ER("Connect callback function pointer is NULL \n");
+                       PRINT_ER("Connect callback function pointer is NULL\n");
                }
        }
 
        PRINT_D(HOSTINF_DBG, "Deallocating connection parameters\n");
        /* Deallocate pstrHostIFconnectAttr->pu8bssid which was prevoisuly allocated by the sending thread */
        if (pstrHostIFconnectAttr->pu8bssid != NULL) {
-               WILC_FREE(pstrHostIFconnectAttr->pu8bssid);
+               kfree(pstrHostIFconnectAttr->pu8bssid);
                pstrHostIFconnectAttr->pu8bssid = NULL;
        }
 
        /* Deallocate pstrHostIFconnectAttr->pu8ssid which was prevoisuly allocated by the sending thread */
        if (pstrHostIFconnectAttr->pu8ssid != NULL) {
-               WILC_FREE(pstrHostIFconnectAttr->pu8ssid);
+               kfree(pstrHostIFconnectAttr->pu8ssid);
                pstrHostIFconnectAttr->pu8ssid = NULL;
        }
 
        /* Deallocate pstrHostIFconnectAttr->pu8IEs which was prevoisuly allocated by the sending thread */
        if (pstrHostIFconnectAttr->pu8IEs != NULL) {
-               WILC_FREE(pstrHostIFconnectAttr->pu8IEs);
+               kfree(pstrHostIFconnectAttr->pu8IEs);
                pstrHostIFconnectAttr->pu8IEs = NULL;
        }
 
-       if (pu8CurrByte != NULL) {
-               WILC_FREE(pu8CurrByte);
-       }
+       if (pu8CurrByte != NULL)
+               kfree(pu8CurrByte);
        return s32Error;
 }
 
@@ -2056,7 +2037,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon
  *  @version           8.0
  */
 
-static s32 Handle_FlushConnect(void *drvHandler)
+static s32 Handle_FlushConnect(tstrWILC_WFIDrv *drvHandler)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWIDList[5];
@@ -2123,7 +2104,7 @@ static s32 Handle_FlushConnect(void *drvHandler)
  *  @date
  *  @version   1.0
  */
-static s32 Handle_ConnectTimeout(void *drvHandler)
+static s32 Handle_ConnectTimeout(tstrWILC_WFIDrv *drvHandler)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrConnectInfo strConnectInfo;
@@ -2141,7 +2122,7 @@ static s32 Handle_ConnectTimeout(void *drvHandler)
        gbScanWhileConnected = false;
 
 
-       WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
+       memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
 
 
        /* First, we will notify the upper layer with the Connection failure {through the Connect Callback function},
@@ -2149,14 +2130,14 @@ static s32 Handle_ConnectTimeout(void *drvHandler)
         *   WID_DISCONNECT} */
        if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult != NULL) {
                if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
-                       WILC_memcpy(strConnectInfo.au8bssid,
+                       memcpy(strConnectInfo.au8bssid,
                                    pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6);
                }
 
                if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
                        strConnectInfo.ReqIEsLen = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen;
-                       strConnectInfo.pu8ReqIEs = (u8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
-                       WILC_memcpy(strConnectInfo.pu8ReqIEs,
+                       strConnectInfo.pu8ReqIEs = WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
+                       memcpy(strConnectInfo.pu8ReqIEs,
                                    pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs,
                                    pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
                }
@@ -2169,11 +2150,11 @@ static s32 Handle_ConnectTimeout(void *drvHandler)
 
                /* Deallocation of strConnectInfo.pu8ReqIEs */
                if (strConnectInfo.pu8ReqIEs != NULL) {
-                       WILC_FREE(strConnectInfo.pu8ReqIEs);
+                       kfree(strConnectInfo.pu8ReqIEs);
                        strConnectInfo.pu8ReqIEs = NULL;
                }
        } else {
-               PRINT_ER("Connect callback function pointer is NULL \n");
+               PRINT_ER("Connect callback function pointer is NULL\n");
        }
 
        /* Here we will notify our firmware also with the Connection failure {through sending to it Cfg packet carrying
@@ -2186,37 +2167,36 @@ static s32 Handle_ConnectTimeout(void *drvHandler)
        PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
 
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv);
-       if (s32Error) {
+       if (s32Error)
                PRINT_ER("Failed to send dissconect config packet\n");
-       }
 
        /* Deallocation of the Saved Connect Request in the global Handle */
        pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
-               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
                pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
        }
 
        if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
-               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
                pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
        }
 
        pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
-               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
                pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
        }
 
-       WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+       memset(u8ConnectedSSID, 0, ETH_ALEN);
        /*BugID_5213*/
        /*Freeing flushed join request params on connect timeout*/
        if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
-               WILC_FREE(gu8FlushedJoinReq);
+               kfree(gu8FlushedJoinReq);
                gu8FlushedJoinReq = NULL;
        }
        if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
-               WILC_FREE(gu8FlushedInfoElemAsoc);
+               kfree(gu8FlushedInfoElemAsoc);
                gu8FlushedInfoElemAsoc = NULL;
        }
 
@@ -2232,7 +2212,7 @@ static s32 Handle_ConnectTimeout(void *drvHandler)
  *  @date
  *  @version   1.0
  */
-static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdNetworkInfo)
+static s32 Handle_RcvdNtwrkInfo(tstrWILC_WFIDrv *drvHandler, tstrRcvdNetworkInfo *pstrRcvdNetworkInfo)
 {
        u32 i;
        bool bNewNtwrkFound;
@@ -2264,7 +2244,7 @@ static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdN
 
                        if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid != NULL) &&
                            (pstrNetworkInfo->au8bssid != NULL)) {
-                               if (WILC_memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid,
+                               if (memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid,
                                                pstrNetworkInfo->au8bssid, 6) == 0) {
                                        if (pstrNetworkInfo->s8rssi <= pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi) {
                                                /*we have already found this network with better rssi, so keep the old cached one and don't
@@ -2294,7 +2274,7 @@ static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdN
 
                                if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid != NULL)
                                    && (pstrNetworkInfo->au8bssid != NULL)) {
-                                       WILC_memcpy(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid,
+                                       memcpy(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid,
                                                    pstrNetworkInfo->au8bssid, 6);
 
                                        pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount++;
@@ -2313,7 +2293,7 @@ static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdN
 
                                }
                        } else {
-                               PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit \n");
+                               PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit\n");
                        }
                } else {
                        pstrNetworkInfo->bNewNetwork = false;
@@ -2332,7 +2312,7 @@ static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdN
 done:
        /* Deallocate pstrRcvdNetworkInfo->pu8Buffer which was prevoisuly allocated by the sending thread */
        if (pstrRcvdNetworkInfo->pu8Buffer != NULL) {
-               WILC_FREE(pstrRcvdNetworkInfo->pu8Buffer);
+               kfree(pstrRcvdNetworkInfo->pu8Buffer);
                pstrRcvdNetworkInfo->pu8Buffer = NULL;
        }
 
@@ -2354,7 +2334,7 @@ done:
  *  @date
  *  @version   1.0
  */
-static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pstrRcvdGnrlAsyncInfo)
+static s32 Handle_RcvdGnrlAsyncInfo(tstrWILC_WFIDrv *drvHandler, tstrRcvdGnrlAsyncInfo *pstrRcvdGnrlAsyncInfo)
 {
        /* TODO: mostafa: till now, this function just handles only the received mac status msg, */
        /*                               which carries only 1 WID which have WID ID = WID_STATUS */
@@ -2371,9 +2351,9 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
        tstrDisconnectNotifInfo strDisconnectNotifInfo;
        s32 s32Err = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
-       if (pstrWFIDrv == NULL) {
+
+       if (pstrWFIDrv == NULL)
                PRINT_ER("Driver handler is NULL\n");
-       }
        PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n", pstrWFIDrv->enuHostIFstate,
                pstrRcvdGnrlAsyncInfo->pu8Buffer[7]);
 
@@ -2417,12 +2397,12 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
 
                        PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo);
 
-                       WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
+                       memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
 
                        if (u8MacStatus == MAC_CONNECTED) {
-                               WILC_memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
+                               memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
 
-                               host_int_get_assoc_res_info((WILC_WFIDrvHandle)pstrWFIDrv,
+                               host_int_get_assoc_res_info(pstrWFIDrv,
                                                            gapu8RcvdAssocResp,
                                                            MAX_ASSOC_RESP_FRAME_SIZE,
                                                            &u32RcvdAssocRespInfoLen);
@@ -2435,7 +2415,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                                        s32Err = ParseAssocRespInfo(gapu8RcvdAssocResp, u32RcvdAssocRespInfoLen,
                                                                    &pstrConnectRespInfo);
                                        if (s32Err) {
-                                               PRINT_ER("ParseAssocRespInfo() returned error %d \n", s32Err);
+                                               PRINT_ER("ParseAssocRespInfo() returned error %d\n", s32Err);
                                        } else {
                                                /* use the necessary parsed Info from the Received Association Response */
                                                strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus;
@@ -2446,8 +2426,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                                                                strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen;
 
 
-                                                               strConnectInfo.pu8RespIEs = (u8 *)WILC_MALLOC(pstrConnectRespInfo->u16RespIEsLen);
-                                                               WILC_memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs,
+                                                               strConnectInfo.pu8RespIEs = WILC_MALLOC(pstrConnectRespInfo->u16RespIEsLen);
+                                                               memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs,
                                                                            pstrConnectRespInfo->u16RespIEsLen);
                                                        }
                                                }
@@ -2466,23 +2446,23 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                         *   So check first the matching between the received mac status and the received status code in Asoc Resp */
                        if ((u8MacStatus == MAC_CONNECTED) &&
                            (strConnectInfo.u16ConnectStatus != SUCCESSFUL_STATUSCODE)) {
-                               PRINT_ER("Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE \n");
-                               WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+                               PRINT_ER("Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n");
+                               memset(u8ConnectedSSID, 0, ETH_ALEN);
 
                        } else if (u8MacStatus == MAC_DISCONNECTED)    {
                                PRINT_ER("Received MAC status is MAC_DISCONNECTED\n");
-                               WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+                               memset(u8ConnectedSSID, 0, ETH_ALEN);
                        }
 
                        /* TODO: mostafa: correct BSSID should be retrieved from actual BSSID received from AP */
                        /*               through a structure of type tstrConnectRespInfo */
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
                                PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n");
-                               WILC_memcpy(strConnectInfo.au8bssid, pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6);
+                               memcpy(strConnectInfo.au8bssid, pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6);
 
                                if ((u8MacStatus == MAC_CONNECTED) &&
                                    (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
-                                       WILC_memcpy(pstrWFIDrv->au8AssociatedBSSID,
+                                       memcpy(pstrWFIDrv->au8AssociatedBSSID,
                                                    pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, ETH_ALEN);
                                }
                        }
@@ -2490,14 +2470,14 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
 
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
                                strConnectInfo.ReqIEsLen = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen;
-                               strConnectInfo.pu8ReqIEs = (u8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
-                               WILC_memcpy(strConnectInfo.pu8ReqIEs,
+                               strConnectInfo.pu8ReqIEs = WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
+                               memcpy(strConnectInfo.pu8ReqIEs,
                                            pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs,
                                            pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
                        }
 
 
-                       WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), NULL);
+                       del_timer(&pstrWFIDrv->hConnectTimer);
                        pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_CONN_RESP,
                                                                           &strConnectInfo,
                                                                           u8MacStatus,
@@ -2512,7 +2492,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                            (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
                                #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 
-                               host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+                               host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
                                #endif
 
                                PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n");
@@ -2521,7 +2501,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                                #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
                                PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n");
                                g_obtainingIP = true;
-                               WILC_TimerStart(&hDuringIpTimer, 10000, NULL, NULL);
+                               mod_timer(&hDuringIpTimer,
+                                         jiffies + msecs_to_jiffies(10000));
                                #endif
 
                                #ifdef WILC_PARSE_SCAN_IN_HOST
@@ -2540,30 +2521,30 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
 
                        /* Deallocation */
                        if (strConnectInfo.pu8RespIEs != NULL) {
-                               WILC_FREE(strConnectInfo.pu8RespIEs);
+                               kfree(strConnectInfo.pu8RespIEs);
                                strConnectInfo.pu8RespIEs = NULL;
                        }
 
                        if (strConnectInfo.pu8ReqIEs != NULL) {
-                               WILC_FREE(strConnectInfo.pu8ReqIEs);
+                               kfree(strConnectInfo.pu8ReqIEs);
                                strConnectInfo.pu8ReqIEs = NULL;
                        }
 
 
                        pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
-                               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+                               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
                                pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
                        }
 
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
-                               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+                               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
                                pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
                        }
 
                        pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
-                               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+                               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
                                pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
                        }
 
@@ -2572,11 +2553,11 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                        /* Disassociation or Deauthentication frame has been received */
                        PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n");
 
-                       WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
+                       memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
 
                        if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
-                               PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >> \n\n");
-                               WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+                               PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n");
+                               del_timer(&pstrWFIDrv->hScanTimer);
                                Handle_ScanDone((void *)pstrWFIDrv, SCAN_EVENT_ABORTED);
                        }
 
@@ -2588,7 +2569,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                                #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 
                                g_obtainingIP = false;
-                               host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+                               host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
                                #endif
 
                                pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF,
@@ -2598,10 +2579,10 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                                                                                   pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid);
 
                        } else {
-                               PRINT_ER("Connect result callback function is NULL \n");
+                               PRINT_ER("Connect result callback function is NULL\n");
                        }
 
-                       WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
+                       memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
 
 
                        /* Deallocation */
@@ -2611,25 +2592,25 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                        /*
                         * if(strDisconnectNotifInfo.ie != NULL)
                         * {
-                        *      WILC_FREE(strDisconnectNotifInfo.ie);
+                        *      kfree(strDisconnectNotifInfo.ie);
                         *      strDisconnectNotifInfo.ie = NULL;
                         * }
                         */
 
                        pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
-                               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+                               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
                                pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
                        }
 
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
-                               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+                               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
                                pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
                        }
 
                        pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
                        if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
-                               WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+                               kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
                                pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
                        }
 
@@ -2637,11 +2618,11 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                        /*Freeing flushed join request params on receiving*/
                        /*MAC_DISCONNECTED while connected*/
                        if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
-                               WILC_FREE(gu8FlushedJoinReq);
+                               kfree(gu8FlushedJoinReq);
                                gu8FlushedJoinReq = NULL;
                        }
                        if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
-                               WILC_FREE(gu8FlushedInfoElemAsoc);
+                               kfree(gu8FlushedInfoElemAsoc);
                                gu8FlushedInfoElemAsoc = NULL;
                        }
 
@@ -2651,13 +2632,12 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
                } else if ((u8MacStatus == MAC_DISCONNECTED) &&
                           (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL)) {
                        PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW while scanning\n");
-                       PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >> \n\n");
+                       PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >>\n\n");
                        /*Abort the running scan*/
-                       WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
-                       if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
-                               Handle_ScanDone((void *)pstrWFIDrv, SCAN_EVENT_ABORTED);
+                       del_timer(&pstrWFIDrv->hScanTimer);
+                       if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult)
+                               Handle_ScanDone(pstrWFIDrv, SCAN_EVENT_ABORTED);
 
-                       }
                }
 
        }
@@ -2669,7 +2649,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
 
        /* Deallocate pstrRcvdGnrlAsyncInfo->pu8Buffer which was prevoisuly allocated by the sending thread */
        if (pstrRcvdGnrlAsyncInfo->pu8Buffer != NULL) {
-               WILC_FREE(pstrRcvdGnrlAsyncInfo->pu8Buffer);
+               kfree(pstrRcvdGnrlAsyncInfo->pu8Buffer);
                pstrRcvdGnrlAsyncInfo->pu8Buffer = NULL;
        }
 
@@ -2685,7 +2665,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst
  *  @date
  *  @version   1.0
  */
-static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
+static int Handle_Key(tstrWILC_WFIDrv *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -2726,7 +2706,7 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
                        strWIDList[2].s32ValueSize = sizeof(char);
 
 
-                       pu8keybuf = (u8 *)WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
+                       pu8keybuf = WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
 
 
                        if (pu8keybuf == NULL) {
@@ -2734,11 +2714,11 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
                                return -1;
                        }
 
-                       WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+                       memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
                                    pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
 
 
-                       WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
+                       kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
 
                        strWIDList[3].u16WIDid = (u16)WID_WEP_KEY_VALUE;
                        strWIDList[3].enuWIDtype = WID_STR;
@@ -2747,7 +2727,7 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
 
 
                        s32Error = SendConfigPkt(SET_CFG, strWIDList, 4, true, (u32)pstrWFIDrv);
-                       WILC_FREE(pu8keybuf);
+                       kfree(pu8keybuf);
 
 
                }
@@ -2755,19 +2735,19 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
 
                if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
                        PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
-                       pu8keybuf = (u8 *)WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2);
+                       pu8keybuf = WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2);
                        if (pu8keybuf == NULL) {
                                PRINT_ER("No buffer to send Key\n");
                                return -1;
                        }
                        pu8keybuf[0] = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx;
 
-                       WILC_memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen, 1);
+                       memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen, 1);
 
-                       WILC_memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+                       memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
                                    pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
 
-                       WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
+                       kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
 
                        strWID.u16WIDid = (u16)WID_ADD_WEP_KEY;
                        strWID.enuWIDtype       = WID_STR;
@@ -2775,7 +2755,7 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
                        strWID.s32ValueSize = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2;
 
                        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
-                       WILC_FREE(pu8keybuf);
+                       kfree(pu8keybuf);
                } else if (pstrHostIFkeyAttr->u8KeyAction & REMOVEKEY)    {
 
                        PRINT_D(HOSTINF_DBG, "Removing key\n");
@@ -2803,14 +2783,14 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
        case WPARxGtk:
                        #ifdef WILC_AP_EXTERNAL_MLME
                if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) {
-                       pu8keybuf = (u8 *)WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
+                       pu8keybuf = WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
                        if (pu8keybuf == NULL) {
                                PRINT_ER("No buffer to send RxGTK Key\n");
                                ret = -1;
                                goto _WPARxGtk_end_case_;
                        }
 
-                       WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
+                       memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
 
 
                        /*|----------------------------------------------------------------------------|
@@ -2821,14 +2801,14 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
 
 
                        if (pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq != NULL)
-                               WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
+                               memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
 
 
-                       WILC_memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
+                       memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
 
-                       WILC_memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+                       memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
 
-                       WILC_memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+                       memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
                                    pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
                        /* pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode =  0X51; */
                        strWIDList[0].u16WIDid = (u16)WID_11I_MODE;
@@ -2843,7 +2823,7 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
 
                        s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, true, (u32)pstrWFIDrv);
 
-                       WILC_FREE(pu8keybuf);
+                       kfree(pu8keybuf);
 
                        /* ////////////////////////// */
                        up(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -2854,14 +2834,14 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
                if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
                        PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n");
 
-                       pu8keybuf = (u8 *)WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
+                       pu8keybuf = WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
                        if (pu8keybuf == NULL) {
                                PRINT_ER("No buffer to send RxGTK Key\n");
                                ret = -1;
                                goto _WPARxGtk_end_case_;
                        }
 
-                       WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
+                       memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
 
 
                        /*|----------------------------------------------------------------------------|
@@ -2869,18 +2849,17 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
                         * |------------|---------|-------|------------|---------------|----------------|
                         |      6 bytes  | 8 byte  |1 byte |  1 byte    |   16 bytes    |         8 bytes        |*/
 
-                       if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) {
-                               WILC_memcpy(pu8keybuf, pstrWFIDrv->au8AssociatedBSSID, ETH_ALEN);
-                       } else {
-                               PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED \n");
-                       }
+                       if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED)
+                               memcpy(pu8keybuf, pstrWFIDrv->au8AssociatedBSSID, ETH_ALEN);
+                       else
+                               PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED\n");
 
-                       WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
+                       memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
 
-                       WILC_memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
+                       memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
 
-                       WILC_memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
-                       WILC_memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+                       memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+                       memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
                                    pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
 
                        strWID.u16WIDid = (u16)WID_ADD_RX_GTK;
@@ -2890,15 +2869,15 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
 
                        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
-                       WILC_FREE(pu8keybuf);
+                       kfree(pu8keybuf);
 
                        /* ////////////////////////// */
                        up(&(pstrWFIDrv->hSemTestKeyBlock));
                        /* ///////////////////////// */
                }
 _WPARxGtk_end_case_:
-               WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
-               WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq);
+               kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
+               kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq);
                if (ret == -1)
                        return ret;
 
@@ -2909,7 +2888,7 @@ _WPARxGtk_end_case_:
                if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) {
 
 
-                       pu8keybuf = (u8 *)WILC_MALLOC(PTK_KEY_MSG_LEN + 1);
+                       pu8keybuf = WILC_MALLOC(PTK_KEY_MSG_LEN + 1);
 
 
 
@@ -2926,12 +2905,12 @@ _WPARxGtk_end_case_:
                         |      6 bytes    |    1 byte    |   1byte      |   16 bytes    |        8 bytes         |        8 bytes        |
                         |-----------------------------------------------------------------------------|*/
 
-                       WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6);  /*1 bytes Key Length */
+                       memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6);  /*1 bytes Key Length */
 
-                       WILC_memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
-                       WILC_memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+                       memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
+                       memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
                        /*16 byte TK*/
-                       WILC_memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+                       memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
                                    pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
 
 
@@ -2946,7 +2925,7 @@ _WPARxGtk_end_case_:
                        strWIDList[1].s32ValueSize = PTK_KEY_MSG_LEN + 1;
 
                        s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, true, (u32)pstrWFIDrv);
-                       WILC_FREE(pu8keybuf);
+                       kfree(pu8keybuf);
 
                        /* ////////////////////////// */
                        up(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -2956,7 +2935,7 @@ _WPARxGtk_end_case_:
                if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
 
 
-                       pu8keybuf = (u8 *)WILC_MALLOC(PTK_KEY_MSG_LEN);
+                       pu8keybuf = WILC_MALLOC(PTK_KEY_MSG_LEN);
 
 
 
@@ -2973,11 +2952,11 @@ _WPARxGtk_end_case_:
                         |      6 bytes          |      1byte     |   16 bytes   |        8 bytes         |        8 bytes        |
                         |-----------------------------------------------------------------------------|*/
 
-                       WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6);  /*1 bytes Key Length */
+                       memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6);  /*1 bytes Key Length */
 
-                       WILC_memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+                       memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
                        /*16 byte TK*/
-                       WILC_memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+                       memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
                                    pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
 
 
@@ -2987,7 +2966,7 @@ _WPARxGtk_end_case_:
                        strWID.s32ValueSize = PTK_KEY_MSG_LEN;
 
                        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
-                       WILC_FREE(pu8keybuf);
+                       kfree(pu8keybuf);
 
                        /* ////////////////////////// */
                        up(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -2995,7 +2974,7 @@ _WPARxGtk_end_case_:
                }
 
 _WPAPtk_end_case_:
-               WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
+               kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
                if (ret == -1)
                        return ret;
 
@@ -3006,7 +2985,7 @@ _WPAPtk_end_case_:
 
                PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n");
 
-               pu8keybuf = (u8 *)WILC_MALLOC((pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1);
+               pu8keybuf = WILC_MALLOC((pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1);
                if (pu8keybuf == NULL) {
                        PRINT_ER("No buffer to send PMKSA Key\n");
                        return -1;
@@ -3016,8 +2995,8 @@ _WPAPtk_end_case_:
 
                for (i = 0; i < pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid; i++) {
 
-                       WILC_memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, ETH_ALEN);
-                       WILC_memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, PMKID_LEN);
+                       memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, ETH_ALEN);
+                       memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, PMKID_LEN);
                }
 
                strWID.u16WIDid = (u16)WID_PMKID_INFO;
@@ -3027,7 +3006,7 @@ _WPAPtk_end_case_:
 
                s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
-               WILC_FREE(pu8keybuf);
+               kfree(pu8keybuf);
                break;
        }
 
@@ -3048,7 +3027,7 @@ _WPAPtk_end_case_:
  *  @date
  *  @version   1.0
  */
-static void Handle_Disconnect(void *drvHandler)
+static void Handle_Disconnect(tstrWILC_WFIDrv *drvHandler)
 {
        tstrWID strWID;
 
@@ -3069,10 +3048,10 @@ static void Handle_Disconnect(void *drvHandler)
        #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 
        g_obtainingIP = false;
-       host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+       host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
        #endif
 
-       WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+       memset(u8ConnectedSSID, 0, ETH_ALEN);
 
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv);
 
@@ -3082,14 +3061,14 @@ static void Handle_Disconnect(void *drvHandler)
        } else {
                tstrDisconnectNotifInfo strDisconnectNotifInfo;
 
-               WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
+               memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
 
                strDisconnectNotifInfo.u16reason = 0;
                strDisconnectNotifInfo.ie = NULL;
                strDisconnectNotifInfo.ie_len = 0;
 
                if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
-                       WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+                       del_timer(&pstrWFIDrv->hScanTimer);
                        pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, NULL,
                                                                        pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
 
@@ -3102,48 +3081,48 @@ static void Handle_Disconnect(void *drvHandler)
                        /*Stop connect timer, if connection in progress*/
                        if (pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) {
                                PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n");
-                               WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), NULL);
+                               del_timer(&pstrWFIDrv->hConnectTimer);
                        }
 
                        pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
                                                                           0, &strDisconnectNotifInfo, pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid);
                } else {
-                       PRINT_ER("strWILC_UsrConnReq.pfUserConnectResult = NULL \n");
+                       PRINT_ER("strWILC_UsrConnReq.pfUserConnectResult = NULL\n");
                }
 
                gbScanWhileConnected = false;
 
                pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
 
-               WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
+               memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
 
 
                /* Deallocation */
                pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
                if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
-                       WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+                       kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
                        pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
                }
 
                if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
-                       WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+                       kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
                        pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
                }
 
                pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
                if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
-                       WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+                       kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
                        pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
                }
 
 
                /*BugID_5137*/
                if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
-                       WILC_FREE(gu8FlushedJoinReq);
+                       kfree(gu8FlushedJoinReq);
                        gu8FlushedJoinReq = NULL;
                }
                if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
-                       WILC_FREE(gu8FlushedInfoElemAsoc);
+                       kfree(gu8FlushedInfoElemAsoc);
                        gu8FlushedInfoElemAsoc = NULL;
                }
 
@@ -3161,7 +3140,7 @@ static void Handle_Disconnect(void *drvHandler)
 }
 
 
-void resolve_disconnect_aberration(void *drvHandler)
+void resolve_disconnect_aberration(tstrWILC_WFIDrv *drvHandler)
 {
        tstrWILC_WFIDrv *pstrWFIDrv;
 
@@ -3170,10 +3149,10 @@ void resolve_disconnect_aberration(void *drvHandler)
                return;
        if ((pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) || (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTING)) {
                PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n");
-               host_int_disconnect((WILC_WFIDrvHandle)pstrWFIDrv, 1);
+               host_int_disconnect(pstrWFIDrv, 1);
        }
 }
-static s32 Switch_Log_Terminal(void *drvHandler)
+static s32 Switch_Log_Terminal(tstrWILC_WFIDrv *drvHandler)
 {
 
 
@@ -3194,7 +3173,7 @@ static s32 Switch_Log_Terminal(void *drvHandler)
                PRINT_D(HOSTINF_DBG, "Failed to switch log terminal\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE);
        } else {
-               PRINT_INFO(HOSTINF_DBG, "MAC address set :: \n");
+               PRINT_INFO(HOSTINF_DBG, "MAC address set ::\n");
 
 
        }
@@ -3217,13 +3196,14 @@ static s32 Switch_Log_Terminal(void *drvHandler)
  *  @date
  *  @version   1.0
  */
-static s32 Handle_GetChnl(void *drvHandler)
+static s32 Handle_GetChnl(tstrWILC_WFIDrv *drvHandler)
 {
 
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
        strWID.u16WIDid = (u16)WID_CURRENT_CHANNEL;
        strWID.enuWIDtype = WID_CHAR;
        strWID.ps8WidVal = (s8 *)&gu8Chnl;
@@ -3261,7 +3241,7 @@ static s32 Handle_GetChnl(void *drvHandler)
  *  @date
  *  @version   1.0
  */
-static void Handle_GetRssi(void *drvHandler)
+static void Handle_GetRssi(tstrWILC_WFIDrv *drvHandler)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -3291,7 +3271,7 @@ static void Handle_GetRssi(void *drvHandler)
 }
 
 
-static void Handle_GetLinkspeed(void *drvHandler)
+static void Handle_GetLinkspeed(tstrWILC_WFIDrv *drvHandler)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -3321,7 +3301,7 @@ static void Handle_GetLinkspeed(void *drvHandler)
 
 }
 
-s32 Handle_GetStatistics(void *drvHandler, tstrStatistics *pstrStatistics)
+s32 Handle_GetStatistics(tstrWILC_WFIDrv *drvHandler, tstrStatistics *pstrStatistics)
 {
        tstrWID strWIDList[5];
        uint32_t u32WidsCount = 0, s32Error = 0;
@@ -3382,7 +3362,7 @@ s32 Handle_GetStatistics(void *drvHandler, tstrStatistics *pstrStatistics)
  *  @date
  *  @version   1.0
  */
-static s32 Handle_Get_InActiveTime(void *drvHandler, tstrHostIfStaInactiveT *strHostIfStaInactiveT)
+static s32 Handle_Get_InActiveTime(tstrWILC_WFIDrv *drvHandler, tstrHostIfStaInactiveT *strHostIfStaInactiveT)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -3394,11 +3374,11 @@ static s32 Handle_Get_InActiveTime(void *drvHandler, tstrHostIfStaInactiveT *str
        strWID.u16WIDid = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
        strWID.enuWIDtype = WID_STR;
        strWID.s32ValueSize = ETH_ALEN;
-       strWID.ps8WidVal = (u8 *)WILC_MALLOC(strWID.s32ValueSize);
+       strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
 
 
        stamac = strWID.ps8WidVal;
-       WILC_memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN);
+       memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN);
 
 
        PRINT_D(CFG80211_DBG, "SETING STA inactive time\n");
@@ -3451,21 +3431,21 @@ static s32 Handle_Get_InActiveTime(void *drvHandler, tstrHostIfStaInactiveT *str
  *  @date
  *  @version   1.0
  */
-static void Handle_AddBeacon(void *drvHandler, tstrHostIFSetBeacon *pstrSetBeaconParam)
+static void Handle_AddBeacon(tstrWILC_WFIDrv *drvHandler, tstrHostIFSetBeacon *pstrSetBeaconParam)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        u8 *pu8CurrByte;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
        PRINT_D(HOSTINF_DBG, "Adding BEACON\n");
 
        strWID.u16WIDid = (u16)WID_ADD_BEACON;
        strWID.enuWIDtype = WID_BIN;
        strWID.s32ValueSize = pstrSetBeaconParam->u32HeadLen + pstrSetBeaconParam->u32TailLen + 16;
        strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
        *pu8CurrByte++ = (pstrSetBeaconParam->u32Interval & 0xFF);
@@ -3508,9 +3488,9 @@ static void Handle_AddBeacon(void *drvHandler, tstrHostIFSetBeacon *pstrSetBeaco
        WILC_CATCH(s32Error)
        {
        }
-       WILC_FREE_IF_TRUE(strWID.ps8WidVal);
-       WILC_FREE_IF_TRUE(pstrSetBeaconParam->pu8Head);
-       WILC_FREE_IF_TRUE(pstrSetBeaconParam->pu8Tail);
+       kfree(strWID.ps8WidVal);
+       kfree(pstrSetBeaconParam->pu8Head);
+       kfree(pstrSetBeaconParam->pu8Tail);
 }
 
 
@@ -3523,20 +3503,20 @@ static void Handle_AddBeacon(void *drvHandler, tstrHostIFSetBeacon *pstrSetBeaco
  *  @date
  *  @version   1.0
  */
-static void Handle_DelBeacon(void *drvHandler, tstrHostIFDelBeacon *pstrDelBeacon)
+static void Handle_DelBeacon(tstrWILC_WFIDrv *drvHandler, tstrHostIFDelBeacon *pstrDelBeacon)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        u8 *pu8CurrByte;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
        strWID.u16WIDid = (u16)WID_DEL_BEACON;
        strWID.enuWIDtype = WID_CHAR;
        strWID.s32ValueSize = sizeof(char);
        strWID.ps8WidVal = &gu8DelBcn;
 
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
 
@@ -3573,16 +3553,15 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer, tstrWILC_AddStaParam *pstrSta
        pu8CurrByte = pu8Buffer;
 
        PRINT_D(HOSTINF_DBG, "Packing STA params\n");
-       WILC_memcpy(pu8CurrByte, pstrStationParam->au8BSSID, ETH_ALEN);
+       memcpy(pu8CurrByte, pstrStationParam->au8BSSID, ETH_ALEN);
        pu8CurrByte +=  ETH_ALEN;
 
        *pu8CurrByte++ = pstrStationParam->u16AssocID & 0xFF;
        *pu8CurrByte++ = (pstrStationParam->u16AssocID >> 8) & 0xFF;
 
        *pu8CurrByte++ = pstrStationParam->u8NumRates;
-       if (pstrStationParam->u8NumRates > 0) {
-               WILC_memcpy(pu8CurrByte, pstrStationParam->pu8Rates, pstrStationParam->u8NumRates);
-       }
+       if (pstrStationParam->u8NumRates > 0)
+               memcpy(pu8CurrByte, pstrStationParam->pu8Rates, pstrStationParam->u8NumRates);
        pu8CurrByte += pstrStationParam->u8NumRates;
 
        *pu8CurrByte++ = pstrStationParam->bIsHTSupported;
@@ -3590,7 +3569,7 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer, tstrWILC_AddStaParam *pstrSta
        *pu8CurrByte++ = (pstrStationParam->u16HTCapInfo >> 8) & 0xFF;
 
        *pu8CurrByte++ = pstrStationParam->u8AmpduParams;
-       WILC_memcpy(pu8CurrByte, pstrStationParam->au8SuppMCsSet, WILC_SUPP_MCS_SET_SIZE);
+       memcpy(pu8CurrByte, pstrStationParam->au8SuppMCsSet, WILC_SUPP_MCS_SET_SIZE);
        pu8CurrByte += WILC_SUPP_MCS_SET_SIZE;
 
        *pu8CurrByte++ = pstrStationParam->u16HTExtParams & 0xFF;
@@ -3621,21 +3600,21 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer, tstrWILC_AddStaParam *pstrSta
  *  @date
  *  @version   1.0
  */
-static void Handle_AddStation(void *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
+static void Handle_AddStation(tstrWILC_WFIDrv *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        u8 *pu8CurrByte;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
        PRINT_D(HOSTINF_DBG, "Handling add station\n");
        strWID.u16WIDid = (u16)WID_ADD_STA;
        strWID.enuWIDtype = WID_BIN;
        strWID.s32ValueSize = WILC_ADD_STA_LENGTH + pstrStationParam->u8NumRates;
 
        strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
        pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
@@ -3651,8 +3630,8 @@ static void Handle_AddStation(void *drvHandler, tstrWILC_AddStaParam *pstrStatio
        WILC_CATCH(s32Error)
        {
        }
-       WILC_FREE_IF_TRUE(pstrStationParam->pu8Rates);
-       WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+       kfree(pstrStationParam->pu8Rates);
+       kfree(strWID.ps8WidVal);
 }
 
 /**
@@ -3664,24 +3643,25 @@ static void Handle_AddStation(void *drvHandler, tstrWILC_AddStaParam *pstrStatio
  *  @date
  *  @version   1.0
  */
-static void Handle_DelAllSta(void *drvHandler, tstrHostIFDelAllSta *pstrDelAllStaParam)
+static void Handle_DelAllSta(tstrWILC_WFIDrv *drvHandler, tstrHostIFDelAllSta *pstrDelAllStaParam)
 {
        s32 s32Error = WILC_SUCCESS;
+
        tstrWID strWID;
        u8 *pu8CurrByte;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
        u8 i;
        u8 au8Zero_Buff[6] = {0};
+
        strWID.u16WIDid = (u16)WID_DEL_ALL_STA;
        strWID.enuWIDtype = WID_STR;
        strWID.s32ValueSize = (pstrDelAllStaParam->u8Num_AssocSta * ETH_ALEN) + 1;
 
-       PRINT_D(HOSTINF_DBG, "Handling delete station \n");
+       PRINT_D(HOSTINF_DBG, "Handling delete station\n");
 
        strWID.ps8WidVal = WILC_MALLOC((pstrDelAllStaParam->u8Num_AssocSta * ETH_ALEN) + 1);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
 
@@ -3689,7 +3669,7 @@ static void Handle_DelAllSta(void *drvHandler, tstrHostIFDelAllSta *pstrDelAllSt
 
        for (i = 0; i < MAX_NUM_STA; i++) {
                if (memcmp(pstrDelAllStaParam->au8Sta_DelAllSta[i], au8Zero_Buff, ETH_ALEN))
-                       WILC_memcpy(pu8CurrByte, pstrDelAllStaParam->au8Sta_DelAllSta[i], ETH_ALEN);
+                       memcpy(pu8CurrByte, pstrDelAllStaParam->au8Sta_DelAllSta[i], ETH_ALEN);
                else
                        continue;
 
@@ -3700,14 +3680,14 @@ static void Handle_DelAllSta(void *drvHandler, tstrHostIFDelAllSta *pstrDelAllSt
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
        if (s32Error) {
 
-               PRINT_ER("Failed to send add station config packe\n");
+               PRINT_ER("Failed to send add station config packet\n");
                WILC_ERRORREPORT(s32Error, WILC_FAIL);
        }
 
        WILC_CATCH(s32Error)
        {
        }
-       WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+       kfree(strWID.ps8WidVal);
 
        up(&hWaitResponse);
 }
@@ -3722,7 +3702,7 @@ static void Handle_DelAllSta(void *drvHandler, tstrHostIFDelAllSta *pstrDelAllSt
  *  @date
  *  @version   1.0
  */
-static void Handle_DelStation(void *drvHandler, tstrHostIFDelSta *pstrDelStaParam)
+static void Handle_DelStation(tstrWILC_WFIDrv *drvHandler, tstrHostIFDelSta *pstrDelStaParam)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -3733,29 +3713,28 @@ static void Handle_DelStation(void *drvHandler, tstrHostIFDelSta *pstrDelStaPara
        strWID.enuWIDtype = WID_BIN;
        strWID.s32ValueSize = ETH_ALEN;
 
-       PRINT_D(HOSTINF_DBG, "Handling delete station \n");
+       PRINT_D(HOSTINF_DBG, "Handling delete station\n");
 
        strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
 
-       WILC_memcpy(pu8CurrByte, pstrDelStaParam->au8MacAddr, ETH_ALEN);
+       memcpy(pu8CurrByte, pstrDelStaParam->au8MacAddr, ETH_ALEN);
 
        /*Sending Cfg*/
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv);
        if (s32Error) {
 
-               PRINT_ER("Failed to send add station config packe\n");
+               PRINT_ER("Failed to send add station config packet\n");
                WILC_ERRORREPORT(s32Error, WILC_FAIL);
        }
 
        WILC_CATCH(s32Error)
        {
        }
-       WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+       kfree(strWID.ps8WidVal);
 }
 
 
@@ -3768,7 +3747,7 @@ static void Handle_DelStation(void *drvHandler, tstrHostIFDelSta *pstrDelStaPara
  *  @date
  *  @version   1.0
  */
-static void Handle_EditStation(void *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
+static void Handle_EditStation(tstrWILC_WFIDrv *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -3781,9 +3760,8 @@ static void Handle_EditStation(void *drvHandler, tstrWILC_AddStaParam *pstrStati
 
        PRINT_D(HOSTINF_DBG, "Handling edit station\n");
        strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
        pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
@@ -3799,8 +3777,8 @@ static void Handle_EditStation(void *drvHandler, tstrWILC_AddStaParam *pstrStati
        WILC_CATCH(s32Error)
        {
        }
-       WILC_FREE_IF_TRUE(pstrStationParam->pu8Rates);
-       WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+       kfree(pstrStationParam->pu8Rates);
+       kfree(strWID.ps8WidVal);
 }
 #endif /*WILC_AP_EXTERNAL_MLME*/
 
@@ -3814,7 +3792,7 @@ static void Handle_EditStation(void *drvHandler, tstrWILC_AddStaParam *pstrStati
  *  @date
  *  @version   1.0
  */
-static int Handle_RemainOnChan(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
+static int Handle_RemainOnChan(tstrWILC_WFIDrv *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
 {
        s32 s32Error = WILC_SUCCESS;
        u8 u8remain_on_chan_flag;
@@ -3856,30 +3834,30 @@ static int Handle_RemainOnChan(void *drvHandler, tstrHostIfRemainOnChan *pstrHos
        strWID.u16WIDid = (u16)WID_REMAIN_ON_CHAN;
        strWID.enuWIDtype       = WID_STR;
        strWID.s32ValueSize = 2;
-       strWID.ps8WidVal = (s8 *)WILC_MALLOC(strWID.s32ValueSize);
+       strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
 
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        strWID.ps8WidVal[0] = u8remain_on_chan_flag;
        strWID.ps8WidVal[1] = (s8)pstrHostIfRemainOnChan->u16Channel;
 
        /*Sending Cfg*/
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
-       if (s32Error != WILC_SUCCESS) {
+       if (s32Error != WILC_SUCCESS)
                PRINT_ER("Failed to set remain on channel\n");
-       }
 
        WILC_CATCH(-1)
        {
                P2P_LISTEN_STATE = 1;
-               WILC_TimerStart(&(pstrWFIDrv->hRemainOnChannel), pstrHostIfRemainOnChan->u32duration, (void *)pstrWFIDrv, NULL);
+               pstrWFIDrv->hRemainOnChannel.data = (unsigned long)pstrWFIDrv;
+               mod_timer(&pstrWFIDrv->hRemainOnChannel,
+                         jiffies +
+                         msecs_to_jiffies(pstrHostIfRemainOnChan->u32duration));
 
                /*Calling CFG ready_on_channel*/
-               if (pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady) {
+               if (pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady)
                        pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady(pstrWFIDrv->strHostIfRemainOnChan.pVoid);
-               }
 
                if (pstrWFIDrv->u8RemainOnChan_pendingreq)
                        pstrWFIDrv->u8RemainOnChan_pendingreq = 0;
@@ -3896,7 +3874,7 @@ static int Handle_RemainOnChan(void *drvHandler, tstrHostIfRemainOnChan *pstrHos
  *  @date
  *  @version   1.0
  */
-static int Handle_RegisterFrame(void *drvHandler, tstrHostIfRegisterFrame *pstrHostIfRegisterFrame)
+static int Handle_RegisterFrame(tstrWILC_WFIDrv *drvHandler, tstrHostIfRegisterFrame *pstrHostIfRegisterFrame)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -3909,15 +3887,14 @@ static int Handle_RegisterFrame(void *drvHandler, tstrHostIfRegisterFrame *pstrH
        strWID.u16WIDid = (u16)WID_REGISTER_FRAME;
        strWID.enuWIDtype = WID_STR;
        strWID.ps8WidVal = WILC_MALLOC(sizeof(u16) + 2);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
 
        *pu8CurrByte++ = pstrHostIfRegisterFrame->bReg;
        *pu8CurrByte++ = pstrHostIfRegisterFrame->u8Regid;
-       WILC_memcpy(pu8CurrByte, &(pstrHostIfRegisterFrame->u16FrameType), sizeof(u16));
+       memcpy(pu8CurrByte, &(pstrHostIfRegisterFrame->u16FrameType), sizeof(u16));
 
 
        strWID.s32ValueSize = sizeof(u16) + 2;
@@ -3949,7 +3926,7 @@ static int Handle_RegisterFrame(void *drvHandler, tstrHostIfRegisterFrame *pstrH
  *  @version           1.0
  */
 #define FALSE_FRMWR_CHANNEL 100
-static u32 Handle_ListenStateExpired(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
+static u32 Handle_ListenStateExpired(tstrWILC_WFIDrv *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
 {
        u8 u8remain_on_chan_flag;
        tstrWID strWID;
@@ -3968,9 +3945,8 @@ static u32 Handle_ListenStateExpired(void *drvHandler, tstrHostIfRemainOnChan *p
                strWID.s32ValueSize = 2;
                strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
 
-               if (strWID.ps8WidVal == NULL) {
+               if (strWID.ps8WidVal == NULL)
                        PRINT_ER("Failed to allocate memory\n");
-               }
 
                strWID.ps8WidVal[0] = u8remain_on_chan_flag;
                strWID.ps8WidVal[1] = FALSE_FRMWR_CHANNEL;
@@ -4006,25 +3982,24 @@ _done_:
  *  @date
  *  @version           1.0
  */
-static void ListenTimerCB(void *pvArg)
+static void ListenTimerCB(unsigned long arg)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
-       tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg;
+       tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)arg;
        /*Stopping remain-on-channel timer*/
-       WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), NULL);
+       del_timer(&pstrWFIDrv->hRemainOnChannel);
 
        /* prepare the Timer Callback message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED;
        strHostIFmsg.drvHandler = pstrWFIDrv;
        strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = pstrWFIDrv->strHostIfRemainOnChan.u32ListenSessionID;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -4042,19 +4017,19 @@ static void ListenTimerCB(void *pvArg)
  *  @date
  *  @version   1.0
  */
-static void Handle_PowerManagement(void *drvHandler, tstrHostIfPowerMgmtParam *strPowerMgmtParam)
+static void Handle_PowerManagement(tstrWILC_WFIDrv *drvHandler, tstrHostIfPowerMgmtParam *strPowerMgmtParam)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        s8 s8PowerMode;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
        strWID.u16WIDid = (u16)WID_POWER_MANAGEMENT;
 
-       if (strPowerMgmtParam->bIsEnabled == true)      {
+       if (strPowerMgmtParam->bIsEnabled == true)
                s8PowerMode = MIN_FAST_PS;
-       } else {
+       else
                s8PowerMode = NO_POWERSAVE;
-       }
        PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode);
        strWID.ps8WidVal = &s8PowerMode;
        strWID.s32ValueSize = sizeof(char);
@@ -4083,7 +4058,7 @@ static void Handle_PowerManagement(void *drvHandler, tstrHostIfPowerMgmtParam *s
  *  @date
  *  @version   1.0
  */
-static void Handle_SetMulticastFilter(void *drvHandler, tstrHostIFSetMulti *strHostIfSetMulti)
+static void Handle_SetMulticastFilter(tstrWILC_WFIDrv *drvHandler, tstrHostIFSetMulti *strHostIfSetMulti)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -4095,9 +4070,8 @@ static void Handle_SetMulticastFilter(void *drvHandler, tstrHostIFSetMulti *strH
        strWID.enuWIDtype = WID_BIN;
        strWID.s32ValueSize = sizeof(tstrHostIFSetMulti) + ((strHostIfSetMulti->u32count) * ETH_ALEN);
        strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
-       if (strWID.ps8WidVal == NULL) {
+       if (strWID.ps8WidVal == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
 
        pu8CurrByte = strWID.ps8WidVal;
        *pu8CurrByte++ = (strHostIfSetMulti->bIsEnabled & 0xFF);
@@ -4123,7 +4097,7 @@ static void Handle_SetMulticastFilter(void *drvHandler, tstrHostIFSetMulti *strH
        WILC_CATCH(s32Error)
        {
        }
-       WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+       kfree(strWID.ps8WidVal);
 
 }
 
@@ -4138,7 +4112,7 @@ static void Handle_SetMulticastFilter(void *drvHandler, tstrHostIFSetMulti *strH
  *  @date                      Feb. 2014
  *  @version           9.0
  */
-static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+static s32 Handle_AddBASession(tstrWILC_WFIDrv *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -4146,7 +4120,7 @@ static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
        char *ptr = NULL;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
 
-       PRINT_D(HOSTINF_DBG, "Opening Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d \nBufferSize == %d \nSessionTimeOut = %d\n",
+       PRINT_D(HOSTINF_DBG, "Opening Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\nBufferSize == %d\nSessionTimeOut = %d\n",
                strHostIfBASessionInfo->au8Bssid[0],
                strHostIfBASessionInfo->au8Bssid[1],
                strHostIfBASessionInfo->au8Bssid[2],
@@ -4156,14 +4130,14 @@ static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
 
        strWID.u16WIDid = (u16)WID_11E_P_ACTION_REQ;
        strWID.enuWIDtype = WID_STR;
-       strWID.ps8WidVal = (u8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
+       strWID.ps8WidVal = WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
        strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE;
        ptr = strWID.ps8WidVal;
        /* *ptr++ = 0x14; */
        *ptr++ = 0x14;
        *ptr++ = 0x3;
        *ptr++ = 0x0;
-       WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+       memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
        ptr += ETH_ALEN;
        *ptr++ = strHostIfBASessionInfo->u8Ted;
        /* BA Policy*/
@@ -4195,7 +4169,7 @@ static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
        *ptr++ = 15;
        *ptr++ = 7;
        *ptr++ = 0x2;
-       WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+       memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
        ptr += ETH_ALEN;
        /* TID*/
        *ptr++ = strHostIfBASessionInfo->u8Ted;
@@ -4209,7 +4183,7 @@ static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
        if (strWID.ps8WidVal != NULL)
-               WILC_FREE(strWID.ps8WidVal);
+               kfree(strWID.ps8WidVal);
 
        return s32Error;
 
@@ -4226,14 +4200,14 @@ static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
  *  @date                      Feb. 2013
  *  @version           9.0
  */
-static s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+static s32 Handle_DelBASession(tstrWILC_WFIDrv *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        char *ptr = NULL;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
 
-       PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d\n",
+       PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n",
                strHostIfBASessionInfo->au8Bssid[0],
                strHostIfBASessionInfo->au8Bssid[1],
                strHostIfBASessionInfo->au8Bssid[2],
@@ -4241,14 +4215,14 @@ static s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
 
        strWID.u16WIDid = (u16)WID_11E_P_ACTION_REQ;
        strWID.enuWIDtype = WID_STR;
-       strWID.ps8WidVal = (u8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
+       strWID.ps8WidVal = WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
        strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE;
        ptr = strWID.ps8WidVal;
        /* *ptr++ = 0x14; */
        *ptr++ = 0x14;
        *ptr++ = 0x3;
        *ptr++ = 0x2;
-       WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+       memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
        ptr += ETH_ALEN;
        *ptr++ = strHostIfBASessionInfo->u8Ted;
        /* BA direction = recipent*/
@@ -4269,7 +4243,7 @@ static s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
        *ptr++ = 15;
        *ptr++ = 7;
        *ptr++ = 0x3;
-       WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+       memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
        ptr += ETH_ALEN;
        /* TID*/
        *ptr++ = strHostIfBASessionInfo->u8Ted;
@@ -4277,7 +4251,7 @@ static s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
        s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
 
        if (strWID.ps8WidVal != NULL)
-               WILC_FREE(strWID.ps8WidVal);
+               kfree(strWID.ps8WidVal);
 
        /*BugID_5222*/
        up(&hWaitResponse);
@@ -4296,14 +4270,14 @@ static s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHos
  *  @date                      Feb. 2013
  *  @version           9.0
  */
-static s32 Handle_DelAllRxBASessions(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+static s32 Handle_DelAllRxBASessions(tstrWILC_WFIDrv *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
        char *ptr = NULL;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
 
-       PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d\n",
+       PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n",
                strHostIfBASessionInfo->au8Bssid[0],
                strHostIfBASessionInfo->au8Bssid[1],
                strHostIfBASessionInfo->au8Bssid[2],
@@ -4311,13 +4285,13 @@ static s32 Handle_DelAllRxBASessions(void *drvHandler, tstrHostIfBASessionInfo *
 
        strWID.u16WIDid = (u16)WID_DEL_ALL_RX_BA;
        strWID.enuWIDtype = WID_STR;
-       strWID.ps8WidVal = (u8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
+       strWID.ps8WidVal = WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
        strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE;
        ptr = strWID.ps8WidVal;
        *ptr++ = 0x14;
        *ptr++ = 0x3;
        *ptr++ = 0x2;
-       WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+       memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
        ptr += ETH_ALEN;
        *ptr++ = strHostIfBASessionInfo->u8Ted;
        /* BA direction = recipent*/
@@ -4331,7 +4305,7 @@ static s32 Handle_DelAllRxBASessions(void *drvHandler, tstrHostIfBASessionInfo *
 
 
        if (strWID.ps8WidVal != NULL)
-               WILC_FREE(strWID.ps8WidVal);
+               kfree(strWID.ps8WidVal);
 
        /*BugID_5222*/
        up(&hWaitResponse);
@@ -4355,10 +4329,10 @@ static int hostIFthread(void *pvArg)
        tstrHostIFmsg strHostIFmsg;
        tstrWILC_WFIDrv *pstrWFIDrv;
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        while (1) {
-               WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret, NULL);
+               WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret);
                pstrWFIDrv = (tstrWILC_WFIDrv *)strHostIFmsg.drvHandler;
                if (strHostIFmsg.u16MsgId == HOST_IF_MSG_EXIT) {
                        PRINT_D(GENERIC_DBG, "THREAD: Exiting HostIfThread\n");
@@ -4369,15 +4343,15 @@ static int hostIFthread(void *pvArg)
                /*Re-Queue HIF message*/
                if ((!g_wilc_initialized)) {
                        PRINT_D(GENERIC_DBG, "--WAIT--");
-                       WILC_Sleep(200);
-                       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+                       usleep_range(200 * 1000, 200 * 1000);
+                       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
                        continue;
                }
 
                if (strHostIFmsg.u16MsgId == HOST_IF_MSG_CONNECT && pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL) {
                        PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n");
-                       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-                       WILC_Sleep(2);
+                       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+                       usleep_range(2 * 1000, 2 * 1000);
                        continue;
                }
 
@@ -4425,14 +4399,13 @@ static int hostIFthread(void *pvArg)
                        break;
 
                case HOST_IF_MSG_RCVD_SCAN_COMPLETE:
-                       WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+                       del_timer(&pstrWFIDrv->hScanTimer);
                        PRINT_D(HOSTINF_DBG, "scan completed successfully\n");
 
                        /*BugID_5213*/
                        /*Allow chip sleep, only if both interfaces are not connected*/
-                       if (!linux_wlan_get_num_conn_ifcs()) {
+                       if (!linux_wlan_get_num_conn_ifcs())
                                chip_sleep_manually(INFINITE_SLEEP_TIME);
-                       }
 
                        Handle_ScanDone(strHostIFmsg.drvHandler, SCAN_EVENT_DONE);
 
@@ -4492,7 +4465,7 @@ static int hostIFthread(void *pvArg)
                        break;
 
                case HOST_IF_MSG_CONNECT_TIMER_FIRED:
-                       PRINT_D(HOSTINF_DBG, "Connect Timeout \n");
+                       PRINT_D(HOSTINF_DBG, "Connect Timeout\n");
                        Handle_ConnectTimeout(strHostIFmsg.drvHandler);
                        break;
 
@@ -4563,7 +4536,7 @@ static int hostIFthread(void *pvArg)
                        break;
 
                default:
-                       PRINT_ER("[Host Interface] undefined Received Msg ID  \n");
+                       PRINT_ER("[Host Interface] undefined Received Msg ID\n");
                        break;
                }
        }
@@ -4573,30 +4546,32 @@ static int hostIFthread(void *pvArg)
        return 0;
 }
 
-static void TimerCB_Scan(void *pvArg)
+static void TimerCB_Scan(unsigned long arg)
 {
+       void *pvArg = (void *)arg;
        tstrHostIFmsg strHostIFmsg;
 
        /* prepare the Timer Callback message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.drvHandler = pvArg;
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN_TIMER_FIRED;
 
        /* send the message */
-       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
 }
 
-static void TimerCB_Connect(void *pvArg)
+static void TimerCB_Connect(unsigned long arg)
 {
+       void *pvArg = (void *)arg;
        tstrHostIFmsg strHostIFmsg;
 
        /* prepare the Timer Callback message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.drvHandler = pvArg;
        strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT_TIMER_FIRED;
 
        /* send the message */
-       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
 }
 
 
@@ -4613,7 +4588,7 @@ static void TimerCB_Connect(void *pvArg)
  *  @version           1.0
  */
 /* Check implementation in core adding 9 bytes to the input! */
-s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress)
+s32 host_int_remove_key(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8StaAddress)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -4642,19 +4617,18 @@ s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8keyIdx)
+s32 host_int_remove_wep_key(tstrWILC_WFIDrv *hWFIDrv, u8 u8keyIdx)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /* prepare the Remove Wep Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4668,9 +4642,9 @@ s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8keyIdx)
        uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8keyIdx;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
-               PRINT_ER("Error in sending message queue : Request to remove WEP key \n");
+               PRINT_ER("Error in sending message queue : Request to remove WEP key\n");
        down(&(pstrWFIDrv->hSemTestKeyBlock));
 
        WILC_CATCH(s32Error)
@@ -4692,19 +4666,18 @@ s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8keyIdx)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index)
+s32 host_int_set_WEPDefaultKeyID(tstrWILC_WFIDrv *hWFIDrv, u8 u8Index)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /* prepare the Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4717,7 +4690,7 @@ s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index)
        uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Index;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER("Error in sending message queue : Default key index\n");
        down(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -4749,20 +4722,19 @@ s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx)
+s32 host_int_add_wep_key_bss_sta(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx)
 {
 
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
 
-       }
 
        /* prepare the Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4772,9 +4744,9 @@ s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
 
 
        strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
-       uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = (u8 *)WILC_MALLOC(u8WepKeylen);
+       uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = WILC_MALLOC(u8WepKeylen);
 
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
                    pu8WepKey, u8WepKeylen);
 
 
@@ -4785,7 +4757,7 @@ s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
        uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Keyidx;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER("Error in sending message queue :WEP Key\n");
        down(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -4815,7 +4787,7 @@ s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
  *  @date              28 FEB 2013
  *  @version           1.0
  */
-s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type)
+s32 host_int_add_wep_key_bss_ap(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -4823,13 +4795,12 @@ s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
        tstrHostIFmsg strHostIFmsg;
        u8 i;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
 
-       }
 
        /* prepare the Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        if (INFO) {
                for (i = 0; i < u8WepKeylen; i++)
@@ -4842,10 +4813,10 @@ s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
 
 
        strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
-       uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = (u8 *)WILC_MALLOC((u8WepKeylen));
+       uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = WILC_MALLOC((u8WepKeylen));
 
 
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
                    pu8WepKey, (u8WepKeylen));
 
 
@@ -4861,7 +4832,7 @@ s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
        strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
        uniHostIFkeyAttr.strHostIFwepAttr.tenuAuth_type = tenuAuth_type;
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
 
        if (s32Error)
                PRINT_ER("Error in sending message queue :WEP Key\n");
@@ -4891,7 +4862,7 @@ s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
+s32 host_int_add_ptk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
                             const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -4899,18 +4870,16 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen
        tstrHostIFmsg strHostIFmsg;
        u8 u8KeyLen = u8PtkKeylen;
        u32 i;
-       if (pstrWFIDrv == NULL) {
+
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
-       if (pu8RxMic != NULL) {
+       if (pu8RxMic != NULL)
                u8KeyLen += RX_MIC_KEY_LEN;
-       }
-       if (pu8TxMic != NULL) {
+       if (pu8TxMic != NULL)
                u8KeyLen += TX_MIC_KEY_LEN;
-       }
 
        /* prepare the Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4927,15 +4896,15 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen
 
 
        strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
-       uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (u8 *)WILC_MALLOC(u8PtkKeylen);
+       uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = WILC_MALLOC(u8PtkKeylen);
 
 
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
                    pu8Ptk, u8PtkKeylen);
 
        if (pu8RxMic != NULL) {
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
                            pu8RxMic, RX_MIC_KEY_LEN);
                if (INFO) {
                        for (i = 0; i < RX_MIC_KEY_LEN; i++)
@@ -4944,7 +4913,7 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen
        }
        if (pu8TxMic != NULL) {
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
                            pu8TxMic, TX_MIC_KEY_LEN);
                if (INFO) {
                        for (i = 0; i < TX_MIC_KEY_LEN; i++)
@@ -4962,14 +4931,13 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
 
        if (s32Error)
                PRINT_ER("Error in sending message queue:  PTK Key\n");
 
        /* ////////////// */
        down(&(pstrWFIDrv->hSemTestKeyBlock));
-       /* WILC_Sleep(100); */
        /* /////// */
 
        WILC_CATCH(s32Error)
@@ -4993,7 +4961,7 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
+s32 host_int_add_rx_gtk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
                                u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
                                const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode)
 {
@@ -5002,24 +4970,21 @@ s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkK
        tstrHostIFmsg strHostIFmsg;
        u8 u8KeyLen = u8GtkKeylen;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
        /* prepare the Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
-       if (pu8RxMic != NULL) {
+       if (pu8RxMic != NULL)
                u8KeyLen += RX_MIC_KEY_LEN;
-       }
-       if (pu8TxMic != NULL) {
+       if (pu8TxMic != NULL)
                u8KeyLen += TX_MIC_KEY_LEN;
-       }
        if (KeyRSC != NULL) {
                strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
-               uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq = (u8 *)WILC_MALLOC(u32KeyRSClen);
+               uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq = WILC_MALLOC(u32KeyRSClen);
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq,
                            KeyRSC, u32KeyRSClen);
        }
 
@@ -5039,20 +5004,20 @@ s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkK
 
 
        strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
-       uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (u8 *)WILC_MALLOC(u8KeyLen);
+       uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = WILC_MALLOC(u8KeyLen);
 
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
                    pu8RxGtk, u8GtkKeylen);
 
        if (pu8RxMic != NULL) {
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
                            pu8RxMic, RX_MIC_KEY_LEN);
 
        }
        if (pu8TxMic != NULL) {
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
                            pu8TxMic, TX_MIC_KEY_LEN);
 
        }
@@ -5068,12 +5033,11 @@ s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkK
 
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER("Error in sending message queue:  RX GTK\n");
        /* ////////////// */
        down(&(pstrWFIDrv->hSemTestKeyBlock));
-       /* WILC_Sleep(100); */
        /* /////// */
 
        WILC_CATCH(s32Error)
@@ -5103,7 +5067,7 @@ s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkK
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray)
+s32 host_int_set_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -5111,12 +5075,11 @@ s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8P
        u32 i;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /* prepare the Key Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
        strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = PMKSA;
@@ -5125,15 +5088,15 @@ s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8P
 
        for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) {
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, &pu8PmkidInfoArray->pmkidlist[i].bssid,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, &pu8PmkidInfoArray->pmkidlist[i].bssid,
                            ETH_ALEN);
 
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, &pu8PmkidInfoArray->pmkidlist[i].pmkid,
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, &pu8PmkidInfoArray->pmkidlist[i].pmkid,
                            PMKID_LEN);
        }
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER(" Error in sending messagequeue: PMKID Info\n");
 
@@ -5166,7 +5129,7 @@ s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8P
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
+s32 host_int_get_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PmkidInfoArray,
                                    u32 u32PmkidInfoLen)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -5195,14 +5158,12 @@ s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassPhrase,
+s32 host_int_set_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PassPhrase,
                                                 u8 u8Psklength)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
-       /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
 
-       /* u8 u8Psklength = WILC_strlen(pu8PassPhrase); */
        /*validating psk length*/
        if ((u8Psklength > 7) && (u8Psklength < 65)) {
                strWID.u16WIDid = (u16)WID_11I_PSK;
@@ -5224,20 +5185,20 @@ s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassP
  *  @date              19 April 2012
  *  @version           1.0
  */
-s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
+s32 host_int_get_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
 
 
        /* prepare the Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_MAC_ADDRESS;
        strHostIFmsg.uniHostIFmsgBody.strHostIfGetMacAddress.u8MacAddress = pu8MacAddress;
        strHostIFmsg.drvHandler = hWFIDrv;
        /* send the message */
-       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send get mac address\n");
                return WILC_FAIL;
@@ -5258,7 +5219,7 @@ s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
  *  @date              16 July 2012
  *  @version           1.0
  */
-s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
+s32 host_int_set_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
@@ -5266,12 +5227,12 @@ s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
        PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]);
 
        /* prepare setting mac address message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_MAC_ADDRESS;
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress.u8MacAddress, pu8MacAddress, ETH_ALEN);
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress.u8MacAddress, pu8MacAddress, ETH_ALEN);
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send message queue: Set mac address\n");
                WILC_ERRORREPORT(s32Error, s32Error);
@@ -5299,7 +5260,7 @@ s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv,
                                                 u8 *pu8PassPhrase, u8 u8Psklength)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -5346,7 +5307,7 @@ s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
  *  @version           1.0
  */
 #ifndef CONNECT_DIRECT
-s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_site_survey_results(tstrWILC_WFIDrv *hWFIDrv,
                                             u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
                                             u32 u32MaxSiteSrvyFragLen)
 {
@@ -5396,7 +5357,7 @@ s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource)
+s32 host_int_set_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 scanSource)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -5426,7 +5387,7 @@ s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource)
  *  @version           1.0
  */
 
-s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource)
+s32 host_int_get_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ScanSource)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -5451,7 +5412,7 @@ s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
+s32 host_int_set_join_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8bssid,
                                  const u8 *pu8ssid, size_t ssidLen,
                                  const u8 *pu8IEs, size_t IEsLen,
                                  tWILCpfConnectResult pfConnectResult, void *pvUserArg,
@@ -5464,9 +5425,8 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
        tstrHostIFmsg strHostIFmsg;
        tenuScanConnTimer enuScanConnTimer;
 
-       if (pstrWFIDrv == NULL || pfConnectResult == NULL) {
+       if (pstrWFIDrv == NULL || pfConnectResult == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        if (hWFIDrv == NULL) {
                PRINT_ER("Driver not initialized: gWFiDrvHandle = NULL\n");
@@ -5486,7 +5446,7 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
  *      }
  */
        /* prepare the Connect Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT;
 
@@ -5499,39 +5459,41 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
        strHostIFmsg.drvHandler = hWFIDrv;
 
        if (pu8bssid != NULL) {
-               strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid = (u8 *)WILC_MALLOC(6); /* will be deallocated by the receiving thread */
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid,
+               strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid = WILC_MALLOC(6); /* will be deallocated by the receiving thread */
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid,
                            pu8bssid, 6);
        }
 
        if (pu8ssid != NULL) {
                strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.ssidLen = ssidLen;
-               strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid = (u8 *)WILC_MALLOC(ssidLen); /* will be deallocated by the receiving thread */
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid,
+               strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid = WILC_MALLOC(ssidLen); /* will be deallocated by the receiving thread */
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid,
 
                            pu8ssid, ssidLen);
        }
 
        if (pu8IEs != NULL) {
                strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.IEsLen = IEsLen;
-               strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs = (u8 *)WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */
-               WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs,
+               strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs = WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */
+               memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs,
                            pu8IEs, IEsLen);
        }
-       if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING) {
+       if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING)
                pstrWFIDrv->enuHostIFstate = HOST_IF_CONNECTING;
-       else
+       else
                PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' as state is %d\n", pstrWFIDrv->enuHostIFstate);
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send message queue: Set join request\n");
                WILC_ERRORREPORT(s32Error, WILC_FAIL);
        }
 
        enuScanConnTimer = CONNECT_TIMER;
-       WILC_TimerStart(&(pstrWFIDrv->hConnectTimer), HOST_IF_CONNECT_TIMEOUT, (void *) hWFIDrv, NULL);
+       pstrWFIDrv->hConnectTimer.data = (unsigned long)hWFIDrv;
+       mod_timer(&pstrWFIDrv->hConnectTimer,
+                 jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
 
        WILC_CATCH(s32Error)
        {
@@ -5553,7 +5515,7 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
  *  @version   8.0
  */
 
-s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv)
+s32 host_int_flush_join_req(tstrWILC_WFIDrv *hWFIDrv)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
@@ -5564,16 +5526,15 @@ s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv)
        }
 
 
-       if (hWFIDrv  == NULL) {
+       if (hWFIDrv  == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_FLUSH_CONNECT;
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send message queue: Flush join request\n");
                WILC_ERRORREPORT(s32Error, WILC_FAIL);
@@ -5597,14 +5558,14 @@ s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode)
+s32 host_int_disconnect(tstrWILC_WFIDrv *hWFIDrv, u16 u16ReasonCode)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
 
@@ -5614,13 +5575,13 @@ s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode)
        }
 
        /* prepare the Disconnect Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_DISCONNECT;
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER("Failed to send message queue: disconnect\n");
        /* ////////////// */
@@ -5646,7 +5607,7 @@ s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id)
+s32 host_int_disconnect_station(tstrWILC_WFIDrv *hWFIDrv, u8 assoc_id)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -5686,7 +5647,7 @@ s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id)
  *  @version           1.0
  */
 
-s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
+s32 host_int_get_assoc_req_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocReqInfo,
                                        u32 u32AssocReqInfoLen)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -5713,7 +5674,7 @@ s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
+s32 host_int_get_assoc_res_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocRespInfo,
                                        u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -5721,7 +5682,7 @@ s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
 
@@ -5763,7 +5724,7 @@ s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
+s32 host_int_get_rx_power_level(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8RxPowerLevel,
                                        u32 u32RxPowerLevelLen)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -5794,26 +5755,24 @@ s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum)
+s32 host_int_set_mac_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 u8ChNum)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /* prepare the set channel message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_CHANNEL;
        strHostIFmsg.uniHostIFmsgBody.strHostIFSetChan.u8SetChan = u8ChNum;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -5831,12 +5790,11 @@ s32 host_int_wait_msg_queue_idle(void)
 
        /* prepare the set driver handler message */
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_Q_IDLE;
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -5849,7 +5807,7 @@ s32 host_int_wait_msg_queue_idle(void)
 
 }
 
-s32 host_int_set_wfi_drv_handler(u32 u32address)
+s32 host_int_set_wfi_drv_handler(tstrWILC_WFIDrv *u32address)
 {
        s32 s32Error = WILC_SUCCESS;
 
@@ -5858,15 +5816,14 @@ s32 host_int_set_wfi_drv_handler(u32 u32address)
 
        /* prepare the set driver handler message */
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_WFIDRV_HANDLER;
        strHostIFmsg.uniHostIFmsgBody.strHostIfSetDrvHandler.u32Address = u32address;
        /* strHostIFmsg.drvHandler=hWFIDrv; */
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -5877,7 +5834,7 @@ s32 host_int_set_wfi_drv_handler(u32 u32address)
 
 
 
-s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode)
+s32 host_int_set_operation_mode(tstrWILC_WFIDrv *hWFIDrv, u32 u32mode)
 {
        s32 s32Error = WILC_SUCCESS;
 
@@ -5886,15 +5843,14 @@ s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode)
 
        /* prepare the set driver handler message */
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_OPERATION_MODE;
        strHostIFmsg.uniHostIFmsgBody.strHostIfSetOperationMode.u32Mode = u32mode;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -5918,25 +5874,25 @@ s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo)
+s32 host_int_get_host_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ChNo)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
 
        /* prepare the Get Channel Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_CHNL;
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER("Failed to send get host channel param's message queue ");
        down(&(pstrWFIDrv->hSemGetCHNL));
@@ -5964,7 +5920,7 @@ s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_test_set_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 u32TestMemAddr)
+s32 host_int_test_set_int_wid(tstrWILC_WFIDrv *hWFIDrv, u32 u32TestMemAddr)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWID strWID;
@@ -5972,7 +5928,7 @@ s32 host_int_test_set_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 u32TestMemAddr)
 
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
 
@@ -6011,28 +5967,28 @@ s32 host_int_test_set_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 u32TestMemAddr)
  *  @date
  *  @version           1.0
  */
-s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu32InactiveTime)
+s32 host_int_get_inactive_time(tstrWILC_WFIDrv *hWFIDrv, const u8 *mac, u32 *pu32InactiveTime)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT.mac,
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT.mac,
                    mac, ETH_ALEN);
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_INACTIVETIME;
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error)
                PRINT_ER("Failed to send get host channel param's message queue ");
 
@@ -6057,7 +6013,7 @@ s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_test_get_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 *pu32TestMemAddr)
+s32 host_int_test_get_int_wid(tstrWILC_WFIDrv *hWFIDrv, u32 *pu32TestMemAddr)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -6066,7 +6022,7 @@ s32 host_int_test_get_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 *pu32TestMemAddr)
 
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
 
@@ -6106,7 +6062,7 @@ s32 host_int_test_get_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 *pu32TestMemAddr)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi)
+s32 host_int_get_rssi(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8Rssi)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
@@ -6114,13 +6070,13 @@ s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi)
 
 
        /* prepare the Get RSSI Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI;
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send get host channel param's message queue ");
                return WILC_FAIL;
@@ -6141,7 +6097,7 @@ s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi)
        return s32Error;
 }
 
-s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd)
+s32 host_int_get_link_speed(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8lnkspd)
 {
        tstrHostIFmsg strHostIFmsg;
        s32 s32Error = WILC_SUCCESS;
@@ -6151,13 +6107,13 @@ s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd)
 
 
        /* prepare the Get LINKSPEED Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_LINKSPEED;
        strHostIFmsg.drvHandler = hWFIDrv;
 
        /* send the message */
-       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send GET_LINKSPEED to message queue ");
                return WILC_FAIL;
@@ -6178,20 +6134,20 @@ s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd)
        return s32Error;
 }
 
-s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics)
+s32 host_int_get_statistics(tstrWILC_WFIDrv *hWFIDrv, tstrStatistics *pstrStatistics)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
 
 
        /* prepare the Get RSSI Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_STATISTICS;
        strHostIFmsg.uniHostIFmsgBody.pUserData = (char *)pstrStatistics;
        strHostIFmsg.drvHandler = hWFIDrv;
        /* send the message */
-       s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Failed to send get host channel param's message queue ");
                return WILC_FAIL;
@@ -6218,7 +6174,7 @@ s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStati
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
+s32 host_int_scan(tstrWILC_WFIDrv *hWFIDrv, u8 u8ScanSource,
                          u8 u8ScanType, u8 *pu8ChnlFreqList,
                          u8 u8ChnlListLen, const u8 *pu8IEs,
                          size_t IEsLen, tWILCpfScanResult ScanResult,
@@ -6229,13 +6185,12 @@ s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
        tstrHostIFmsg strHostIFmsg;
        tenuScanConnTimer enuScanConnTimer;
 
-       if (pstrWFIDrv == NULL || ScanResult == NULL)   {
+       if (pstrWFIDrv == NULL || ScanResult == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
 
        /* prepare the Scan Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN;
 
@@ -6253,17 +6208,17 @@ s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
        strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pvUserArg = pvUserArg;
 
        strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.u8ChnlListLen = u8ChnlListLen;
-       strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList = (u8 *)WILC_MALLOC(u8ChnlListLen);        /* will be deallocated by the receiving thread */
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList,
+       strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList = WILC_MALLOC(u8ChnlListLen);        /* will be deallocated by the receiving thread */
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList,
                    pu8ChnlFreqList, u8ChnlListLen);
 
        strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.IEsLen = IEsLen;
-       strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs = (u8 *)WILC_MALLOC(IEsLen);        /* will be deallocated by the receiving thread */
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs,
+       strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs = WILC_MALLOC(IEsLen);        /* will be deallocated by the receiving thread */
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs,
                    pu8IEs, IEsLen);
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        if (s32Error) {
                PRINT_ER("Error in sending message queue scanning parameters: Error(%d)\n", s32Error);
                WILC_ERRORREPORT(s32Error, WILC_FAIL);
@@ -6271,8 +6226,9 @@ s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
 
        enuScanConnTimer = SCAN_TIMER;
        PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n");
-       WILC_TimerStart(&(pstrWFIDrv->hScanTimer), HOST_IF_SCAN_TIMEOUT, (void *) hWFIDrv, NULL);
-
+       pstrWFIDrv->hScanTimer.data = (unsigned long)hWFIDrv;
+       mod_timer(&pstrWFIDrv->hScanTimer,
+                 jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
 
        WILC_CATCH(s32Error)
        {
@@ -6292,7 +6248,7 @@ s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
+s32 hif_set_cfg(tstrWILC_WFIDrv *hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
 {
 
        s32 s32Error = WILC_SUCCESS;
@@ -6301,16 +6257,15 @@ s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
        tstrHostIFmsg strHostIFmsg;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
        /* prepare the WiphyParams Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_CFG_PARAMS;
        strHostIFmsg.uniHostIFmsgBody.strHostIFCfgParamAttr.pstrCfgParamVal = *pstrCfgParamVal;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
 
        WILC_CATCH(s32Error)
        {
@@ -6334,7 +6289,7 @@ s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value)
+s32 hif_get_cfg(tstrWILC_WFIDrv *hWFIDrv, u16 u16WID, u16 *pu16WID_Value)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -6342,7 +6297,7 @@ s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value)
        down(&(pstrWFIDrv->gtOsCfgValuesSem));
 
        if (pstrWFIDrv == NULL) {
-               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+               PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
        }
        PRINT_D(HOSTINF_DBG, "Getting configuration parameters\n");
@@ -6469,9 +6424,10 @@ void host_int_send_join_leave_info_to_host
  *  @version           1.0
  */
 
-void GetPeriodicRSSI(void *pvArg)
+static void GetPeriodicRSSI(unsigned long arg)
 {
-       tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg;
+       tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)arg;
+
        if (pstrWFIDrv == NULL) {
                PRINT_ER("Driver handler is NULL\n");
                return;
@@ -6482,19 +6438,20 @@ void GetPeriodicRSSI(void *pvArg)
                tstrHostIFmsg strHostIFmsg;
 
                /* prepare the Get RSSI Message */
-               WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+               memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
                strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI;
                strHostIFmsg.drvHandler = pstrWFIDrv;
 
                /* send the message */
-               s32Error =      WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+               s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
                if (s32Error) {
                        PRINT_ER("Failed to send get host channel param's message queue ");
                        return;
                }
        }
-       WILC_TimerStart(&(g_hPeriodicRSSI), 5000, (void *)pstrWFIDrv, NULL);
+       g_hPeriodicRSSI.data = (unsigned long)pstrWFIDrv;
+       mod_timer(&g_hPeriodicRSSI, jiffies + msecs_to_jiffies(5000));
 }
 
 
@@ -6515,7 +6472,7 @@ static u32 u32Intialized;
 static u32 msgQ_created;
 static u32 clients_count;
 
-s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
+s32 host_int_init(tstrWILC_WFIDrv **phWFIDrv)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv;
@@ -6535,16 +6492,16 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
 
 
        /*Allocate host interface private structure*/
-       pstrWFIDrv  = (tstrWILC_WFIDrv *)WILC_MALLOC(sizeof(tstrWILC_WFIDrv));
+       pstrWFIDrv  = WILC_MALLOC(sizeof(tstrWILC_WFIDrv));
        if (pstrWFIDrv == NULL) {
                /* WILC_ERRORREPORT(s32Error,WILC_NO_MEM); */
                s32Error = WILC_NO_MEM;
                PRINT_ER("Failed to allocate memory\n");
                goto _fail_timer_2;
        }
-       WILC_memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv));
+       memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv));
        /*return driver handle to user*/
-       *phWFIDrv = (WILC_WFIDrvHandle)pstrWFIDrv;
+       *phWFIDrv = pstrWFIDrv;
        /*save into globl handle*/
 
        #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
@@ -6575,9 +6532,7 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
        PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count);
 
        if (clients_count == 0) {
-
-               s32Error = WILC_MsgQueueCreate(&gMsgQHostIF, NULL);
-
+               s32Error = WILC_MsgQueueCreate(&gMsgQHostIF);
 
                if (s32Error < 0) {
                        PRINT_ER("Failed to creat MQ\n");
@@ -6590,47 +6545,24 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
                        s32Error = WILC_FAIL;
                        goto _fail_mq_;
                }
-               s32Error = WILC_TimerCreate(&(g_hPeriodicRSSI), GetPeriodicRSSI, NULL);
-               if (s32Error < 0) {
-                       PRINT_ER("Failed to creat Timer\n");
-                       goto _fail_timer_1;
-               }
-               WILC_TimerStart(&(g_hPeriodicRSSI), 5000, (void *)pstrWFIDrv, NULL);
-
+               setup_timer(&g_hPeriodicRSSI, GetPeriodicRSSI,
+                           (unsigned long)pstrWFIDrv);
+               mod_timer(&g_hPeriodicRSSI, jiffies + msecs_to_jiffies(5000));
        }
 
 
-       s32Error = WILC_TimerCreate(&(pstrWFIDrv->hScanTimer), TimerCB_Scan, NULL);
-       if (s32Error < 0) {
-               PRINT_ER("Failed to creat Timer\n");
-               goto _fail_thread_;
-       }
-
-       s32Error = WILC_TimerCreate(&(pstrWFIDrv->hConnectTimer), TimerCB_Connect, NULL);
-       if (s32Error < 0) {
-               PRINT_ER("Failed to creat Timer\n");
-               goto _fail_timer_1;
-       }
+       setup_timer(&pstrWFIDrv->hScanTimer, TimerCB_Scan, 0);
 
+       setup_timer(&pstrWFIDrv->hConnectTimer, TimerCB_Connect, 0);
 
        #ifdef WILC_P2P
        /*Remain on channel timer*/
-       s32Error = WILC_TimerCreate(&(pstrWFIDrv->hRemainOnChannel), ListenTimerCB, NULL);
-       if (s32Error < 0) {
-               PRINT_ER("Failed to creat Remain-on-channel Timer\n");
-               goto _fail_timer_3;
-       }
+       setup_timer(&pstrWFIDrv->hRemainOnChannel, ListenTimerCB, 0);
        #endif
 
        sema_init(&(pstrWFIDrv->gtOsCfgValuesSem), 1);
        down(&(pstrWFIDrv->gtOsCfgValuesSem));
 
-
-
-#ifdef SIMULATION
-       TransportInit();
-#endif
-
        pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
        /* gWFiDrvHandle->bPendingConnRequest = false; */
 
@@ -6666,11 +6598,6 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
                goto _fail_mem_;
        }
 
-#ifdef SIMULATION
-       /*Initialize Simulaor*/
-       CoreConfigSimulatorInit();
-#endif
-
        u32Intialized = 1;
        clients_count++; /* increase number of created entities */
 
@@ -6679,20 +6606,17 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
 
 _fail_mem_:
        if (pstrWFIDrv != NULL)
-               WILC_FREE(pstrWFIDrv);
+               kfree(pstrWFIDrv);
 #ifdef WILC_P2P
-_fail_timer_3:
-       WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), NULL);
+       del_timer_sync(&pstrWFIDrv->hRemainOnChannel);
 #endif
 _fail_timer_2:
        up(&(pstrWFIDrv->gtOsCfgValuesSem));
-       WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), NULL);
-_fail_timer_1:
-       WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), NULL);
-_fail_thread_:
+       del_timer_sync(&pstrWFIDrv->hConnectTimer);
+       del_timer_sync(&pstrWFIDrv->hScanTimer);
        kthread_stop(HostIFthreadHandler);
 _fail_mq_:
-       WILC_MsgQueueDestroy(&gMsgQHostIF, NULL);
+       WILC_MsgQueueDestroy(&gMsgQHostIF);
 _fail_:
        return s32Error;
 
@@ -6708,7 +6632,7 @@ _fail_:
  *  @version           1.0
  */
 
-s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv)
+s32 host_int_deinit(tstrWILC_WFIDrv *hWFIDrv)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrHostIFmsg strHostIFmsg;
@@ -6737,28 +6661,28 @@ s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv)
        /*BugID_5348*/
        /*Destroy all timers before acquiring hSemDeinitDrvHandle*/
        /*to guarantee handling all messages befor proceeding*/
-       if (WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), NULL)) {
-               PRINT_D(HOSTINF_DBG, ">> Scan timer is active \n");
+       if (del_timer_sync(&pstrWFIDrv->hScanTimer)) {
+               PRINT_D(HOSTINF_DBG, ">> Scan timer is active\n");
                /* msleep(HOST_IF_SCAN_TIMEOUT+1000); */
        }
 
-       if (WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), NULL)) {
-               PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+       if (del_timer_sync(&pstrWFIDrv->hConnectTimer)) {
+               PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
                /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
        }
 
 
-       if (WILC_TimerDestroy(&(g_hPeriodicRSSI), NULL)) {
-               PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+       if (del_timer_sync(&g_hPeriodicRSSI)) {
+               PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
                /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
        }
 
        #ifdef WILC_P2P
        /*Destroy Remain-onchannel Timer*/
-       WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), NULL);
+       del_timer_sync(&pstrWFIDrv->hRemainOnChannel);
        #endif
 
-       host_int_set_wfi_drv_handler((u32)NULL);
+       host_int_set_wfi_drv_handler(NULL);
        down(&hSemDeinitDrvHandle);
 
 
@@ -6770,39 +6694,30 @@ s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv)
                pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = NULL;
        }
        /*deinit configurator and simulator*/
-#ifdef SIMULATION
-       CoreConfigSimulatorDeInit();
-#endif
        CoreConfiguratorDeInit();
-#ifdef SIMULATION
-       TransportDeInit();
-#endif
 
        pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
 
        gbScanWhileConnected = false;
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        if (clients_count == 1) {
-               if (WILC_TimerDestroy(&g_hPeriodicRSSI, NULL)) {
-                       PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+               if (del_timer_sync(&g_hPeriodicRSSI)) {
+                       PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
                        /* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
                }
                strHostIFmsg.u16MsgId = HOST_IF_MSG_EXIT;
                strHostIFmsg.drvHandler = hWFIDrv;
 
 
-               s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-               if (s32Error != WILC_SUCCESS) {
+               s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+               if (s32Error != WILC_SUCCESS)
                        PRINT_ER("Error in sending deinit's message queue message function: Error(%d)\n", s32Error);
-               }
 
                down(&hSemHostIFthrdEnd);
 
-
-
-               WILC_MsgQueueDestroy(&gMsgQHostIF, NULL);
+               WILC_MsgQueueDestroy(&gMsgQHostIF);
                msgQ_created = 0;
        }
 
@@ -6812,7 +6727,7 @@ s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv)
        u32Intialized = 0;
        /* gWFiDrvHandle = NULL; */
        if (pstrWFIDrv != NULL) {
-               WILC_FREE(pstrWFIDrv);
+               kfree(pstrWFIDrv);
                /* pstrWFIDrv=NULL; */
 
        }
@@ -6854,24 +6769,20 @@ void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length)
        }
 
        /* prepare the Asynchronous Network Info message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_NTWRK_INFO;
        strHostIFmsg.drvHandler = pstrWFIDrv;
 
        strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.u32Length = u32Length;
-       strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer = (u8 *)WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer,
+       strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer = WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer,
                    pu8Buffer, u32Length);
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                PRINT_ER("Error in sending network info message queue message parameters: Error(%d)\n", s32Error);
-       }
-
-
-       return;
 }
 
 /**
@@ -6897,7 +6808,7 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
 
        drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
        pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
-       PRINT_D(HOSTINF_DBG, "General asynchronous info packet received \n");
+       PRINT_D(HOSTINF_DBG, "General asynchronous info packet received\n");
 
 
        if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) {
@@ -6916,7 +6827,7 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
        }
 
        /* prepare the General Asynchronous Info message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO;
@@ -6924,19 +6835,17 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length)
 
 
        strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.u32Length = u32Length;
-       strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer = (u8 *)WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
-       WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer,
+       strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer = WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
+       memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer,
                    pu8Buffer, u32Length);
 
        /* send the message */
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                PRINT_ER("Error in sending message queue asynchronous message info: Error(%d)\n", s32Error);
-       }
 
        /*BugID_5348*/
        up(&hSemHostIntDeinit);
-       return;
 }
 
 /**
@@ -6954,20 +6863,20 @@ void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length)
        tstrHostIFmsg strHostIFmsg;
        u32 drvHandler;
        tstrWILC_WFIDrv *pstrWFIDrv = NULL;
+
        drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
        pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
 
 
        PRINT_D(GENERIC_DBG, "Scan notification received %p\n", pstrWFIDrv);
 
-       if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) {
+       if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle)
                return;
-       }
 
        /*if there is an ongoing scan request*/
        if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
                /* prepare theScan Done message */
-               WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+               memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
                strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_SCAN_COMPLETE;
                strHostIFmsg.drvHandler = pstrWFIDrv;
@@ -6978,14 +6887,13 @@ void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length)
 
                /*strHostIFmsg.uniHostIFmsgBody.strScanComplete.u32Length = u32Length;
                 * strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer  = (u8*)WILC_MALLOC(u32Length);
-                * WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer,
+                * memcpy(strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer,
                 *                        pu8Buffer, u32Length); */
 
                /* send the message */
-               s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-               if (s32Error) {
+               s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+               if (s32Error)
                        PRINT_ER("Error in sending message queue scan complete parameters: Error(%d)\n", s32Error);
-               }
        }
 
 
@@ -7008,18 +6916,17 @@ void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length)
  *  @date
  *  @version           1.0
  */
-s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg)
+s32 host_int_remain_on_channel(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /* prepare the remainonchan Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_REMAIN_ON_CHAN;
@@ -7031,10 +6938,9 @@ s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32
        strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7057,29 +6963,27 @@ s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32
  *  @date
  *  @version           1.0
  */
-s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID)
+s32 host_int_ListenStateExpired(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /*Stopping remain-on-channel timer*/
-       WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), NULL);
+       del_timer(&pstrWFIDrv->hRemainOnChannel);
 
        /* prepare the timer fire Message */
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
        strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED;
        strHostIFmsg.drvHandler = hWFIDrv;
        strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7095,17 +6999,16 @@ s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID)
  *  @author
  *  @date
  *  @version           1.0*/
-s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bReg)
+s32 host_int_frame_register(tstrWILC_WFIDrv *hWFIDrv, u16 u16FrameType, bool bReg)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_REGISTER_FRAME;
@@ -7128,10 +7031,9 @@ s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bR
        strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame.bReg = bReg;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7155,7 +7057,7 @@ s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bR
  *  @date
  *  @version   1.0
  */
-s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
+s32 host_int_add_beacon(tstrWILC_WFIDrv *hWFIDrv, u32 u32Interval,
                                u32 u32DTIMPeriod,
                                u32 u32HeadLen, u8 *pu8Head,
                                u32 u32TailLen, u8 *pu8Tail)
@@ -7165,11 +7067,10 @@ s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
        tstrHostIFmsg strHostIFmsg;
        tstrHostIFSetBeacon *pstrSetBeaconParam = &strHostIFmsg.uniHostIFmsgBody.strHostIFSetBeacon;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n");
 
@@ -7180,38 +7081,33 @@ s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
        pstrSetBeaconParam->u32Interval = u32Interval;
        pstrSetBeaconParam->u32DTIMPeriod = u32DTIMPeriod;
        pstrSetBeaconParam->u32HeadLen = u32HeadLen;
-       pstrSetBeaconParam->pu8Head = (u8 *)WILC_MALLOC(u32HeadLen);
-       if (pstrSetBeaconParam->pu8Head == NULL) {
+       pstrSetBeaconParam->pu8Head = WILC_MALLOC(u32HeadLen);
+       if (pstrSetBeaconParam->pu8Head == NULL)
                WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-       }
-       WILC_memcpy(pstrSetBeaconParam->pu8Head, pu8Head, u32HeadLen);
+       memcpy(pstrSetBeaconParam->pu8Head, pu8Head, u32HeadLen);
        pstrSetBeaconParam->u32TailLen = u32TailLen;
 
        /* Bug 4599 : if tail length = 0 skip allocating & copying */
        if (u32TailLen > 0) {
-               pstrSetBeaconParam->pu8Tail = (u8 *)WILC_MALLOC(u32TailLen);
-               if (pstrSetBeaconParam->pu8Tail == NULL) {
+               pstrSetBeaconParam->pu8Tail = WILC_MALLOC(u32TailLen);
+               if (pstrSetBeaconParam->pu8Tail == NULL)
                        WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
-               }
-               WILC_memcpy(pstrSetBeaconParam->pu8Tail, pu8Tail, u32TailLen);
+               memcpy(pstrSetBeaconParam->pu8Tail, pu8Tail, u32TailLen);
        } else {
                pstrSetBeaconParam->pu8Tail = NULL;
        }
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
 
        WILC_CATCH(s32Error)
        {
-               if (pstrSetBeaconParam->pu8Head != NULL) {
-                       WILC_FREE(pstrSetBeaconParam->pu8Head);
-               }
+               if (pstrSetBeaconParam->pu8Head != NULL)
+                       kfree(pstrSetBeaconParam->pu8Head);
 
-               if (pstrSetBeaconParam->pu8Tail != NULL) {
-                       WILC_FREE(pstrSetBeaconParam->pu8Tail);
-               }
+               if (pstrSetBeaconParam->pu8Tail != NULL)
+                       kfree(pstrSetBeaconParam->pu8Tail);
        }
 
        return s32Error;
@@ -7228,22 +7124,21 @@ s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
  *  @date
  *  @version   1.0
  */
-s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv)
+s32 host_int_del_beacon(tstrWILC_WFIDrv *hWFIDrv)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BEACON;
        strHostIFmsg.drvHandler = hWFIDrv;
        PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n");
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
        WILC_ERRORCHECK(s32Error);
 
        WILC_CATCH(s32Error)
@@ -7262,7 +7157,7 @@ s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv)
  *  @date
  *  @version   1.0
  */
-s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
+s32 host_int_add_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -7270,11 +7165,10 @@ s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrSt
        tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n");
 
@@ -7283,20 +7177,20 @@ s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrSt
        strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_STATION;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       WILC_memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
+       memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
        if (pstrAddStationMsg->u8NumRates > 0) {
                u8 *rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates);
+
                WILC_NULLCHECK(s32Error, rates);
 
-               WILC_memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
+               memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
                pstrAddStationMsg->pu8Rates = rates;
        }
 
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
 
        WILC_CATCH(s32Error)
        {
@@ -7313,18 +7207,17 @@ s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrSt
  *  @date
  *  @version   1.0
  */
-s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr)
+s32 host_int_del_station(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8MacAddr)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
        tstrHostIFDelSta *pstrDelStationMsg = &strHostIFmsg.uniHostIFmsgBody.strDelStaParam;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n");
 
@@ -7336,14 +7229,13 @@ s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr)
 
        /*BugID_4795: Handling situation of deleting all stations*/
        if (pu8MacAddr == NULL)
-               WILC_memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN);
+               memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN);
        else
-               WILC_memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN);
+               memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN);
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
 
        WILC_CATCH(s32Error)
        {
@@ -7359,7 +7251,7 @@ s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr)
  *  @date
  *  @version   1.0
  */
-s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN])
+s32 host_int_del_allstation(tstrWILC_WFIDrv *hWFIDrv, u8 pu8MacAddr[][ETH_ALEN])
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -7370,11 +7262,10 @@ s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]
        u8 u8AssocNumb = 0;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n");
 
@@ -7385,7 +7276,7 @@ s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]
        /* Handling situation of deauthenticing all associated stations*/
        for (i = 0; i < MAX_NUM_STA; i++) {
                if (memcmp(pu8MacAddr[i], au8Zero_Buff, ETH_ALEN)) {
-                       WILC_memcpy(pstrDelAllStationMsg->au8Sta_DelAllSta[i], pu8MacAddr[i], ETH_ALEN);
+                       memcpy(pstrDelAllStationMsg->au8Sta_DelAllSta[i], pu8MacAddr[i], ETH_ALEN);
                        PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", pstrDelAllStationMsg->au8Sta_DelAllSta[i][0], pstrDelAllStationMsg->au8Sta_DelAllSta[i][1], pstrDelAllStationMsg->au8Sta_DelAllSta[i][2], pstrDelAllStationMsg->au8Sta_DelAllSta[i][3], pstrDelAllStationMsg->au8Sta_DelAllSta[i][4],
                                pstrDelAllStationMsg->au8Sta_DelAllSta[i][5]);
                        u8AssocNumb++;
@@ -7397,13 +7288,12 @@ s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]
        }
 
        pstrDelAllStationMsg->u8Num_AssocSta = u8AssocNumb;
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
 
 
-       if (s32Error) {
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
 
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7423,38 +7313,37 @@ s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]
  *  @date
  *  @version   1.0
  */
-s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
+s32 host_int_edit_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
        tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n");
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_EDIT_STATION;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       WILC_memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
+       memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
        if (pstrAddStationMsg->u8NumRates > 0) {
                u8 *rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates);
+
                WILC_NULLCHECK(s32Error, rates);
-               WILC_memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
+               memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
                pstrAddStationMsg->pu8Rates = rates;
        }
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
        }
@@ -7463,22 +7352,21 @@ s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrS
 #endif /*WILC_AP_EXTERNAL_MLME*/
 uint32_t wilc_get_chipid(uint8_t);
 
-s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
+s32 host_int_set_power_mgmt(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32Timeout)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
        tstrHostIfPowerMgmtParam *pstrPowerMgmtParam = &strHostIFmsg.uniHostIFmsgBody.strPowerMgmtparam;
 
-       PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d << \n\n", bIsEnabled);
+       PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", bIsEnabled);
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n");
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        /* prepare the WiphyParams Message */
@@ -7489,17 +7377,16 @@ s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32T
        pstrPowerMgmtParam->u32Timeout = u32Timeout;
 
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
        }
        return s32Error;
 }
 
-s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32count)
+s32 host_int_setup_multicast_filter(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32count)
 {
        s32 s32Error = WILC_SUCCESS;
 
@@ -7508,13 +7395,12 @@ s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled,
        tstrHostIFSetMulti *pstrMulticastFilterParam = &strHostIFmsg.uniHostIFmsgBody.strHostIfSetMulti;
 
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
        PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n");
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
 
        /* prepare the WiphyParams Message */
@@ -7524,10 +7410,9 @@ s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled,
        pstrMulticastFilterParam->bIsEnabled = bIsEnabled;
        pstrMulticastFilterParam->u32count = u32count;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
        }
@@ -7568,17 +7453,17 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
 
        pNewJoinBssParam = WILC_MALLOC(sizeof(tstrJoinBssParam));
        if (pNewJoinBssParam != NULL) {
-               WILC_memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam));
+               memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam));
                pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod;
                pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod;
                pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo;
-               WILC_memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6);
+               memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6);
                /*for(i=0; i<6;i++)
                 *      PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->au8bssid[i]);*/
-               WILC_memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1);
+               memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1);
                pNewJoinBssParam->ssidLen = ptstrNetworkInfo->u8SsidLen;
-               WILC_memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3);
-               WILC_memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3);
+               memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3);
+               memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3);
                /*for(i=0; i<pNewJoinBssParam->ssidLen;i++)
                 *      PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->ssid[i]);*/
 
@@ -7633,9 +7518,8 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
                                pNewJoinBssParam->wmm_cap = true;
 
                                /* Check if Bit 7 is set indicating U-APSD capability */
-                               if (pu8IEs[index + 8] & (1 << 7)) {
+                               if (pu8IEs[index + 8] & (1 << 7))
                                        pNewJoinBssParam->uapsd_cap = true;
-                               }
                                index += pu8IEs[index + 1] + 2;
                                continue;
                        }
@@ -7645,6 +7529,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
                                 (pu8IEs[index + 4] == 0x9a) && /* OUI */
                                 (pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) { /* OUI Type     */
                                u16 u16P2P_count;
+
                                pNewJoinBssParam->tsf = ptstrNetworkInfo->u32Tsf;
                                pNewJoinBssParam->u8NoaEnbaled = 1;
                                pNewJoinBssParam->u8Index = pu8IEs[index + 9];
@@ -7656,20 +7541,20 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
                                } else
                                        pNewJoinBssParam->u8OppEnable = 0;
                                /* HOSTINF_DBG */
-                               PRINT_D(GENERIC_DBG, "P2P Dump \n");
+                               PRINT_D(GENERIC_DBG, "P2P Dump\n");
                                for (i = 0; i < pu8IEs[index + 7]; i++)
-                                       PRINT_D(GENERIC_DBG, " %x \n", pu8IEs[index + 9 + i]);
+                                       PRINT_D(GENERIC_DBG, " %x\n", pu8IEs[index + 9 + i]);
 
                                pNewJoinBssParam->u8Count = pu8IEs[index + 11];
                                u16P2P_count = index + 12;
 
-                               WILC_memcpy(pNewJoinBssParam->au8Duration, pu8IEs + u16P2P_count, 4);
+                               memcpy(pNewJoinBssParam->au8Duration, pu8IEs + u16P2P_count, 4);
                                u16P2P_count += 4;
 
-                               WILC_memcpy(pNewJoinBssParam->au8Interval, pu8IEs + u16P2P_count, 4);
+                               memcpy(pNewJoinBssParam->au8Interval, pu8IEs + u16P2P_count, 4);
                                u16P2P_count += 4;
 
-                               WILC_memcpy(pNewJoinBssParam->au8StartTime, pu8IEs + u16P2P_count, 4);
+                               memcpy(pNewJoinBssParam->au8StartTime, pu8IEs + u16P2P_count, 4);
 
                                index += pu8IEs[index + 1] + 2;
                                continue;
@@ -7698,7 +7583,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
                                rsnIndex += 7; /* skipping id, length, version(2B) and first 3 bytes of gcipher */
                                pNewJoinBssParam->rsn_grp_policy = pu8IEs[rsnIndex];
                                rsnIndex++;
-                               /* PRINT_D(HOSTINF_DBG,"Group Policy: %0x \n",pNewJoinBssParam->rsn_grp_policy); */
+                               /* PRINT_D(HOSTINF_DBG,"Group Policy: %0x\n",pNewJoinBssParam->rsn_grp_policy); */
                                /* initialize policies with invalid values */
 
                                jumpOffset = pu8IEs[rsnIndex] * 4; /* total no.of bytes of pcipher field (count*4) */
@@ -7709,7 +7594,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
                                pcipherCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex];
                                rsnIndex += 2; /* jump 2 bytes of pcipher count */
 
-                               /* PRINT_D(HOSTINF_DBG,"\npcipher:%d \n",pcipherCount); */
+                               /* PRINT_D(HOSTINF_DBG,"\npcipher:%d\n",pcipherCount); */
                                for (i = pcipherTotalCount, j = 0; i < pcipherCount + pcipherTotalCount && i < 3; i++, j++) {
                                        /* each count corresponds to 4 bytes, only last byte is saved */
                                        pNewJoinBssParam->rsn_pcip_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1];
@@ -7755,7 +7640,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
 void host_int_freeJoinParams(void *pJoinParams)
 {
        if ((tstrJoinBssParam *)pJoinParams != NULL)
-               WILC_FREE((tstrJoinBssParam *)pJoinParams);
+               kfree((tstrJoinBssParam *)pJoinParams);
        else
                PRINT_ER("Unable to FREE null pointer\n");
 }
@@ -7771,7 +7656,7 @@ void host_int_freeJoinParams(void *pJoinParams)
  *  @date
  *  @version           1.0**/
 
-static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID, short int BufferSize,
+static int host_int_addBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID, short int BufferSize,
                                 short int SessionTimeout, void *drvHandler)
 {
        s32 s32Error = WILC_SUCCESS;
@@ -7779,11 +7664,10 @@ static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char T
        tstrHostIFmsg strHostIFmsg;
        tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_BA_SESSION;
@@ -7794,10 +7678,9 @@ static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char T
        pBASessionInfo->u16SessionTimeout = SessionTimeout;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7807,18 +7690,17 @@ static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char T
 }
 
 
-s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
+s32 host_int_delBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
        tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BA_SESSION;
@@ -7827,10 +7709,9 @@ s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
        pBASessionInfo->u8Ted = TID;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7842,18 +7723,17 @@ s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
        return s32Error;
 }
 
-s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
+s32 host_int_del_All_Rx_BASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
        tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS;
@@ -7862,10 +7742,9 @@ s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char
        pBASessionInfo->u8Ted = TID;
        strHostIFmsg.drvHandler = hWFIDrv;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7885,7 +7764,7 @@ s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char
  *  @author            Abdelrahman Sobhy
  *  @date
  *  @version           1.0*/
-s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
+s32 host_int_setup_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *u16ipadd, u8 idx)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -7894,11 +7773,10 @@ s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
        /* TODO: Enable This feature on softap firmware */
        return 0;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_IPADDRESS;
@@ -7907,10 +7785,9 @@ s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
        strHostIFmsg.drvHandler = hWFIDrv;
        strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx = idx;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
@@ -7929,29 +7806,27 @@ s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
  *  @author            Abdelrahman Sobhy
  *  @date
  *  @version           1.0*/
-s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
+s32 host_int_get_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *u16ipadd, u8 idx)
 {
        s32 s32Error = WILC_SUCCESS;
        tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
        tstrHostIFmsg strHostIFmsg;
 
-       if (pstrWFIDrv == NULL) {
+       if (pstrWFIDrv == NULL)
                WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
-       }
 
-       WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+       memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
 
        /* prepare the WiphyParams Message */
        strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_IPADDRESS;
 
        strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.au8IPAddr = u16ipadd;
-       strHostIFmsg.drvHandler=hWFIDrv;
-       strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx= idx;
+       strHostIFmsg.drvHandler = hWFIDrv;
+       strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx = idx;
 
-       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
-       if (s32Error) {
+       s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+       if (s32Error)
                WILC_ERRORREPORT(s32Error, s32Error);
-       }
        WILC_CATCH(s32Error)
        {
 
index 38db740745cd2e9bb7445926cbbe63e22eba66f2..e66dee9af5da6b2529889f5505f0cb49b2814836 100644 (file)
@@ -11,7 +11,6 @@
 #define HOST_INT_H
 
 #include "coreconfigurator.h"
-#include "coreconfigsimulator.h"
 /*****************************************************************************/
 /*                                                             Macros                                       */
 /*****************************************************************************/
@@ -368,10 +367,10 @@ typedef struct {
        struct semaphore hSemGetCHNL;
        struct semaphore hSemInactiveTime;
 /* timer handlers */
-       WILC_TimerHandle hScanTimer;
-       WILC_TimerHandle hConnectTimer;
+       struct timer_list hScanTimer;
+       struct timer_list hConnectTimer;
        #ifdef WILC_P2P
-       WILC_TimerHandle hRemainOnChannel;
+       struct timer_list hRemainOnChannel;
        #endif
 
        bool IFC_UP;
@@ -433,7 +432,7 @@ typedef struct {
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress);
+s32 host_int_remove_key(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8StaAddress);
 /**
  *  @brief              removes WEP key
  *  @details    valid only in BSS STA mode if External Supplicant support is enabled.
@@ -448,7 +447,7 @@ s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
+s32 host_int_remove_wep_key(tstrWILC_WFIDrv *hWFIDrv, u8 u8Index);
 /**
  *  @brief              sets WEP deafault key
  *  @details    Sets the index of the WEP encryption key in use,
@@ -461,7 +460,7 @@ s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
+s32 host_int_set_WEPDefaultKeyID(tstrWILC_WFIDrv *hWFIDrv, u8 u8Index);
 
 /**
  *  @brief              sets WEP deafault key
@@ -482,7 +481,7 @@ s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx);
+s32 host_int_add_wep_key_bss_sta(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx);
 /**
  *  @brief              host_int_add_wep_key_bss_ap
  *  @details    valid only in AP mode if External Supplicant support is enabled.
@@ -497,7 +496,7 @@ s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
  *  @date              28 Feb 2013
  *  @version           1.0
  */
-s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type);
+s32 host_int_add_wep_key_bss_ap(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type);
 
 /**
  *  @brief              adds ptk Key
@@ -515,7 +514,7 @@ s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
+s32 host_int_add_ptk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
                             const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx);
 
 /**
@@ -530,7 +529,7 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen
  *  @date              15 April 2013
  *  @version           1.0
  */
-s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu32InactiveTime);
+s32 host_int_get_inactive_time(tstrWILC_WFIDrv *hWFIDrv, const u8 *mac, u32 *pu32InactiveTime);
 
 /**
  *  @brief              adds Rx GTk Key
@@ -548,7 +547,7 @@ s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
+s32 host_int_add_rx_gtk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
                                u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
                                const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode);
 
@@ -569,7 +568,7 @@ s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkK
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_add_tx_gtk(WILC_WFIDrvHandle hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx);
+s32 host_int_add_tx_gtk(tstrWILC_WFIDrv *hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx);
 
 /**
  *  @brief              caches the pmkid
@@ -592,7 +591,7 @@ s32 host_int_add_tx_gtk(WILC_WFIDrvHandle hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8
  *  @version           1.0
  */
 
-s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray);
+s32 host_int_set_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray);
 /**
  *  @brief              gets the cached the pmkid info
  *  @details    valid only in BSS STA mode if External Supplicant
@@ -616,7 +615,7 @@ s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8P
  *  @version           1.0
  */
 
-s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
+s32 host_int_get_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PmkidInfoArray,
                                    u32 u32PmkidInfoLen);
 
 /**
@@ -633,7 +632,7 @@ s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassPhrase,
+s32 host_int_set_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PassPhrase,
                                                 u8 u8Psklength);
 /**
  *  @brief              gets the pass phrase
@@ -649,7 +648,7 @@ s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassP
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv,
                                                 u8 *pu8PassPhrase, u8 u8Psklength);
 
 /**
@@ -663,7 +662,7 @@ s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
  *  @date              19 April 2012
  *  @version           1.0
  */
-s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
+s32 host_int_get_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress);
 
 /**
  *  @brief              sets mac address
@@ -676,7 +675,7 @@ s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
  *  @date              16 July 2012
  *  @version           1.0
  */
-s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
+s32 host_int_set_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress);
 
 /**
  *  @brief              wait until msg q is empty
@@ -721,7 +720,7 @@ s32 host_int_wait_msg_queue_idle(void);
  *  @version           1.0
  */
 #ifndef CONNECT_DIRECT
-s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_site_survey_results(tstrWILC_WFIDrv *hWFIDrv,
                                             u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
                                             u32 u32MaxSiteSrvyFragLen);
 #endif
@@ -742,7 +741,7 @@ s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
  *  @version           1.0
  */
 
-s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource);
+s32 host_int_set_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 scanSource);
 /**
  *  @brief              gets scan source of the last scan
  *  @details
@@ -758,7 +757,7 @@ s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource);
+s32 host_int_get_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ScanSource);
 
 /**
  *  @brief              sets a join request
@@ -772,7 +771,7 @@ s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource);
  *  @version           1.0
  */
 
-s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
+s32 host_int_set_join_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8bssid,
                                  const u8 *pu8ssid, size_t ssidLen,
                                  const u8 *pu8IEs, size_t IEsLen,
                                  tWILCpfConnectResult pfConnectResult, void *pvUserArg,
@@ -792,7 +791,7 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
  *  @version           8.0
  */
 
-s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv);
+s32 host_int_flush_join_req(tstrWILC_WFIDrv *hWFIDrv);
 
 
 /**
@@ -806,7 +805,7 @@ s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode);
+s32 host_int_disconnect(tstrWILC_WFIDrv *hWFIDrv, u16 u16ReasonCode);
 
 /**
  *  @brief              disconnects a sta
@@ -819,7 +818,7 @@ s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id);
+s32 host_int_disconnect_station(tstrWILC_WFIDrv *hWFIDrv, u8 assoc_id);
 /**
  *  @brief              gets a Association request info
  *  @details
@@ -846,7 +845,7 @@ s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id);
  *  @version           1.0
  */
 
-s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
+s32 host_int_get_assoc_req_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocReqInfo,
                                        u32 u32AssocReqInfoLen);
 /**
  *  @brief              gets a Association Response info
@@ -860,7 +859,7 @@ s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
  *  @version           1.0
  */
 
-s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
+s32 host_int_get_assoc_res_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocRespInfo,
                                        u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen);
 /**
  *  @brief              gets a Association Response info
@@ -877,7 +876,7 @@ s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
+s32 host_int_get_rx_power_level(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8RxPowerLevel,
                                        u32 u32RxPowerLevelLen);
 
 /**
@@ -895,7 +894,7 @@ s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum);
+s32 host_int_set_mac_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 u8ChNum);
 
 /**
  *  @brief              gets the current channel index
@@ -912,7 +911,7 @@ s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo);
+s32 host_int_get_host_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ChNo);
 /**
  *  @brief              gets the sta rssi
  *  @details    gets the currently maintained RSSI value for the station.
@@ -926,8 +925,8 @@ s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi);
-s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd);
+s32 host_int_get_rssi(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8Rssi);
+s32 host_int_get_link_speed(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8lnkspd);
 /**
  *  @brief              scans a set of channels
  *  @details
@@ -945,7 +944,7 @@ s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
+s32 host_int_scan(tstrWILC_WFIDrv *hWFIDrv, u8 u8ScanSource,
                          u8 u8ScanType, u8 *pu8ChnlFreqList,
                          u8 u8ChnlListLen, const u8 *pu8IEs,
                          size_t IEsLen, tWILCpfScanResult ScanResult,
@@ -961,7 +960,7 @@ s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal);
+s32 hif_set_cfg(tstrWILC_WFIDrv *hWFIDrv, tstrCfgParamVal *pstrCfgParamVal);
 
 /**
  *  @brief              gets configuration wids values
@@ -975,7 +974,7 @@ s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value);
+s32 hif_get_cfg(tstrWILC_WFIDrv *hWFIDrv, u16 u16WID, u16 *pu16WID_Value);
 /*****************************************************************************/
 /*                                                     Notification Functions                                                   */
 /*****************************************************************************/
@@ -1022,7 +1021,7 @@ void host_int_send_network_info_to_host
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv);
+s32 host_int_init(tstrWILC_WFIDrv **phWFIDrv);
 
 /**
  *  @brief              host interface initialization function
@@ -1033,7 +1032,7 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv);
  *  @date              8 March 2012
  *  @version           1.0
  */
-s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv);
+s32 host_int_deinit(tstrWILC_WFIDrv *hWFIDrv);
 
 
 /*!
@@ -1058,7 +1057,7 @@ s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv);
  *  @version           1.0 Description
  *
  */
-s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
+s32 host_int_add_beacon(tstrWILC_WFIDrv *hWFIDrv, u32 u32Interval,
                                u32 u32DTIMPeriod,
                                u32 u32HeadLen, u8 *pu8Head,
                                u32 u32TailLen, u8 *pu8tail);
@@ -1076,7 +1075,7 @@ s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
  *  @date              10 Julys 2012
  *  @version           1.0 Description
  */
-s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv);
+s32 host_int_del_beacon(tstrWILC_WFIDrv *hWFIDrv);
 
 /*!
  *  @fn                s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam strStaParams)
@@ -1091,7 +1090,7 @@ s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv);
  *  @date              12 July 2012
  *  @version           1.0 Description
  */
-s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
+s32 host_int_add_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
 
 /*!
  *  @fn                s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, const u8* pu8MacAddr)
@@ -1106,7 +1105,7 @@ s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrSt
  *  @date              09 April 2014
  *  @version           1.0 Description
  */
-s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]);
+s32 host_int_del_allstation(tstrWILC_WFIDrv *hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]);
 
 /*!
  *  @fn                s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, u8* pu8MacAddr)
@@ -1121,7 +1120,7 @@ s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]
  *  @date              15 July 2012
  *  @version           1.0 Description
  */
-s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr);
+s32 host_int_del_station(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8MacAddr);
 
 /*!
  *  @fn                s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam strStaParams)
@@ -1136,7 +1135,7 @@ s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr);
  *  @date              15 July 2012
  *  @version           1.0 Description
  */
-s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
+s32 host_int_edit_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
 
 /*!
  *  @fn                s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
@@ -1153,7 +1152,7 @@ s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrS
  *  @date              24 November 2012
  *  @version           1.0 Description
  */
-s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout);
+s32 host_int_set_power_mgmt(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32Timeout);
 /*  @param[in,out]     hWFIDrv         handle to the wifi driver
  *  @param[in] bIsEnabled      TRUE if enabled, FALSE otherwise
  *  @param[in] u8count         count of mac address entries in the filter table
@@ -1165,7 +1164,7 @@ s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32T
  *  @date              24 November 2012
  *  @version           1.0 Description
  */
-s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32count);
+s32 host_int_setup_multicast_filter(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32count);
 /**
  *  @brief           host_int_setup_ipaddress
  *  @details       set IP address on firmware
@@ -1175,7 +1174,7 @@ s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled,
  *  @date
  *  @version   1.0
  */
-s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
+s32 host_int_setup_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8IPAddr, u8 idx);
 
 
 /**
@@ -1187,7 +1186,7 @@ s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
  *  @date
  *  @version   1.0
  */
-s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
+s32 host_int_delBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID);
 
 /**
  *  @brief           host_int_delBASession
@@ -1198,7 +1197,7 @@ s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
  *  @date
  *  @version   1.0
  */
-s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
+s32 host_int_del_All_Rx_BASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID);
 
 
 /**
@@ -1210,7 +1209,7 @@ s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char
  *  @date
  *  @version   1.0
  */
-s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
+s32 host_int_get_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8IPAddr, u8 idx);
 
 #ifdef WILC_P2P
 /**
@@ -1222,7 +1221,7 @@ s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
  *  @date
  *  @version   1.0
  */
-s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg);
+s32 host_int_remain_on_channel(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg);
 
 /**
  *  @brief              host_int_ListenStateExpired
@@ -1238,7 +1237,7 @@ s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32
  *  @date
  *  @version           1.0
  */
-s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID);
+s32 host_int_ListenStateExpired(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID);
 
 /**
  *  @brief           host_int_frame_register
@@ -1249,7 +1248,7 @@ s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID);
  *  @date
  *  @version   1.0
  */
-s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bReg);
+s32 host_int_frame_register(tstrWILC_WFIDrv *hWFIDrv, u16 u16FrameType, bool bReg);
 #endif
 /**
  *  @brief           host_int_set_wfi_drv_handler
@@ -1260,18 +1259,18 @@ s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bR
  *  @date
  *  @version   1.0
  */
-s32 host_int_set_wfi_drv_handler(u32 u32address);
-s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode);
+s32 host_int_set_wfi_drv_handler(tstrWILC_WFIDrv *u32address);
+s32 host_int_set_operation_mode(tstrWILC_WFIDrv *hWFIDrv, u32 u32mode);
 
-static s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent);
+static s32 Handle_ScanDone(tstrWILC_WFIDrv *drvHandler, tenuScanEvent enuEvent);
 
-static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID, short int BufferSize,
+static int host_int_addBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID, short int BufferSize,
                                 short int SessionTimeout, void *drvHandler);
 
 
 void host_int_freeJoinParams(void *pJoinParams);
 
-s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics);
+s32 host_int_get_statistics(tstrWILC_WFIDrv *hWFIDrv, tstrStatistics *pstrStatistics);
 
 /*****************************************************************************/
 /*                                                                                                                                                      */
index f5296f53a3d24186e235db3972b6eac75c3a6cdc..123468a9582fc0019ed7ab1ed77c6f104100f68f 100644 (file)
@@ -6,20 +6,15 @@
  *  @date      01 MAR 2012
  *  @version   1.0
  */
-
-#ifndef SIMULATION
 #include "wilc_wfi_cfgoperations.h"
 #include "linux_wlan_common.h"
 #include "wilc_wlan_if.h"
 #include "wilc_wlan.h"
-#endif
+
 #ifdef WILC_FULLY_HOSTING_AP
 #include "wilc_host_ap.h"
 #endif
 #ifdef WILC_AP_EXTERNAL_MLME
-#ifdef SIMULATION
-#include "wilc_wfi_cfgoperations.h"
-#endif
 
 struct wilc_wfi_radiotap_hdr {
        struct ieee80211_radiotap_header hdr;
@@ -39,9 +34,7 @@ extern linux_wlan_t *g_linux_wlan;
 
 static struct net_device *wilc_wfi_mon; /* global monitor netdev */
 
-#ifdef SIMULATION
-extern int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev);
-#elif USE_WIRELESS
+#if USE_WIRELESS
 extern int  mac_xmit(struct sk_buff *skb, struct net_device *dev);
 #endif
 
@@ -237,14 +230,12 @@ static void mgmt_tx_complete(void *priv, int status)
 }
 static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
 {
-       linux_wlan_t *nic;
        struct tx_complete_mon_data *mgmt_tx = NULL;
 
        if (dev == NULL) {
                PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n");
                return WILC_FAIL;
        }
-       nic = netdev_priv(dev);
 
        netif_stop_queue(dev);
        mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC);
@@ -298,7 +289,6 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
 static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
                                     struct net_device *dev)
 {
-       struct ieee80211_radiotap_header *rtap_hdr;
        u32 rtap_len, i, ret = 0;
        struct WILC_WFI_mon_priv  *mon_priv;
 
@@ -318,7 +308,6 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
                return WILC_FAIL;
        }
 
-       rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
 
        rtap_len = ieee80211_get_radiotap_len(skb->data);
        if (skb->len < rtap_len) {
@@ -378,9 +367,7 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
        PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name);
        PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name);
 
-       #ifdef SIMULATION
-       ret = WILC_WFI_Tx(skb, mon_priv->real_ndev);
-       #elif USE_WIRELESS
+       #if USE_WIRELESS
        /* Identify if Ethernet or MAC header (data or mgmt) */
        memcpy(srcAdd, &skb->data[10], 6);
        memcpy(bssid, &skb->data[16], 6);
@@ -495,7 +482,7 @@ static void WILC_WFI_mon_setup(struct net_device *dev)
        ether_setup(dev);
        dev->tx_queue_len = 0;
        dev->type = ARPHRD_IEEE80211_RADIOTAP;
-       memset(dev->dev_addr, 0, ETH_ALEN);
+       eth_zero_addr(dev->dev_addr);
 
        #ifdef USE_WIRELESS
        {
@@ -571,7 +558,7 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi
  *  @date      12 JUL 2012
  *  @version   1.0
  */
-int WILC_WFI_deinit_mon_interface()
+int WILC_WFI_deinit_mon_interface(void)
 {
        bool rollback_lock = false;
 
index b352c504a77d273d23712addeaca6ae79013451a..b3cc9f5c7937c2834999dc172749c34ecc404ed1 100644 (file)
@@ -1,4 +1,3 @@
-#ifndef SIMULATION
 #include "wilc_wfi_cfgoperations.h"
 #include "linux_wlan_common.h"
 #include "wilc_wlan_if.h"
@@ -72,7 +71,7 @@ extern void resolve_disconnect_aberration(void *drvHandler);
 extern u8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
 void wilc1000_wlan_deinit(linux_wlan_t *nic);
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-extern WILC_TimerHandle hDuringIpTimer;
+extern struct timer_list hDuringIpTimer;
 #endif
 
 static int linux_wlan_device_power(int on_off)
@@ -103,7 +102,6 @@ static int linux_wlan_device_detection(int on_off)
        return 0;
 }
 
-
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr);
 
@@ -116,7 +114,6 @@ static struct notifier_block g_dev_notifier = {
                if (g_linux_wlan->oup.wlan_cleanup != NULL) \
                        g_linux_wlan->oup.wlan_cleanup(); }
 
-
 #ifndef STA_FIRMWARE
 #define STA_FIRMWARE   "wifi_firmware.bin"
 #endif
@@ -129,15 +126,12 @@ static struct notifier_block g_dev_notifier = {
 #define P2P_CONCURRENCY_FIRMWARE       "wifi_firmware_p2p_concurrency.bin"
 #endif
 
-
-
 typedef struct android_wifi_priv_cmd {
        char *buf;
        int used_len;
        int total_len;
 } android_wifi_priv_cmd;
 
-
 #define IRQ_WAIT       1
 #define IRQ_NO_WAIT    0
 /*
@@ -158,7 +152,6 @@ void linux_wlan_unlock(void *vp);
 extern void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size);
 extern void WILC_WFI_p2p_rx(struct net_device *dev, uint8_t *buff, uint32_t size);
 
-
 static void *internal_alloc(uint32_t size, uint32_t flag);
 static void linux_wlan_tx_complete(void *priv, int status);
 void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset);
@@ -170,8 +163,6 @@ static struct net_device_stats *mac_stats(struct net_device *dev);
 static int  mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd);
 static void wilc_set_multicast_list(struct net_device *dev);
 
-
-
 /*
  * for now - in frmw_to_linux there should be private data to be passed to it
  * and this data should be pointer to net device
@@ -200,22 +191,18 @@ volatile int WatchDogdebuggerCounter;
 char DebugBuffer[DEGUG_BUFFER_LENGTH + 20] = {0};
 static char *ps8current = DebugBuffer;
 
-
-
 void printk_later(const char *format, ...)
 {
        va_list args;
-       va_start (args, format);
-       ps8current += vsprintf (ps8current, format, args);
-       va_end (args);
-       if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH) {
+       va_start(args, format);
+       ps8current += vsprintf(ps8current, format, args);
+       va_end(args);
+       if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH)
                ps8current = DebugBuffer;
-       }
 
 }
 
-
-void dump_logs()
+void dump_logs(void)
 {
        if (DebugBuffer[0]) {
                DebugBuffer[DEGUG_BUFFER_LENGTH] = 0;
@@ -229,7 +216,7 @@ void dump_logs()
        }
 }
 
-void Reset_WatchDogdebugger()
+void Reset_WatchDogdebugger(void)
 {
        WatchDogdebuggerCounter = 0;
 }
@@ -246,11 +233,8 @@ static int DebuggingThreadTask(void *vp)
                WatchDogdebuggerCounter = 0;
        }
 }
-
-
 #endif
 
-
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr)
 {
@@ -298,25 +282,22 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event
 
                PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n");
 
-
                /*If we are in station mode or client mode*/
                if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
                        pstrWFIDrv->IFC_UP = 1;
                        g_obtainingIP = false;
-                       WILC_TimerStop(&hDuringIpTimer, NULL);
+                       del_timer(&hDuringIpTimer);
                        PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
                }
 
-
-
                if (bEnablePS)
-                       host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 1, 0);
+                       host_int_set_power_mgmt(pstrWFIDrv, 1, 0);
 
                PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
 
                pIP_Add_buff = (char *) (&(dev_iface->ifa_address));
-               PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
-               host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+               PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
+               host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
 
                break;
 
@@ -330,17 +311,16 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event
                }
 
                if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
-                       host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+                       host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
 
                resolve_disconnect_aberration(pstrWFIDrv);
 
-
                PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label);
 
                pIP_Add_buff = null_ip;
-               PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
+               PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
 
-               host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+               host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
 
                break;
 
@@ -387,8 +367,6 @@ void linux_wlan_disable_irq(int wait)
 #if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
 static irqreturn_t isr_uh_routine(int irq, void *user_data)
 {
-
-
        int_rcvdU++;
 #if (RX_BH_TYPE != RX_BH_THREADED_IRQ)
        linux_wlan_disable_irq(IRQ_NO_WAIT);
@@ -440,19 +418,14 @@ static void isr_bh_routine(struct work_struct *work)
        #else
                return;
        #endif
-
-
-
        }
 
        int_rcvdB++;
        PRINT_D(INT_DBG, "Interrupt received BH\n");
-       if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) {
+       if (g_linux_wlan->oup.wlan_handle_rx_isr != 0)
                g_linux_wlan->oup.wlan_handle_rx_isr();
-       } else {
+       else
                PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n");
-       }
-
 
 #if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
        return IRQ_HANDLED;
@@ -476,18 +449,16 @@ static int isr_bh_routine(void *vp)
                }
                int_rcvdB++;
                PRINT_D(INT_DBG, "Interrupt received BH\n");
-               if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) {
+               if (g_linux_wlan->oup.wlan_handle_rx_isr != 0)
                        g_linux_wlan->oup.wlan_handle_rx_isr();
-               } else {
+               else
                        PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n");
-               }
        }
 
        return 0;
 }
 #endif
 
-
 #if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
 static int init_irq(linux_wlan_t *p_nic)
 {
@@ -504,9 +475,9 @@ static int init_irq(linux_wlan_t *p_nic)
  *
  * ex) nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
  */
-#elif defined (NM73131_0_BOARD)
+#elif defined(NM73131_0_BOARD)
                nic->dev_irq_num = IRQ_WILC1000;
-#elif defined (PANDA_BOARD)
+#elif defined(PANDA_BOARD)
                gpio_export(GPIO_NUM, 1);
                nic->dev_irq_num = OMAP_GPIO_IRQ(GPIO_NUM);
                irq_set_irq_type(nic->dev_irq_num, IRQ_TYPE_LEVEL_LOW);
@@ -518,7 +489,6 @@ static int init_irq(linux_wlan_t *p_nic)
                PRINT_ER("could not obtain gpio for WILC_INTR\n");
        }
 
-
 #if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
        if ((ret != -1) && (request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine,
                                                  IRQF_TRIGGER_LOW | IRQF_ONESHOT,               /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/
@@ -554,7 +524,6 @@ static void deinit_irq(linux_wlan_t *nic)
 #endif
 }
 
-
 /*
  *      OS functions
  */
@@ -601,7 +570,6 @@ void linux_wlan_free(void *vp)
        }
 }
 
-
 static void *internal_alloc(uint32_t size, uint32_t flag)
 {
        char *pntr = NULL;
@@ -610,7 +578,6 @@ static void *internal_alloc(uint32_t size, uint32_t flag)
        return (void *)pntr;
 }
 
-
 static void linux_wlan_init_lock(char *lockName, void *plock, int count)
 {
        sema_init((struct semaphore *)plock, count);
@@ -638,25 +605,22 @@ static int linux_wlan_lock_timeout(void *vp, u32 timeout)
 {
        int error = -1;
        PRINT_D(LOCK_DBG, "Locking %p\n", vp);
-       if (vp != NULL) {
+       if (vp != NULL)
                error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout));
-       } else {
+       else
                PRINT_ER("Failed, mutex is NULL\n");
-       }
        return error;
 }
 
 void linux_wlan_unlock(void *vp)
 {
        PRINT_D(LOCK_DBG, "Unlocking %p\n", vp);
-       if (vp != NULL) {
+       if (vp != NULL)
                up((struct semaphore *)vp);
-       } else {
+       else
                PRINT_ER("Failed, mutex is NULL\n");
-       }
 }
 
-
 static void linux_wlan_init_mutex(char *lockName, void *plock, int count)
 {
        mutex_init((struct mutex *)plock);
@@ -702,7 +666,6 @@ static void linux_wlan_unlock_mutex(void *vp)
        }
 }
 
-
 /*Added by Amr - BugID_4720*/
 static void linux_wlan_init_spin_lock(char *lockName, void *plock, int count)
 {
@@ -780,9 +743,8 @@ struct net_device *GetIfHandler(uint8_t *pMacHeader)
                }
        }
        PRINT_INFO(INIT_DBG, "Invalide handle\n");
-       for (i = 0; i < 25; i++) {
+       for (i = 0; i < 25; i++)
                PRINT_D(INIT_DBG, "%02x ", pMacHeader[i]);
-       }
        Bssid  = pMacHeader + 18;
        Bssid1 = pMacHeader + 12;
        for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
@@ -822,9 +784,8 @@ int linux_wlan_get_num_conn_ifcs(void)
        uint8_t ret_val = 0;
 
        for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
-               if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6)) {
+               if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6))
                        ret_val++;
-               }
        }
        return ret_val;
 }
@@ -868,7 +829,6 @@ static int linux_wlan_txq_task(void *vp)
 #define TX_BACKOFF_WEIGHT_MIN (0)
 #define TX_BACKOFF_WEIGHT_UNIT_MS (10)
        int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
-       signed long timeout;
 #endif
 
        /* inform wilc1000_wlan_init that TXQ task is started. */
@@ -906,7 +866,6 @@ static int linux_wlan_txq_task(void *vp)
                        }
 
                        if (ret == WILC_TX_ERR_NO_BUF) { /* failed to allocate buffers in chip. */
-                               timeout = msecs_to_jiffies(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
                                do {
                                        /* Back off from sending packets for some time. */
                                        /* schedule_timeout will allow RX task to run and free buffers.*/
@@ -915,15 +874,13 @@ static int linux_wlan_txq_task(void *vp)
                                        msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
                                } while (/*timeout*/ 0);
                                backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
-                               if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) {
+                               if (backoff_weight > TX_BACKOFF_WEIGHT_MAX)
                                        backoff_weight = TX_BACKOFF_WEIGHT_MAX;
-                               }
                        } else {
                                if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) {
                                        backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP;
-                                       if (backoff_weight < TX_BACKOFF_WEIGHT_MIN) {
+                                       if (backoff_weight < TX_BACKOFF_WEIGHT_MIN)
                                                backoff_weight = TX_BACKOFF_WEIGHT_MIN;
-                                       }
                                }
                        }
                        /*TODO: drop packets after a certain time/number of retry count. */
@@ -946,7 +903,6 @@ int linux_wlan_get_firmware(perInterface_wlan_t *p_nic)
        const struct firmware *wilc_firmware;
        char *firmware;
 
-
        if (nic->iftype == AP_MODE)
                firmware = AP_FIRMWARE;
        else if (nic->iftype == STATION_MODE)
@@ -958,8 +914,6 @@ int linux_wlan_get_firmware(perInterface_wlan_t *p_nic)
                firmware = P2P_CONCURRENCY_FIRMWARE;
        }
 
-
-
        if (nic == NULL) {
                PRINT_ER("NIC is NULL\n");
                goto _fail_;
@@ -970,7 +924,6 @@ int linux_wlan_get_firmware(perInterface_wlan_t *p_nic)
                goto _fail_;
        }
 
-
        /*      the firmare should be located in /lib/firmware in
         *      root file system with the name specified above */
 
@@ -1054,9 +1007,8 @@ static int linux_wlan_firmware_download(linux_wlan_t *p_nic)
         **/
        PRINT_D(INIT_DBG, "Downloading Firmware ...\n");
        ret = g_linux_wlan->oup.wlan_firmware_download(g_linux_wlan->wilc_firmware->data, g_linux_wlan->wilc_firmware->size);
-       if (ret < 0) {
+       if (ret < 0)
                goto _FAIL_;
-       }
 
        /* Freeing FW buffer */
        PRINT_D(INIT_DBG, "Freeing FW buffer ...\n");
@@ -1064,13 +1016,12 @@ static int linux_wlan_firmware_download(linux_wlan_t *p_nic)
        release_firmware(g_linux_wlan->wilc_firmware);
        g_linux_wlan->wilc_firmware = NULL;
 
-       PRINT_D(INIT_DBG, "Download Succeeded \n");
+       PRINT_D(INIT_DBG, "Download Succeeded\n");
 
 _FAIL_:
        return ret;
 }
 
-
 /* startup configuration - could be changed later using iconfig*/
 static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_nic)
 {
@@ -1096,7 +1047,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_n
        PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]);
        wilc_get_chipid(0);
 
-
        if (g_linux_wlan->oup.wlan_cfg_set == NULL) {
                PRINT_D(INIT_DBG, "Null p[ointer\n");
                goto _fail_;
@@ -1116,7 +1066,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_n
        if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0))
                goto _fail_;
 
-
        /* c_val[0] = RATE_AUTO; / * bug 4275: Enable autorate and limit it to 24Mbps * / */
        c_val[0] = RATE_AUTO;
        if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
@@ -1351,7 +1300,6 @@ _fail_:
        return -1;
 }
 
-
 /**************************/
 void wilc1000_wlan_deinit(linux_wlan_t *nic)
 {
@@ -1385,16 +1333,12 @@ void wilc1000_wlan_deinit(linux_wlan_t *nic)
                  #endif
                #endif
 
-
                /* not sure if the following unlocks are needed or not*/
-               if (&g_linux_wlan->rxq_event != NULL) {
+               if (&g_linux_wlan->rxq_event != NULL)
                        linux_wlan_unlock(&g_linux_wlan->rxq_event);
-               }
 
-               if (&g_linux_wlan->txq_event != NULL) {
+               if (&g_linux_wlan->txq_event != NULL)
                        linux_wlan_unlock(&g_linux_wlan->txq_event);
-               }
-
 
        #if (RX_BH_TYPE == RX_BH_WORK_QUEUE)
                /*Removing the work struct from the linux kernel workqueue*/
@@ -1412,7 +1356,6 @@ void wilc1000_wlan_deinit(linux_wlan_t *nic)
                PRINT_D(INIT_DBG, "Deinitializing IRQ\n");
                deinit_irq(g_linux_wlan);
 
-
                if (&g_linux_wlan->oup != NULL) {
                        if (g_linux_wlan->oup.wlan_stop != NULL)
                                g_linux_wlan->oup.wlan_stop();
@@ -1442,7 +1385,6 @@ void wilc1000_wlan_deinit(linux_wlan_t *nic)
        } else {
                PRINT_D(INIT_DBG, "wilc1000 is not initialized\n");
        }
-       return;
 }
 
 int wlan_init_locks(linux_wlan_t *p_nic)
@@ -1536,7 +1478,7 @@ void linux_to_wlan(wilc_wlan_inp_t *nwi, linux_wlan_t *nic)
 
        nwi->os_context.txq_wait_event = (void *)&g_linux_wlan->txq_event;
 
-#if defined (MEMORY_STATIC)
+#if defined(MEMORY_STATIC)
        nwi->os_context.rx_buffer_size = LINUX_RX_SIZE;
 #endif
        nwi->os_context.rxq_critical_section = (void *)&g_linux_wlan->rxq_cs;
@@ -1673,17 +1615,14 @@ static void wlan_deinitialize_threads(linux_wlan_t *nic)
        if (&g_linux_wlan->rxq_event != NULL)
                linux_wlan_unlock(&g_linux_wlan->rxq_event);
 
-
        if (g_linux_wlan->rxq_thread != NULL) {
                kthread_stop(g_linux_wlan->rxq_thread);
                g_linux_wlan->rxq_thread = NULL;
        }
 
-
        if (&g_linux_wlan->txq_event != NULL)
                linux_wlan_unlock(&g_linux_wlan->txq_event);
 
-
        if (g_linux_wlan->txq_thread != NULL) {
                kthread_stop(g_linux_wlan->txq_thread);
                g_linux_wlan->txq_thread = NULL;
@@ -1747,14 +1686,12 @@ static int linux_wlan_read_mac_addr(void *vp)
                }
        }
 
-       if (index == array_size) {
+       if (index == array_size)
                PRINT_ER("random MAC\n");
-       }
 
 exit:
-       if (fp && !IS_ERR(fp)) {
+       if (fp && !IS_ERR(fp))
                filp_close(fp, NULL);
-       }
 
        set_fs(old_fs);
 
@@ -1786,9 +1723,8 @@ uint8_t wilc1000_prepare_11b_core(wilc_wlan_inp_t *nwi,   wilc_wlan_oup_t *nwo, li
 
                sdio_register_driver(&wilc_bus);
 
-               while (!probe) {
+               while (!probe)
                        msleep(100);
-               }
                probe = 0;
                g_linux_wlan->wilc_sdio_func = local_sdio_func;
                linux_to_wlan(nwi, nic);
@@ -1820,9 +1756,8 @@ int repeat_power_cycle(perInterface_wlan_t *nic)
        sdio_register_driver(&wilc_bus);
 
        /* msleep(1000); */
-       while (!probe) {
+       while (!probe)
                msleep(100);
-       }
        probe = 0;
        g_linux_wlan->wilc_sdio_func = local_sdio_func;
        linux_to_wlan(&nwi, g_linux_wlan);
@@ -1834,7 +1769,7 @@ int repeat_power_cycle(perInterface_wlan_t *nic)
        #endif
 
        if (linux_wlan_get_firmware(nic)) {
-               PRINT_ER("Can't get firmware \n");
+               PRINT_ER("Can't get firmware\n");
                ret = -1;
                goto __fail__;
        }
@@ -1847,9 +1782,8 @@ int repeat_power_cycle(perInterface_wlan_t *nic)
        }
        /* Start firmware*/
        ret = linux_wlan_start_firmware(nic);
-       if (ret < 0) {
+       if (ret < 0)
                PRINT_ER("Failed to start firmware\n");
-       }
 __fail__:
        return ret;
 }
@@ -1871,9 +1805,8 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
 
 #ifdef STATIC_MACADDRESS
                wilc_mac_thread = kthread_run(linux_wlan_read_mac_addr, NULL, "wilc_mac_thread");
-               if (wilc_mac_thread < 0) {
+               if (wilc_mac_thread < 0)
                        PRINT_ER("couldn't create Mac addr thread\n");
-               }
 #endif
 
                linux_to_wlan(&nwi, g_linux_wlan);
@@ -1889,7 +1822,6 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
                /*Save the oup structre into global pointer*/
                gpstrWlanOps = &g_linux_wlan->oup;
 
-
                ret = wlan_initialize_threads(nic);
                if (ret < 0) {
                        PRINT_ER("Initializing Threads FAILED\n");
@@ -1922,12 +1854,11 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
 #endif
 
                if (linux_wlan_get_firmware(nic)) {
-                       PRINT_ER("Can't get firmware \n");
+                       PRINT_ER("Can't get firmware\n");
                        ret = -EIO;
                        goto _fail_irq_enable_;
                }
 
-
                /*Download firmware*/
                ret = linux_wlan_firmware_download(g_linux_wlan);
                if (ret < 0) {
@@ -1967,7 +1898,6 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic)
                g_linux_wlan->wilc1000_initialized = 1;
                return 0; /*success*/
 
-
 _fail_fw_start_:
                if (&g_linux_wlan->oup != NULL) {
                        if (g_linux_wlan->oup.wlan_stop != NULL)
@@ -1996,12 +1926,11 @@ _fail_locks_:
        return ret;
 }
 
-
 /*
  *      - this function will be called automatically by OS when module inserted.
  */
 
-#if !defined (NM73131_0_BOARD)
+#if !defined(NM73131_0_BOARD)
 int mac_init_fn(struct net_device *ndev)
 {
 
@@ -2028,12 +1957,11 @@ int mac_init_fn(struct net_device *ndev)
 }
 #endif
 
-
 void    WILC_WFI_frame_register(struct wiphy *wiphy, struct net_device *dev,
                                u16 frame_type, bool reg);
 
 /* This fn is called, when this device is setup using ifconfig */
-#if !defined (NM73131_0_BOARD)
+#if !defined(NM73131_0_BOARD)
 int mac_open(struct net_device *ndev)
 {
        perInterface_wlan_t *nic;
@@ -2078,7 +2006,7 @@ int mac_open(struct net_device *ndev)
        for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
                if (ndev == g_linux_wlan->strInterfaceInfo[i].wilc_netdev) {
                        memcpy(g_linux_wlan->strInterfaceInfo[i].aSrcAddress, mac_add, ETH_ALEN);
-                       g_linux_wlan->strInterfaceInfo[i].drvHandler = (u32)priv->hWILCWFIDrv;
+                       g_linux_wlan->strInterfaceInfo[i].drvHandler = priv->hWILCWFIDrv;
                        break;
                }
        }
@@ -2092,7 +2020,6 @@ int mac_open(struct net_device *ndev)
                goto _err_;
        }
 
-
        WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev,
                                nic->g_struct_frame_reg[0].frame_type, nic->g_struct_frame_reg[0].reg);
        WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev,
@@ -2131,7 +2058,6 @@ struct net_device_stats *mac_stats(struct net_device *dev)
 {
        perInterface_wlan_t *nic = netdev_priv(dev);
 
-
        return &nic->netstats;
 }
 
@@ -2146,17 +2072,16 @@ static void wilc_set_multicast_list(struct net_device *dev)
        priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
        pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
 
-
        if (!dev)
                return;
 
-       PRINT_D(INIT_DBG, "Setting Multicast List with count = %d. \n", dev->mc.count);
+       PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", dev->mc.count);
 
        if (dev->flags & IFF_PROMISC) {
                /* Normally, we should configure the chip to retrive all packets
                 * but we don't wanna support this right now */
                /* TODO: add promiscuous mode support */
-               PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets \n");
+               PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n");
                return;
        }
 
@@ -2165,27 +2090,27 @@ static void wilc_set_multicast_list(struct net_device *dev)
        if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
                PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n");
                /* get all multicast packets */
-               host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, false, 0);
+               host_int_setup_multicast_filter(pstrWFIDrv, false, 0);
                return;
        }
 
        /* No multicast?  Just get our own stuff */
        if ((dev->mc.count) == 0) {
                PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n");
-               host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, true, 0);
+               host_int_setup_multicast_filter(pstrWFIDrv, true, 0);
                return;
        }
 
        /* Store all of the multicast addresses in the hardware filter */
        netdev_for_each_mc_addr(ha, dev)
        {
-               WILC_memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN);
+               memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN);
                PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
                        gau8MulticastMacAddrList[i][0], gau8MulticastMacAddrList[i][1], gau8MulticastMacAddrList[i][2], gau8MulticastMacAddrList[i][3], gau8MulticastMacAddrList[i][4], gau8MulticastMacAddrList[i][5]);
                i++;
        }
 
-       host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, true, (dev->mc.count));
+       host_int_setup_multicast_filter(pstrWFIDrv, true, (dev->mc.count));
 
        return;
 
@@ -2195,11 +2120,10 @@ static void linux_wlan_tx_complete(void *priv, int status)
 {
 
        struct tx_complete_data *pv_data = (struct tx_complete_data *)priv;
-       if (status == 1) {
+       if (status == 1)
                PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
-       } else {
+       else
                PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
-       }
        /* Free the SK Buffer, its work is done */
        dev_kfree_skb(pv_data->skb);
        linux_wlan_free(pv_data);
@@ -2215,7 +2139,7 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
        struct ethhdr *eth_h;
        nic = netdev_priv(ndev);
 
-       PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d \n========\n", int_rcvdU, int_rcvdB, int_clrd);
+       PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d\n========\n", int_rcvdU, int_rcvdB, int_clrd);
        PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n");
 
        /* Stop the network interface queue */
@@ -2237,18 +2161,16 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
        tx_data->skb  = skb;
 
        eth_h = (struct ethhdr *)(skb->data);
-       if (eth_h->h_proto == 0x8e88) {
+       if (eth_h->h_proto == 0x8e88)
                PRINT_D(INIT_DBG, "EAPOL transmitted\n");
-       }
 
        /*get source and dest ip addresses*/
        ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
 
        pu8UdpBuffer = (char *)ih + sizeof(struct iphdr);
-       if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68)) {
+       if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68))
                PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", pu8UdpBuffer[248], pu8UdpBuffer[249], pu8UdpBuffer[250]);
 
-       }
        PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb);
 
        /* Send packet to MAC HW - for now the tx_complete function will be just status
@@ -2269,7 +2191,6 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
        QueueCount = WILC_Xmit_data((void *)tx_data, HOST_TO_WLAN);
        #endif /* WILC_FULLY_HOSTING_AP */
 
-
        if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) {
                netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev);
                netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev);
@@ -2278,7 +2199,6 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev)
        return 0;
 }
 
-
 int mac_close(struct net_device *ndev)
 {
        struct WILC_WFI_priv *priv;
@@ -2301,8 +2221,6 @@ int mac_close(struct net_device *ndev)
 
        pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
 
-
-
        PRINT_D(GENERIC_DBG, "Mac close\n");
 
        if (g_linux_wlan == NULL) {
@@ -2348,7 +2266,6 @@ int mac_close(struct net_device *ndev)
        return 0;
 }
 
-
 int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
 {
 
@@ -2359,8 +2276,6 @@ int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
        struct WILC_WFI_priv *priv;
        s32 s32Error = WILC_SUCCESS;
 
-
-
        /* struct iwreq *wrq = (struct iwreq *) req;    // tony moved to case SIOCSIWPRIV */
        #ifdef USE_WIRELESS
        nic = netdev_priv(ndev);
@@ -2422,9 +2337,7 @@ int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
 
 done:
 
-       if (buff != NULL) {
-               kfree(buff);
-       }
+       kfree(buff);
 
        return s32Error;
 }
@@ -2455,7 +2368,6 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset)
                frame_len = size;
                buff_to_send = buff;
 
-
                /* Need to send the packet up to the host, allocate a skb buffer */
                skb = dev_alloc_skb(frame_len);
                if (skb == NULL) {
@@ -2465,14 +2377,12 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset)
 
                skb_reserve(skb, (unsigned int)skb->data & 0x3);
 
-               if (g_linux_wlan == NULL || wilc_netdev == NULL) {
+               if (g_linux_wlan == NULL || wilc_netdev == NULL)
                        PRINT_ER("wilc_netdev in g_linux_wlan is NULL");
-               }
                skb->dev = wilc_netdev;
 
-               if (skb->dev == NULL) {
+               if (skb->dev == NULL)
                        PRINT_ER("skb->dev is NULL\n");
-               }
 
                /*
                 * for(i=0;i<40;i++)
@@ -2502,9 +2412,8 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset)
                ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
 
                pu8UdpBuffer = (char *)ih + sizeof(struct iphdr);
-               if (buff_to_send[35] == 67 && buff_to_send[37] == 68) {
+               if (buff_to_send[35] == 67 && buff_to_send[37] == 68)
                        PRINT_D(RX_DBG, "DHCP Message received\n");
-               }
                if (buff_to_send[12] == 0x88 && buff_to_send[13] == 0x8e)
                        PRINT_D(GENERIC_DBG, "eapol received\n");
                        #endif
@@ -2516,9 +2425,8 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset)
                PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats);
        }
                #ifndef TCP_ENHANCEMENTS
-       else {
+       else
                PRINT_ER("Discard sending packet with len = %d\n", size);
-       }
                #endif
 }
 
@@ -2541,9 +2449,8 @@ void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size)
        #ifdef WILC_P2P
        nic = netdev_priv(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); /* p2p0 */
        if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) ||
-           (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg)) {
+           (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg))
                WILC_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[1].wilc_netdev, buff, size);
-       }
        #endif
 }
 
@@ -2557,7 +2464,7 @@ int wilc_netdev_init(void)
        linux_wlan_init_lock("close_exit_sync", &close_exit_sync, 0);
 
        /*create the common structure*/
-       g_linux_wlan = (linux_wlan_t *)WILC_MALLOC(sizeof(linux_wlan_t));
+       g_linux_wlan = WILC_MALLOC(sizeof(linux_wlan_t));
        memset(g_linux_wlan, 0, sizeof(linux_wlan_t));
 
        /*Reset interrupt count debug*/
@@ -2625,7 +2532,6 @@ int wilc_netdev_init(void)
                }
                #endif
 
-
                if (register_netdev(ndev)) {
                        PRINT_ER("Device couldn't be registered - %s\n", ndev->name);
                        return -1; /* ERROR */
@@ -2638,7 +2544,7 @@ int wilc_netdev_init(void)
 
        #ifndef WILC_SDIO
        if (!linux_spi_init(&g_linux_wlan->wilc_spidev)) {
-               PRINT_ER("Can't initialize SPI \n");
+               PRINT_ER("Can't initialize SPI\n");
                return -1; /* ERROR */
        }
        g_linux_wlan->wilc_spidev = wilc_spi_dev;
@@ -2649,13 +2555,10 @@ int wilc_netdev_init(void)
        return 0;
 }
 
-
 /*The 1st function called after module inserted*/
 static int __init init_wilc_driver(void)
 {
-
-
-#if defined (WILC_DEBUGFS)
+#if defined(WILC_DEBUGFS)
        if (wilc_debugfs_init() < 0) {
                PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n");
                return -1;
@@ -2674,17 +2577,15 @@ static int __init init_wilc_driver(void)
                int ret;
 
                ret = sdio_register_driver(&wilc_bus);
-               if (ret < 0) {
+               if (ret < 0)
                        PRINT_D(INIT_DBG, "init_wilc_driver: Failed register sdio driver\n");
-               }
 
                return ret;
        }
 #else
        PRINT_D(INIT_DBG, "Initializing netdev\n");
-       if (wilc_netdev_init()) {
+       if (wilc_netdev_init())
                PRINT_ER("Couldn't initialize netdev\n");
-       }
        return 0;
 #endif
 }
@@ -2702,18 +2603,15 @@ static void __exit exit_wilc_driver(void)
                unregister_inetaddr_notifier(&g_dev_notifier);
        #endif
 
-               for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
+               for (i = 0; i < NUM_CONCURRENT_IFC; i++)
                        nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
-               }
        }
 
-
        if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) {
                release_firmware(g_linux_wlan->wilc_firmware);
                g_linux_wlan->wilc_firmware = NULL;
        }
 
-
        if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL)
                                       || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) {
                PRINT_D(INIT_DBG, "Waiting for mac_close ....\n");
@@ -2723,17 +2621,15 @@ static void __exit exit_wilc_driver(void)
                else
                        PRINT_D(INIT_DBG, "mac_closed\n");
 
-
                for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
                        /* close all opened interfaces */
                        if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) {
-                               if (nic[i]->mac_opened) {
+                               if (nic[i]->mac_opened)
                                        mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
-                               }
                        }
                }
                for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
-                       PRINT_D(INIT_DBG, "Unregistering netdev %p \n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
+                       PRINT_D(INIT_DBG, "Unregistering netdev %p\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
                        unregister_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
                        #ifdef USE_WIRELESS
                        PRINT_D(INIT_DBG, "Freeing Wiphy...\n");
@@ -2744,7 +2640,6 @@ static void __exit exit_wilc_driver(void)
                }
        }
 
-
 #ifdef USE_WIRELESS
 #ifdef WILC_AP_EXTERNAL_MLME
        /* Bug 4600 : WILC_WFI_deinit_mon_interface was already called at mac_close */
@@ -2764,12 +2659,12 @@ static void __exit exit_wilc_driver(void)
 
                linux_wlan_deinit_lock(&close_exit_sync);
                if (g_linux_wlan != NULL) {
-                       WILC_FREE(g_linux_wlan);
+                       kfree(g_linux_wlan);
                        g_linux_wlan = NULL;
                }
                printk("Module_exit Done.\n");
 
-#if defined (WILC_DEBUGFS)
+#if defined(WILC_DEBUGFS)
                wilc_debugfs_remove();
 #endif
 
@@ -2780,4 +2675,3 @@ static void __exit exit_wilc_driver(void)
 module_exit(exit_wilc_driver);
 
 MODULE_LICENSE("GPL");
-#endif
index 2476bfda1b4684cc739401c8afdeba9ba66197f9..e6ebf3e89129eaf82d4059c856e0ac7571d192da 100644 (file)
@@ -39,8 +39,8 @@ enum debug_region {
 #define FIRM_DBG                (1 << Firmware_debug)
 
 #if defined (WILC_DEBUGFS)
-extern int wilc_debugfs_init(void);
-extern void wilc_debugfs_remove(void);
+int wilc_debugfs_init(void);
+void wilc_debugfs_remove(void);
 
 extern atomic_t REGION;
 extern atomic_t DEBUG_LEVEL;
index 858e3a191bce8baee64568adace64ac1525976d2..37f31f4558b5cb3b4325f0d1a9405d124c5a367c 100644 (file)
@@ -31,7 +31,6 @@
 struct sdio_func *local_sdio_func;
 extern linux_wlan_t *g_linux_wlan;
 extern int wilc_netdev_init(void);
-extern int sdio_clear_int(void);
 extern void wilc_handle_isr(void);
 
 static unsigned int sdio_default_speed;
index c328208cda29040c8ea8cc4ac8d0ca7a508bcdb6..ae111862e7a967a98ddaafcc901b9014a7c8264c 100644 (file)
@@ -48,38 +48,28 @@ static ssize_t wilc_debug_level_read(struct file *file, char __user *userbuf, si
        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 }
 
-static ssize_t wilc_debug_level_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf,
+                                       size_t count, loff_t *ppos)
 {
-       char buffer[128] = {};
        int flag = 0;
+       int ret;
 
-       if (count > sizeof(buffer))
-               return -EINVAL;
-
-       if (copy_from_user(buffer, buf, count)) {
-               return -EFAULT;
-       }
-
-       flag = buffer[0] - '0';
-
-       if (flag > 0) {
-               flag = DEBUG | ERR;
-       } else if (flag < 0) {
-               flag = 100;
-       }
+       ret = kstrtouint_from_user(buf, count, 16, &flag);
+       if (ret)
+               return ret;
 
        if (flag > DBG_LEVEL_ALL) {
                printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&DEBUG_LEVEL));
-               return -EFAULT;
+               return -EINVAL;
        }
 
        atomic_set(&DEBUG_LEVEL, (int)flag);
 
-       if (flag == 0) {
+       if (flag == 0)
                printk("Debug-level disabled\n");
-       } else {
+       else
                printk("Debug-level enabled\n");
-       }
+
        return count;
 }
 
index 529457816f655ce17cb41448c6055075b4b92bf3..c3f6a0a1c9adda09920d34c2ed9911e89baa36a4 100644 (file)
@@ -8,9 +8,6 @@
 #define LINUX_TX_SIZE  (64 * 1024)
 #define WILC1000_FW_SIZE (4 * 1024)
 
-#define DECLARE_WILC_BUFFER(name)      \
-       void *exported_ ## name = NULL;
-
 #define MALLOC_WILC_BUFFER(name, size) \
        exported_ ## name = kmalloc(size, GFP_KERNEL);    \
        if (!exported_ ## name) {   \
@@ -24,9 +21,9 @@
 /*
  * Add necessary buffer pointers
  */
-DECLARE_WILC_BUFFER(g_tx_buf)
-DECLARE_WILC_BUFFER(g_rx_buf)
-DECLARE_WILC_BUFFER(g_fw_buf)
+void *exported_g_tx_buf;
+void *exported_g_rx_buf;
+void *exported_g_fw_buf;
 
 void *get_tx_buffer(void)
 {
@@ -65,12 +62,10 @@ static void __exit wilc_module_deinit(void)
        FREE_WILC_BUFFER(g_tx_buf)
        FREE_WILC_BUFFER(g_rx_buf)
        FREE_WILC_BUFFER(g_fw_buf)
-
-       return;
 }
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Tony Cho");
 MODULE_DESCRIPTION("WILC1xxx Memory Manager");
 pure_initcall(wilc_module_init);
-module_exit(wilc_module_deinit);
\ No newline at end of file
+module_exit(wilc_module_deinit);
diff --git a/drivers/staging/wilc1000/wilc_log.h b/drivers/staging/wilc1000/wilc_log.h
deleted file mode 100644 (file)
index 2269ebd..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __WILC_LOG_H__
-#define __WILC_LOG_H__
-
-/* Errors will always get printed */
-#define WILC_ERROR(...) do {  WILC_PRINTF("(ERR)(%s:%d) ", __WILC_FUNCTION__, __WILC_LINE__); \
-                             WILC_PRINTF(__VA_ARGS__); \
-                               } while (0)
-
-/* Wraning only printed if verbosity is 1 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 0)
-#define WILC_WARN(...) do { WILC_PRINTF("(WRN)"); \
-                           WILC_PRINTF(__VA_ARGS__); \
-                               } while (0)
-#else
-#define WILC_WARN(...) (0)
-#endif
-
-/* Info only printed if verbosity is 2 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 1)
-#define WILC_INFO(...) do {  WILC_PRINTF("(INF)"); \
-                            WILC_PRINTF(__VA_ARGS__); \
-                               } while (0)
-#else
-#define WILC_INFO(...) (0)
-#endif
-
-/* Debug is only printed if verbosity is 3 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 2)
-#define WILC_DBG(...) do { WILC_PRINTF("(DBG)(%s:%d) ", __WILC_FUNCTION__, __WILC_LINE__); \
-                          WILC_PRINTF(__VA_ARGS__); \
-                       } while (0)
-
-#else
-#define WILC_DBG(...) (0)
-#endif
-
-/* Function In/Out is only printed if verbosity is 4 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 3)
-#define WILC_FN_IN do { WILC_PRINTF("(FIN) (%s:%d) \n", __WILC_FUNCTION__, __WILC_LINE__);  } while (0)
-#define WILC_FN_OUT(ret) do { WILC_PRINTF("(FOUT) (%s:%d) %d.\n", __WILC_FUNCTION__, __WILC_LINE__, (ret));  } while (0)
-#else
-#define WILC_FN_IN (0)
-#define WILC_FN_OUT(ret) (0)
-#endif
-
-
-#endif
\ No newline at end of file
index c70707fefb660eef29858583d54dcff944040ee9..e90a95705a7d5332725fc903a269f19b6fd42005 100644 (file)
@@ -9,50 +9,8 @@
 void *WILC_MemoryAlloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
                       char *pcFileName, u32 u32LineNo)
 {
-       if (u32Size > 0) {
+       if (u32Size > 0)
                return kmalloc(u32Size, GFP_ATOMIC);
-       } else {
+       else
                return NULL;
-       }
-}
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void *WILC_MemoryCalloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
-                       char *pcFileName, u32 u32LineNo)
-{
-       return kcalloc(u32Size, 1, GFP_KERNEL);
-}
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void *WILC_MemoryRealloc(void *pvOldBlock, u32 u32NewSize,
-                        tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 u32LineNo)
-{
-       if (u32NewSize == 0) {
-               kfree(pvOldBlock);
-               return NULL;
-       } else if (pvOldBlock == NULL)   {
-               return kmalloc(u32NewSize, GFP_KERNEL);
-       } else {
-               return krealloc(pvOldBlock, u32NewSize, GFP_KERNEL);
-       }
-
-}
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void WILC_MemoryFree(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
-                    char *pcFileName, u32 u32LineNo)
-{
-       kfree(pvBlock);
 }
index 372d7053e87334bd2de0760c0ebe05de4549ac7e..f19cec11a69a80728c1afbab1f12f9dfd4519585 100644 (file)
@@ -38,8 +38,6 @@ typedef struct {
  *  @sa                sttrWILC_MemoryAttrs
  *  @sa                WILC_MALLOC
  *  @sa                WILC_MALLOC_EX
- *  @sa                WILC_NEW
- *  @sa                WILC_NEW_EX
  *  @author    syounan
  *  @date      16 Aug 2010
  *  @version   1.0
@@ -47,78 +45,6 @@ typedef struct {
 void *WILC_MemoryAlloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
                       char *pcFileName, u32 u32LineNo);
 
-/*!
- *  @brief     Allocates a given size of bytes and zero filling it
- *  @param[in] u32Size size of memory in bytes to be allocated
- *  @param[in] strAttrs Optional attributes, NULL for default
- *              if not NULL, pAllocationPool should point to the pool to use for
- *              this allocation. if NULL memory will be allocated directly from
- *              the system
- *  @param[in] pcFileName file name of the calling code for debugging
- *  @param[in] u32LineNo line number of the calling code for debugging
- *  @return    The new allocated block, NULL if allocation fails
- *  @note      It is recommended to use of of the wrapper macros instead of
- *              calling this function directly
- *  @sa                sttrWILC_MemoryAttrs
- *  @sa                WILC_CALLOC
- *  @sa                WILC_CALLOC_EX
- *  @sa                WILC_NEW_0
- *  @sa                WILC_NEW_0_EX
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-void *WILC_MemoryCalloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
-                       char *pcFileName, u32 u32LineNo);
-
-/*!
- *  @brief     Reallocates a given block to a new size
- *  @param[in] pvOldBlock the old memory block, if NULL then this function
- *              behaves as a new allocation function
- *  @param[in] u32NewSize size of the new memory block in bytes, if zero then
- *              this function behaves as a free function
- *  @param[in] strAttrs Optional attributes, NULL for default
- *              if pAllocationPool!=NULL and pvOldBlock==NULL, pAllocationPool
- *              should point to the pool to use for this allocation.
- *              if pAllocationPool==NULL and pvOldBlock==NULL memory will be
- *              allocated directly from        the system
- *              if and pvOldBlock!=NULL, pAllocationPool will not be inspected
- *              and reallocation is done from the same pool as the original block
- *  @param[in] pcFileName file name of the calling code for debugging
- *  @param[in] u32LineNo line number of the calling code for debugging
- *  @return    The new allocated block, possibly same as pvOldBlock
- *  @note      It is recommended to use of of the wrapper macros instead of
- *              calling this function directly
- *  @sa                sttrWILC_MemoryAttrs
- *  @sa                WILC_REALLOC
- *  @sa                WILC_REALLOC_EX
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-void *WILC_MemoryRealloc(void *pvOldBlock, u32 u32NewSize,
-                        tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 u32LineNo);
-
-/*!
- *  @brief     Frees given block
- *  @param[in] pvBlock the memory block to be freed
- *  @param[in] strAttrs Optional attributes, NULL for default
- *  @param[in] pcFileName file name of the calling code for debugging
- *  @param[in] u32LineNo line number of the calling code for debugging
- *  @note      It is recommended to use of of the wrapper macros instead of
- *              calling this function directly
- *  @sa                sttrWILC_MemoryAttrs
- *  @sa                WILC_FREE
- *  @sa                WILC_FREE_EX
- *  @sa                WILC_FREE_SET_NULL
- *  @sa                WILC_FREE_IF_TRUE
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-void WILC_MemoryFree(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
-                       char *pcFileName, u32 u32LineNo);
-
 /*!
  * @brief      standrad malloc wrapper with custom attributes
  */
@@ -126,62 +52,6 @@ void WILC_MemoryFree(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
        (WILC_MemoryAlloc( \
                 (__size__), __attrs__, NULL, 0))
 
-/*!
- * @brief      standrad calloc wrapper with custom attributes
- */
-       #define WILC_CALLOC_EX(__size__, __attrs__) \
-       (WILC_MemoryCalloc( \
-                (__size__), __attrs__, NULL, 0))
-
-/*!
- * @brief      standrad realloc wrapper with custom attributes
- */
-       #define WILC_REALLOC_EX(__ptr__, __new_size__, __attrs__) \
-       (WILC_MemoryRealloc( \
-                (__ptr__), (__new_size__), __attrs__, NULL, 0))
-/*!
- * @brief      standrad free wrapper with custom attributes
- */
-       #define WILC_FREE_EX(__ptr__, __attrs__) \
-       (WILC_MemoryFree( \
-                (__ptr__), __attrs__, NULL, 0))
-
-/*!
- * @brief      Allocates a block (with custom attributes) of given type and number of
- * elements
- */
-#define WILC_NEW_EX(__struct_type__, __n_structs__, __attrs__) \
-       ((__struct_type__ *)WILC_MALLOC_EX( \
-                sizeof(__struct_type__) * (u32)(__n_structs__), __attrs__))
-
-/*!
- * @brief      Allocates a block (with custom attributes) of given type and number of
- * elements and Zero-fills it
- */
-#define WILC_NEW_0_EX(__struct_type__, __n_structs__, __attrs__) \
-       ((__struct_type__ *)WILC_CALLOC_EX( \
-                sizeof(__struct_type__) * (u32)(__n_structs__), __attrs__))
-
-/*!
- * @brief      Frees a block (with custom attributes), also setting the original pointer
- * to NULL
- */
-#define WILC_FREE_SET_NULL_EX(__ptr__, __attrs__) do { \
-               if (__ptr__ != NULL) { \
-                       WILC_FREE_EX(__ptr__, __attrs__); \
-                       __ptr__ = NULL; \
-               } \
-} while (0)
-
-/*!
- * @brief      Frees a block (with custom attributes) if the pointer expression evaluates
- * to true
- */
-#define WILC_FREE_IF_TRUE_EX(__ptr__, __attrs__) do { \
-               if (__ptr__ != NULL) { \
-                       WILC_FREE_EX(__ptr__, __attrs__); \
-               } \
-} while (0)
 
 /*!
  * @brief      standrad malloc wrapper with default attributes
@@ -189,51 +59,8 @@ void WILC_MemoryFree(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
 #define WILC_MALLOC(__size__) \
        WILC_MALLOC_EX(__size__, NULL)
 
-/*!
- * @brief      standrad calloc wrapper with default attributes
- */
-#define WILC_CALLOC(__size__) \
-       WILC_CALLOC_EX(__size__, NULL)
-
-/*!
- * @brief      standrad realloc wrapper with default attributes
- */
-#define WILC_REALLOC(__ptr__, __new_size__) \
-       WILC_REALLOC_EX(__ptr__, __new_size__, NULL)
 
-/*!
- * @brief      standrad free wrapper with default attributes
- */
-#define WILC_FREE(__ptr__) \
-       WILC_FREE_EX(__ptr__, NULL)
 
-/*!
- * @brief      Allocates a block (with default attributes) of given type and number of
- * elements
- */
-#define WILC_NEW(__struct_type__, __n_structs__) \
-       WILC_NEW_EX(__struct_type__, __n_structs__, NULL)
-
-/*!
- * @brief      Allocates a block (with default attributes) of given type and number of
- * elements and Zero-fills it
- */
-#define WILC_NEW_0(__struct_type__, __n_structs__) \
-       WILC_NEW_O_EX(__struct_type__, __n_structs__, NULL)
-
-/*!
- * @brief      Frees a block (with default attributes), also setting the original pointer
- * to NULL
- */
-#define WILC_FREE_SET_NULL(__ptr__) \
-       WILC_FREE_SET_NULL_EX(__ptr__, NULL)
-
-/*!
- * @brief      Frees a block (with default attributes) if the pointer expression evaluates
- * to true
- */
-#define WILC_FREE_IF_TRUE(__ptr__) \
-       WILC_FREE_IF_TRUE_EX(__ptr__, NULL)
 
 
 #endif
index 16bcef4b5c00a54f52fc135761971d73c9fb8bae..70e4fa6a07a65969af35529745d5c38d56399c81 100644 (file)
@@ -8,8 +8,7 @@
  *  @note              copied from FLO glue implementatuion
  *  @version           1.0
  */
-WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
-                              tstrWILC_MsgQueueAttrs *pstrAttrs)
+WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle)
 {
        spin_lock_init(&pHandle->strCriticalSection);
        sema_init(&pHandle->hSem, 0);
@@ -25,8 +24,7 @@ WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
  *  @note              copied from FLO glue implementatuion
  *  @version           1.0
  */
-WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
-                               tstrWILC_MsgQueueAttrs *pstrAttrs)
+WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle)
 {
 
        pHandle->bExiting = true;
@@ -39,7 +37,7 @@ WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
 
        while (pHandle->pstrMessageList != NULL) {
                Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
-               WILC_FREE(pHandle->pstrMessageList);
+               kfree(pHandle->pstrMessageList);
                pHandle->pstrMessageList = pstrMessge;
        }
 
@@ -53,8 +51,7 @@ WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
  *  @version           1.0
  */
 WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
-                            const void *pvSendBuffer, u32 u32SendBufferSize,
-                            tstrWILC_MsgQueueAttrs *pstrAttrs)
+                            const void *pvSendBuffer, u32 u32SendBufferSize)
 {
        WILC_ErrNo s32RetStatus = WILC_SUCCESS;
        unsigned long flags;
@@ -71,13 +68,13 @@ WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
        spin_lock_irqsave(&pHandle->strCriticalSection, flags);
 
        /* construct a new message */
-       pstrMessage = WILC_NEW(Message, 1);
+       pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
        WILC_NULLCHECK(s32RetStatus, pstrMessage);
        pstrMessage->u32Length = u32SendBufferSize;
        pstrMessage->pstrNext = NULL;
        pstrMessage->pvBuffer = WILC_MALLOC(u32SendBufferSize);
        WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer);
-       WILC_memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize);
+       memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize);
 
 
        /* add it to the message queue */
@@ -100,9 +97,9 @@ WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
                /* error occured, free any allocations */
                if (pstrMessage != NULL) {
                        if (pstrMessage->pvBuffer != NULL) {
-                               WILC_FREE(pstrMessage->pvBuffer);
+                               kfree(pstrMessage->pvBuffer);
                        }
-                       WILC_FREE(pstrMessage);
+                       kfree(pstrMessage);
                }
        }
 
@@ -119,8 +116,7 @@ WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
  */
 WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle,
                             void *pvRecvBuffer, u32 u32RecvBufferSize,
-                            u32 *pu32ReceivedLength,
-                            tstrWILC_MsgQueueAttrs *pstrAttrs)
+                            u32 *pu32ReceivedLength)
 {
 
        Message *pstrMessage;
@@ -170,13 +166,13 @@ WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle,
 
                /* consume the message */
                pHandle->u32ReceiversCount--;
-               WILC_memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
+               memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
                *pu32ReceivedLength = pstrMessage->u32Length;
 
                pHandle->pstrMessageList = pstrMessage->pstrNext;
 
-               WILC_FREE(pstrMessage->pvBuffer);
-               WILC_FREE(pstrMessage);
+               kfree(pstrMessage->pvBuffer);
+               kfree(pstrMessage);
 
                spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
 
index 35b10019eebd079c5068fd47515bfa0a8e008e0b..ef1d2fa20c50a835f4a8c61ecbea1906d68b52b5 100644 (file)
 #include "wilc_platform.h"
 #include "wilc_errorsupport.h"
 #include "wilc_memory.h"
-#include "wilc_strutils.h"
-
-/*!
- *  @struct             tstrWILC_MsgQueueAttrs
- *  @brief             Message Queue API options
- *  @author            syounan
- *  @date              30 Aug 2010
- *  @version           1.0
- */
-typedef struct {
-       /* a dummy member to avoid compiler errors*/
-       u8 dummy;
-
-} tstrWILC_MsgQueueAttrs;
 
 /*!
  *  @brief             Creates a new Message queue
@@ -37,14 +23,11 @@ typedef struct {
  *  @param[in,out]     pHandle handle to the message queue object
  *  @param[in] pstrAttrs Optional attributes, NULL for default
  *  @return            Error code indicating sucess/failure
- *  @sa                        tstrWILC_MsgQueueAttrs
  *  @author            syounan
  *  @date              30 Aug 2010
  *  @version           1.0
  */
-WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
-                              tstrWILC_MsgQueueAttrs *pstrAttrs);
-
+WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle);
 
 /*!
  *  @brief             Sends a message
@@ -57,15 +40,12 @@ WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
  *  @param[in] u32SendBufferSize the size of the data to send
  *  @param[in] pstrAttrs Optional attributes, NULL for default
  *  @return            Error code indicating sucess/failure
- *  @sa                        tstrWILC_MsgQueueAttrs
  *  @author            syounan
  *  @date              30 Aug 2010
  *  @version           1.0
  */
 WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
-                            const void *pvSendBuffer, u32 u32SendBufferSize,
-                            tstrWILC_MsgQueueAttrs *pstrAttrs);
-
+                            const void *pvSendBuffer, u32 u32SendBufferSize);
 
 /*!
  *  @brief             Receives a message
@@ -79,30 +59,23 @@ WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
  *  @param[out]        pu32ReceivedLength the length of received data
  *  @param[in] pstrAttrs Optional attributes, NULL for default
  *  @return            Error code indicating sucess/failure
- *  @sa                        tstrWILC_MsgQueueAttrs
  *  @author            syounan
  *  @date              30 Aug 2010
  *  @version           1.0
  */
 WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle,
                             void *pvRecvBuffer, u32 u32RecvBufferSize,
-                            u32 *pu32ReceivedLength,
-                            tstrWILC_MsgQueueAttrs *pstrAttrs);
-
+                            u32 *pu32ReceivedLength);
 
 /*!
  *  @brief             Destroys an existing  Message queue
  *  @param[in] pHandle handle to the message queue object
  *  @param[in] pstrAttrs Optional attributes, NULL for default
  *  @return            Error code indicating sucess/failure
- *  @sa                        tstrWILC_MsgQueueAttrs
  *  @author            syounan
  *  @date              30 Aug 2010
  *  @version           1.0
  */
-WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
-                               tstrWILC_MsgQueueAttrs *pstrAttrs);
-
-
+WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle);
 
 #endif
diff --git a/drivers/staging/wilc1000/wilc_osconfig.h b/drivers/staging/wilc1000/wilc_osconfig.h
deleted file mode 100644 (file)
index f9c2514..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Logs options */
-#define WILC_LOGS_NOTHING          0
-#define WILC_LOGS_WARN             1
-#define WILC_LOGS_WARN_INFO        2
-#define WILC_LOGS_WARN_INFO_DBG    3
-#define WILC_LOGS_WARN_INFO_DBG_FN 4
-#define WILC_LOGS_ALL              5
-
-#define WILC_LOG_VERBOSITY_LEVEL WILC_LOGS_ALL
index e97aa96006e00550651b129e582b5d637849b613..cb483253e788ec0d1dab0c0b4ae9a2e34b0024bc 100644 (file)
 #define WILC_OSW_INTERFACE_VER 2
 
 /* Os Configuration File */
-#include "wilc_osconfig.h"
 #include "wilc_platform.h"
 
-/* Logging Functions */
-#include "wilc_log.h"
-
 /* Error reporting and handling support */
 #include "wilc_errorsupport.h"
 
-/* Sleep support */
-#include "wilc_sleep.h"
-
-/* Timer support */
-#include "wilc_timer.h"
-
 /* Memory support */
 #include "wilc_memory.h"
 
-/* String Utilities */
-#include "wilc_strutils.h"
 
 /* Message Queue */
 #include "wilc_msgqueue.h"
index d03532cc3af21d09dd6242601dfb43b8679733c8..1e56973f2f933c4f96a3df699ff21ee5a4577076 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __WILC_platfrom_H__
-#define __WILC_platfrom_H__
+#ifndef __WILC_platform_H__
+#define __WILC_platform_H__
 
 #include <linux/kthread.h>
 #include <linux/semaphore.h>
  *      OS specific types
  *******************************************************************/
 
-typedef struct timer_list WILC_TimerHandle;
-
-
-
 /* Message Queue type is a structure */
 typedef struct __Message_struct {
        void *pvBuffer;
index 897e47e317ff769cc066a42a23f4905326465d7d..5a18148a593e3f2b6416138b6fee4a95bc6b78cc 100644 (file)
 #include "wilc_wlan_if.h"
 #include "wilc_wlan.h"
 
-
-#ifdef WILC1000_SINGLE_TRANSFER
-#define WILC_SDIO_BLOCK_SIZE 256
-#else
- #if defined(PLAT_AML8726_M3) /* johnny */
-       #define WILC_SDIO_BLOCK_SIZE 512
-       #define MAX_SEG_SIZE (1 << 12) /* 4096 */
- #else
-       #define WILC_SDIO_BLOCK_SIZE 512
- #endif
-#endif
+#define WILC_SDIO_BLOCK_SIZE 512
 
 typedef struct {
        void *os_context;
@@ -90,7 +80,6 @@ static int sdio_set_func0_csa_address_byte0(uint32_t adr)
 {
        sdio_cmd52_t cmd;
 
-
        /**
         *      Review: BIG ENDIAN
         **/
@@ -108,6 +97,7 @@ static int sdio_set_func0_csa_address_byte0(uint32_t adr)
 _fail_:
        return 0;
 }
+
 static int sdio_set_func0_block_size(uint32_t block_size)
 {
        sdio_cmd52_t cmd;
@@ -170,6 +160,7 @@ static int sdio_clear_int(void)
 #ifndef WILC_SDIO_IRQ_GPIO
        /* uint32_t sts; */
        sdio_cmd52_t cmd;
+
        cmd.read_write = 0;
        cmd.function = 1;
        cmd.raw = 0;
@@ -181,6 +172,7 @@ static int sdio_clear_int(void)
        return cmd.data;
 #else
        uint32_t reg;
+
        if (!sdio_read_reg(WILC_HOST_RX_CTRL_0, &reg)) {
                g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0);
                return 0;
@@ -197,6 +189,7 @@ uint32_t sdio_xfer_cnt(void)
 {
        uint32_t cnt = 0;
        sdio_cmd52_t cmd;
+
        cmd.read_write = 0;
        cmd.function = 1;
        cmd.raw = 0;
@@ -222,8 +215,6 @@ uint32_t sdio_xfer_cnt(void)
        cnt |= (cmd.data << 16);
 
        return cnt;
-
-
 }
 
 /********************************************
@@ -263,6 +254,7 @@ static int sdio_write_reg(uint32_t addr, uint32_t data)
 
        if ((addr >= 0xf0) && (addr <= 0xff)) {
                sdio_cmd52_t cmd;
+
                cmd.read_write = 1;
                cmd.function = 0;
                cmd.raw = 0;
@@ -325,16 +317,6 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size)
                cmd.function = 0;
                cmd.address = 0x10f;
        } else {
-#ifdef WILC1000_SINGLE_TRANSFER
-               /**
-                *      has to be block aligned...
-                **/
-               nleft = size % block_size;
-               if (nleft > 0) {
-                       size += block_size;
-                       size &= ~(block_size - 1);
-               }
-#else
                /**
                 *      has to be word aligned...
                 **/
@@ -342,7 +324,6 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size)
                        size += 4;
                        size &= ~0x3;
                }
-#endif
 
                /**
                 *      func 1 access
@@ -355,89 +336,6 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size)
        nleft = size % block_size;
 
        if (nblk > 0) {
-
-#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */
-               int i;
-
-               for (i = 0; i < nblk; i++) {
-                       cmd.block_mode = 0; /* 1; */
-                       cmd.increment = 1;
-                       cmd.count = block_size; /* nblk; */
-                       cmd.buffer = buf;
-                       cmd.block_size = block_size;
-                       if (addr > 0) {
-                               if (!sdio_set_func0_csa_address(addr))
-                                       goto _fail_;
-                       }
-                       if (!g_sdio.sdio_cmd53(&cmd)) {
-                               g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr);
-                               goto _fail_;
-                       }
-
-                       if (addr > 0)
-                               addr += block_size;     /* addr += nblk*block_size; */
-
-                       buf += block_size;              /* buf += nblk*block_size; */
-               }
-
-#elif defined(PLAT_AML8726_M3) /* johnny */
-
-               int i;
-               int rest;
-               int seg_cnt;
-
-               seg_cnt = (nblk * block_size) / MAX_SEG_SIZE;
-               rest = (nblk * block_size) & (MAX_SEG_SIZE - 1);
-
-               for (i = 0; i < seg_cnt; i++) {
-                       cmd.block_mode = 1;
-                       cmd.increment = 1;
-                       cmd.count = MAX_SEG_SIZE / block_size;
-                       cmd.buffer = buf;
-                       cmd.block_size = block_size;
-
-                       if (addr > 0) {
-                               if (!sdio_set_func0_csa_address(addr))
-                                       goto _fail_;
-                       }
-                       if (!g_sdio.sdio_cmd53(&cmd)) {
-                               g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr);
-                               goto _fail_;
-                       }
-
-                       if (addr > 0)
-                               addr += MAX_SEG_SIZE;
-
-                       buf += MAX_SEG_SIZE;
-
-               }
-
-
-               if (rest > 0) {
-                       cmd.block_mode = 1;
-                       cmd.increment = 1;
-                       cmd.count = rest / block_size;
-                       cmd.buffer = buf;
-                       cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */
-
-                       if (addr > 0) {
-                               if (!sdio_set_func0_csa_address(addr))
-                                       goto _fail_;
-                       }
-                       if (!g_sdio.sdio_cmd53(&cmd)) {
-                               g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr);
-                               goto _fail_;
-                       }
-
-                       if (addr > 0)
-                               addr += rest;
-
-                       buf += rest;
-
-               }
-
-#else
-
                cmd.block_mode = 1;
                cmd.increment = 1;
                cmd.count = nblk;
@@ -454,11 +352,8 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size)
                if (addr > 0)
                        addr += nblk * block_size;
                buf += nblk * block_size;
-
-#endif /* platform */
        }
 
-
        if (nleft > 0) {
                cmd.block_mode = 0;
                cmd.increment = 1;
@@ -488,6 +383,7 @@ static int sdio_read_reg(uint32_t addr, uint32_t *data)
 {
        if ((addr >= 0xf0) && (addr <= 0xff)) {
                sdio_cmd52_t cmd;
+
                cmd.read_write = 0;
                cmd.function = 0;
                cmd.raw = 0;
@@ -552,16 +448,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size)
                cmd.function = 0;
                cmd.address = 0x10f;
        } else {
-#ifdef WILC1000_SINGLE_TRANSFER
-               /**
-                *      has to be block aligned...
-                **/
-               nleft = size % block_size;
-               if (nleft > 0) {
-                       size += block_size;
-                       size &= ~(block_size - 1);
-               }
-#else
                /**
                 *      has to be word aligned...
                 **/
@@ -569,7 +455,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size)
                        size += 4;
                        size &= ~0x3;
                }
-#endif
 
                /**
                 *      func 1 access
@@ -582,89 +467,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size)
        nleft = size % block_size;
 
        if (nblk > 0) {
-
-#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */
-
-               int i;
-
-               for (i = 0; i < nblk; i++) {
-                       cmd.block_mode = 0; /* 1; */
-                       cmd.increment = 1;
-                       cmd.count = block_size; /* nblk; */
-                       cmd.buffer = buf;
-                       cmd.block_size = block_size;
-                       if (addr > 0) {
-                               if (!sdio_set_func0_csa_address(addr))
-                                       goto _fail_;
-                       }
-                       if (!g_sdio.sdio_cmd53(&cmd)) {
-                               g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
-                               goto _fail_;
-                       }
-                       if (addr > 0)
-                               addr += block_size;             /* addr += nblk*block_size; */
-                       buf += block_size;              /* buf += nblk*block_size; */
-               }
-
-#elif defined(PLAT_AML8726_M3) /* johnny */
-
-               int i;
-               int rest;
-               int seg_cnt;
-
-               seg_cnt = (nblk * block_size) / MAX_SEG_SIZE;
-               rest = (nblk * block_size) & (MAX_SEG_SIZE - 1);
-
-               for (i = 0; i < seg_cnt; i++) {
-                       cmd.block_mode = 1;
-                       cmd.increment = 1;
-                       cmd.count = MAX_SEG_SIZE / block_size;
-                       cmd.buffer = buf;
-                       cmd.block_size = block_size;
-
-
-                       if (addr > 0) {
-                               if (!sdio_set_func0_csa_address(addr))
-                                       goto _fail_;
-                       }
-                       if (!g_sdio.sdio_cmd53(&cmd)) {
-                               g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
-                               goto _fail_;
-                       }
-
-                       if (addr > 0)
-                               addr += MAX_SEG_SIZE;
-
-                       buf += MAX_SEG_SIZE;
-
-               }
-
-
-               if (rest > 0) {
-                       cmd.block_mode = 1;
-                       cmd.increment = 1;
-                       cmd.count = rest / block_size;
-                       cmd.buffer = buf;
-                       cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */
-
-                       if (addr > 0) {
-                               if (!sdio_set_func0_csa_address(addr))
-                                       goto _fail_;
-                       }
-                       if (!g_sdio.sdio_cmd53(&cmd)) {
-                               g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
-                               goto _fail_;
-                       }
-
-                       if (addr > 0)
-                               addr += rest;
-
-                       buf += rest;
-
-               }
-
-#else
-
                cmd.block_mode = 1;
                cmd.increment = 1;
                cmd.count = nblk;
@@ -681,8 +483,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size)
                if (addr > 0)
                        addr += nblk * block_size;
                buf += nblk * block_size;
-
-#endif /* platform */
        }       /* if (nblk > 0) */
 
        if (nleft > 0) {
@@ -784,6 +584,7 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
        sdio_cmd52_t cmd;
        int loop;
        uint32_t chipid;
+
        memset(&g_sdio, 0, sizeof(wilc_sdio_t));
 
        g_sdio.dPrint = func;
@@ -891,14 +692,12 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
                goto _fail_;
        }
        g_sdio.dPrint(N_ERR, "[wilc sdio]: chipid (%08x)\n", chipid);
-       if ((chipid & 0xfff) > 0x2a0) {
+       if ((chipid & 0xfff) > 0x2a0)
                g_sdio.has_thrpt_enh3 = 1;
-       } else {
+       else
                g_sdio.has_thrpt_enh3 = 0;
-       }
        g_sdio.dPrint(N_ERR, "[wilc sdio]: has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3);
 
-
        return 1;
 
 _fail_:
@@ -925,23 +724,21 @@ static int sdio_read_size(uint32_t *size)
        /**
         *      Read DMA count in words
         **/
-       {
-               cmd.read_write = 0;
-               cmd.function = 0;
-               cmd.raw = 0;
-               cmd.address = 0xf2;
-               cmd.data = 0;
-               g_sdio.sdio_cmd52(&cmd);
-               tmp = cmd.data;
+       cmd.read_write = 0;
+       cmd.function = 0;
+       cmd.raw = 0;
+       cmd.address = 0xf2;
+       cmd.data = 0;
+       g_sdio.sdio_cmd52(&cmd);
+       tmp = cmd.data;
 
-               /* cmd.read_write = 0; */
-               /* cmd.function = 0; */
-               /* cmd.raw = 0; */
-               cmd.address = 0xf3;
-               cmd.data = 0;
-               g_sdio.sdio_cmd52(&cmd);
-               tmp |= (cmd.data << 8);
-       }
+       /* cmd.read_write = 0; */
+       /* cmd.function = 0; */
+       /* cmd.raw = 0; */
+       cmd.address = 0xf3;
+       cmd.data = 0;
+       g_sdio.sdio_cmd52(&cmd);
+       tmp |= (cmd.data << 8);
 
        *size = tmp;
        return 1;
@@ -966,26 +763,21 @@ static int sdio_read_int(uint32_t *int_status)
        cmd.data = 0;
        g_sdio.sdio_cmd52(&cmd);
 
-       if (cmd.data & (1 << 0)) {
+       if (cmd.data & (1 << 0))
                tmp |= INT_0;
-       }
-       if (cmd.data & (1 << 2)) {
+       if (cmd.data & (1 << 2))
                tmp |= INT_1;
-       }
-       if (cmd.data & (1 << 3)) {
+       if (cmd.data & (1 << 3))
                tmp |= INT_2;
-       }
-       if (cmd.data & (1 << 4)) {
+       if (cmd.data & (1 << 4))
                tmp |= INT_3;
-       }
-       if (cmd.data & (1 << 5)) {
+       if (cmd.data & (1 << 5))
                tmp |= INT_4;
-       }
-       if (cmd.data & (1 << 6)) {
+       if (cmd.data & (1 << 6))
                tmp |= INT_5;
-       }
        {
                int i;
+
                for (i = g_sdio.nint; i < MAX_NUM_INT; i++) {
                        if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) {
                                g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt (1) : tmp=%x, data=%x\n", tmp, cmd.data);
@@ -1024,6 +816,7 @@ static int sdio_clear_int_ext(uint32_t val)
 #ifdef WILC_SDIO_IRQ_GPIO
                {
                        uint32_t flags;
+
                        flags = val & ((1 << MAX_NUN_INT_THRPT_ENH2) - 1);
                        reg = flags;
                }
@@ -1041,6 +834,7 @@ static int sdio_clear_int_ext(uint32_t val)
                        reg |= (1 << 7);
                if (reg) {
                        sdio_cmd52_t cmd;
+
                        cmd.read_write = 1;
                        cmd.function = 0;
                        cmd.raw = 0;
@@ -1060,6 +854,7 @@ static int sdio_clear_int_ext(uint32_t val)
                        /* see below. has_thrpt_enh2 uses register 0xf8 to clear interrupts. */
                        /* Cannot clear multiple interrupts. Must clear each interrupt individually */
                        uint32_t flags;
+
                        flags = val & ((1 << MAX_NUM_INT) - 1);
                        if (flags) {
                                int i;
@@ -1068,6 +863,7 @@ static int sdio_clear_int_ext(uint32_t val)
                                for (i = 0; i < g_sdio.nint; i++) {
                                        if (flags & 1) {
                                                sdio_cmd52_t cmd;
+
                                                cmd.read_write = 1;
                                                cmd.function = 0;
                                                cmd.raw = 0;
@@ -1085,9 +881,8 @@ static int sdio_clear_int_ext(uint32_t val)
                                                break;
                                        flags >>= 1;
                                }
-                               if (!ret) {
+                               if (!ret)
                                        goto _fail_;
-                               }
                                for (i = g_sdio.nint; i < MAX_NUM_INT; i++) {
                                        if (flags & 1)
                                                g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt cleared %d...\n", i);
@@ -1097,7 +892,6 @@ static int sdio_clear_int_ext(uint32_t val)
                }
 #endif /* WILC_SDIO_IRQ_GPIO */
 
-
                {
                        uint32_t vmm_ctl;
 
@@ -1138,7 +932,6 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
 {
        uint32_t reg;
 
-
        if (nint > MAX_NUM_INT) {
                g_sdio.dPrint(N_ERR, "[wilc sdio]: Too many interupts (%d)...\n", nint);
                return 0;
@@ -1148,7 +941,6 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
                return 0;
        }
 
-
        g_sdio.nint = nint;
 
        /**
@@ -1170,7 +962,6 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
                uint32_t reg;
                int ret, i;
 
-
                /**
                 *      interrupt pin mux select
                 **/
@@ -1195,9 +986,8 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
                        return 0;
                }
 
-               for (i = 0; (i < 5) && (nint > 0); i++, nint--) {
+               for (i = 0; (i < 5) && (nint > 0); i++, nint--)
                        reg |= (1 << (27 + i));
-               }
                ret = sdio_write_reg(WILC_INTR_ENABLE, reg);
                if (!ret) {
                        g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
@@ -1210,9 +1000,8 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
                                return 0;
                        }
 
-                       for (i = 0; (i < 3) && (nint > 0); i++, nint--) {
+                       for (i = 0; (i < 3) && (nint > 0); i++, nint--)
                                reg |= (1 << i);
-                       }
 
                        ret = sdio_read_reg(WILC_INTR2_ENABLE, &reg);
                        if (!ret) {
@@ -1225,7 +1014,6 @@ static int sdio_sync_ext(int nint /*  how mant interrupts to enable. */)
        return 1;
 }
 
-
 /********************************************
  *
  *      Global sdio HIF function table
diff --git a/drivers/staging/wilc1000/wilc_sleep.c b/drivers/staging/wilc1000/wilc_sleep.c
deleted file mode 100644 (file)
index adab3ca..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#include "wilc_sleep.h"
-
-/*
- *  @author    mdaftedar
- *  @date      10 Aug 2010
- *  @version   1.0
- */
-void WILC_Sleep(u32 u32TimeMilliSec)
-{
-       if (u32TimeMilliSec <= 4000000) {
-               u32 u32Temp = u32TimeMilliSec * 1000;
-               usleep_range(u32Temp, u32Temp);
-       } else {
-               msleep(u32TimeMilliSec);
-       }
-
-}
diff --git a/drivers/staging/wilc1000/wilc_sleep.h b/drivers/staging/wilc1000/wilc_sleep.h
deleted file mode 100644 (file)
index cf9047f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __WILC_SLEEP_H__
-#define __WILC_SLEEP_H__
-
-#include <linux/types.h>
-#include <linux/delay.h>
-
-/*!
- *  @brief     forces the current thread to sleep until the given time has elapsed
- *  @param[in] u32TimeMilliSec Time to sleep in Milli seconds
- *  @sa                WILC_SleepMicrosec
- *  @author    syounan
- *  @date      10 Aug 2010
- *  @version   1.0
- *  @note      This function offers a relatively innacurate and low resolution
- *              sleep, for accurate high resolution sleep use u32TimeMicoSec
- */
-/* TODO: remove and open-code in callers */
-void WILC_Sleep(u32 u32TimeMilliSec);
-
-#endif
index abea5df656d78ce9ddada4c14755b8b8bae7094c..1bf7d314ae342ed3cbe6237b75b1686e604be1be 100644 (file)
@@ -374,11 +374,10 @@ static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz,
                return result;
        }
 
-       if (!g_spi.crc_off) {
+       if (!g_spi.crc_off)
                wb[len - 1] = (crc7(0x7f, (const uint8_t *)&wb[0], len - 1)) << 1;
-       } else {
+       else
                len -= 1;
-       }
 
 #define NUM_SKIP_BYTES (1)
 #define NUM_RSP_BYTES (2)
@@ -522,11 +521,10 @@ static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz,
                        if (sz > 0) {
                                int nbytes;
 
-                               if (sz <= (DATA_PKT_SZ - ix)) {
+                               if (sz <= (DATA_PKT_SZ - ix))
                                        nbytes = sz;
-                               } else {
+                               else
                                        nbytes = DATA_PKT_SZ - ix;
-                               }
 
                                /**
                                 * Read bytes
@@ -557,11 +555,10 @@ static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz,
                        while (sz > 0) {
                                int nbytes;
 
-                               if (sz <= DATA_PKT_SZ) {
+                               if (sz <= DATA_PKT_SZ)
                                        nbytes = sz;
-                               } else {
+                               else
                                        nbytes = DATA_PKT_SZ;
-                               }
 
                                /**
                                 * read data response only on the next DMA cycles not
diff --git a/drivers/staging/wilc1000/wilc_strutils.c b/drivers/staging/wilc1000/wilc_strutils.c
deleted file mode 100644 (file)
index e014595..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-
-#define _CRT_SECURE_NO_DEPRECATE
-
-#include "wilc_strutils.h"
-
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count)
-{
-       return memcmp(pvArg1, pvArg2, u32Count);
-}
-
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, u32 u32Count)
-{
-       memcpy(pvTarget, pvSource, u32Count);
-}
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count)
-{
-       return memset(pvTarget, u8SetValue, u32Count);
-}
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-char *WILC_strncpy(char *pcTarget, const char *pcSource,
-                       u32 u32Count)
-{
-       return strncpy(pcTarget, pcSource, u32Count);
-}
-
-s32 WILC_strncmp(const char *pcStr1, const char *pcStr2,
-                        u32 u32Count)
-{
-       s32 s32Result;
-
-       if (pcStr1 == NULL && pcStr2 == NULL)   {
-               s32Result = 0;
-       } else if (pcStr1 == NULL)         {
-               s32Result = -1;
-       } else if (pcStr2 == NULL)         {
-               s32Result = 1;
-       } else {
-               s32Result = strncmp(pcStr1, pcStr2, u32Count);
-               if (s32Result < 0) {
-                       s32Result = -1;
-               } else if (s32Result > 0)    {
-                       s32Result = 1;
-               }
-       }
-
-       return s32Result;
-}
-
-/*!
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-u32 WILC_strlen(const char *pcStr)
-{
-       return (u32)strlen(pcStr);
-}
diff --git a/drivers/staging/wilc1000/wilc_strutils.h b/drivers/staging/wilc1000/wilc_strutils.h
deleted file mode 100644 (file)
index d144557..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef __WILC_STRUTILS_H__
-#define __WILC_STRUTILS_H__
-
-/*!
- *  @file      wilc_strutils.h
- *  @brief     Basic string utilities
- *  @author    syounan
- *  @sa                wilc_oswrapper.h top level OS wrapper file
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include "wilc_errorsupport.h"
-
-/*!
- *  @brief     Compares two memory buffers
- *  @param[in] pvArg1 pointer to the first memory location
- *  @param[in] pvArg2 pointer to the second memory location
- *  @param[in] u32Count the size of the memory buffers
- *  @return    0 if the 2 buffers are equal, 1 if pvArg1 is bigger than pvArg2,
- *              -1 if pvArg1 smaller than pvArg2
- *  @note      this function repeats the functionality of standard memcmp
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count);
-
-/*!
- *  @brief     Internal implementation for memory copy
- *  @param[in] pvTarget the target buffer to which the data is copied into
- *  @param[in] pvSource pointer to the second memory location
- *  @param[in] u32Count the size of the data to copy
- *  @note      this function should not be used directly, use WILC_memcpy instead
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, u32 u32Count);
-
-/*!
- *  @brief     Copies the contents of a memory buffer into another
- *  @param[in] pvTarget the target buffer to which the data is copied into
- *  @param[in] pvSource pointer to the second memory location
- *  @param[in] u32Count the size of the data to copy
- *  @return    WILC_SUCCESS if copy is successfully handeled
- *              WILC_FAIL if copy failed
- *  @note      this function repeats the functionality of standard memcpy,
- *              however memcpy is undefined if the two buffers overlap but this
- *              implementation will check for overlap and report error
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-static WILC_ErrNo WILC_memcpy(void *pvTarget, const void *pvSource, u32 u32Count)
-{
-       if (
-               (((u8 *)pvTarget <= (u8 *)pvSource)
-                && (((u8 *)pvTarget + u32Count) > (u8 *)pvSource))
-
-               || (((u8 *)pvSource <= (u8 *)pvTarget)
-                   && (((u8 *)pvSource + u32Count) > (u8 *)pvTarget))
-               ) {
-               /* ovelapped memory, return Error */
-               return WILC_FAIL;
-       } else {
-               WILC_memcpy_INTERNAL(pvTarget, pvSource, u32Count);
-               return WILC_SUCCESS;
-       }
-}
-
-/*!
- *  @brief     Sets the contents of a memory buffer with the given value
- *  @param[in] pvTarget the target buffer which contsnts will be set
- *  @param[in] u8SetValue the value to be used
- *  @param[in] u32Count the size of the memory buffer
- *  @return    value of pvTarget
- *  @note      this function repeats the functionality of standard memset
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count);
-
-/*!
- *  @brief     copies the contents of source string into the target string
- *  @param[in] pcTarget the target string buffer
- *  @param[in] pcSource the source string the will be copied
- *  @param[in] u32Count copying will proceed until a null character in pcSource
- *              is encountered or u32Count of bytes copied
- *  @return    value of pcTarget
- *  @note      this function repeats the functionality of standard strncpy
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-char *WILC_strncpy(char *pcTarget, const char *pcSource,
-                       u32 u32Count);
-
-/*!
- *  @brief     Compares two strings up to u32Count characters
- *  @details   Compares 2 strings reporting which is bigger, NULL is considered
- *              the smallest string, then a zero length string then all other
- *              strings depending on thier ascii characters order with small case
- *              converted to uppder case
- *  @param[in] pcStr1 the first string, NULL is valid and considered smaller
- *              than any other non-NULL string (incliding zero lenght strings)
- *  @param[in] pcStr2 the second string, NULL is valid and considered smaller
- *              than any other non-NULL string (incliding zero lenght strings)
- *  @param[in] u32Count copying will proceed until a null character in pcStr1 or
- *              pcStr2 is encountered or u32Count of bytes copied
- *  @return    0 if the 2 strings are equal, 1 if pcStr1 is bigger than pcStr2,
- *              -1 if pcStr1 smaller than pcStr2
- *  @author    aabozaeid
- *  @date      7 Dec 2010
- *  @version   1.0
- */
-s32 WILC_strncmp(const char *pcStr1, const char *pcStr2,
-                        u32 u32Count);
-
-/*!
- *  @brief     gets the length of a string
- *  @param[in] pcStr the string
- *  @return    the length
- *  @note      this function repeats the functionality of standard strlen
- *  @author    syounan
- *  @date      18 Aug 2010
- *  @version   1.0
- */
-u32 WILC_strlen(const char *pcStr);
-
-#endif
diff --git a/drivers/staging/wilc1000/wilc_timer.c b/drivers/staging/wilc1000/wilc_timer.c
deleted file mode 100644 (file)
index dc71157..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-
-#include "wilc_timer.h"
-
-WILC_ErrNo WILC_TimerCreate(WILC_TimerHandle *pHandle,
-       tpfWILC_TimerFunction pfCallback, tstrWILC_TimerAttrs *pstrAttrs)
-{
-       WILC_ErrNo s32RetStatus = WILC_SUCCESS;
-       setup_timer(pHandle, (void(*)(unsigned long))pfCallback, 0);
-
-       return s32RetStatus;
-}
-
-WILC_ErrNo WILC_TimerDestroy(WILC_TimerHandle *pHandle,
-       tstrWILC_TimerAttrs *pstrAttrs)
-{
-       WILC_ErrNo s32RetStatus = WILC_FAIL;
-       if (pHandle != NULL) {
-               s32RetStatus = del_timer_sync(pHandle);
-               pHandle = NULL;
-       }
-
-       return s32RetStatus;
-}
-
-
-WILC_ErrNo WILC_TimerStart(WILC_TimerHandle *pHandle, u32 u32Timeout,
-       void *pvArg, tstrWILC_TimerAttrs *pstrAttrs)
-{
-       WILC_ErrNo s32RetStatus = WILC_FAIL;
-       if (pHandle != NULL) {
-               pHandle->data = (unsigned long)pvArg;
-               s32RetStatus = mod_timer(pHandle, (jiffies + msecs_to_jiffies(u32Timeout)));
-       }
-       return s32RetStatus;
-}
-
-WILC_ErrNo WILC_TimerStop(WILC_TimerHandle *pHandle,
-       tstrWILC_TimerAttrs *pstrAttrs)
-{
-       WILC_ErrNo s32RetStatus = WILC_FAIL;
-       if (pHandle != NULL)
-               s32RetStatus = del_timer(pHandle);
-
-       return s32RetStatus;
-}
diff --git a/drivers/staging/wilc1000/wilc_timer.h b/drivers/staging/wilc1000/wilc_timer.h
deleted file mode 100644 (file)
index 931269d..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-#ifndef __WILC_TIMER_H__
-#define __WILC_TIMER_H__
-
-/*!
- *  @file      wilc_timer.h
- *  @brief     Timer (One Shot and Periodic) OS wrapper functionality
- *  @author    syounan
- *  @sa                wilc_oswrapper.h top level OS wrapper file
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-
-#include "wilc_platform.h"
-#include "wilc_errorsupport.h"
-
-typedef void (*tpfWILC_TimerFunction)(void *);
-
-/*!
- *  @struct             tstrWILC_TimerAttrs
- *  @brief             Timer API options
- *  @author            syounan
- *  @date              16 Aug 2010
- *  @version           1.0
- */
-typedef struct {
-       /* a dummy member to avoid compiler errors*/
-       u8 dummy;
-} tstrWILC_TimerAttrs;
-
-/*!
- *  @brief     Creates a new timer
- *  @details   Timers are a useful utility to execute some callback function
- *              in the future.
- *              A timer object has 3 states : IDLE, PENDING and EXECUTING
- *              IDLE : initial timer state after creation, no execution for the
- *              callback function is planned
- *              PENDING : a request to execute the callback function is made
- *              using WILC_TimerStart.
- *              EXECUTING : the timer has expired and its callback is now
- *              executing, when execution is done the timer returns to PENDING
- *              if the feature CONFIG_WILC_TIMER_PERIODIC is enabled and
- *              the flag tstrWILC_TimerAttrs.bPeriodicTimer is set. otherwise the
- *              timer will return to IDLE
- *  @param[out]        pHandle handle to the newly created timer object
- *  @param[in] pfEntry pointer to the callback function to be called when the
- *              timer expires
- *              the underlaying OS may put many restrictions on what can be
- *              called inside a timer's callback, as a general rule no blocking
- *              operations (IO or semaphore Acquision) should be perfomred
- *              It is recommended that the callback will be as short as possible
- *              and only flags other threads to do the actual work
- *              also it should be noted that the underlaying OS maynot give any
- *              guarentees on which contect this callback will execute in
- *  @param[in] pstrAttrs Optional attributes, NULL for default
- *  @return    Error code indicating sucess/failure
- *  @sa                WILC_TimerAttrs
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-WILC_ErrNo WILC_TimerCreate(WILC_TimerHandle *pHandle,
-                           tpfWILC_TimerFunction pfCallback, tstrWILC_TimerAttrs *pstrAttrs);
-
-
-/*!
- *  @brief     Destroys a given timer
- *  @details   This will destroy a given timer freeing any resources used by it
- *              if the timer was PENDING Then must be cancelled as well(i.e.
- *              goes to        IDLE, same effect as calling WILC_TimerCancel first)
- *              if the timer was EXECUTING then the callback will be allowed to
- *              finish first then all resources are freed
- *  @param[in] pHandle handle to the timer object
- *  @param[in] pstrAttrs Optional attributes, NULL for default
- *  @return    Error code indicating sucess/failure
- *  @sa                WILC_TimerAttrs
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-WILC_ErrNo WILC_TimerDestroy(WILC_TimerHandle *pHandle,
-                            tstrWILC_TimerAttrs *pstrAttrs);
-
-/*!
- *  @brief     Starts a given timer
- *  @details   This function will move the timer to the PENDING state until the
- *              given time expires (in msec) then the callback function will be
- *              executed (timer in EXECUTING state) after execution is dene the
- *              timer either goes to IDLE (if bPeriodicTimer==false) or
- *              PENDING with same timeout value (if bPeriodicTimer==true)
- *  @param[in] pHandle handle to the timer object
- *  @param[in] u32Timeout timeout value in msec after witch the callback
- *              function will be executed. Timeout value of 0 is not allowed for
- *              periodic timers
- *  @param[in] pstrAttrs Optional attributes, NULL for default,
- *              set bPeriodicTimer to run this timer as a periodic timer
- *  @return    Error code indicating sucess/failure
- *  @sa                WILC_TimerAttrs
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-WILC_ErrNo WILC_TimerStart(WILC_TimerHandle *pHandle, u32 u32Timeout, void *pvArg,
-                          tstrWILC_TimerAttrs *pstrAttrs);
-
-
-/*!
- *  @brief     Stops a given timer
- *  @details   This function will move the timer to the IDLE state cancelling
- *              any sheduled callback execution.
- *              if this function is called on a timer already in the IDLE state
- *              it will have no effect.
- *              if this function is called on a timer in EXECUTING state
- *              (callback has already started) it will wait until executing is
- *              done then move the timer to the IDLE state (which is trivial
- *              work if the timer is non periodic)
- *  @param[in] pHandle handle to the timer object
- *  @param[in] pstrAttrs Optional attributes, NULL for default,
- *  @return    Error code indicating sucess/failure
- *  @sa                WILC_TimerAttrs
- *  @author    syounan
- *  @date      16 Aug 2010
- *  @version   1.0
- */
-WILC_ErrNo WILC_TimerStop(WILC_TimerHandle *pHandle,
-                         tstrWILC_TimerAttrs *pstrAttrs);
-
-
-
-#endif
diff --git a/drivers/staging/wilc1000/wilc_type.h b/drivers/staging/wilc1000/wilc_type.h
deleted file mode 100644 (file)
index 5f36e7f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* ////////////////////////////////////////////////////////////////////////// */
-/*  */
-/* Copyright (c) Atmel Corporation.  All rights reserved. */
-/*  */
-/* Module Name:  wilc_type.h */
-/*  */
-/*  */
-/* //////////////////////////////////////////////////////////////////////////// */
-#ifndef WILC_TYPE_H
-#define WILC_TYPE_H
-
-/********************************************
- *
- *      Type Defines
- *
- ********************************************/
-#ifdef WIN32
-typedef char int8_t;
-typedef short int16_t;
-typedef long int32_t;
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned long uint32_t;
-#else
-#ifdef _linux_
-/*typedef unsigned char         uint8_t;
- * typedef unsigned short       uint16_t;
- * typedef unsigned long        uint32_t;*/
-#include <stdint.h>
-#else
-#include "wilc_oswrapper.h"
-#endif
-#endif
-#endif
index 92064db9eb05589a37127e97c5bd0a715087bf9c..a6edc973f636babacc4fd8f51956bd197958610e 100644 (file)
@@ -22,7 +22,6 @@
 #define IS_MGMT_STATUS_SUCCES                  0x040
 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
 
-extern void linux_wlan_free(void *vp);
 extern int linux_wlan_get_firmware(perInterface_wlan_t *p_nic);
 extern void linux_wlan_unlock(void *vp);
 extern u16 Set_machw_change_vir_if(bool bValue);
@@ -33,9 +32,9 @@ extern int mac_close(struct net_device *ndev);
 tstrNetworkInfo astrLastScannedNtwrksShadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
 u32 u32LastScannedNtwrksCountShadow;
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-WILC_TimerHandle hDuringIpTimer;
+struct timer_list hDuringIpTimer;
 #endif
-WILC_TimerHandle hAgingTimer;
+struct timer_list hAgingTimer;
 static u8 op_ifcs;
 extern u8 u8ConnectedSSID[6];
 
@@ -112,7 +111,7 @@ u8 u8P2P_oui[] = {0x50, 0x6f, 0x9A, 0x09};
 u8 u8P2Plocalrandom = 0x01;
 u8 u8P2Precvrandom = 0x00;
 u8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
-bool bWilc_ie = false;
+bool bWilc_ie;
 #endif
 
 static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
@@ -135,25 +134,23 @@ struct add_key_params g_add_ptk_key_params;
 struct wilc_wfi_key g_key_ptk_params;
 struct wilc_wfi_wep_key g_key_wep_params;
 u8 g_flushing_in_progress;
-bool g_ptk_keys_saved = false;
-bool g_gtk_keys_saved = false;
-bool g_wep_keys_saved = false;
+bool g_ptk_keys_saved;
+bool g_gtk_keys_saved;
+bool g_wep_keys_saved;
 
 #define AGING_TIME     (9 * 1000)
 #define duringIP_TIME 15000
 
 void clear_shadow_scan(void *pUserVoid)
 {
-       struct WILC_WFI_priv *priv;
        int i;
-       priv = (struct WILC_WFI_priv *)pUserVoid;
        if (op_ifcs == 0) {
-               WILC_TimerDestroy(&hAgingTimer, NULL);
+               del_timer_sync(&hAgingTimer);
                PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n");
 
                for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
                        if (astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs != NULL) {
-                               WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs);
+                               kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
                                astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs = NULL;
                        }
 
@@ -204,7 +201,7 @@ void refresh_scan(void *pUserVoid, uint8_t all, bool bDirectScan)
                                channel = ieee80211_get_channel(wiphy, s32Freq);
 
                                rssi = get_rssi_avg(pstrNetworkInfo);
-                               if (WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) {
+                               if (memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan)      {
                                        bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
                                                                  pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
                                                                  (size_t)pstrNetworkInfo->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL);
@@ -219,9 +216,7 @@ void refresh_scan(void *pUserVoid, uint8_t all, bool bDirectScan)
 
 void reset_shadow_found(void *pUserVoid)
 {
-       struct WILC_WFI_priv *priv;
        int i;
-       priv = (struct WILC_WFI_priv *)pUserVoid;
        for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
                astrLastScannedNtwrksShadow[i].u8Found = 0;
 
@@ -230,28 +225,24 @@ void reset_shadow_found(void *pUserVoid)
 
 void update_scan_time(void *pUserVoid)
 {
-       struct WILC_WFI_priv *priv;
        int i;
-       priv = (struct WILC_WFI_priv *)pUserVoid;
        for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
                astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
        }
 }
 
-void remove_network_from_shadow(void *pUserVoid)
+static void remove_network_from_shadow(unsigned long arg)
 {
-       struct WILC_WFI_priv *priv;
        unsigned long now = jiffies;
        int i, j;
 
-       priv = (struct WILC_WFI_priv *)pUserVoid;
 
        for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
                if (time_after(now, astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) {
-                       PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s \n", astrLastScannedNtwrksShadow[i].au8ssid);
+                       PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
 
                        if (astrLastScannedNtwrksShadow[i].pu8IEs != NULL) {
-                               WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs);
+                               kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
                                astrLastScannedNtwrksShadow[i].pu8IEs = NULL;
                        }
 
@@ -265,14 +256,16 @@ void remove_network_from_shadow(void *pUserVoid)
        }
 
        PRINT_D(CFG80211_DBG, "Number of cached networks: %d\n", u32LastScannedNtwrksCountShadow);
-       if (u32LastScannedNtwrksCountShadow != 0)
-               WILC_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, NULL);
-       else
+       if (u32LastScannedNtwrksCountShadow != 0) {
+               hAgingTimer.data = arg;
+               mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
+       } else {
                PRINT_D(CFG80211_DBG, "No need to restart Aging timer\n");
+       }
 }
 
 #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-void clear_duringIP(void *pUserVoid)
+static void clear_duringIP(unsigned long arg)
 {
        PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n");
        g_obtainingIP = false;
@@ -281,19 +274,18 @@ void clear_duringIP(void *pUserVoid)
 
 int8_t is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid)
 {
-       struct WILC_WFI_priv *priv;
        int8_t state = -1;
        int i;
 
-       priv = (struct WILC_WFI_priv *)pUserVoid;
        if (u32LastScannedNtwrksCountShadow == 0) {
                PRINT_D(CFG80211_DBG, "Starting Aging timer\n");
-               WILC_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, NULL);
+               hAgingTimer.data = (unsigned long)pUserVoid;
+               mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
                state = -1;
        } else {
                /* Linear search for now */
                for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
-                       if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
+                       if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
                                        pstrNetworkInfo->au8bssid, 6) == 0) {
                                state = i;
                                break;
@@ -305,11 +297,9 @@ int8_t is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid)
 
 void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams)
 {
-       struct WILC_WFI_priv *priv;
        int8_t ap_found = is_network_in_shadow(pstrNetworkInfo, pUserVoid);
        uint32_t ap_index = 0;
        uint8_t rssi_index = 0;
-       priv = (struct WILC_WFI_priv *)pUserVoid;
 
        if (u32LastScannedNtwrksCountShadow >= MAX_NUM_SCANNED_NETWORKS_SHADOW) {
                PRINT_D(CFG80211_DBG, "Shadow network reached its maximum limit\n");
@@ -334,10 +324,10 @@ void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, vo
        astrLastScannedNtwrksShadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo;
 
        astrLastScannedNtwrksShadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen;
-       WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
+       memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
                    pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen);
 
-       WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid,
+       memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid,
                    pstrNetworkInfo->au8bssid, ETH_ALEN);
 
        astrLastScannedNtwrksShadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod;
@@ -347,10 +337,10 @@ void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, vo
        astrLastScannedNtwrksShadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen;
        astrLastScannedNtwrksShadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf;
        if (ap_found != -1)
-               WILC_FREE(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
+               kfree(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
        astrLastScannedNtwrksShadow[ap_index].pu8IEs =
-               (u8 *)WILC_MALLOC(pstrNetworkInfo->u16IEsLen);        /* will be deallocated by the WILC_WFI_CfgScan() function */
-       WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs,
+               WILC_MALLOC(pstrNetworkInfo->u16IEsLen);        /* will be deallocated by the WILC_WFI_CfgScan() function */
+       memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs,
                    pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen);
 
        astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScan = jiffies;
@@ -406,7 +396,7 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo
                                WILC_NULLCHECK(s32Error, channel);
 
                                PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d,"
-                                          "BeaconPeriod: %d \n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100),
+                                          "BeaconPeriod: %d\n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100),
                                           pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod);
 
                                if (pstrNetworkInfo->bNewNetwork == true) {
@@ -426,7 +416,7 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo
 
                                                /*P2P peers are sent to WPA supplicant and added to shadow table*/
 
-                                               if (!(WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) {
+                                               if (!(memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) {
                                                        bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,  pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
                                                                                  pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
                                                                                  (size_t)pstrNetworkInfo->u16IEsLen, (((s32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL);
@@ -441,8 +431,8 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo
                                        u32 i;
                                        /* So this network is discovered before, we'll just update its RSSI */
                                        for (i = 0; i < priv->u32RcvdChCount; i++) {
-                                               if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) {
-                                                       PRINT_D(CFG80211_DBG, "Update RSSI of %s \n", astrLastScannedNtwrksShadow[i].au8ssid);
+                                               if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) {
+                                                       PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
 
                                                        astrLastScannedNtwrksShadow[i].s8rssi = pstrNetworkInfo->s8rssi;
                                                        astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
@@ -452,15 +442,14 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo
                                }
                        }
                } else if (enuScanEvent == SCAN_EVENT_DONE)    {
-                       PRINT_D(CFG80211_DBG, "Scan Done[%p] \n", priv->dev);
-                       PRINT_D(CFG80211_DBG, "Refreshing Scan ... \n");
+                       PRINT_D(CFG80211_DBG, "Scan Done[%p]\n", priv->dev);
+                       PRINT_D(CFG80211_DBG, "Refreshing Scan ...\n");
                        refresh_scan(priv, 1, false);
 
-                       if (priv->u32RcvdChCount > 0) {
-                               PRINT_D(CFG80211_DBG, "%d Network(s) found \n", priv->u32RcvdChCount);
-                       } else {
-                               PRINT_D(CFG80211_DBG, "No networks found \n");
-                       }
+                       if (priv->u32RcvdChCount > 0)
+                               PRINT_D(CFG80211_DBG, "%d Network(s) found\n", priv->u32RcvdChCount);
+                       else
+                               PRINT_D(CFG80211_DBG, "No networks found\n");
 
                        down(&(priv->hSemScanReq));
 
@@ -477,7 +466,7 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo
                else if (enuScanEvent == SCAN_EVENT_ABORTED) {
                        down(&(priv->hSemScanReq));
 
-                       PRINT_D(CFG80211_DBG, "Scan Aborted \n");
+                       PRINT_D(CFG80211_DBG, "Scan Aborted\n");
                        if (priv->pstrScanReq != NULL) {
 
                                update_scan_time(priv);
@@ -515,7 +504,7 @@ int WILC_WFI_Set_PMKSA(u8 *bssid, struct WILC_WFI_priv *priv)
 
        for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
 
-               if (!WILC_memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid,
+               if (!memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid,
                                 ETH_ALEN)) {
                        PRINT_D(CFG80211_DBG, "PMKID successful comparison");
 
@@ -586,7 +575,7 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
                         *  = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */
                        u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
                        linux_wlan_set_bssid(priv->dev, NullBssid);
-                       WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+                       memset(u8ConnectedSSID, 0, ETH_ALEN);
 
                        /*BugID_5457*/
                        /*Invalidate u8WLANChannel value on wlan0 disconnect*/
@@ -595,7 +584,7 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
                                u8WLANChannel = INVALID_CHANNEL;
                        #endif
 
-                       PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d \n", u16ConnectStatus, u8MacStatus);
+                       PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus);
                }
 
                if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
@@ -604,14 +593,14 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
 
                        PRINT_INFO(CFG80211_DBG, "Connection Successful:: BSSID: %x%x%x%x%x%x\n", pstrConnectInfo->au8bssid[0],
                                   pstrConnectInfo->au8bssid[1], pstrConnectInfo->au8bssid[2], pstrConnectInfo->au8bssid[3], pstrConnectInfo->au8bssid[4], pstrConnectInfo->au8bssid[5]);
-                       WILC_memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
+                       memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
 
                        /* BugID_4209: if this network has expired in the scan results in the above nl80211 layer, refresh them here by calling
                         *  cfg80211_inform_bss() with the last Scan results before calling cfg80211_connect_result() to avoid
                         *  Linux kernel warning generated at the nl80211 layer */
 
                        for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
-                               if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
+                               if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
                                                pstrConnectInfo->au8bssid, ETH_ALEN) == 0) {
                                        unsigned long now = jiffies;
 
@@ -652,9 +641,9 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
                u8P2Plocalrandom = 0x01;
                u8P2Precvrandom = 0x00;
                bWilc_ie = false;
-               WILC_memset(priv->au8AssociatedBss, 0, ETH_ALEN);
+               memset(priv->au8AssociatedBss, 0, ETH_ALEN);
                linux_wlan_set_bssid(priv->dev, NullBssid);
-               WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+               memset(u8ConnectedSSID, 0, ETH_ALEN);
 
                /*BugID_5457*/
                /*Invalidate u8WLANChannel value on wlan0 disconnect*/
@@ -675,7 +664,8 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent,
                        pstrDisconnectNotifInfo->u16reason = 1;
                }
                cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
-                                     pstrDisconnectNotifInfo->ie_len, GFP_KERNEL);
+                                     pstrDisconnectNotifInfo->ie_len, false,
+                                     GFP_KERNEL);
 
        }
 
@@ -747,7 +737,7 @@ static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *r
 
        priv->u32RcvdChCount = 0;
 
-       host_int_set_wfi_drv_handler((u32)priv->hWILCWFIDrv);
+       host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
 
 
        reset_shadow_found(priv);
@@ -777,20 +767,20 @@ static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *r
 
                                if (request->ssids[i].ssid != NULL && request->ssids[i].ssid_len != 0) {
                                        strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = WILC_MALLOC(request->ssids[i].ssid_len);
-                                       WILC_memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
+                                       memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
                                        strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len;
                                } else {
-                                       PRINT_D(CFG80211_DBG, "Received one NULL SSID \n");
+                                       PRINT_D(CFG80211_DBG, "Received one NULL SSID\n");
                                        strHiddenNetwork.u8ssidnum -= 1;
                                }
                        }
-                       PRINT_D(CFG80211_DBG, "Trigger Scan Request \n");
+                       PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
                        s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
                                                 au8ScanChanList, request->n_channels,
                                                 (const u8 *)request->ie, request->ie_len,
                                                 CfgScanResult, (void *)priv, &strHiddenNetwork);
                } else {
-                       PRINT_D(CFG80211_DBG, "Trigger Scan Request \n");
+                       PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
                        s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
                                                 au8ScanChanList, request->n_channels,
                                                 (const u8 *)request->ie, request->ie_len,
@@ -799,7 +789,7 @@ static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *r
 
        } else {
                PRINT_ER("Requested num of scanned channels is greater than the max, supported"
-                        " channels \n");
+                        " channels\n");
        }
 
        if (s32Error != WILC_SUCCESS) {
@@ -842,21 +832,21 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
        priv = wiphy_priv(wiphy);
        pstrWFIDrv = (tstrWILC_WFIDrv *)(priv->hWILCWFIDrv);
 
-       host_int_set_wfi_drv_handler((u32)priv->hWILCWFIDrv);
+       host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
 
        PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv);
        #ifdef WILC_P2P
-       if (!(WILC_strncmp(sme->ssid, "DIRECT-", 7))) {
+       if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
                PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
                pstrWFIDrv->u8P2PConnect = 1;
        } else
                pstrWFIDrv->u8P2PConnect = 0;
        #endif
-       PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d \n", sme->ssid, sme->auth_type);
+       PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
 
        for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
                if ((sme->ssid_len == astrLastScannedNtwrksShadow[i].u8SsidLen) &&
-                   WILC_memcmp(astrLastScannedNtwrksShadow[i].au8ssid,
+                   memcmp(astrLastScannedNtwrksShadow[i].au8ssid,
                                sme->ssid,
                                sme->ssid_len) == 0) {
                        PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid);
@@ -868,7 +858,7 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
                        } else {
                                /* BSSID is also passed from the user, so decision of matching
                                 * should consider also this passed BSSID */
-                               if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
+                               if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
                                                sme->bssid,
                                                ETH_ALEN) == 0) {
                                        PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n");
@@ -898,8 +888,8 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
        }
 
        priv->WILC_WFI_wep_default = 0;
-       WILC_memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
-       WILC_memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
+       memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
+       memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
 
        PRINT_INFO(CFG80211_DBG, "sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions);
        PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group);
@@ -928,7 +918,7 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
                        }
                        priv->WILC_WFI_wep_default = sme->key_idx;
                        priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
-                       WILC_memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
+                       memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
 
                        /*BugID_5137*/
                        g_key_wep_params.key_len = sme->key_len;
@@ -946,7 +936,7 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
 
                        priv->WILC_WFI_wep_default = sme->key_idx;
                        priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
-                       WILC_memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
+                       memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
 
                        /*BugID_5137*/
                        g_key_wep_params.key_len = sme->key_len;
@@ -1057,7 +1047,7 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev,
                                         tenuAuth_type, pstrNetworkInfo->u8channel,
                                         pstrNetworkInfo->pJoinParams);
        if (s32Error != WILC_SUCCESS) {
-               PRINT_ER("host_int_set_join_req(): Error(%d) \n", s32Error);
+               PRINT_ER("host_int_set_join_req(): Error(%d)\n", s32Error);
                s32Error = -ENOENT;
                goto done;
        }
@@ -1162,7 +1152,7 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
 
                        priv->WILC_WFI_wep_default = key_index;
                        priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
-                       WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
+                       memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
 
                        PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n", key_index);
                        PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n", params->key_len);
@@ -1181,10 +1171,10 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
                        break;
                }
                                #endif
-               if (WILC_memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
+               if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
                        priv->WILC_WFI_wep_default = key_index;
                        priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
-                       WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
+                       memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
 
                        PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n", key_index);
                        PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n", params->key_len);
@@ -1203,21 +1193,20 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
                if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
 
                        if (priv->wilc_gtk[key_index] == NULL) {
-                               priv->wilc_gtk[key_index] = (struct wilc_wfi_key *)WILC_MALLOC(sizeof(struct wilc_wfi_key));
+                               priv->wilc_gtk[key_index] = WILC_MALLOC(sizeof(struct wilc_wfi_key));
                                priv->wilc_gtk[key_index]->key = NULL;
                                priv->wilc_gtk[key_index]->seq = NULL;
 
                        }
                        if (priv->wilc_ptk[key_index] == NULL) {
-                               priv->wilc_ptk[key_index] = (struct wilc_wfi_key *)WILC_MALLOC(sizeof(struct wilc_wfi_key));
+                               priv->wilc_ptk[key_index] = WILC_MALLOC(sizeof(struct wilc_wfi_key));
                                priv->wilc_ptk[key_index]->key = NULL;
                                priv->wilc_ptk[key_index]->seq = NULL;
                        }
 
 
 
-                       if (!pairwise)
-                       {
+                       if (!pairwise) {
                                if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
                                        u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
                                else
@@ -1233,18 +1222,18 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
                                }
                                /* if there has been previous allocation for the same index through its key, free that memory and allocate again*/
                                if (priv->wilc_gtk[key_index]->key)
-                                       WILC_FREE(priv->wilc_gtk[key_index]->key);
+                                       kfree(priv->wilc_gtk[key_index]->key);
 
-                               priv->wilc_gtk[key_index]->key = (u8 *)WILC_MALLOC(params->key_len);
-                               WILC_memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
+                               priv->wilc_gtk[key_index]->key = WILC_MALLOC(params->key_len);
+                               memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
 
                                /* if there has been previous allocation for the same index through its seq, free that memory and allocate again*/
                                if (priv->wilc_gtk[key_index]->seq)
-                                       WILC_FREE(priv->wilc_gtk[key_index]->seq);
+                                       kfree(priv->wilc_gtk[key_index]->seq);
 
                                if ((params->seq_len) > 0) {
-                                       priv->wilc_gtk[key_index]->seq = (u8 *)WILC_MALLOC(params->seq_len);
-                                       WILC_memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
+                                       priv->wilc_gtk[key_index]->seq = WILC_MALLOC(params->seq_len);
+                                       memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
                                }
 
                                priv->wilc_gtk[key_index]->cipher = params->cipher;
@@ -1279,15 +1268,15 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
                                }
 
                                if (priv->wilc_ptk[key_index]->key)
-                                       WILC_FREE(priv->wilc_ptk[key_index]->key);
+                                       kfree(priv->wilc_ptk[key_index]->key);
 
-                               priv->wilc_ptk[key_index]->key = (u8 *)WILC_MALLOC(params->key_len);
+                               priv->wilc_ptk[key_index]->key = WILC_MALLOC(params->key_len);
 
                                if (priv->wilc_ptk[key_index]->seq)
-                                       WILC_FREE(priv->wilc_ptk[key_index]->seq);
+                                       kfree(priv->wilc_ptk[key_index]->seq);
 
                                if ((params->seq_len) > 0)
-                                       priv->wilc_ptk[key_index]->seq = (u8 *)WILC_MALLOC(params->seq_len);
+                                       priv->wilc_ptk[key_index]->seq = WILC_MALLOC(params->seq_len);
 
                                if (INFO) {
                                        for (i = 0; i < params->key_len; i++)
@@ -1297,10 +1286,10 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
                                                PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
                                }
 
-                               WILC_memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
+                               memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
 
                                if ((params->seq_len) > 0)
-                                       WILC_memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
+                                       memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
 
                                priv->wilc_ptk[key_index]->cipher = params->cipher;
                                priv->wilc_ptk[key_index]->key_len = params->key_len;
@@ -1315,8 +1304,7 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k
 
                {
                        u8mode = 0;
-                       if (!pairwise)
-                       {
+                       if (!pairwise) {
                                if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
                                        /* swap the tx mic by rx mic */
                                        pu8RxMic = params->key + 24;
@@ -1437,7 +1425,7 @@ static int WILC_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev,
 
                /*Delete saved WEP keys params, if any*/
                if (g_key_wep_params.key != NULL) {
-                       WILC_FREE(g_key_wep_params.key);
+                       kfree(g_key_wep_params.key);
                        g_key_wep_params.key = NULL;
                }
 
@@ -1448,16 +1436,16 @@ static int WILC_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev,
 
                        if (priv->wilc_gtk[key_index]->key != NULL) {
 
-                               WILC_FREE(priv->wilc_gtk[key_index]->key);
+                               kfree(priv->wilc_gtk[key_index]->key);
                                priv->wilc_gtk[key_index]->key = NULL;
                        }
                        if (priv->wilc_gtk[key_index]->seq) {
 
-                               WILC_FREE(priv->wilc_gtk[key_index]->seq);
+                               kfree(priv->wilc_gtk[key_index]->seq);
                                priv->wilc_gtk[key_index]->seq = NULL;
                        }
 
-                       WILC_FREE(priv->wilc_gtk[key_index]);
+                       kfree(priv->wilc_gtk[key_index]);
                        priv->wilc_gtk[key_index] = NULL;
 
                }
@@ -1466,35 +1454,35 @@ static int WILC_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev,
 
                        if (priv->wilc_ptk[key_index]->key) {
 
-                               WILC_FREE(priv->wilc_ptk[key_index]->key);
+                               kfree(priv->wilc_ptk[key_index]->key);
                                priv->wilc_ptk[key_index]->key = NULL;
                        }
                        if (priv->wilc_ptk[key_index]->seq) {
 
-                               WILC_FREE(priv->wilc_ptk[key_index]->seq);
+                               kfree(priv->wilc_ptk[key_index]->seq);
                                priv->wilc_ptk[key_index]->seq = NULL;
                        }
-                       WILC_FREE(priv->wilc_ptk[key_index]);
+                       kfree(priv->wilc_ptk[key_index]);
                        priv->wilc_ptk[key_index] = NULL;
                }
        #endif
 
                /*Delete saved PTK and GTK keys params, if any*/
                if (g_key_ptk_params.key != NULL) {
-                       WILC_FREE(g_key_ptk_params.key);
+                       kfree(g_key_ptk_params.key);
                        g_key_ptk_params.key = NULL;
                }
                if (g_key_ptk_params.seq != NULL) {
-                       WILC_FREE(g_key_ptk_params.seq);
+                       kfree(g_key_ptk_params.seq);
                        g_key_ptk_params.seq = NULL;
                }
 
                if (g_key_gtk_params.key != NULL) {
-                       WILC_FREE(g_key_gtk_params.key);
+                       kfree(g_key_gtk_params.key);
                        g_key_gtk_params.key = NULL;
                }
                if (g_key_gtk_params.seq != NULL) {
-                       WILC_FREE(g_key_gtk_params.seq);
+                       kfree(g_key_gtk_params.seq);
                        g_key_gtk_params.seq = NULL;
                }
 
@@ -1503,7 +1491,7 @@ static int WILC_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev,
        }
 
        if (key_index >= 0 && key_index <= 3) {
-               WILC_memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
+               memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
                priv->WILC_WFI_wep_key_len[key_index] = 0;
 
                PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index);
@@ -1588,7 +1576,7 @@ static int WILC_WFI_set_default_key(struct wiphy *wiphy, struct net_device *netd
 
        priv = wiphy_priv(wiphy);
 
-       PRINT_D(CFG80211_DBG, "Setting default key with idx = %d \n", key_index);
+       PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index);
 
        if (key_index != priv->WILC_WFI_wep_default) {
 
@@ -1633,7 +1621,6 @@ static int WILC_WFI_dump_survey(struct wiphy *wiphy, struct net_device *netdev,
  *  @version   1.0
  */
 
-extern uint32_t Statisitcs_totalAcks, Statisitcs_DroppedAcks;
 static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev,
                                const u8 *mac, struct station_info *sinfo)
 {
@@ -1689,7 +1676,7 @@ static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev,
                 * kernel version 3.0.0
                 */
                sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
-                                               BIT( NL80211_STA_INFO_RX_PACKETS) |
+                                               BIT(NL80211_STA_INFO_RX_PACKETS) |
                                                BIT(NL80211_STA_INFO_TX_PACKETS) |
                                                BIT(NL80211_STA_INFO_TX_FAILED) |
                                                BIT(NL80211_STA_INFO_TX_BITRATE);
@@ -1701,11 +1688,10 @@ static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev,
                sinfo->txrate.legacy = strStatistics.u8LinkSpeed * 10;
 
 #ifdef TCP_ENHANCEMENTS
-               if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)) {
+               if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED))
                        Enable_TCP_ACK_Filter(true);
-               } else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)   {
+               else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)
                        Enable_TCP_ACK_Filter(false);
-               }
 #endif
 
                PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets,
@@ -1826,7 +1812,7 @@ static int WILC_WFI_set_wiphy_params(struct wiphy *wiphy, u32 changed)
        priv = wiphy_priv(wiphy);
 
        pstrCfgParamVal.u32SetCfgFlag = 0;
-       PRINT_D(CFG80211_DBG, "Setting Wiphy params \n");
+       PRINT_D(CFG80211_DBG, "Setting Wiphy params\n");
 
        if (changed & WIPHY_PARAM_RETRY_SHORT) {
                PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n",
@@ -1909,7 +1895,7 @@ static int WILC_WFI_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
 
        for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
-               if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
+               if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
                                 ETH_ALEN)) {
                        /*If bssid already exists and pmkid value needs to reset*/
                        flag = PMKID_FOUND;
@@ -1919,9 +1905,9 @@ static int WILC_WFI_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
        }
        if (i < WILC_MAX_NUM_PMKIDS) {
                PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n");
-               WILC_memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
+               memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
                            ETH_ALEN);
-               WILC_memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
+               memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
                            PMKID_LEN);
                if (!(flag == PMKID_FOUND))
                        priv->pmkid_list.numpmkid++;
@@ -1959,11 +1945,11 @@ static int WILC_WFI_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
        PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n");
 
        for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
-               if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
+               if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
                                 ETH_ALEN)) {
                        /*If bssid is found, reset the values*/
                        PRINT_D(CFG80211_DBG, "Reseting PMKID values\n");
-                       WILC_memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid));
+                       memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid));
                        flag = PMKID_FOUND;
                        break;
                }
@@ -1971,10 +1957,10 @@ static int WILC_WFI_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
        if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
                for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
-                       WILC_memcpy(priv->pmkid_list.pmkidlist[i].bssid,
+                       memcpy(priv->pmkid_list.pmkidlist[i].bssid,
                                    priv->pmkid_list.pmkidlist[i + 1].bssid,
                                    ETH_ALEN);
-                       WILC_memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
+                       memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
                                    priv->pmkid_list.pmkidlist[i].pmkid,
                                    PMKID_LEN);
                }
@@ -2002,7 +1988,7 @@ static int  WILC_WFI_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
        PRINT_D(CFG80211_DBG,  "Flushing  PMKID key values\n");
 
        /*Get cashed Pmkids and set all with zeros*/
-       WILC_memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr));
+       memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr));
 
        return 0;
 }
@@ -2074,11 +2060,10 @@ void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len)
                }
                #endif  /* USE_SUPPLICANT_GO_INTENT */
 
-               if (buf[index] ==  CHANLIST_ATTR_ID) {
+               if (buf[index] ==  CHANLIST_ATTR_ID)
                        channel_list_attr_index = index;
-               } else if (buf[index] ==  OPERCHAN_ATTR_ID)   {
+               else if (buf[index] ==  OPERCHAN_ATTR_ID)
                        op_channel_attr_index = index;
-               }
                index += buf[index + 1] + 3; /* ID,Length byte */
        }
 
@@ -2160,11 +2145,10 @@ void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype)
                }
                #endif
 
-               if (buf[index] ==  CHANLIST_ATTR_ID) {
+               if (buf[index] ==  CHANLIST_ATTR_ID)
                        channel_list_attr_index = index;
-               } else if (buf[index] ==  OPERCHAN_ATTR_ID)   {
+               else if (buf[index] ==  OPERCHAN_ATTR_ID)
                        op_channel_attr_index = index;
-               }
                index += buf[index + 1] + 3; /* ID,Length byte */
        }
 
@@ -2218,7 +2202,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, uint8_t *buff, uint32_t size)
        pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
 
        /* Get WILC header */
-       WILC_memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
+       memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
 
        /* The packet offset field conain info about what type of managment frame */
        /* we are dealing with and ack status */
@@ -2270,11 +2254,11 @@ void WILC_WFI_p2p_rx (struct net_device *dev, uint8_t *buff, uint32_t size)
                                case PUBLIC_ACT_VENDORSPEC:
                                        /*Now we have a public action vendor specific action frame, check if its a p2p public action frame
                                         * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
-                                       if (!WILC_memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
+                                       if (!memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
                                                if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
                                                        if (!bWilc_ie) {
                                                                for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
-                                                                       if (!WILC_memcmp(u8P2P_vendorspec, &buff[i], 6)) {
+                                                                       if (!memcmp(u8P2P_vendorspec, &buff[i], 6)) {
                                                                                u8P2Precvrandom = buff[i + 6];
                                                                                bWilc_ie = true;
                                                                                PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", u8P2Precvrandom);
@@ -2287,7 +2271,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, uint8_t *buff, uint32_t size)
                                                        if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
                                                              || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
                                                                for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
-                                                                       if (buff[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buff[i + 2], 4))) {
+                                                                       if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buff[i + 2], 4))) {
                                                                                WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
                                                                                break;
                                                                        }
@@ -2351,7 +2335,7 @@ static void WILC_WFI_RemainOnChannelReady(void *pUserVoid)
        struct WILC_WFI_priv *priv;
        priv = (struct WILC_WFI_priv *)pUserVoid;
 
-       PRINT_D(HOSTINF_DBG, "Remain on channel ready \n");
+       PRINT_D(HOSTINF_DBG, "Remain on channel ready\n");
 
        priv->bInP2PlistenState = true;
 
@@ -2379,7 +2363,7 @@ static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID)
 
        /*BugID_5477*/
        if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
-               PRINT_D(GENERIC_DBG, "Remain on channel expired \n");
+               PRINT_D(GENERIC_DBG, "Remain on channel expired\n");
 
                priv->bInP2PlistenState = false;
 
@@ -2485,7 +2469,7 @@ static int   WILC_WFI_cancel_remain_on_channel(struct wiphy *wiphy,
  */
 void WILC_WFI_add_wilcvendorspec(u8 *buff)
 {
-       WILC_memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
+       memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
 }
 /**
  *  @brief      WILC_WFI_mgmt_tx_frame
@@ -2528,17 +2512,17 @@ int WILC_WFI_mgmt_tx(struct wiphy *wiphy,
        if (ieee80211_is_mgmt(mgmt->frame_control)) {
 
                /*mgmt frame allocation*/
-               mgmt_tx = (struct p2p_mgmt_data *)WILC_MALLOC(sizeof(struct p2p_mgmt_data));
+               mgmt_tx = WILC_MALLOC(sizeof(struct p2p_mgmt_data));
                if (mgmt_tx == NULL) {
                        PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
                        return WILC_FAIL;
                }
-               mgmt_tx->buff = (char *)WILC_MALLOC(buf_len);
+               mgmt_tx->buff = WILC_MALLOC(buf_len);
                if (mgmt_tx->buff == NULL) {
                        PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
                        return WILC_FAIL;
                }
-               WILC_memcpy(mgmt_tx->buff, buf, len);
+               memcpy(mgmt_tx->buff, buf, len);
                mgmt_tx->size = len;
 
 
@@ -2583,7 +2567,7 @@ int WILC_WFI_mgmt_tx(struct wiphy *wiphy,
                                {
                                        /*Now we have a public action vendor specific action frame, check if its a p2p public action frame
                                         * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
-                                       if (!WILC_memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
+                                       if (!memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
                                                /*For the connection of two WILC's connection generate a rand number to determine who will be a GO*/
                                                if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
                                                        if (u8P2Plocalrandom == 1 && u8P2Precvrandom < u8P2Plocalrandom) {
@@ -2600,7 +2584,7 @@ int WILC_WFI_mgmt_tx(struct wiphy *wiphy,
 
                                                                /*Search for the p2p information information element , after the Public action subtype theres a byte for teh dialog token, skip that*/
                                                                for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
-                                                                       if (buf[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buf[i + 2], 4))) {
+                                                                       if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buf[i + 2], 4))) {
                                                                                if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
                                                                                        WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, nic->iftype);
 
@@ -2862,7 +2846,7 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
 
        #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
        g_obtainingIP = false;
-       WILC_TimerStop(&hDuringIpTimer, NULL);
+       del_timer(&hDuringIpTimer);
        PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
        #endif
        /*BugID_5137*/
@@ -2886,7 +2870,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
 
                /*Remove the enteries of the previously connected clients*/
                memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
-               #ifndef SIMULATION
                #ifdef WILC_P2P
                interface_type = nic->iftype;
                nic->iftype = STATION_MODE;
@@ -2907,15 +2890,15 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
 
                        /*Setting interface 1 drv handler and mac address in newly downloaded FW*/
                        host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
-                       host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                       host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
                        host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
 
                        /*Add saved WEP keys, if any*/
                        if (g_wep_keys_saved) {
-                               host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                               host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                             g_key_wep_params.key_idx);
-                               host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                               host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                             g_key_wep_params.key,
                                                             g_key_wep_params.key_len,
                                                             g_key_wep_params.key_idx);
@@ -2964,7 +2947,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                        host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0);
                }
                #endif
-               #endif
                break;
 
        case NL80211_IFTYPE_P2P_CLIENT:
@@ -2979,7 +2961,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                priv->wdev->iftype = type;
                nic->monitor_flag = 0;
 
-               #ifndef SIMULATION
                #ifdef WILC_P2P
 
                PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
@@ -2995,15 +2976,15 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                        g_wilc_initialized = 1;
 
                        host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
-                       host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                       host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
                        host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
 
                        /*Add saved WEP keys, if any*/
                        if (g_wep_keys_saved) {
-                               host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                               host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                             g_key_wep_params.key_idx);
-                               host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                               host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                             g_key_wep_params.key,
                                                             g_key_wep_params.key_len,
                                                             g_key_wep_params.key_idx);
@@ -3053,7 +3034,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                        }
                }
                #endif
-               #endif
                break;
 
        case NL80211_IFTYPE_AP:
@@ -3064,7 +3044,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                nic->iftype = AP_MODE;
                PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
 
-               #ifndef SIMULATION
                PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n");
                linux_wlan_get_firmware(nic);
                #ifdef WILC_P2P
@@ -3086,7 +3065,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                        }
                }
                #endif
-               #endif
                break;
 
        case NL80211_IFTYPE_P2P_GO:
@@ -3094,7 +3072,7 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
 
                #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
                g_obtainingIP = true;
-               WILC_TimerStart(&hDuringIpTimer, duringIP_TIME, NULL, NULL);
+               mod_timer(&hDuringIpTimer, jiffies + msecs_to_jiffies(duringIP_TIME));
                #endif
                host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
                /*BugID_5222*/
@@ -3110,7 +3088,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
 
                PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
 
-               #ifndef SIMULATION
                #ifdef WILC_P2P
                PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
 
@@ -3127,15 +3104,15 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
 
                /*Setting interface 1 drv handler and mac address in newly downloaded FW*/
                host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
-               host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+               host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                        g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
                host_int_set_operation_mode(priv->hWILCWFIDrv, AP_MODE);
 
                /*Add saved WEP keys, if any*/
                if (g_wep_keys_saved) {
-                       host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                       host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                     g_key_wep_params.key_idx);
-                       host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+                       host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
                                                     g_key_wep_params.key,
                                                     g_key_wep_params.key_len,
                                                     g_key_wep_params.key_idx);
@@ -3185,7 +3162,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev
                        }
                }
                #endif
-               #endif
                break;
 
        default:
@@ -3234,7 +3210,7 @@ static int WILC_WFI_start_ap(struct wiphy *wiphy, struct net_device *dev,
        priv = wiphy_priv(wiphy);
        PRINT_D(HOSTAPD_DBG, "Starting ap\n");
 
-       PRINT_D(HOSTAPD_DBG, "Interval = %d \n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
+       PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
                settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len);
 
        s32Error = WILC_WFI_CfgSetChannel(wiphy, &settings->chandef);
@@ -3353,7 +3329,7 @@ static int  WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev,
 {
        s32 s32Error = WILC_SUCCESS;
        struct WILC_WFI_priv *priv;
-       tstrWILC_AddStaParam strStaParams = {{0}};
+       tstrWILC_AddStaParam strStaParams = { {0} };
        perInterface_wlan_t *nic;
 
 
@@ -3365,8 +3341,8 @@ static int  WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
                #ifndef WILC_FULLY_HOSTING_AP
 
-               WILC_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
-               WILC_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
+               memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
+               memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
                strStaParams.u16AssocID = params->aid;
                strStaParams.u8NumRates = params->supported_rates_len;
                strStaParams.pu8Rates = params->supported_rates;
@@ -3384,7 +3360,7 @@ static int  WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev,
                        strStaParams.bIsHTSupported = true;
                        strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
                        strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
-                       WILC_memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
+                       memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
                        strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
                        strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
                        strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
@@ -3407,7 +3383,7 @@ static int  WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev,
 
                #else
                PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid);
-               WILC_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
+               memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
 
                PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4],
                        priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]);
@@ -3450,7 +3426,7 @@ static int WILC_WFI_del_station(struct wiphy *wiphy, struct net_device *dev,
 
 
                if (mac == NULL) {
-                       PRINT_D(HOSTAPD_DBG, "All associated stations \n");
+                       PRINT_D(HOSTAPD_DBG, "All associated stations\n");
                        s32Error = host_int_del_allstation(priv->hWILCWFIDrv, priv->assoc_stainfo.au8Sta_AssociatedBss);
                } else {
                        PRINT_D(HOSTAPD_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
@@ -3484,7 +3460,7 @@ static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev,
 {
        s32 s32Error = WILC_SUCCESS;
        struct WILC_WFI_priv *priv;
-       tstrWILC_AddStaParam strStaParams = {{0}};
+       tstrWILC_AddStaParam strStaParams = { {0} };
        perInterface_wlan_t *nic;
 
 
@@ -3498,7 +3474,7 @@ static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev,
        if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
                #ifndef WILC_FULLY_HOSTING_AP
 
-               WILC_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
+               memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
                strStaParams.u16AssocID = params->aid;
                strStaParams.u8NumRates = params->supported_rates_len;
                strStaParams.pu8Rates = params->supported_rates;
@@ -3514,7 +3490,7 @@ static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev,
                        strStaParams.bIsHTSupported = true;
                        strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
                        strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
-                       WILC_memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
+                       memcpy(strStaParams.au8SuppMCsSet, &params->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
                        strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
                        strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
                        strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
@@ -3581,13 +3557,8 @@ struct wireless_dev *WILC_WFI_add_virt_intf(struct wiphy *wiphy, const char *nam
                new_ifc = WILC_WFI_init_mon_interface(name, nic->wilc_netdev);
                if (new_ifc != NULL) {
                        PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n");
-                       #ifdef SIMULATION
-                       priv = netdev_priv(priv->wdev->netdev);
-                       priv->monitor_flag = 1;
-                       #else
                        nic = netdev_priv(priv->wdev->netdev);
                        nic->monitor_flag = 1;
-                       #endif
                } else
                        PRINT_ER("Error in initializing monitor interface\n ");
        }
@@ -3856,9 +3827,9 @@ int WILC_WFI_InitHostInt(struct net_device *net)
        PRINT_D(INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr);
        priv = wdev_priv(net->ieee80211_ptr);
        if (op_ifcs == 0) {
-               s32Error = WILC_TimerCreate(&(hAgingTimer), remove_network_from_shadow, NULL);
+               setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
                #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-               s32Error = WILC_TimerCreate(&(hDuringIpTimer), clear_duringIP, NULL);
+               setup_timer(&hDuringIpTimer, clear_duringIP, 0);
                #endif
        }
        op_ifcs++;
@@ -3908,7 +3879,7 @@ int WILC_WFI_DeInitHostInt(struct net_device *net)
        #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
        if (op_ifcs == 0) {
                PRINT_D(CORECONFIG_DBG, "destroy during ip\n");
-               WILC_TimerDestroy(&hDuringIpTimer, NULL);
+               del_timer_sync(&hDuringIpTimer);
        }
        #endif
 
index c25350cb58c8e2a6331c8e1a4831c451fe127eb8..97b663b7fd1496952097ddab1d053342c33298bf 100644 (file)
@@ -123,7 +123,7 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi
 #ifdef TCP_ENHANCEMENTS
 #define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
 #define DEFAULT_LINK_SPEED 72
-extern void Enable_TCP_ACK_Filter(bool value);
+void Enable_TCP_ACK_Filter(bool value);
 #endif
 
 #endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.c b/drivers/staging/wilc1000/wilc_wfi_netdevice.c
deleted file mode 100644 (file)
index ab66ce4..0000000
+++ /dev/null
@@ -1,951 +0,0 @@
-/*!
- *  @file      wilc_wfi_netdevice.c
- *  @brief     File Operations OS wrapper functionality
- *  @author    mdaftedar
- *  @sa                wilc_wfi_netdevice.h
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-
-#ifdef SIMULATION
-
-#include "wilc_wfi_cfgoperations.h"
-#include "host_interface.h"
-
-
-MODULE_AUTHOR("Mai Daftedar");
-MODULE_LICENSE("Dual BSD/GPL");
-
-
-struct net_device *WILC_WFI_devs[2];
-
-/*
- * Transmitter lockup simulation, normally disabled.
- */
-static int lockup;
-module_param(lockup, int, 0);
-
-static int timeout = WILC_WFI_TIMEOUT;
-module_param(timeout, int, 0);
-
-/*
- * Do we run in NAPI mode?
- */
-static int use_napi ;
-module_param(use_napi, int, 0);
-
-
-/*
- * A structure representing an in-flight packet.
- */
-struct WILC_WFI_packet {
-       struct WILC_WFI_packet *next;
-       struct net_device *dev;
-       int datalen;
-       u8 data[ETH_DATA_LEN];
-};
-
-
-
-int pool_size = 8;
-module_param(pool_size, int, 0);
-
-
-static void WILC_WFI_TxTimeout(struct net_device *dev);
-static void (*WILC_WFI_Interrupt)(int, void *, struct pt_regs *);
-
-/**
- *  @brief      WILC_WFI_SetupPool
- *  @details    Set up a device's packet pool.
- *  @param[in]  struct net_device *dev : Network Device Pointer
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_SetupPool(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       int i;
-       struct WILC_WFI_packet *pkt;
-
-       priv->ppool = NULL;
-       for (i = 0; i < pool_size; i++) {
-               pkt = kmalloc (sizeof (struct WILC_WFI_packet), GFP_KERNEL);
-               if (pkt == NULL) {
-                       PRINT_D(RX_DBG, "Ran out of memory allocating packet pool\n");
-                       return;
-               }
-               pkt->dev = dev;
-               pkt->next = priv->ppool;
-               priv->ppool = pkt;
-       }
-}
-
-/**
- *  @brief      WILC_WFI_TearDownPool
- *  @details    Internal cleanup function that's called after the network device
- *              driver is unregistered
- *  @param[in]  struct net_device *dev : Network Device Driver
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_TearDownPool(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       struct WILC_WFI_packet *pkt;
-
-       while ((pkt = priv->ppool)) {
-               priv->ppool = pkt->next;
-               kfree (pkt);
-               /* FIXME - in-flight packets ? */
-       }
-}
-
-/**
- *  @brief      WILC_WFI_GetTxBuffer
- *  @details    Buffer/pool management
- *  @param[in]  net_device *dev : Network Device Driver Structure
- *  @return     struct WILC_WFI_packet
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-struct WILC_WFI_packet *WILC_WFI_GetTxBuffer(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       unsigned long flags;
-       struct WILC_WFI_packet *pkt;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       pkt = priv->ppool;
-       priv->ppool = pkt->next;
-       if (priv->ppool == NULL) {
-               PRINT_INFO(RX_DBG, "Pool empty\n");
-               netif_stop_queue(dev);
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return pkt;
-}
-/**
- *  @brief      WILC_WFI_ReleaseBuffer
- *  @details    Buffer/pool management
- *  @param[in]  WILC_WFI_packet *pkt : Structure holding in-flight packet
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_ReleaseBuffer(struct WILC_WFI_packet *pkt)
-{
-       unsigned long flags;
-       struct WILC_WFI_priv *priv = netdev_priv(pkt->dev);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       pkt->next = priv->ppool;
-       priv->ppool = pkt;
-       spin_unlock_irqrestore(&priv->lock, flags);
-       if (netif_queue_stopped(pkt->dev) && pkt->next == NULL)
-               netif_wake_queue(pkt->dev);
-}
-
-/**
- *  @brief      WILC_WFI_EnqueueBuf
- *  @details    Enqueuing packets in an RX buffer queue
- *  @param[in]  WILC_WFI_packet *pkt : Structure holding in-flight packet
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_EnqueueBuf(struct net_device *dev, struct WILC_WFI_packet *pkt)
-{
-       unsigned long flags;
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       pkt->next = priv->rx_queue;   /* FIXME - misorders packets */
-       priv->rx_queue = pkt;
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/**
- *  @brief      WILC_WFI_DequeueBuf
- *  @details    Dequeuing packets from the RX buffer queue
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @return     WILC_WFI_packet *pkt : Structure holding in-flight pac
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-struct WILC_WFI_packet *WILC_WFI_DequeueBuf(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       struct WILC_WFI_packet *pkt;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       pkt = priv->rx_queue;
-       if (pkt != NULL)
-               priv->rx_queue = pkt->next;
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return pkt;
-}
-/**
- *  @brief      WILC_WFI_RxInts
- *  @details    Enable and disable receive interrupts.
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @param[in] enable : Enable/Disable flag
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-static void WILC_WFI_RxInts(struct net_device *dev, int enable)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       priv->rx_int_enabled = enable;
-}
-
-/**
- *  @brief      WILC_WFI_Open
- *  @details    Open Network Device Driver, called when the network
- *              interface is opened. It starts the interface's transmit queue.
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @param[in] enable : Enable/Disable flag
- *  @return     int : Returns 0 upon success.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_Open(struct net_device *dev)
-{
-       /* request_region(), request_irq(), ....  (like fops->open) */
-       /*
-        * Assign the hardware address of the board: use "\0SNULx", where
-        * x is 0 or 1. The first byte is '\0' to avoid being a multicast
-        * address (the first byte of multicast addrs is odd).
-        */
-       memcpy(dev->dev_addr, "\0WLAN0", ETH_ALEN);
-       if (dev == WILC_WFI_devs[1])
-               dev->dev_addr[ETH_ALEN - 1]++;  /* \0SNUL1 */
-
-       WILC_WFI_InitHostInt(dev);
-       netif_start_queue(dev);
-       return 0;
-}
-/**
- *  @brief      WILC_WFI_Release
- *  @details    Release Network Device Driver, called when the network
- *              interface is stopped or brought down. This function marks
- *              the network driver as not being able to transmit
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @return     int : Return 0 on Success.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_Release(struct net_device *dev)
-{
-       /* release ports, irq and such -- like fops->close */
-
-       netif_stop_queue(dev); /* can't transmit any more */
-
-       return 0;
-}
-/**
- *  @brief      WILC_WFI_Config
- *  @details    Configuration changes (passed on by ifconfig)
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @param[in] struct ifmap *map : Contains the ioctl implementation for the
- *              network driver.
- *  @return     int : Return 0 on Success.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_Config(struct net_device *dev, struct ifmap *map)
-{
-       if (dev->flags & IFF_UP) /* can't act on a running interface */
-               return -EBUSY;
-
-       /* Don't allow changing the I/O address */
-       if (map->base_addr != dev->base_addr) {
-               PRINT_D(RX_DBG, KERN_WARNING "WILC_WFI: Can't change I/O address\n");
-               return -EOPNOTSUPP;
-       }
-
-       /* Allow changing the IRQ */
-       if (map->irq != dev->irq) {
-               dev->irq = map->irq;
-               /* request_irq() is delayed to open-time */
-       }
-
-       /* ignore other fields */
-       return 0;
-}
-/**
- *  @brief      WILC_WFI_Rx
- *  @details    Receive a packet: retrieve, encapsulate and pass over to upper
- *              levels
- *  @param[in]   net_device *dev : Network Device Driver Structure
- *  @param[in] WILC_WFI_packet :
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_Rx(struct net_device *dev, struct WILC_WFI_packet *pkt)
-{
-       int i;
-       struct sk_buff *skb;
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       s8 rssi;
-       /*
-        * The packet has been retrieved from the transmission
-        * medium. Build an skb around it, so upper layers can handle it
-        */
-
-
-       skb = dev_alloc_skb(pkt->datalen + 2);
-       if (!skb) {
-               if (printk_ratelimit())
-                       PRINT_D(RX_DBG, "WILC_WFI rx: low on mem - packet dropped\n");
-               priv->stats.rx_dropped++;
-               goto out;
-       }
-       skb_reserve(skb, 2);  /* align IP on 16B boundary */
-       memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
-
-       if (priv->monitor_flag) {
-               PRINT_INFO(RX_DBG, "In monitor device name %s\n", dev->name);
-               priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy);
-               PRINT_D(RX_DBG, "VALUE PASSED IN OF HRWD %p\n", priv->hWILCWFIDrv);
-               /* host_int_get_rssi(priv->hWILCWFIDrv, &(rssi)); */
-               if (INFO) {
-                       for (i = 14; i < skb->len; i++)
-                               PRINT_INFO(RX_DBG, "RXdata[%d] %02x\n", i, skb->data[i]);
-               }
-               WILC_WFI_monitor_rx(dev, skb);
-               return;
-       }
-out:
-       return;
-}
-
-/**
- *  @brief      WILC_WFI_Poll
- *  @details    The poll implementation
- *  @param[in]   struct napi_struct *napi :
- *  @param[in] int budget :
- *  @return     int : Return 0 on Success.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-static int WILC_WFI_Poll(struct napi_struct *napi, int budget)
-{
-       int npackets = 0;
-       struct sk_buff *skb;
-       struct WILC_WFI_priv  *priv = container_of(napi, struct WILC_WFI_priv, napi);
-       struct net_device  *dev =  priv->dev;
-       struct WILC_WFI_packet *pkt;
-
-       while (npackets < budget && priv->rx_queue) {
-               pkt = WILC_WFI_DequeueBuf(dev);
-               skb = dev_alloc_skb(pkt->datalen + 2);
-               if (!skb) {
-                       if (printk_ratelimit())
-                               PRINT_D(RX_DBG, "WILC_WFI: packet dropped\n");
-                       priv->stats.rx_dropped++;
-                       WILC_WFI_ReleaseBuffer(pkt);
-                       continue;
-               }
-               skb_reserve(skb, 2);  /* align IP on 16B boundary */
-               memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
-               skb->dev = dev;
-               skb->protocol = eth_type_trans(skb, dev);
-               skb->ip_summed = CHECKSUM_UNNECESSARY;  /* don't check it */
-               netif_receive_skb(skb);
-               /* Maintain stats */
-               npackets++;
-               WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, pkt->datalen, WILC_WFI_RX_PKT);
-               WILC_WFI_ReleaseBuffer(pkt);
-       }
-       /* If we processed all packets, we're done; tell the kernel and re-enable ints */
-       if (npackets < budget) {
-               napi_complete(napi);
-               WILC_WFI_RxInts(dev, 1);
-       }
-       return npackets;
-}
-
-/**
- *  @brief      WILC_WFI_Poll
- *  @details    The typical interrupt entry point
- *  @param[in]   struct napi_struct *napi :
- *  @param[in] int budget :
- *  @return     int : Return 0 on Success.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-static void WILC_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       int statusword;
-       struct WILC_WFI_priv *priv;
-       struct WILC_WFI_packet *pkt = NULL;
-       /*
-        * As usual, check the "device" pointer to be sure it is
-        * really interrupting.
-        * Then assign "struct device *dev"
-        */
-       struct net_device *dev = (struct net_device *)dev_id;
-       /* ... and check with hw if it's really ours */
-
-       /* paranoid */
-       if (!dev)
-               return;
-
-       /* Lock the device */
-       priv = netdev_priv(dev);
-       spin_lock(&priv->lock);
-
-       /* retrieve statusword: real netdevices use I/O instructions */
-       statusword = priv->status;
-       priv->status = 0;
-       if (statusword & WILC_WFI_RX_INTR) {
-               /* send it to WILC_WFI_rx for handling */
-               pkt = priv->rx_queue;
-               if (pkt) {
-                       priv->rx_queue = pkt->next;
-                       WILC_WFI_Rx(dev, pkt);
-               }
-       }
-       if (statusword & WILC_WFI_TX_INTR) {
-               /* a transmission is over: free the skb */
-               WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT);
-               dev_kfree_skb(priv->skb);
-       }
-
-       /* Unlock the device and we are done */
-       spin_unlock(&priv->lock);
-       if (pkt)
-               WILC_WFI_ReleaseBuffer(pkt);  /* Do this outside the lock! */
-       return;
-}
-/**
- *  @brief      WILC_WFI_NapiInterrupt
- *  @details    A NAPI interrupt handler
- *  @param[in]   irq:
- *  @param[in] dev_id:
- *  @param[in] pt_regs:
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-static void WILC_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       int statusword;
-       struct WILC_WFI_priv *priv;
-
-       /*
-        * As usual, check the "device" pointer for shared handlers.
-        * Then assign "struct device *dev"
-        */
-       struct net_device *dev = (struct net_device *)dev_id;
-       /* ... and check with hw if it's really ours */
-
-       /* paranoid */
-       if (!dev)
-               return;
-
-       /* Lock the device */
-       priv = netdev_priv(dev);
-       spin_lock(&priv->lock);
-
-       /* retrieve statusword: real netdevices use I/O instructions */
-       statusword = priv->status;
-       priv->status = 0;
-       if (statusword & WILC_WFI_RX_INTR) {
-               WILC_WFI_RxInts(dev, 0);   /* Disable further interrupts */
-               napi_schedule(&priv->napi);
-       }
-       if (statusword & WILC_WFI_TX_INTR) {
-               /* a transmission is over: free the skb */
-
-               WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT);
-               dev_kfree_skb(priv->skb);
-       }
-
-       /* Unlock the device and we are done */
-       spin_unlock(&priv->lock);
-       return;
-}
-
-/**
- *  @brief      MI_WFI_HwTx
- *  @details    Transmit a packet (low level interface)
- *  @param[in]   buf:
- *  @param[in] len:
- *  @param[in] net_device *dev:
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_HwTx(char *buf, int len, struct net_device *dev)
-{
-       /*
-        * This function deals with hw details. This interface loops
-        * back the packet to the other WILC_WFI interface (if any).
-        * In other words, this function implements the WILC_WFI behaviour,
-        * while all other procedures are rather device-independent
-        */
-       struct iphdr *ih;
-       struct net_device *dest;
-       struct WILC_WFI_priv *priv;
-       u32 *saddr, *daddr;
-       struct WILC_WFI_packet *tx_buffer;
-
-
-       /* I am paranoid. Ain't I? */
-       if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
-               PRINT_D(RX_DBG, "WILC_WFI: Hmm... packet too short (%i octets)\n",
-                       len);
-               return;
-       }
-
-       if (0) {  /* enable this conditional to look at the data */
-               int i;
-               PRINT_D(RX_DBG, "len is %i", len);
-               for (i = 14; i < len; i++)
-                       PRINT_D(RX_DBG, "TXdata[%d] %02x\n", i, buf[i] & 0xff);
-               /*   PRINT_D(RX_DBG, "\n"); */
-       }
-       /*
-        * Ethhdr is 14 bytes, but the kernel arranges for iphdr
-        * to be aligned (i.e., ethhdr is unaligned)
-        */
-       ih = (struct iphdr *)(buf + sizeof(struct ethhdr));
-       saddr = &ih->saddr;
-       daddr = &ih->daddr;
-
-       ((u8 *)saddr)[2] ^= 1;  /* change the third octet (class C) */
-       ((u8 *)daddr)[2] ^= 1;
-
-       ih->check = 0;          /* and rebuild the checksum (ip needs it) */
-       ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl);
-
-
-       if (dev == WILC_WFI_devs[0])
-               PRINT_D(RX_DBG, "%08x:%05i --> %08x:%05i\n",
-                       ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source),
-                       ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest));
-       else
-               PRINT_D(RX_DBG, "%08x:%05i <-- %08x:%05i\n",
-                       ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest),
-                       ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source));
-
-       /*
-        * Ok, now the packet is ready for transmission: first simulate a
-        * receive interrupt on the twin device, then  a
-        * transmission-done on the transmitting device
-        */
-       dest = WILC_WFI_devs[dev == WILC_WFI_devs[0] ? 1 : 0];
-       priv = netdev_priv(dest);
-
-       tx_buffer = WILC_WFI_GetTxBuffer(dev);
-       tx_buffer->datalen = len;
-       memcpy(tx_buffer->data, buf, len);
-       WILC_WFI_EnqueueBuf(dest, tx_buffer);
-       if (priv->rx_int_enabled) {
-               priv->status |= WILC_WFI_RX_INTR;
-               WILC_WFI_Interrupt(0, dest, NULL);
-       }
-
-       priv = netdev_priv(dev);
-       priv->tx_packetlen = len;
-       priv->tx_packetdata = buf;
-       priv->status |= WILC_WFI_TX_INTR;
-       if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) {
-               /* Simulate a dropped transmit interrupt */
-               netif_stop_queue(dev);
-               PRINT_D(RX_DBG, "Simulate lockup at %ld, txp %ld\n", jiffies,
-                       (unsigned long) priv->stats.tx_packets);
-       } else
-               WILC_WFI_Interrupt(0, dev, NULL);
-
-}
-
-/**
- *  @brief      WILC_WFI_Tx
- *  @details    Transmit a packet (called by the kernel)
- *  @param[in]   sk_buff *skb:
- *  @param[in] net_device *dev:
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev)
-{
-       int len;
-       char *data, shortpkt[ETH_ZLEN];
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-
-       /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
-
-       /*  if(priv->monitor_flag) */
-       /*       mac80211_hwsim_monitor_rx(skb); */
-
-
-       data = skb->data;
-       len = skb->len;
-
-       if (len < ETH_ZLEN) {
-               memset(shortpkt, 0, ETH_ZLEN);
-               memcpy(shortpkt, skb->data, skb->len);
-               len = ETH_ZLEN;
-               data = shortpkt;
-       }
-       dev->trans_start = jiffies;  /* save the timestamp */
-
-       /* Remember the skb, so we can free it at interrupt time */
-       priv->skb = skb;
-
-       /* actual deliver of data is device-specific, and not shown here */
-       WILC_WFI_HwTx(data, len, dev);
-
-       return 0;  /* Our simple device can not fail */
-}
-
-/**
- *  @brief      WILC_WFI_TxTimeout
- *  @details    Deal with a transmit timeout.
- *  @param[in] net_device *dev:
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_TxTimeout(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-
-       PRINT_D(RX_DBG, "Transmit timeout at %ld, latency %ld\n", jiffies,
-               jiffies - dev->trans_start);
-       /* Simulate a transmission interrupt to get things moving */
-       priv->status = WILC_WFI_TX_INTR;
-       WILC_WFI_Interrupt(0, dev, NULL);
-       priv->stats.tx_errors++;
-       netif_wake_queue(dev);
-       return;
-}
-
-/**
- *  @brief      WILC_WFI_Ioctl
- *  @details    Ioctl commands
- *  @param[in] net_device *dev:
- *  @param[in] ifreq *rq
- *  @param[in] cmd:
- *  @return     int : Return 0 on Success
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       PRINT_D(RX_DBG, "ioctl\n");
-       return 0;
-}
-
-/**
- *  @brief      WILC_WFI_Stat
- *  @details    Return statistics to the caller
- *  @param[in] net_device *dev:
- *  @return     WILC_WFI_Stats : Return net_device_stats stucture with the
- *              network device driver private data contents.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-struct net_device_stats *WILC_WFI_Stats(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       return &priv->stats;
-}
-
-/**
- *  @brief      WILC_WFI_RebuildHeader
- *  @details    This function is called to fill up an eth header, since arp is not
- *              available on the interface
- *  @param[in] sk_buff *skb:
- *  @return     int : Return 0 on Success
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_RebuildHeader(struct sk_buff *skb)
-{
-       struct ethhdr *eth = (struct ethhdr *) skb->data;
-       struct net_device *dev = skb->dev;
-
-       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-       memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
-       eth->h_dest[ETH_ALEN - 1]   ^= 0x01;  /* dest is us xor 1 */
-       return 0;
-}
-/**
- *  @brief      WILC_WFI_RebuildHeader
- *  @details    This function is called to fill up an eth header, since arp is not
- *              available on the interface
- *  @param[in] sk_buff *skb:
- *  @param[in] struct net_device *dev:
- *  @param[in]   unsigned short type:
- *  @param[in]   const void *saddr,
- *  @param[in]   const void *daddr:
- *  @param[in]          unsigned int len
- *  @return     int : Return 0 on Success
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_Header(struct sk_buff *skb, struct net_device *dev,
-                   unsigned short type, const void *daddr, const void *saddr,
-                   unsigned int len)
-{
-       struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
-
-       eth->h_proto = htons(type);
-       memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
-       memcpy(eth->h_dest,   daddr ? daddr : dev->dev_addr, dev->addr_len);
-       eth->h_dest[ETH_ALEN - 1]   ^= 0x01;  /* dest is us xor 1 */
-       return dev->hard_header_len;
-}
-
-/**
- *  @brief      WILC_WFI_ChangeMtu
- *  @details    The "change_mtu" method is usually not needed.
- *              If you need it, it must be like this.
- *  @param[in] net_device *dev : Network Device Driver Structure
- *  @param[in] new_mtu :
- *  @return     int : Returns 0 on Success.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_ChangeMtu(struct net_device *dev, int new_mtu)
-{
-       unsigned long flags;
-       struct WILC_WFI_priv *priv = netdev_priv(dev);
-       spinlock_t *lock = &priv->lock;
-
-       /* check ranges */
-       if ((new_mtu < 68) || (new_mtu > 1500))
-               return -EINVAL;
-       /*
-        * Do anything you need, and the accept the value
-        */
-       spin_lock_irqsave(lock, flags);
-       dev->mtu = new_mtu;
-       spin_unlock_irqrestore(lock, flags);
-       return 0;  /* success */
-}
-
-static const struct header_ops WILC_WFI_header_ops = {
-       .create  = WILC_WFI_Header,
-       .rebuild = WILC_WFI_RebuildHeader,
-       .cache   = NULL,   /* disable caching */
-};
-
-
-static const struct net_device_ops WILC_WFI_netdev_ops = {
-       .ndo_open = WILC_WFI_Open,
-       .ndo_stop = WILC_WFI_Release,
-       .ndo_set_config = WILC_WFI_Config,
-       .ndo_start_xmit = WILC_WFI_Tx,
-       .ndo_do_ioctl = WILC_WFI_Ioctl,
-       .ndo_get_stats = WILC_WFI_Stats,
-       .ndo_change_mtu = WILC_WFI_ChangeMtu,
-       .ndo_tx_timeout = WILC_WFI_TxTimeout,
-};
-
-/**
- *  @brief      WILC_WFI_Init
- *  @details    The init function (sometimes called probe).
- *              It is invoked by register_netdev()
- *  @param[in] net_device *dev:
- *  @return     NONE
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-void WILC_WFI_Init(struct net_device *dev)
-{
-       struct WILC_WFI_priv *priv;
-
-
-       /*
-        * Then, assign other fields in dev, using ether_setup() and some
-        * hand assignments
-        */
-       ether_setup(dev);  /* assign some of the fields */
-       /* 1- Allocate space */
-
-       dev->netdev_ops      = &WILC_WFI_netdev_ops;
-       dev->header_ops      = &WILC_WFI_header_ops;
-       dev->watchdog_timeo = timeout;
-       /* keep the default flags, just add NOARP */
-       dev->flags           |= IFF_NOARP;
-       dev->features        |= NETIF_F_NO_CSUM;
-       /*
-        * Then, initialize the priv field. This encloses the statistics
-        * and a few private fields.
-        */
-       priv = netdev_priv(dev);
-       memset(priv, 0, sizeof(struct WILC_WFI_priv));
-       priv->dev = dev;
-       netif_napi_add(dev, &priv->napi, WILC_WFI_Poll, 2);
-       /* The last parameter above is the NAPI "weight". */
-       spin_lock_init(&priv->lock);
-       WILC_WFI_RxInts(dev, 1);           /* enable receive interrupts */
-       WILC_WFI_SetupPool(dev);
-}
-
-/**
- *  @brief      WILC_WFI_Stat
- *  @details    Return statistics to the caller
- *  @param[in] net_device *dev:
- *  @return     WILC_WFI_Stats : Return net_device_stats stucture with the
- *              network device driver private data contents.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-
-void WILC_WFI_Cleanup(void)
-{
-       int i;
-       struct WILC_WFI_priv *priv[2];
-
-       /*if(hwsim_mon!=NULL)
-        * {
-        *      PRINT_D(RX_DBG, "Freeing monitor interface\n");
-        *      unregister_netdev(hwsim_mon);
-        *      free_netdev(hwsim_mon);
-        * }*/
-       for (i = 0; i < 2; i++) {
-               priv[i] = netdev_priv(WILC_WFI_devs[i]);
-
-               if (WILC_WFI_devs[i]) {
-                       PRINT_D(RX_DBG, "Unregistering\n");
-                       unregister_netdev(WILC_WFI_devs[i]);
-                       WILC_WFI_TearDownPool(WILC_WFI_devs[i]);
-                       free_netdev(WILC_WFI_devs[i]);
-                       PRINT_D(RX_DBG, "[NETDEV]Stopping interface\n");
-                       WILC_WFI_DeInitHostInt(WILC_WFI_devs[i]);
-                       WILC_WFI_WiphyFree(WILC_WFI_devs[i]);
-               }
-
-       }
-       /* unregister_netdev(hwsim_mon); */
-       WILC_WFI_deinit_mon_interface();
-       return;
-}
-
-
-void StartConfigSim(void);
-
-
-
-
-
-
-
-/**
- *  @brief      WILC_WFI_Stat
- *  @details    Return statistics to the caller
- *  @param[in] net_device *dev:
- *  @return     WILC_WFI_Stats : Return net_device_stats stucture with the
- *              network device driver private data contents.
- *  @author    mdaftedar
- *  @date      01 MAR 2012
- *  @version   1.0
- */
-int WILC_WFI_InitModule(void)
-{
-
-       int result, i, ret = -ENOMEM;
-       struct WILC_WFI_priv *priv[2], *netpriv;
-       struct wireless_dev *wdev;
-       WILC_WFI_Interrupt = use_napi ? WILC_WFI_NapiInterrupt : WILC_WFI_RegularInterrupt;
-       char buf[IFNAMSIZ];
-
-       for (i = 0; i < 2; i++) {
-
-               /* Allocate the net devices */
-               WILC_WFI_devs[i] = alloc_netdev(sizeof(struct WILC_WFI_priv), "wlan%d",
-                                               WILC_WFI_Init);
-               if (WILC_WFI_devs[i] == NULL)
-                       goto out;
-               /* priv[i] = netdev_priv(WILC_WFI_devs[i]); */
-
-               wdev = WILC_WFI_WiphyRegister(WILC_WFI_devs[i]);
-               WILC_WFI_devs[i]->ieee80211_ptr = wdev;
-               netpriv = netdev_priv(WILC_WFI_devs[i]);
-               netpriv->dev->ieee80211_ptr = wdev;
-               netpriv->dev->ml_priv = netpriv;
-               wdev->netdev = netpriv->dev;
-
-               /*Registering the net device*/
-               result = register_netdev(WILC_WFI_devs[i]);
-               if (result)
-                       PRINT_D(RX_DBG, "WILC_WFI: error %i registering device \"%s\"\n",
-                               result, WILC_WFI_devs[i]->name);
-               else
-                       ret = 0;
-       }
-
-
-       /*init atmel driver */
-       priv[0] = netdev_priv(WILC_WFI_devs[0]);
-       priv[1] = netdev_priv(WILC_WFI_devs[1]);
-
-       if (priv[1]->dev->ieee80211_ptr->wiphy->interface_modes && BIT(NL80211_IFTYPE_MONITOR)) {
-               /* snprintf(buf, IFNAMSIZ, "mon.%s",  priv[1]->dev->name); */
-               /*      WILC_WFI_init_mon_interface(); */
-               /*      priv[1]->monitor_flag = 1; */
-
-       }
-       priv[0]->bCfgScanning = false;
-       priv[0]->u32RcvdChCount = 0;
-
-       WILC_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN);
-
-
-       /* ret = host_int_init(&priv[0]->hWILCWFIDrv); */
-       /*copy handle to the other driver*/
-       /* priv[1]->hWILCWFIDrv = priv[0]->hWILCWFIDrv; */
-       if (ret) {
-               PRINT_ER("Error Init Driver\n");
-       }
-
-
-out:
-       if (ret)
-               WILC_WFI_Cleanup();
-       return ret;
-
-
-}
-
-
-module_init(WILC_WFI_InitModule);
-module_exit(WILC_WFI_Cleanup);
-
-#endif
index d413fa3861c0187adaf704121f092cfb706d9129..77f320d125e8b6cf151998063c43b1b1e54d8b76 100644 (file)
@@ -77,12 +77,12 @@ struct WILC_WFI_stats {
 #define num_reg_frame 2
 /*
  * If you use RX_BH_WORK_QUEUE on LPC3131: You may lose the first interrupt on
- * LPC3131 which is important to get the MAC start status when you are blocked inside
- * linux_wlan_firmware_download() which blocks mac_open().
+ * LPC3131 which is important to get the MAC start status when you are blocked
+ * inside linux_wlan_firmware_download() which blocks mac_open().
  */
-#if defined (NM73131_0_BOARD)
+#if defined(NM73131_0_BOARD)
  #define RX_BH_TYPE  RX_BH_KTHREAD
-#elif defined (PANDA_BOARD)
+#elif defined(PANDA_BOARD)
  #define RX_BH_TYPE  RX_BH_THREADED_IRQ
 #else
  #define RX_BH_TYPE  RX_BH_KTHREAD
@@ -95,6 +95,7 @@ struct wilc_wfi_key {
        int seq_len;
        u32 cipher;
 };
+
 struct wilc_wfi_wep_key {
        u8 *key;
        u8 key_len;
@@ -143,14 +144,15 @@ struct WILC_WFI_priv {
        spinlock_t lock;
        struct net_device *dev;
        struct napi_struct napi;
-       WILC_WFIDrvHandle hWILCWFIDrv;
+       tstrWILC_WFIDrv *hWILCWFIDrv;
        WILC_WFIDrvHandle hWILCWFIDrv_2;
        tstrHostIFpmkidAttr pmkid_list;
        struct WILC_WFI_stats netstats;
        u8 WILC_WFI_wep_default;
        u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104];
        u8 WILC_WFI_wep_key_len[4];
-       struct net_device *real_ndev;   /* The real interface that the monitor is on */
+       /* The real interface that the monitor is on */
+       struct net_device *real_ndev;
        struct wilc_wfi_key *wilc_gtk[MAX_NUM_STA];
        struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA];
        u8 wilc_groupkey;
@@ -174,7 +176,7 @@ typedef struct {
 typedef struct {
        uint8_t aSrcAddress[ETH_ALEN];
        uint8_t aBSSID[ETH_ALEN];
-       uint32_t drvHandler;
+       tstrWILC_WFIDrv *drvHandler;
        struct net_device *wilc_netdev;
 } tstrInterfaceInfo;
 typedef struct {
index 3af91f770485d67f18cb6df2b590d3515192aafa..7c53a2bd03812dd0d8026351216234d23f76de47 100644 (file)
@@ -16,7 +16,6 @@
  *      Global
  *
  ********************************************/
-extern unsigned int int_clrd;
 extern wilc_hif_func_t hif_sdio;
 extern wilc_hif_func_t hif_spi;
 extern wilc_cfg_func_t mac_cfg;
@@ -24,8 +23,6 @@ extern wilc_cfg_func_t mac_cfg;
 extern u8 g_wilc_initialized; /* AMR : 0422 RK3026 Crash issue */
 #endif
 extern void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size);
-extern void frmw_to_linux(uint8_t *buff, uint32_t size);
-int sdio_xfer_cnt(void);
 uint32_t wilc_get_chipid(uint8_t update);
 u16 Set_machw_change_vir_if(bool bValue);
 
@@ -118,18 +115,15 @@ static void wilc_debug(uint32_t flag, char *fmt, ...)
 {
        char buf[256];
        va_list args;
-       int len;
 
        if (flag & dbgflag) {
                va_start(args, fmt);
-               len = vsprintf(buf, fmt, args);
+               vsprintf(buf, fmt, args);
                va_end(args);
 
                if (g_wlan.os_func.os_debug)
                        g_wlan.os_func.os_debug(buf);
        }
-
-       return;
 }
 
 static CHIP_PS_STATE_T genuChipPSstate = CHIP_WAKEDUP;
@@ -292,13 +286,13 @@ uint32_t Statisitcs_totalAcks = 0, Statisitcs_DroppedAcks = 0;
 
 #ifdef TCP_ACK_FILTER
 struct Ack_session_info;
-typedef struct Ack_session_info {
+struct Ack_session_info {
        uint32_t Ack_seq_num;
        uint32_t Bigger_Ack_num;
        uint16_t src_port;
        uint16_t dst_port;
        uint16_t status;
-} Ack_session_info_t;
+};
 
 typedef struct {
        uint32_t ack_num;
@@ -319,7 +313,7 @@ struct Ack_session_info *Alloc_head;
 
 #define MAX_TCP_SESSION                25
 #define MAX_PENDING_ACKS               256
-Ack_session_info_t Acks_keep_track_info[2 * MAX_TCP_SESSION];
+struct Ack_session_info Acks_keep_track_info[2 * MAX_TCP_SESSION];
 Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS];
 
 uint32_t PendingAcks_arrBase;
@@ -451,7 +445,7 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(void)
        for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) {
                if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) {
                        struct txq_entry_t *tqe;
-                       PRINT_D(TCP_ENH, "DROP ACK: %u \n", Pending_Acks_info[i].ack_num);
+                       PRINT_D(TCP_ENH, "DROP ACK: %u\n", Pending_Acks_info[i].ack_num);
                        tqe = Pending_Acks_info[i].txqe;
                        if (tqe) {
                                wilc_wlan_txq_remove(tqe);
@@ -467,11 +461,10 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(void)
        Pending_Acks = 0;
        Opened_TCP_session = 0;
 
-       if (PendingAcks_arrBase == 0) {
+       if (PendingAcks_arrBase == 0)
                PendingAcks_arrBase = MAX_TCP_SESSION;
-       } else {
+       else
                PendingAcks_arrBase = 0;
-       }
 
 
        p->os_func.os_spin_unlock(p->txq_spinlock, &p->txq_spinlock_flags);
@@ -735,7 +728,7 @@ INLINE void chip_wakeup(void)
 
                        do {
                                /* Wait for the chip to stabilize*/
-                               WILC_Sleep(2);
+                               usleep_range(2 * 1000, 2 * 1000);
                                /* Make sure chip is awake. This is an extra step that can be removed */
                                /* later to avoid the bus access overhead */
                                if ((wilc_get_chipid(true) == 0)) {
@@ -758,7 +751,7 @@ INLINE void chip_wakeup(void)
                        /* If still off, redo the wake up sequence */
                        while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
                                /* Wait for the chip to stabilize*/
-                               WILC_Sleep(2);
+                               usleep_range(2 * 1000, 2 * 1000);
 
                                /* Make sure chip is awake. This is an extra step that can be removed */
                                /* later to avoid the bus access overhead */
@@ -996,7 +989,7 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount)
                                /**
                                 *      wait for vmm table is ready
                                 **/
-                               PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait... \n");
+                               PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n");
                                release_bus(RELEASE_ALLOW_SLEEP);
                                p->os_func.os_sleep(3); /* wait 3 ms */
                                acquire_bus(ACQUIRE_AND_WAKEUP);
@@ -1063,7 +1056,7 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount)
                        }
 
                        if (entries == 0) {
-                               PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]] \n", reg, i, vmm_table[i - 1]);
+                               PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]);
 
                                /* undo the transaction. */
                                ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, &reg);
@@ -1114,11 +1107,10 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount)
                                /*Bug3959: transmitting mgmt frames received from host*/
                                /*setting bit 30 in the host header to indicate mgmt frame*/
 #ifdef WILC_AP_EXTERNAL_MLME
-                               if (tqe->type == WILC_MGMT_PKT) {
+                               if (tqe->type == WILC_MGMT_PKT)
                                        header |= (1 << 30);
-                               } else {
+                               else
                                        header &= ~(1 << 30);
-                               }
 #endif
 
 #ifdef BIG_ENDIAN
@@ -1213,7 +1205,7 @@ static void wilc_wlan_handle_rxq(void)
 
        do {
                if (p->quit) {
-                       PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function \n");
+                       PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n");
                        p->os_func.os_signal(p->cfg_wait);
                        break;
                }
@@ -1330,8 +1322,7 @@ static void wilc_wlan_handle_rxq(void)
        } while (1);
 
        p->rxq_exit = 1;
-       PRINT_D(RX_DBG, "THREAD: Exiting RX thread \n");
-       return;
+       PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n");
 }
 
 /********************************************
@@ -1414,7 +1405,7 @@ static void wilc_wlan_handle_isr_ext(uint32_t int_status)
                buffer = p->os_func.os_malloc(size);
                if (buffer == NULL) {
                        wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
-                       WILC_Sleep(100);
+                       usleep_range(100 * 1000, 100 * 1000);
                        goto _end_;
                }
 #endif
@@ -1545,11 +1536,10 @@ static int wilc_wlan_firmware_download(const uint8_t *buffer, uint32_t buffer_si
                acquire_bus(ACQUIRE_ONLY);
                offset += 8;
                while (((int)size) && (offset < buffer_size)) {
-                       if (size <= blksz) {
+                       if (size <= blksz)
                                size2 = size;
-                       } else {
+                       else
                                size2 = blksz;
-                       }
                        /* Copy firmware into a DMA coherent buffer */
                        memcpy(dma_buffer, &buffer[offset], size2);
                        ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
@@ -1782,7 +1772,7 @@ static int wilc_wlan_stop(void)
 /******************************************************************************/
        reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31)); /**/
        /**/
-       ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
+       p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
        reg = ~(1 << 10);                                                                                               /**/
        /**/
        ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg);                                 /**/
@@ -2306,11 +2296,10 @@ u16 Set_machw_change_vir_if(bool bValue)
                PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
        }
 
-       if (bValue) {
+       if (bValue)
                reg |= (BIT31);
-       } else {
+       else
                reg &= ~(BIT31);
-       }
 
        ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg);
 
index 0ba7ec69e2b4111e9dbbb55ab7b8e3a9275dc636..244f7108ae92a153172864c77d8d30683ac1e1ca 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef WILC_WLAN_H
 #define WILC_WLAN_H
 
-#include "wilc_type.h"
+#include "wilc_oswrapper.h"
 
 
 #define ISWILC1000(id)   (((id & 0xfffff000) == 0x100000) ? 1 : 0)
index 3cffe55b3a93915c02e84540ba5eec3af769f822..e2842d37b07826000ec1bbb773157ecd346af71d 100644 (file)
@@ -363,8 +363,6 @@ static void wilc_wlan_parse_response_frame(uint8_t *info, int size)
                size -= (2 + len);
                info += (2 + len);
        }
-
-       return;
 }
 
 static int wilc_wlan_parse_info_frame(uint8_t *info, int size)
@@ -513,7 +511,6 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *r
        int ret = 1;
        uint8_t msg_type;
        uint8_t msg_id;
-       uint16_t msg_len;
        #ifdef WILC_FULLY_HOSTING_AP
        u32 *ptru32Frame;
        bool bStatus = frame[2];
@@ -528,11 +525,6 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *r
 
        msg_type = frame[0];
        msg_id = frame[1];      /* seq no */
-#ifdef BIG_ENDIAN
-       msg_len = (frame[2] << 8) | frame[3];
-#else
-       msg_len = (frame[3] << 8) | frame[2];
-#endif
        frame += 4;
        size -= 4;
 
@@ -557,7 +549,7 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *r
 
        case 'L':
 #ifndef SWITCH_LOG_TERMINAL
-               PRINT_ER("Unexpected firmware log message received \n");
+               PRINT_ER("Unexpected firmware log message received\n");
 #else
                PRINT_D(FIRM_DBG, "\nFIRMWARE LOGS :\n<<\n%s\n>>\n", frame);
                break;
@@ -572,18 +564,18 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *r
 #endif
 /*bug3819:*/
        case 'S':
-               PRINT_INFO(RX_DBG, "Scan Notification Received \n");
+               PRINT_INFO(RX_DBG, "Scan Notification Received\n");
                host_int_ScanCompleteReceived(frame - 4, size + 4);
                break;
 
 #ifdef WILC_FULLY_HOSTING_AP
        case 'T':
-               PRINT_INFO(RX_DBG, "TBTT Notification Received \n");
+               PRINT_INFO(RX_DBG, "TBTT Notification Received\n");
                process_tbtt_isr();
                break;
 
        case 'A':
-               PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received \n");
+               PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received\n");
                WILC_mgm_HOSTAPD_ACK(ptru32Frame, bStatus);
                break;
 #endif
index 8ed51e3851187d4b206c4e9c321a70de88b3d50d..5cf74e4c4a708c40b947049a76a4f3b3b4143522 100644 (file)
@@ -20,7 +20,7 @@
 /* #define USE_OLD_SPI_SW */
 
 
-#include "wilc_type.h"
+#include "wilc_oswrapper.h"
 #include "linux_wlan_common.h"
 
 
@@ -43,8 +43,8 @@
  ********************************************/
 
 #define HIF_SDIO           (0)
-#define HIF_SPI            (1 << 0)
-#define HIF_SDIO_GPIO_IRQ  (1 << 2)
+#define HIF_SPI            BIT(0)
+#define HIF_SDIO_GPIO_IRQ  BIT(2)
 
 
 /********************************************
index 55e5199053468f013d2113e574d41044dd3f96ae..964a843c4521b4253cc920be41e279c80bc5be73 100644 (file)
@@ -1,4 +1,4 @@
 obj-$(CONFIG_FB_XGI)  += xgifb.o
 
-xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o vb_util.o
+xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o
 
index 943d463cf1931c5519fd4b403cb840e864c02020..5a6251a4511246756d2c6105fd9a382df51c1b42 100644 (file)
@@ -18,8 +18,8 @@
 #define Index_CR_GPIO_Reg1 0x48
 #define Index_CR_GPIO_Reg3 0x4a
 
-#define GPIOG_EN    (1<<6)
-#define GPIOG_READ  (1<<1)
+#define GPIOG_EN    BIT(6)
+#define GPIOG_READ  BIT(1)
 
 static char *forcecrt2type;
 static char *mode;
@@ -29,7 +29,7 @@ static unsigned int refresh_rate;
 /* -------------------- Macro definitions ---------------------------- */
 
 #ifdef DEBUG
-static void dumpVGAReg(void)
+static void dumpVGAReg(struct xgifb_video_info *xgifb_info)
 {
        u8 i, reg;
 
@@ -48,7 +48,7 @@ static void dumpVGAReg(void)
        }
 }
 #else
-static inline void dumpVGAReg(void)
+static inline void dumpVGAReg(struct xgifb_video_info *xgifb_info)
 {
 }
 #endif
@@ -1073,7 +1073,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
        }
        XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
 
-       dumpVGAReg();
+       dumpVGAReg(xgifb_info);
        return 0;
 }
 
@@ -2019,7 +2019,7 @@ static int xgifb_probe(struct pci_dev *pdev,
                goto error_mtrr;
        }
 
-       dumpVGAReg();
+       dumpVGAReg(xgifb_info);
 
        return 0;
 
index 24573026a7c07e917a396590ef28f8b0dc3d449c..500cabe41a3c59241c2dfa5a263cfb5b508f1263 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef _VBINIT_
 #define _VBINIT_
-extern unsigned char XGIInitNew(struct pci_dev *pdev);
-extern void XGIRegInit(struct vb_device_info *, unsigned long);
+unsigned char XGIInitNew(struct pci_dev *pdev);
+void XGIRegInit(struct vb_device_info *, unsigned long);
 #endif
 
index 5301bec6440d2be935b2d6c2dda56a9f3fd82c56..6f082a7a5a4a4c40238f7e05a93dc3af2c7bf975 100644 (file)
@@ -1,23 +1,23 @@
 #ifndef _VBSETMODE_
 #define _VBSETMODE_
 
-extern void InitTo330Pointer(unsigned char, struct vb_device_info *);
-extern void XGI_UnLockCRT2(struct vb_device_info *);
-extern void XGI_LockCRT2(struct vb_device_info *);
-extern void XGI_DisplayOff(struct xgifb_video_info *,
-                          struct xgi_hw_device_info *,
-                          struct vb_device_info *);
-extern void XGI_GetVBType(struct vb_device_info *);
-extern void XGI_SenseCRT1(struct vb_device_info *);
-extern unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
-                                  struct xgi_hw_device_info *HwDeviceExtension,
-                                  unsigned short ModeNo);
+void InitTo330Pointer(unsigned char, struct vb_device_info *);
+void XGI_UnLockCRT2(struct vb_device_info *);
+void XGI_LockCRT2(struct vb_device_info *);
+void XGI_DisplayOff(struct xgifb_video_info *,
+                   struct xgi_hw_device_info *,
+                   struct vb_device_info *);
+void XGI_GetVBType(struct vb_device_info *);
+void XGI_SenseCRT1(struct vb_device_info *);
+unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
+                           struct xgi_hw_device_info *HwDeviceExtension,
+                           unsigned short ModeNo);
 
-extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
-                                     unsigned short *ModeIdIndex);
-extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
-                                        unsigned short ModeNo,
-                                        unsigned short ModeIdIndex,
-                                        struct vb_device_info *);
+unsigned char XGI_SearchModeID(unsigned short ModeNo,
+                              unsigned short *ModeIdIndex);
+unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+                                 unsigned short ModeNo,
+                                 unsigned short ModeIdIndex,
+                                 struct vb_device_info *);
 
 #endif
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
deleted file mode 100644 (file)
index be3437c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "vgatypes.h"
-#include "vb_util.h"
-
-void xgifb_reg_set(unsigned long port, u8 index, u8 data)
-{
-       outb(index, port);
-       outb(data, port + 1);
-}
-
-u8 xgifb_reg_get(unsigned long port, u8 index)
-{
-       outb(index, port);
-       return inb(port + 1);
-}
-
-void xgifb_reg_and_or(unsigned long port, u8 index,
-               unsigned data_and, unsigned data_or)
-{
-       u8 temp;
-
-       temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
-       temp = (temp & data_and) | data_or;
-       xgifb_reg_set(port, index, temp);
-}
-
-void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and)
-{
-       u8 temp;
-
-       temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
-       temp &= data_and;
-       xgifb_reg_set(port, index, temp);
-}
-
-void xgifb_reg_or(unsigned long port, u8 index, unsigned data_or)
-{
-       u8 temp;
-
-       temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
-       temp |= data_or;
-       xgifb_reg_set(port, index, temp);
-}
index 9161de1d37ddbde59629cd35687c5c3526fc34f7..7bd395fb31b2816137332f6899bf5a9ec31e1a1b 100644 (file)
@@ -1,9 +1,43 @@
 #ifndef _VBUTIL_
 #define _VBUTIL_
-extern void xgifb_reg_set(unsigned long, u8, u8);
-extern u8 xgifb_reg_get(unsigned long, u8);
-extern void xgifb_reg_or(unsigned long, u8, unsigned);
-extern void xgifb_reg_and(unsigned long, u8, unsigned);
-extern void xgifb_reg_and_or(unsigned long, u8, unsigned, unsigned);
+static inline void xgifb_reg_set(unsigned long port, u8 index, u8 data)
+{
+       outb(index, port);
+       outb(data, port + 1);
+}
+
+static inline u8 xgifb_reg_get(unsigned long port, u8 index)
+{
+       outb(index, port);
+       return inb(port + 1);
+}
+
+static inline void xgifb_reg_and_or(unsigned long port, u8 index,
+                                   unsigned data_and, unsigned data_or)
+{
+       u8 temp;
+
+       temp = xgifb_reg_get(port, index);
+       temp = (temp & data_and) | data_or;
+       xgifb_reg_set(port, index, temp);
+}
+
+static inline void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and)
+{
+       u8 temp;
+
+       temp = xgifb_reg_get(port, index);
+       temp &= data_and;
+       xgifb_reg_set(port, index, temp);
+}
+
+static inline void xgifb_reg_or(unsigned long port, u8 index, unsigned data_or)
+{
+       u8 temp;
+
+       temp = xgifb_reg_get(port, index);
+       temp |= data_or;
+       xgifb_reg_set(port, index, temp);
+}
 #endif
 
index cd77a064c772f1bbe897482d2372fe5bc6434328..fd092909a4577a7c4a708516bf3344fee331ad84 100644 (file)
@@ -968,9 +968,9 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
 
        conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
-       if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+       if (hdr->flags & ISCSI_FLAG_CMD_READ)
                cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
-       } else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
+       else
                cmd->targ_xfer_tag = 0xFFFFFFFF;
        cmd->cmd_sn             = be32_to_cpu(hdr->cmdsn);
        cmd->exp_stat_sn        = be32_to_cpu(hdr->exp_statsn);
index c2e9fea90b4a4bc16a0384d79fa9684c9f4176e0..860e840461778271191ba4ee8f1a4011dba5e78c 100644 (file)
@@ -457,8 +457,15 @@ void target_unregister_template(const struct target_core_fabric_ops *fo)
                if (!strcmp(t->tf_ops->name, fo->name)) {
                        BUG_ON(atomic_read(&t->tf_access_cnt));
                        list_del(&t->tf_list);
+                       mutex_unlock(&g_tf_lock);
+                       /*
+                        * Wait for any outstanding fabric se_deve_entry->rcu_head
+                        * callbacks to complete post kfree_rcu(), before allowing
+                        * fabric driver unload of TFO->module to proceed.
+                        */
+                       rcu_barrier();
                        kfree(t);
-                       break;
+                       return;
                }
        }
        mutex_unlock(&g_tf_lock);
index 62ea4e8e70a8935398f2a0e86fc44627dfa3368e..be9cefc07407e80ef5dd7dfcbd8a0d025faf97f6 100644 (file)
@@ -84,8 +84,16 @@ void target_backend_unregister(const struct target_backend_ops *ops)
        list_for_each_entry(tb, &backend_list, list) {
                if (tb->ops == ops) {
                        list_del(&tb->list);
+                       mutex_unlock(&backend_mutex);
+                       /*
+                        * Wait for any outstanding backend driver ->rcu_head
+                        * callbacks to complete post TBO->free_device() ->
+                        * call_rcu(), before allowing backend driver module
+                        * unload of target_backend_ops->owner to proceed.
+                        */
+                       rcu_barrier();
                        kfree(tb);
-                       break;
+                       return;
                }
        }
        mutex_unlock(&backend_mutex);
index b5ba1ec3c35476361103d7dca47a1934cdd3289f..f87d4cef6d398c072e953e7eaa6b5d9d5b469d70 100644 (file)
@@ -1203,17 +1203,13 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
        struct se_dev_entry *deve;
        struct se_session *sess = cmd->se_sess;
        struct se_node_acl *nacl;
+       struct scsi_lun slun;
        unsigned char *buf;
        u32 lun_count = 0, offset = 8;
-
-       if (cmd->data_length < 16) {
-               pr_warn("REPORT LUNS allocation length %u too small\n",
-                       cmd->data_length);
-               return TCM_INVALID_CDB_FIELD;
-       }
+       __be32 len;
 
        buf = transport_kmap_data_sg(cmd);
-       if (!buf)
+       if (cmd->data_length && !buf)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
        /*
@@ -1221,11 +1217,9 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
         * coming via a target_core_mod PASSTHROUGH op, and not through
         * a $FABRIC_MOD.  In that case, report LUN=0 only.
         */
-       if (!sess) {
-               int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
-               lun_count = 1;
+       if (!sess)
                goto done;
-       }
+
        nacl = sess->se_node_acl;
 
        rcu_read_lock();
@@ -1236,10 +1230,12 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
                 * See SPC2-R20 7.19.
                 */
                lun_count++;
-               if ((offset + 8) > cmd->data_length)
+               if (offset >= cmd->data_length)
                        continue;
 
-               int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
+               int_to_scsilun(deve->mapped_lun, &slun);
+               memcpy(buf + offset, &slun,
+                      min(8u, cmd->data_length - offset));
                offset += 8;
        }
        rcu_read_unlock();
@@ -1248,12 +1244,22 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
         * See SPC3 r07, page 159.
         */
 done:
-       lun_count *= 8;
-       buf[0] = ((lun_count >> 24) & 0xff);
-       buf[1] = ((lun_count >> 16) & 0xff);
-       buf[2] = ((lun_count >> 8) & 0xff);
-       buf[3] = (lun_count & 0xff);
-       transport_kunmap_data_sg(cmd);
+       /*
+        * If no LUNs are accessible, report virtual LUN 0.
+        */
+       if (lun_count == 0) {
+               int_to_scsilun(0, &slun);
+               if (cmd->data_length > 8)
+                       memcpy(buf + offset, &slun,
+                              min(8u, cmd->data_length - offset));
+               lun_count = 1;
+       }
+
+       if (buf) {
+               len = cpu_to_be32(lun_count * 8);
+               memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
        return 0;
index 6509c61b96484993333a4198138945f43154fdfd..620dcd405ff6eec9ae65b0af8e93c25daae15d1f 100644 (file)
@@ -68,7 +68,7 @@ struct power_table {
  *     registered cooling device.
  * @cpufreq_state: integer value representing the current state of cpufreq
  *     cooling devices.
- * @cpufreq_val: integer value representing the absolute value of the clipped
+ * @clipped_freq: integer value representing the absolute value of the clipped
  *     frequency.
  * @max_level: maximum cooling level. One less than total number of valid
  *     cpufreq frequencies.
@@ -91,7 +91,7 @@ struct cpufreq_cooling_device {
        int id;
        struct thermal_cooling_device *cool_dev;
        unsigned int cpufreq_state;
-       unsigned int cpufreq_val;
+       unsigned int clipped_freq;
        unsigned int max_level;
        unsigned int *freq_table;       /* In descending order */
        struct cpumask allowed_cpus;
@@ -107,6 +107,9 @@ struct cpufreq_cooling_device {
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
+static unsigned int cpufreq_dev_count;
+
+static DEFINE_MUTEX(cooling_list_lock);
 static LIST_HEAD(cpufreq_dev_list);
 
 /**
@@ -185,14 +188,14 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
 {
        struct cpufreq_cooling_device *cpufreq_dev;
 
-       mutex_lock(&cooling_cpufreq_lock);
+       mutex_lock(&cooling_list_lock);
        list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
                if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) {
-                       mutex_unlock(&cooling_cpufreq_lock);
+                       mutex_unlock(&cooling_list_lock);
                        return get_level(cpufreq_dev, freq);
                }
        }
-       mutex_unlock(&cooling_cpufreq_lock);
+       mutex_unlock(&cooling_list_lock);
 
        pr_err("%s: cpu:%d not part of any cooling device\n", __func__, cpu);
        return THERMAL_CSTATE_INVALID;
@@ -215,29 +218,35 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
                                    unsigned long event, void *data)
 {
        struct cpufreq_policy *policy = data;
-       unsigned long max_freq = 0;
+       unsigned long clipped_freq;
        struct cpufreq_cooling_device *cpufreq_dev;
 
-       switch (event) {
+       if (event != CPUFREQ_ADJUST)
+               return NOTIFY_DONE;
 
-       case CPUFREQ_ADJUST:
-               mutex_lock(&cooling_cpufreq_lock);
-               list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
-                       if (!cpumask_test_cpu(policy->cpu,
-                                             &cpufreq_dev->allowed_cpus))
-                               continue;
+       mutex_lock(&cooling_list_lock);
+       list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
+               if (!cpumask_test_cpu(policy->cpu, &cpufreq_dev->allowed_cpus))
+                       continue;
 
-                       max_freq = cpufreq_dev->cpufreq_val;
+               /*
+                * policy->max is the maximum allowed frequency defined by user
+                * and clipped_freq is the maximum that thermal constraints
+                * allow.
+                *
+                * If clipped_freq is lower than policy->max, then we need to
+                * readjust policy->max.
+                *
+                * But, if clipped_freq is greater than policy->max, we don't
+                * need to do anything.
+                */
+               clipped_freq = cpufreq_dev->clipped_freq;
 
-                       if (policy->max != max_freq)
-                               cpufreq_verify_within_limits(policy, 0,
-                                                            max_freq);
-               }
-               mutex_unlock(&cooling_cpufreq_lock);
+               if (policy->max > clipped_freq)
+                       cpufreq_verify_within_limits(policy, 0, clipped_freq);
                break;
-       default:
-               return NOTIFY_DONE;
        }
+       mutex_unlock(&cooling_list_lock);
 
        return NOTIFY_OK;
 }
@@ -519,7 +528,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
 
        clip_freq = cpufreq_device->freq_table[state];
        cpufreq_device->cpufreq_state = state;
-       cpufreq_device->cpufreq_val = clip_freq;
+       cpufreq_device->clipped_freq = clip_freq;
 
        cpufreq_update_policy(cpu);
 
@@ -861,17 +870,19 @@ __cpufreq_cooling_register(struct device_node *np,
                        pr_debug("%s: freq:%u KHz\n", __func__, freq);
        }
 
-       cpufreq_dev->cpufreq_val = cpufreq_dev->freq_table[0];
+       cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
        cpufreq_dev->cool_dev = cool_dev;
 
        mutex_lock(&cooling_cpufreq_lock);
 
+       mutex_lock(&cooling_list_lock);
+       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+       mutex_unlock(&cooling_list_lock);
+
        /* Register the notifier for first cpufreq cooling device */
-       if (list_empty(&cpufreq_dev_list))
+       if (!cpufreq_dev_count++)
                cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
                                          CPUFREQ_POLICY_NOTIFIER);
-       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
-
        mutex_unlock(&cooling_cpufreq_lock);
 
        return cool_dev;
@@ -1013,13 +1024,17 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
                return;
 
        cpufreq_dev = cdev->devdata;
-       mutex_lock(&cooling_cpufreq_lock);
-       list_del(&cpufreq_dev->node);
 
        /* Unregister the notifier for the last cpufreq cooling device */
-       if (list_empty(&cpufreq_dev_list))
+       mutex_lock(&cooling_cpufreq_lock);
+       if (!--cpufreq_dev_count)
                cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
                                            CPUFREQ_POLICY_NOTIFIER);
+
+       mutex_lock(&cooling_list_lock);
+       list_del(&cpufreq_dev->node);
+       mutex_unlock(&cooling_list_lock);
+
        mutex_unlock(&cooling_cpufreq_lock);
 
        thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
index 63a448f9d93b66eedec7fde829983588fe6251f0..251676902869d673140b3684c64b0c63ea376f77 100644 (file)
@@ -258,8 +258,7 @@ static int allocate_power(struct thermal_zone_device *tz,
        BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
        BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
        BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
-       req_power = devm_kcalloc(&tz->device, num_actors * 5,
-                                sizeof(*req_power), GFP_KERNEL);
+       req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
        if (!req_power) {
                ret = -ENOMEM;
                goto unlock;
@@ -334,7 +333,7 @@ static int allocate_power(struct thermal_zone_device *tz,
                                      max_allocatable_power, current_temp,
                                      (s32)control_temp - (s32)current_temp);
 
-       devm_kfree(&tz->device, req_power);
+       kfree(req_power);
 unlock:
        mutex_unlock(&tz->lock);
 
@@ -426,7 +425,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
                return -EINVAL;
        }
 
-       params = devm_kzalloc(&tz->device, sizeof(*params), GFP_KERNEL);
+       params = kzalloc(sizeof(*params), GFP_KERNEL);
        if (!params)
                return -ENOMEM;
 
@@ -468,14 +467,14 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
        return 0;
 
 free:
-       devm_kfree(&tz->device, params);
+       kfree(params);
        return ret;
 }
 
 static void power_allocator_unbind(struct thermal_zone_device *tz)
 {
        dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
-       devm_kfree(&tz->device, tz->governor_data);
+       kfree(tz->governor_data);
        tz->governor_data = NULL;
 }
 
index 382d3fcba6ccd8e28d56fe45cfebfdaca52ab12f..c3fe026d3168dda14e7388472db49abf27544e4f 100644 (file)
@@ -2712,7 +2712,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
        memcpy(skb_put(skb, size), in_buf, size);
 
        skb->dev = net;
-       skb->protocol = __constant_htons(ETH_P_IP);
+       skb->protocol = htons(ETH_P_IP);
 
        /* Ship it off to the kernel */
        netif_rx(skb);
index ee8bfacf20716481a23a60325b5c99ba9da35508..20932cc9c8f71681038bf5e505fec87d9c402280 100644 (file)
@@ -2147,6 +2147,8 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
 
 static int job_control(struct tty_struct *tty, struct file *file)
 {
+       struct pid *pgrp;
+
        /* Job control check -- must be done at start and after
           every sleep (POSIX.1 7.1.1.4). */
        /* NOTE: not yet done after every sleep pending a thorough
@@ -2156,18 +2158,25 @@ static int job_control(struct tty_struct *tty, struct file *file)
            current->signal->tty != tty)
                return 0;
 
+       rcu_read_lock();
+       pgrp = task_pgrp(current);
+
        spin_lock_irq(&tty->ctrl_lock);
        if (!tty->pgrp)
                printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
-       else if (task_pgrp(current) != tty->pgrp) {
+       else if (pgrp != tty->pgrp) {
                spin_unlock_irq(&tty->ctrl_lock);
-               if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
+               if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
+                       rcu_read_unlock();
                        return -EIO;
-               kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+               }
+               kill_pgrp(pgrp, SIGTTIN, 1);
+               rcu_read_unlock();
                set_thread_flag(TIF_SIGPENDING);
                return -ERESTARTSYS;
        }
        spin_unlock_irq(&tty->ctrl_lock);
+       rcu_read_unlock();
        return 0;
 }
 
index 4d5e8409769c3cc412ba5d428e0f179b4b44fdad..4d5937c185c17bda6d506f00232b3f3598f28b95 100644 (file)
 #include <linux/mutex.h>
 #include <linux/poll.h>
 
+#undef TTY_DEBUG_HANGUP
+#ifdef TTY_DEBUG_HANGUP
+# define tty_debug_hangup(tty, f, args...)     tty_debug(tty, f, ##args)
+#else
+# define tty_debug_hangup(tty, f, args...)     do {} while (0)
+#endif
 
 #ifdef CONFIG_UNIX98_PTYS
 static struct tty_driver *ptm_driver;
@@ -779,6 +785,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
        if (retval)
                goto err_release;
 
+       tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
+
        tty_unlock(tty);
        return 0;
 err_release:
index c43f74c53cd98259056400cc86b9ff355c4993ca..d54dcd87c67e2948c3e39e772dbef0fc48378827 100644 (file)
@@ -42,9 +42,9 @@ struct uart_8250_dma {
        size_t                  rx_size;
        size_t                  tx_size;
 
-       unsigned char           tx_running:1;
-       unsigned char           tx_err: 1;
-       unsigned char           rx_running:1;
+       unsigned char           tx_running;
+       unsigned char           tx_err;
+       unsigned char           rx_running;
 };
 
 struct old_serial_port {
@@ -211,3 +211,14 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
        }
        return 1;
 }
+
+static inline int serial_index(struct uart_port *port)
+{
+       return port->minor - 64;
+}
+
+#if 0
+#define DEBUG_INTR(fmt...)     printk(fmt)
+#else
+#define DEBUG_INTR(fmt...)     do { } while (0)
+#endif
index 37fff12dd4d06b9f561eeabfe2c22f1cb4aa88e4..cfbb9d728e317fae55daa324ab5d8f780cb023f0 100644 (file)
@@ -1,25 +1,23 @@
 /*
- *  Driver for 8250/16550-type serial ports
+ *  Universal/legacy driver for 8250/16550-type serial ports
  *
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  *
  *  Copyright (C) 2001 Russell King.
  *
+ *  Supports: ISA-compatible 8250/16550 ports
+ *           PNP 8250/16550 ports
+ *           early_serial_setup() ports
+ *           userspace-configurable "phantom" ports
+ *           "serial8250" platform devices
+ *           serial8250_register_8250_port() ports
+ *
  * 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.
- *
- * A note about mapbase / membase
- *
- *  mapbase is the physical address of the IO port.
- *  membase is an 'ioremapped' cookie.
  */
 
-#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/ioport.h>
@@ -58,33 +56,10 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
 
 static struct uart_driver serial8250_reg;
 
-static int serial_index(struct uart_port *port)
-{
-       return port->minor - 64;
-}
-
 static unsigned int skip_txen_test; /* force skip of txen test at init time */
 
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...)     printk(fmt)
-#else
-#define DEBUG_INTR(fmt...)     do { } while (0)
-#endif
-
 #define PASS_LIMIT     512
 
-#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)
-
-
 #include <asm/serial.h>
 /*
  * SERIAL_PORT_DFNS tells us about built-in ports that have no
@@ -120,2695 +95,268 @@ static struct hlist_head irq_lists[NR_IRQ_HASH];
 static DEFINE_MUTEX(hash_mutex);       /* Used to walk the hash */
 
 /*
- * Here we define the default xmit fifo size used for each type of UART.
+ * This is the serial driver's interrupt routine.
+ *
+ * Arjan thinks the old way was overly complex, so it got simplified.
+ * Alan disagrees, saying that need the complexity to handle the weird
+ * nature of ISA shared interrupts.  (This is a special exception.)
+ *
+ * In order to handle ISA shared interrupts properly, we need to check
+ * that all ports have been serviced, and therefore the ISA interrupt
+ * line has been de-asserted.
+ *
+ * This means we need to loop through all ports. checking that they
+ * don't have an interrupt pending.
  */
-static const struct serial8250_config uart_config[] = {
-       [PORT_UNKNOWN] = {
-               .name           = "unknown",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_8250] = {
-               .name           = "8250",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16450] = {
-               .name           = "16450",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16550] = {
-               .name           = "16550",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16550A] = {
-               .name           = "16550A",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .rxtrig_bytes   = {1, 4, 8, 14},
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_CIRRUS] = {
-               .name           = "Cirrus",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16650] = {
-               .name           = "ST16650",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_16650V2] = {
-               .name           = "ST16650V2",
-               .fifo_size      = 32,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
-                                 UART_FCR_T_TRIG_00,
-               .rxtrig_bytes   = {8, 16, 24, 28},
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_16750] = {
-               .name           = "TI16750",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
-                                 UART_FCR7_64BYTE,
-               .rxtrig_bytes   = {1, 16, 32, 56},
-               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
-       },
-       [PORT_STARTECH] = {
-               .name           = "Startech",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-       },
-       [PORT_16C950] = {
-               .name           = "16C950/954",
-               .fifo_size      = 128,
-               .tx_loadsz      = 128,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               /* UART_CAP_EFR breaks billionon CF bluetooth card. */
-               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP,
-       },
-       [PORT_16654] = {
-               .name           = "ST16654",
-               .fifo_size      = 64,
-               .tx_loadsz      = 32,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
-                                 UART_FCR_T_TRIG_10,
-               .rxtrig_bytes   = {8, 16, 56, 60},
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_16850] = {
-               .name           = "XR16850",
-               .fifo_size      = 128,
-               .tx_loadsz      = 128,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
-       },
-       [PORT_RSA] = {
-               .name           = "RSA",
-               .fifo_size      = 2048,
-               .tx_loadsz      = 2048,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_NS16550A] = {
-               .name           = "NS16550A",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_NATSEMI,
-       },
-       [PORT_XSCALE] = {
-               .name           = "XScale",
-               .fifo_size      = 32,
-               .tx_loadsz      = 32,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
-       },
-       [PORT_OCTEON] = {
-               .name           = "OCTEON",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_AR7] = {
-               .name           = "AR7",
-               .fifo_size      = 16,
-               .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-       [PORT_U6_16550A] = {
-               .name           = "U6_16550A",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-       [PORT_TEGRA] = {
-               .name           = "Tegra",
-               .fifo_size      = 32,
-               .tx_loadsz      = 8,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
-                                 UART_FCR_T_TRIG_01,
-               .rxtrig_bytes   = {1, 4, 8, 14},
-               .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
-       },
-       [PORT_XR17D15X] = {
-               .name           = "XR17D15X",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
-                                 UART_CAP_SLEEP,
-       },
-       [PORT_XR17V35X] = {
-               .name           = "XR17V35X",
-               .fifo_size      = 256,
-               .tx_loadsz      = 256,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
-                                 UART_FCR_T_TRIG_11,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
-                                 UART_CAP_SLEEP,
-       },
-       [PORT_LPC3220] = {
-               .name           = "LPC3220",
-               .fifo_size      = 64,
-               .tx_loadsz      = 32,
-               .fcr            = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
-                                 UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
-               .flags          = UART_CAP_FIFO,
-       },
-       [PORT_BRCM_TRUMANAGE] = {
-               .name           = "TruManage",
-               .fifo_size      = 1,
-               .tx_loadsz      = 1024,
-               .flags          = UART_CAP_HFIFO,
-       },
-       [PORT_8250_CIR] = {
-               .name           = "CIR port"
-       },
-       [PORT_ALTR_16550_F32] = {
-               .name           = "Altera 16550 FIFO32",
-               .fifo_size      = 32,
-               .tx_loadsz      = 32,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-       [PORT_ALTR_16550_F64] = {
-               .name           = "Altera 16550 FIFO64",
-               .fifo_size      = 64,
-               .tx_loadsz      = 64,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-       [PORT_ALTR_16550_F128] = {
-               .name           = "Altera 16550 FIFO128",
-               .fifo_size      = 128,
-               .tx_loadsz      = 128,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
-workaround of errata A-008006 which states that tx_loadsz should  be
-configured less than Maximum supported fifo bytes */
-       [PORT_16550A_FSL64] = {
-               .name           = "16550A_FSL64",
-               .fifo_size      = 64,
-               .tx_loadsz      = 63,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
-                                 UART_FCR7_64BYTE,
-               .flags          = UART_CAP_FIFO,
-       },
-};
-
-/* Uart divisor latch read */
-static int default_serial_dl_read(struct uart_8250_port *up)
-{
-       return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
-}
-
-/* Uart divisor latch write */
-static void default_serial_dl_write(struct uart_8250_port *up, int value)
-{
-       serial_out(up, UART_DLL, value & 0xff);
-       serial_out(up, UART_DLM, value >> 8 & 0xff);
-}
-
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
-
-/* Au1x00/RT288x UART hardware has a weird register layout */
-static const s8 au_io_in_map[8] = {
-        0,     /* UART_RX  */
-        2,     /* UART_IER */
-        3,     /* UART_IIR */
-        5,     /* UART_LCR */
-        6,     /* UART_MCR */
-        7,     /* UART_LSR */
-        8,     /* UART_MSR */
-       -1,     /* UART_SCR (unmapped) */
-};
-
-static const s8 au_io_out_map[8] = {
-        1,     /* UART_TX  */
-        2,     /* UART_IER */
-        4,     /* UART_FCR */
-        5,     /* UART_LCR */
-        6,     /* UART_MCR */
-       -1,     /* UART_LSR (unmapped) */
-       -1,     /* UART_MSR (unmapped) */
-       -1,     /* UART_SCR (unmapped) */
-};
-
-static unsigned int au_serial_in(struct uart_port *p, int offset)
-{
-       if (offset >= ARRAY_SIZE(au_io_in_map))
-               return UINT_MAX;
-       offset = au_io_in_map[offset];
-       if (offset < 0)
-               return UINT_MAX;
-       return __raw_readl(p->membase + (offset << p->regshift));
-}
-
-static void au_serial_out(struct uart_port *p, int offset, int value)
-{
-       if (offset >= ARRAY_SIZE(au_io_out_map))
-               return;
-       offset = au_io_out_map[offset];
-       if (offset < 0)
-               return;
-       __raw_writel(value, p->membase + (offset << p->regshift));
-}
-
-/* Au1x00 haven't got a standard divisor latch */
-static int au_serial_dl_read(struct uart_8250_port *up)
+static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 {
-       return __raw_readl(up->port.membase + 0x28);
-}
+       struct irq_info *i = dev_id;
+       struct list_head *l, *end = NULL;
+       int pass_counter = 0, handled = 0;
 
-static void au_serial_dl_write(struct uart_8250_port *up, int value)
-{
-       __raw_writel(value, up->port.membase + 0x28);
-}
+       DEBUG_INTR("serial8250_interrupt(%d)...", irq);
 
-#endif
+       spin_lock(&i->lock);
 
-static unsigned int hub6_serial_in(struct uart_port *p, int offset)
-{
-       offset = offset << p->regshift;
-       outb(p->hub6 - 1 + offset, p->iobase);
-       return inb(p->iobase + 1);
-}
+       l = i->head;
+       do {
+               struct uart_8250_port *up;
+               struct uart_port *port;
 
-static void hub6_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = offset << p->regshift;
-       outb(p->hub6 - 1 + offset, p->iobase);
-       outb(value, p->iobase + 1);
-}
+               up = list_entry(l, struct uart_8250_port, list);
+               port = &up->port;
 
-static unsigned int mem_serial_in(struct uart_port *p, int offset)
-{
-       offset = offset << p->regshift;
-       return readb(p->membase + offset);
-}
+               if (port->handle_irq(port)) {
+                       handled = 1;
+                       end = NULL;
+               } else if (end == NULL)
+                       end = l;
 
-static void mem_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = offset << p->regshift;
-       writeb(value, p->membase + offset);
-}
+               l = l->next;
 
-static void mem32_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = offset << p->regshift;
-       writel(value, p->membase + offset);
-}
+               if (l == i->head && pass_counter++ > PASS_LIMIT) {
+                       /* If we hit this, we're dead. */
+                       printk_ratelimited(KERN_ERR
+                               "serial8250: too much work for irq%d\n", irq);
+                       break;
+               }
+       } while (l != end);
 
-static unsigned int mem32_serial_in(struct uart_port *p, int offset)
-{
-       offset = offset << p->regshift;
-       return readl(p->membase + offset);
-}
+       spin_unlock(&i->lock);
 
-static void mem32be_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = offset << p->regshift;
-       iowrite32be(value, p->membase + offset);
-}
+       DEBUG_INTR("end.\n");
 
-static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
-{
-       offset = offset << p->regshift;
-       return ioread32be(p->membase + offset);
+       return IRQ_RETVAL(handled);
 }
 
-static unsigned int io_serial_in(struct uart_port *p, int offset)
+/*
+ * To support ISA shared interrupts, we need to have one interrupt
+ * handler that ensures that the IRQ line has been deasserted
+ * before returning.  Failing to do this will result in the IRQ
+ * line being stuck active, and, since ISA irqs are edge triggered,
+ * no more IRQs will be seen.
+ */
+static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
 {
-       offset = offset << p->regshift;
-       return inb(p->iobase + offset);
-}
+       spin_lock_irq(&i->lock);
 
-static void io_serial_out(struct uart_port *p, int offset, int value)
-{
-       offset = offset << p->regshift;
-       outb(value, p->iobase + offset);
+       if (!list_empty(i->head)) {
+               if (i->head == &up->list)
+                       i->head = i->head->next;
+               list_del(&up->list);
+       } else {
+               BUG_ON(i->head != &up->list);
+               i->head = NULL;
+       }
+       spin_unlock_irq(&i->lock);
+       /* List empty so throw away the hash node */
+       if (i->head == NULL) {
+               hlist_del(&i->node);
+               kfree(i);
+       }
 }
 
-static int serial8250_default_handle_irq(struct uart_port *port);
-static int exar_handle_irq(struct uart_port *port);
-
-static void set_io_from_upio(struct uart_port *p)
+static int serial_link_irq_chain(struct uart_8250_port *up)
 {
-       struct uart_8250_port *up = up_to_u8250p(p);
-
-       up->dl_read = default_serial_dl_read;
-       up->dl_write = default_serial_dl_write;
+       struct hlist_head *h;
+       struct hlist_node *n;
+       struct irq_info *i;
+       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
 
-       switch (p->iotype) {
-       case UPIO_HUB6:
-               p->serial_in = hub6_serial_in;
-               p->serial_out = hub6_serial_out;
-               break;
+       mutex_lock(&hash_mutex);
 
-       case UPIO_MEM:
-               p->serial_in = mem_serial_in;
-               p->serial_out = mem_serial_out;
-               break;
+       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
 
-       case UPIO_MEM32:
-               p->serial_in = mem32_serial_in;
-               p->serial_out = mem32_serial_out;
-               break;
+       hlist_for_each(n, h) {
+               i = hlist_entry(n, struct irq_info, node);
+               if (i->irq == up->port.irq)
+                       break;
+       }
 
-       case UPIO_MEM32BE:
-               p->serial_in = mem32be_serial_in;
-               p->serial_out = mem32be_serial_out;
-               break;
+       if (n == NULL) {
+               i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
+               if (i == NULL) {
+                       mutex_unlock(&hash_mutex);
+                       return -ENOMEM;
+               }
+               spin_lock_init(&i->lock);
+               i->irq = up->port.irq;
+               hlist_add_head(&i->node, h);
+       }
+       mutex_unlock(&hash_mutex);
 
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
-       case UPIO_AU:
-               p->serial_in = au_serial_in;
-               p->serial_out = au_serial_out;
-               up->dl_read = au_serial_dl_read;
-               up->dl_write = au_serial_dl_write;
-               break;
-#endif
+       spin_lock_irq(&i->lock);
 
-       default:
-               p->serial_in = io_serial_in;
-               p->serial_out = io_serial_out;
-               break;
-       }
-       /* Remember loaded iotype */
-       up->cur_iotype = p->iotype;
-       p->handle_irq = serial8250_default_handle_irq;
-}
+       if (i->head) {
+               list_add(&up->list, i->head);
+               spin_unlock_irq(&i->lock);
 
-static void
-serial_port_out_sync(struct uart_port *p, int offset, int value)
-{
-       switch (p->iotype) {
-       case UPIO_MEM:
-       case UPIO_MEM32:
-       case UPIO_MEM32BE:
-       case UPIO_AU:
-               p->serial_out(p, offset, value);
-               p->serial_in(p, UART_LCR);      /* safe, no side-effects */
-               break;
-       default:
-               p->serial_out(p, offset, value);
+               ret = 0;
+       } else {
+               INIT_LIST_HEAD(&up->list);
+               i->head = &up->list;
+               spin_unlock_irq(&i->lock);
+               irq_flags |= up->port.irqflags;
+               ret = request_irq(up->port.irq, serial8250_interrupt,
+                                 irq_flags, "serial", i);
+               if (ret < 0)
+                       serial_do_unlink(i, up);
        }
-}
 
-/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-{
-       serial_out(up, UART_SCR, offset);
-       serial_out(up, UART_ICR, value);
+       return ret;
 }
 
-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+static void serial_unlink_irq_chain(struct uart_8250_port *up)
 {
-       unsigned int value;
+       /*
+        * yes, some broken gcc emit "warning: 'i' may be used uninitialized"
+        * but no, we are not going to take a patch that assigns NULL below.
+        */
+       struct irq_info *i;
+       struct hlist_node *n;
+       struct hlist_head *h;
 
-       serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
-       serial_out(up, UART_SCR, offset);
-       value = serial_in(up, UART_ICR);
-       serial_icr_write(up, UART_ACR, up->acr);
+       mutex_lock(&hash_mutex);
 
-       return value;
-}
+       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
 
-/*
- * FIFO support.
- */
-static void serial8250_clear_fifos(struct uart_8250_port *p)
-{
-       if (p->capabilities & UART_CAP_FIFO) {
-               serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
-               serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
-                              UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-               serial_out(p, UART_FCR, 0);
+       hlist_for_each(n, h) {
+               i = hlist_entry(n, struct irq_info, node);
+               if (i->irq == up->port.irq)
+                       break;
        }
-}
 
-void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
-{
-       serial8250_clear_fifos(p);
-       serial_out(p, UART_FCR, p->fcr);
-}
-EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+       BUG_ON(n == NULL);
+       BUG_ON(i->head == NULL);
 
-void serial8250_rpm_get(struct uart_8250_port *p)
-{
-       if (!(p->capabilities & UART_CAP_RPM))
-               return;
-       pm_runtime_get_sync(p->port.dev);
-}
-EXPORT_SYMBOL_GPL(serial8250_rpm_get);
+       if (list_empty(i->head))
+               free_irq(up->port.irq, i);
 
-void serial8250_rpm_put(struct uart_8250_port *p)
-{
-       if (!(p->capabilities & UART_CAP_RPM))
-               return;
-       pm_runtime_mark_last_busy(p->port.dev);
-       pm_runtime_put_autosuspend(p->port.dev);
+       serial_do_unlink(i, up);
+       mutex_unlock(&hash_mutex);
 }
-EXPORT_SYMBOL_GPL(serial8250_rpm_put);
 
 /*
- * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
- * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
- * empty and the HW can idle again.
+ * This function is used to handle ports that do not have an
+ * interrupt.  This doesn't work very well for 16450's, but gives
+ * barely passable results for a 16550A.  (Although at the expense
+ * of much CPU overhead).
  */
-static void serial8250_rpm_get_tx(struct uart_8250_port *p)
+static void serial8250_timeout(unsigned long data)
 {
-       unsigned char rpm_active;
-
-       if (!(p->capabilities & UART_CAP_RPM))
-               return;
+       struct uart_8250_port *up = (struct uart_8250_port *)data;
 
-       rpm_active = xchg(&p->rpm_tx_active, 1);
-       if (rpm_active)
-               return;
-       pm_runtime_get_sync(p->port.dev);
+       up->port.handle_irq(&up->port);
+       mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
 }
 
-static void serial8250_rpm_put_tx(struct uart_8250_port *p)
+static void serial8250_backup_timeout(unsigned long data)
 {
-       unsigned char rpm_active;
+       struct uart_8250_port *up = (struct uart_8250_port *)data;
+       unsigned int iir, ier = 0, lsr;
+       unsigned long flags;
 
-       if (!(p->capabilities & UART_CAP_RPM))
-               return;
-
-       rpm_active = xchg(&p->rpm_tx_active, 0);
-       if (!rpm_active)
-               return;
-       pm_runtime_mark_last_busy(p->port.dev);
-       pm_runtime_put_autosuspend(p->port.dev);
-}
-
-/*
- * IER sleep support.  UARTs which have EFRs need the "extended
- * capability" bit enabled.  Note that on XR16C850s, we need to
- * reset LCR to write to IER.
- */
-static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
-{
-       unsigned char lcr = 0, efr = 0;
-       /*
-        * Exar UARTs have a SLEEP register that enables or disables
-        * each UART to enter sleep mode separately.  On the XR17V35x the
-        * register is accessible to each UART at the UART_EXAR_SLEEP
-        * offset but the UART channel may only write to the corresponding
-        * bit.
-        */
-       serial8250_rpm_get(p);
-       if ((p->port.type == PORT_XR17V35X) ||
-          (p->port.type == PORT_XR17D15X)) {
-               serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
-               goto out;
-       }
-
-       if (p->capabilities & UART_CAP_SLEEP) {
-               if (p->capabilities & UART_CAP_EFR) {
-                       lcr = serial_in(p, UART_LCR);
-                       efr = serial_in(p, UART_EFR);
-                       serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
-                       serial_out(p, UART_EFR, UART_EFR_ECB);
-                       serial_out(p, UART_LCR, 0);
-               }
-               serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
-               if (p->capabilities & UART_CAP_EFR) {
-                       serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
-                       serial_out(p, UART_EFR, efr);
-                       serial_out(p, UART_LCR, lcr);
-               }
-       }
-out:
-       serial8250_rpm_put(p);
-}
-
-#ifdef CONFIG_SERIAL_8250_RSA
-/*
- * Attempts to turn on the RSA FIFO.  Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __enable_rsa(struct uart_8250_port *up)
-{
-       unsigned char mode;
-       int result;
-
-       mode = serial_in(up, UART_RSA_MSR);
-       result = mode & UART_RSA_MSR_FIFO;
-
-       if (!result) {
-               serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
-               mode = serial_in(up, UART_RSA_MSR);
-               result = mode & UART_RSA_MSR_FIFO;
-       }
-
-       if (result)
-               up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
-       return result;
-}
-
-static void enable_rsa(struct uart_8250_port *up)
-{
-       if (up->port.type == PORT_RSA) {
-               if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
-                       spin_lock_irq(&up->port.lock);
-                       __enable_rsa(up);
-                       spin_unlock_irq(&up->port.lock);
-               }
-               if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
-                       serial_out(up, UART_RSA_FRR, 0);
-       }
-}
-
-/*
- * Attempts to turn off the RSA FIFO.  Returns zero on failure.
- * It is unknown why interrupts were disabled in here.  However,
- * the caller is expected to preserve this behaviour by grabbing
- * the spinlock before calling this function.
- */
-static void disable_rsa(struct uart_8250_port *up)
-{
-       unsigned char mode;
-       int result;
-
-       if (up->port.type == PORT_RSA &&
-           up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
-               spin_lock_irq(&up->port.lock);
-
-               mode = serial_in(up, UART_RSA_MSR);
-               result = !(mode & UART_RSA_MSR_FIFO);
-
-               if (!result) {
-                       serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
-                       mode = serial_in(up, UART_RSA_MSR);
-                       result = !(mode & UART_RSA_MSR_FIFO);
-               }
-
-               if (result)
-                       up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
-               spin_unlock_irq(&up->port.lock);
-       }
-}
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-/*
- * This is a quickie test to see how big the FIFO is.
- * It doesn't work at all the time, more's the pity.
- */
-static int size_fifo(struct uart_8250_port *up)
-{
-       unsigned char old_fcr, old_mcr, old_lcr;
-       unsigned short old_dl;
-       int count;
-
-       old_lcr = serial_in(up, UART_LCR);
-       serial_out(up, UART_LCR, 0);
-       old_fcr = serial_in(up, UART_FCR);
-       old_mcr = serial_in(up, UART_MCR);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                   UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-       serial_out(up, UART_MCR, UART_MCR_LOOP);
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       old_dl = serial_dl_read(up);
-       serial_dl_write(up, 0x0001);
-       serial_out(up, UART_LCR, 0x03);
-       for (count = 0; count < 256; count++)
-               serial_out(up, UART_TX, count);
-       mdelay(20);/* FIXME - schedule_timeout */
-       for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
-            (count < 256); count++)
-               serial_in(up, UART_RX);
-       serial_out(up, UART_FCR, old_fcr);
-       serial_out(up, UART_MCR, old_mcr);
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       serial_dl_write(up, old_dl);
-       serial_out(up, UART_LCR, old_lcr);
-
-       return count;
-}
-
-/*
- * Read UART ID using the divisor method - set DLL and DLM to zero
- * and the revision will be in DLL and device type in DLM.  We
- * preserve the device state across this.
- */
-static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
-{
-       unsigned char old_dll, old_dlm, old_lcr;
-       unsigned int id;
-
-       old_lcr = serial_in(p, UART_LCR);
-       serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
-
-       old_dll = serial_in(p, UART_DLL);
-       old_dlm = serial_in(p, UART_DLM);
-
-       serial_out(p, UART_DLL, 0);
-       serial_out(p, UART_DLM, 0);
-
-       id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
-
-       serial_out(p, UART_DLL, old_dll);
-       serial_out(p, UART_DLM, old_dlm);
-       serial_out(p, UART_LCR, old_lcr);
-
-       return id;
-}
-
-/*
- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
- * When this function is called we know it is at least a StarTech
- * 16650 V2, but it might be one of several StarTech UARTs, or one of
- * its clones.  (We treat the broken original StarTech 16650 V1 as a
- * 16550, and why not?  Startech doesn't seem to even acknowledge its
- * existence.)
- *
- * What evil have men's minds wrought...
- */
-static void autoconfig_has_efr(struct uart_8250_port *up)
-{
-       unsigned int id1, id2, id3, rev;
-
-       /*
-        * Everything with an EFR has SLEEP
-        */
-       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-
-       /*
-        * First we check to see if it's an Oxford Semiconductor UART.
-        *
-        * If we have to do this here because some non-National
-        * Semiconductor clone chips lock up if you try writing to the
-        * LSR register (which serial_icr_read does)
-        */
-
-       /*
-        * Check for Oxford Semiconductor 16C950.
-        *
-        * EFR [4] must be set else this test fails.
-        *
-        * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
-        * claims that it's needed for 952 dual UART's (which are not
-        * recommended for new designs).
-        */
-       up->acr = 0;
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-       serial_out(up, UART_EFR, UART_EFR_ECB);
-       serial_out(up, UART_LCR, 0x00);
-       id1 = serial_icr_read(up, UART_ID1);
-       id2 = serial_icr_read(up, UART_ID2);
-       id3 = serial_icr_read(up, UART_ID3);
-       rev = serial_icr_read(up, UART_REV);
-
-       DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-
-       if (id1 == 0x16 && id2 == 0xC9 &&
-           (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
-               up->port.type = PORT_16C950;
-
-               /*
-                * Enable work around for the Oxford Semiconductor 952 rev B
-                * chip which causes it to seriously miscalculate baud rates
-                * when DLL is 0.
-                */
-               if (id3 == 0x52 && rev == 0x01)
-                       up->bugs |= UART_BUG_QUOT;
-               return;
-       }
-
-       /*
-        * We check for a XR16C850 by setting DLL and DLM to 0, and then
-        * reading back DLL and DLM.  The chip type depends on the DLM
-        * value read back:
-        *  0x10 - XR16C850 and the DLL contains the chip revision.
-        *  0x12 - XR16C2850.
-        *  0x14 - XR16C854.
-        */
-       id1 = autoconfig_read_divisor_id(up);
-       DEBUG_AUTOCONF("850id=%04x ", id1);
-
-       id2 = id1 >> 8;
-       if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
-               up->port.type = PORT_16850;
-               return;
-       }
-
-       /*
-        * It wasn't an XR16C850.
-        *
-        * We distinguish between the '654 and the '650 by counting
-        * how many bytes are in the FIFO.  I'm using this for now,
-        * since that's the technique that was sent to me in the
-        * serial driver update, but I'm not convinced this works.
-        * I've had problems doing this in the past.  -TYT
-        */
-       if (size_fifo(up) == 64)
-               up->port.type = PORT_16654;
-       else
-               up->port.type = PORT_16650V2;
-}
-
-/*
- * We detected a chip without a FIFO.  Only two fall into
- * this category - the original 8250 and the 16450.  The
- * 16450 has a scratch register (accessible with LCR=0)
- */
-static void autoconfig_8250(struct uart_8250_port *up)
-{
-       unsigned char scratch, status1, status2;
-
-       up->port.type = PORT_8250;
-
-       scratch = serial_in(up, UART_SCR);
-       serial_out(up, UART_SCR, 0xa5);
-       status1 = serial_in(up, UART_SCR);
-       serial_out(up, UART_SCR, 0x5a);
-       status2 = serial_in(up, UART_SCR);
-       serial_out(up, UART_SCR, scratch);
-
-       if (status1 == 0xa5 && status2 == 0x5a)
-               up->port.type = PORT_16450;
-}
-
-static int broken_efr(struct uart_8250_port *up)
-{
-       /*
-        * Exar ST16C2550 "A2" devices incorrectly detect as
-        * having an EFR, and report an ID of 0x0201.  See
-        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
-        */
-       if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
-               return 1;
-
-       return 0;
-}
-
-/*
- * We know that the chip has FIFOs.  Does it have an EFR?  The
- * EFR is located in the same register position as the IIR and
- * we know the top two bits of the IIR are currently set.  The
- * EFR should contain zero.  Try to read the EFR.
- */
-static void autoconfig_16550a(struct uart_8250_port *up)
-{
-       unsigned char status1, status2;
-       unsigned int iersave;
-
-       up->port.type = PORT_16550A;
-       up->capabilities |= UART_CAP_FIFO;
-
-       /*
-        * XR17V35x UARTs have an extra divisor register, DLD
-        * that gets enabled with when DLAB is set which will
-        * cause the device to incorrectly match and assign
-        * port type to PORT_16650.  The EFR for this UART is
-        * found at offset 0x09. Instead check the Deice ID (DVID)
-        * register for a 2, 4 or 8 port UART.
-        */
-       if (up->port.flags & UPF_EXAR_EFR) {
-               status1 = serial_in(up, UART_EXAR_DVID);
-               if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
-                       DEBUG_AUTOCONF("Exar XR17V35x ");
-                       up->port.type = PORT_XR17V35X;
-                       up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
-                                               UART_CAP_SLEEP;
-
-                       return;
-               }
-
-       }
-
-       /*
-        * Check for presence of the EFR when DLAB is set.
-        * Only ST16C650V1 UARTs pass this test.
-        */
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       if (serial_in(up, UART_EFR) == 0) {
-               serial_out(up, UART_EFR, 0xA8);
-               if (serial_in(up, UART_EFR) != 0) {
-                       DEBUG_AUTOCONF("EFRv1 ");
-                       up->port.type = PORT_16650;
-                       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-               } else {
-                       serial_out(up, UART_LCR, 0);
-                       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                                  UART_FCR7_64BYTE);
-                       status1 = serial_in(up, UART_IIR) >> 5;
-                       serial_out(up, UART_FCR, 0);
-                       serial_out(up, UART_LCR, 0);
-
-                       if (status1 == 7)
-                               up->port.type = PORT_16550A_FSL64;
-                       else
-                               DEBUG_AUTOCONF("Motorola 8xxx DUART ");
-               }
-               serial_out(up, UART_EFR, 0);
-               return;
-       }
-
-       /*
-        * Maybe it requires 0xbf to be written to the LCR.
-        * (other ST16C650V2 UARTs, TI16C752A, etc)
-        */
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-       if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
-               DEBUG_AUTOCONF("EFRv2 ");
-               autoconfig_has_efr(up);
-               return;
-       }
-
-       /*
-        * Check for a National Semiconductor SuperIO chip.
-        * Attempt to switch to bank 2, read the value of the LOOP bit
-        * from EXCR1. Switch back to bank 0, change it in MCR. Then
-        * switch back to bank 2, read it from EXCR1 again and check
-        * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
-        */
-       serial_out(up, UART_LCR, 0);
-       status1 = serial_in(up, UART_MCR);
-       serial_out(up, UART_LCR, 0xE0);
-       status2 = serial_in(up, 0x02); /* EXCR1 */
-
-       if (!((status2 ^ status1) & UART_MCR_LOOP)) {
-               serial_out(up, UART_LCR, 0);
-               serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
-               serial_out(up, UART_LCR, 0xE0);
-               status2 = serial_in(up, 0x02); /* EXCR1 */
-               serial_out(up, UART_LCR, 0);
-               serial_out(up, UART_MCR, status1);
-
-               if ((status2 ^ status1) & UART_MCR_LOOP) {
-                       unsigned short quot;
-
-                       serial_out(up, UART_LCR, 0xE0);
-
-                       quot = serial_dl_read(up);
-                       quot <<= 3;
-
-                       if (ns16550a_goto_highspeed(up))
-                               serial_dl_write(up, quot);
-
-                       serial_out(up, UART_LCR, 0);
-
-                       up->port.uartclk = 921600*16;
-                       up->port.type = PORT_NS16550A;
-                       up->capabilities |= UART_NATSEMI;
-                       return;
-               }
-       }
-
-       /*
-        * No EFR.  Try to detect a TI16750, which only sets bit 5 of
-        * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
-        * Try setting it with and without DLAB set.  Cheap clones
-        * set bit 5 without DLAB set.
-        */
-       serial_out(up, UART_LCR, 0);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-       status1 = serial_in(up, UART_IIR) >> 5;
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-       status2 = serial_in(up, UART_IIR) >> 5;
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       serial_out(up, UART_LCR, 0);
-
-       DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-
-       if (status1 == 6 && status2 == 7) {
-               up->port.type = PORT_16750;
-               up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
-               return;
-       }
-
-       /*
-        * Try writing and reading the UART_IER_UUE bit (b6).
-        * If it works, this is probably one of the Xscale platform's
-        * internal UARTs.
-        * We're going to explicitly set the UUE bit to 0 before
-        * trying to write and read a 1 just to make sure it's not
-        * already a 1 and maybe locked there before we even start start.
-        */
-       iersave = serial_in(up, UART_IER);
-       serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
-       if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
-               /*
-                * OK it's in a known zero state, try writing and reading
-                * without disturbing the current state of the other bits.
-                */
-               serial_out(up, UART_IER, iersave | UART_IER_UUE);
-               if (serial_in(up, UART_IER) & UART_IER_UUE) {
-                       /*
-                        * It's an Xscale.
-                        * We'll leave the UART_IER_UUE bit set to 1 (enabled).
-                        */
-                       DEBUG_AUTOCONF("Xscale ");
-                       up->port.type = PORT_XSCALE;
-                       up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
-                       return;
-               }
-       } else {
-               /*
-                * If we got here we couldn't force the IER_UUE bit to 0.
-                * Log it and continue.
-                */
-               DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
-       }
-       serial_out(up, UART_IER, iersave);
-
-       /*
-        * Exar uarts have EFR in a weird location
-        */
-       if (up->port.flags & UPF_EXAR_EFR) {
-               DEBUG_AUTOCONF("Exar XR17D15x ");
-               up->port.type = PORT_XR17D15X;
-               up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
-                                   UART_CAP_SLEEP;
-
-               return;
-       }
-
-       /*
-        * We distinguish between 16550A and U6 16550A by counting
-        * how many bytes are in the FIFO.
-        */
-       if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
-               up->port.type = PORT_U6_16550A;
-               up->capabilities |= UART_CAP_AFE;
-       }
-}
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port.  It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A.  The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up)
-{
-       unsigned char status1, scratch, scratch2, scratch3;
-       unsigned char save_lcr, save_mcr;
-       struct uart_port *port = &up->port;
-       unsigned long flags;
-       unsigned int old_capabilities;
-
-       if (!port->iobase && !port->mapbase && !port->membase)
-               return;
-
-       DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
-                      serial_index(port), port->iobase, port->membase);
-
-       /*
-        * We really do need global IRQs disabled here - we're going to
-        * be frobbing the chips IRQ enable register to see if it exists.
-        */
-       spin_lock_irqsave(&port->lock, flags);
-
-       up->capabilities = 0;
-       up->bugs = 0;
-
-       if (!(port->flags & UPF_BUGGY_UART)) {
-               /*
-                * Do a simple existence test first; if we fail this,
-                * there's no point trying anything else.
-                *
-                * 0x80 is used as a nonsense port to prevent against
-                * false positives due to ISA bus float.  The
-                * assumption is that 0x80 is a non-existent port;
-                * which should be safe since include/asm/io.h also
-                * makes this assumption.
-                *
-                * Note: this is safe as long as MCR bit 4 is clear
-                * and the device is in "PC" mode.
-                */
-               scratch = serial_in(up, UART_IER);
-               serial_out(up, UART_IER, 0);
-#ifdef __i386__
-               outb(0xff, 0x080);
-#endif
-               /*
-                * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
-                * 16C754B) allow only to modify them if an EFR bit is set.
-                */
-               scratch2 = serial_in(up, UART_IER) & 0x0f;
-               serial_out(up, UART_IER, 0x0F);
-#ifdef __i386__
-               outb(0, 0x080);
-#endif
-               scratch3 = serial_in(up, UART_IER) & 0x0f;
-               serial_out(up, UART_IER, scratch);
-               if (scratch2 != 0 || scratch3 != 0x0F) {
-                       /*
-                        * We failed; there's nothing here
-                        */
-                       spin_unlock_irqrestore(&port->lock, flags);
-                       DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-                                      scratch2, scratch3);
-                       goto out;
-               }
-       }
-
-       save_mcr = serial_in(up, UART_MCR);
-       save_lcr = serial_in(up, UART_LCR);
-
-       /*
-        * Check to see if a UART is really there.  Certain broken
-        * internal modems based on the Rockwell chipset fail this
-        * test, because they apparently don't implement the loopback
-        * test mode.  So this test is skipped on the COM 1 through
-        * COM 4 ports.  This *should* be safe, since no board
-        * manufacturer would be stupid enough to design a board
-        * that conflicts with COM 1-4 --- we hope!
-        */
-       if (!(port->flags & UPF_SKIP_TEST)) {
-               serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
-               status1 = serial_in(up, UART_MSR) & 0xF0;
-               serial_out(up, UART_MCR, save_mcr);
-               if (status1 != 0x90) {
-                       spin_unlock_irqrestore(&port->lock, flags);
-                       DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-                                      status1);
-                       goto out;
-               }
-       }
-
-       /*
-        * We're pretty sure there's a port here.  Lets find out what
-        * type of port it is.  The IIR top two bits allows us to find
-        * out if it's 8250 or 16450, 16550, 16550A or later.  This
-        * determines what we test for next.
-        *
-        * We also initialise the EFR (if any) to zero for later.  The
-        * EFR occupies the same register location as the FCR and IIR.
-        */
-       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-       serial_out(up, UART_EFR, 0);
-       serial_out(up, UART_LCR, 0);
-
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       scratch = serial_in(up, UART_IIR) >> 6;
-
-       switch (scratch) {
-       case 0:
-               autoconfig_8250(up);
-               break;
-       case 1:
-               port->type = PORT_UNKNOWN;
-               break;
-       case 2:
-               port->type = PORT_16550;
-               break;
-       case 3:
-               autoconfig_16550a(up);
-               break;
-       }
-
-#ifdef CONFIG_SERIAL_8250_RSA
-       /*
-        * Only probe for RSA ports if we got the region.
-        */
-       if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
-           __enable_rsa(up))
-               port->type = PORT_RSA;
-#endif
-
-       serial_out(up, UART_LCR, save_lcr);
-
-       port->fifosize = uart_config[up->port.type].fifo_size;
-       old_capabilities = up->capabilities;
-       up->capabilities = uart_config[port->type].flags;
-       up->tx_loadsz = uart_config[port->type].tx_loadsz;
-
-       if (port->type == PORT_UNKNOWN)
-               goto out_lock;
-
-       /*
-        * Reset the UART.
-        */
-#ifdef CONFIG_SERIAL_8250_RSA
-       if (port->type == PORT_RSA)
-               serial_out(up, UART_RSA_FRR, 0);
-#endif
-       serial_out(up, UART_MCR, save_mcr);
-       serial8250_clear_fifos(up);
-       serial_in(up, UART_RX);
-       if (up->capabilities & UART_CAP_UUE)
-               serial_out(up, UART_IER, UART_IER_UUE);
-       else
-               serial_out(up, UART_IER, 0);
-
-out_lock:
-       spin_unlock_irqrestore(&port->lock, flags);
-       if (up->capabilities != old_capabilities) {
-               printk(KERN_WARNING
-                      "ttyS%d: detected caps %08x should be %08x\n",
-                      serial_index(port), old_capabilities,
-                      up->capabilities);
-       }
-out:
-       DEBUG_AUTOCONF("iir=%d ", scratch);
-       DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
-}
-
-static void autoconfig_irq(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-       unsigned char save_mcr, save_ier;
-       unsigned char save_ICP = 0;
-       unsigned int ICP = 0;
-       unsigned long irqs;
-       int irq;
-
-       if (port->flags & UPF_FOURPORT) {
-               ICP = (port->iobase & 0xfe0) | 0x1f;
-               save_ICP = inb_p(ICP);
-               outb_p(0x80, ICP);
-               inb_p(ICP);
-       }
-
-       /* forget possible initially masked and pending IRQ */
-       probe_irq_off(probe_irq_on());
-       save_mcr = serial_in(up, UART_MCR);
-       save_ier = serial_in(up, UART_IER);
-       serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
-       irqs = probe_irq_on();
-       serial_out(up, UART_MCR, 0);
-       udelay(10);
-       if (port->flags & UPF_FOURPORT) {
-               serial_out(up, UART_MCR,
-                           UART_MCR_DTR | UART_MCR_RTS);
-       } else {
-               serial_out(up, UART_MCR,
-                           UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-       }
-       serial_out(up, UART_IER, 0x0f); /* enable all intrs */
-       serial_in(up, UART_LSR);
-       serial_in(up, UART_RX);
-       serial_in(up, UART_IIR);
-       serial_in(up, UART_MSR);
-       serial_out(up, UART_TX, 0xFF);
-       udelay(20);
-       irq = probe_irq_off(irqs);
-
-       serial_out(up, UART_MCR, save_mcr);
-       serial_out(up, UART_IER, save_ier);
-
-       if (port->flags & UPF_FOURPORT)
-               outb_p(save_ICP, ICP);
-
-       port->irq = (irq > 0) ? irq : 0;
-}
-
-static inline void __stop_tx(struct uart_8250_port *p)
-{
-       if (p->ier & UART_IER_THRI) {
-               p->ier &= ~UART_IER_THRI;
-               serial_out(p, UART_IER, p->ier);
-               serial8250_rpm_put_tx(p);
-       }
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       serial8250_rpm_get(up);
-       __stop_tx(up);
-
-       /*
-        * We really want to stop the transmitter from sending.
-        */
-       if (port->type == PORT_16C950) {
-               up->acr |= UART_ACR_TXDIS;
-               serial_icr_write(up, UART_ACR, up->acr);
-       }
-       serial8250_rpm_put(up);
-}
-
-static void serial8250_start_tx(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       serial8250_rpm_get_tx(up);
-
-       if (up->dma && !up->dma->tx_dma(up))
-               return;
-
-       if (!(up->ier & UART_IER_THRI)) {
-               up->ier |= UART_IER_THRI;
-               serial_port_out(port, UART_IER, up->ier);
-
-               if (up->bugs & UART_BUG_TXEN) {
-                       unsigned char lsr;
-                       lsr = serial_in(up, UART_LSR);
-                       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-                       if (lsr & UART_LSR_THRE)
-                               serial8250_tx_chars(up);
-               }
-       }
-
-       /*
-        * Re-enable the transmitter if we disabled it.
-        */
-       if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
-               up->acr &= ~UART_ACR_TXDIS;
-               serial_icr_write(up, UART_ACR, up->acr);
-       }
-}
-
-static void serial8250_throttle(struct uart_port *port)
-{
-       port->throttle(port);
-}
-
-static void serial8250_unthrottle(struct uart_port *port)
-{
-       port->unthrottle(port);
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       serial8250_rpm_get(up);
-
-       up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
-       up->port.read_status_mask &= ~UART_LSR_DR;
-       serial_port_out(port, UART_IER, up->ier);
-
-       serial8250_rpm_put(up);
-}
-
-static void serial8250_disable_ms(struct uart_port *port)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-
-       /* no MSR capabilities */
-       if (up->bugs & UART_BUG_NOMSR)
-               return;
-
-       up->ier &= ~UART_IER_MSI;
-       serial_port_out(port, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       /* no MSR capabilities */
-       if (up->bugs & UART_BUG_NOMSR)
-               return;
-
-       up->ier |= UART_IER_MSI;
-
-       serial8250_rpm_get(up);
-       serial_port_out(port, UART_IER, up->ier);
-       serial8250_rpm_put(up);
-}
-
-/*
- * serial8250_rx_chars: processes according to the passed in LSR
- * value, and returns the remaining LSR bits not handled
- * by this Rx routine.
- */
-unsigned char
-serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
-{
-       struct uart_port *port = &up->port;
-       unsigned char ch;
-       int max_count = 256;
-       char flag;
-
-       do {
-               if (likely(lsr & UART_LSR_DR))
-                       ch = serial_in(up, UART_RX);
-               else
-                       /*
-                        * Intel 82571 has a Serial Over Lan device that will
-                        * set UART_LSR_BI without setting UART_LSR_DR when
-                        * it receives a break. To avoid reading from the
-                        * receive buffer without UART_LSR_DR bit set, we
-                        * just force the read character to be 0
-                        */
-                       ch = 0;
-
-               flag = TTY_NORMAL;
-               port->icount.rx++;
-
-               lsr |= up->lsr_saved_flags;
-               up->lsr_saved_flags = 0;
-
-               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
-                       if (lsr & UART_LSR_BI) {
-                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);
-                               port->icount.brk++;
-                               /*
-                                * We do the SysRQ and SAK checking
-                                * here because otherwise the break
-                                * may get masked by ignore_status_mask
-                                * or read_status_mask.
-                                */
-                               if (uart_handle_break(port))
-                                       goto ignore_char;
-                       } else if (lsr & UART_LSR_PE)
-                               port->icount.parity++;
-                       else if (lsr & UART_LSR_FE)
-                               port->icount.frame++;
-                       if (lsr & UART_LSR_OE)
-                               port->icount.overrun++;
-
-                       /*
-                        * Mask off conditions which should be ignored.
-                        */
-                       lsr &= port->read_status_mask;
-
-                       if (lsr & UART_LSR_BI) {
-                               DEBUG_INTR("handling break....");
-                               flag = TTY_BREAK;
-                       } else if (lsr & UART_LSR_PE)
-                               flag = TTY_PARITY;
-                       else if (lsr & UART_LSR_FE)
-                               flag = TTY_FRAME;
-               }
-               if (uart_handle_sysrq_char(port, ch))
-                       goto ignore_char;
-
-               uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
-
-ignore_char:
-               lsr = serial_in(up, UART_LSR);
-       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
-       spin_unlock(&port->lock);
-       tty_flip_buffer_push(&port->state->port);
-       spin_lock(&port->lock);
-       return lsr;
-}
-EXPORT_SYMBOL_GPL(serial8250_rx_chars);
-
-void serial8250_tx_chars(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-       struct circ_buf *xmit = &port->state->xmit;
-       int count;
-
-       if (port->x_char) {
-               serial_out(up, UART_TX, port->x_char);
-               port->icount.tx++;
-               port->x_char = 0;
-               return;
-       }
-       if (uart_tx_stopped(port)) {
-               serial8250_stop_tx(port);
-               return;
-       }
-       if (uart_circ_empty(xmit)) {
-               __stop_tx(up);
-               return;
-       }
-
-       count = up->tx_loadsz;
-       do {
-               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-               if (up->capabilities & UART_CAP_HFIFO) {
-                       if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
-                           BOTH_EMPTY)
-                               break;
-               }
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);
-
-       DEBUG_INTR("THRE...");
-
-       /*
-        * With RPM enabled, we have to wait until the FIFO is empty before the
-        * HW can go idle. So we get here once again with empty FIFO and disable
-        * the interrupt and RPM in __stop_tx()
-        */
-       if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
-               __stop_tx(up);
-}
-EXPORT_SYMBOL_GPL(serial8250_tx_chars);
-
-/* Caller holds uart port lock */
-unsigned int serial8250_modem_status(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-       unsigned int status = serial_in(up, UART_MSR);
-
-       status |= up->msr_saved_flags;
-       up->msr_saved_flags = 0;
-       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
-           port->state != NULL) {
-               if (status & UART_MSR_TERI)
-                       port->icount.rng++;
-               if (status & UART_MSR_DDSR)
-                       port->icount.dsr++;
-               if (status & UART_MSR_DDCD)
-                       uart_handle_dcd_change(port, status & UART_MSR_DCD);
-               if (status & UART_MSR_DCTS)
-                       uart_handle_cts_change(port, status & UART_MSR_CTS);
-
-               wake_up_interruptible(&port->state->port.delta_msr_wait);
-       }
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(serial8250_modem_status);
-
-/*
- * This handles the interrupt from one port.
- */
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
-{
-       unsigned char status;
-       unsigned long flags;
-       struct uart_8250_port *up = up_to_u8250p(port);
-       int dma_err = 0;
-
-       if (iir & UART_IIR_NO_INT)
-               return 0;
-
-       spin_lock_irqsave(&port->lock, flags);
-
-       status = serial_port_in(port, UART_LSR);
-
-       DEBUG_INTR("status = %x...", status);
-
-       if (status & (UART_LSR_DR | UART_LSR_BI)) {
-               if (up->dma)
-                       dma_err = up->dma->rx_dma(up, iir);
-
-               if (!up->dma || dma_err)
-                       status = serial8250_rx_chars(up, status);
-       }
-       serial8250_modem_status(up);
-       if ((!up->dma || (up->dma && up->dma->tx_err)) &&
-           (status & UART_LSR_THRE))
-               serial8250_tx_chars(up);
-
-       spin_unlock_irqrestore(&port->lock, flags);
-       return 1;
-}
-EXPORT_SYMBOL_GPL(serial8250_handle_irq);
-
-static int serial8250_default_handle_irq(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned int iir;
-       int ret;
-
-       serial8250_rpm_get(up);
-
-       iir = serial_port_in(port, UART_IIR);
-       ret = serial8250_handle_irq(port, iir);
-
-       serial8250_rpm_put(up);
-       return ret;
-}
-
-/*
- * These Exar UARTs have an extra interrupt indicator that could
- * fire for a few unimplemented interrupts.  One of which is a
- * wakeup event when coming out of sleep.  Put this here just
- * to be on the safe side that these interrupts don't go unhandled.
- */
-static int exar_handle_irq(struct uart_port *port)
-{
-       unsigned char int0, int1, int2, int3;
-       unsigned int iir = serial_port_in(port, UART_IIR);
-       int ret;
-
-       ret = serial8250_handle_irq(port, iir);
-
-       if ((port->type == PORT_XR17V35X) ||
-          (port->type == PORT_XR17D15X)) {
-               int0 = serial_port_in(port, 0x80);
-               int1 = serial_port_in(port, 0x81);
-               int2 = serial_port_in(port, 0x82);
-               int3 = serial_port_in(port, 0x83);
-       }
-
-       return ret;
-}
-
-/*
- * This is the serial driver's interrupt routine.
- *
- * Arjan thinks the old way was overly complex, so it got simplified.
- * Alan disagrees, saying that need the complexity to handle the weird
- * nature of ISA shared interrupts.  (This is a special exception.)
- *
- * In order to handle ISA shared interrupts properly, we need to check
- * that all ports have been serviced, and therefore the ISA interrupt
- * line has been de-asserted.
- *
- * This means we need to loop through all ports. checking that they
- * don't have an interrupt pending.
- */
-static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
-{
-       struct irq_info *i = dev_id;
-       struct list_head *l, *end = NULL;
-       int pass_counter = 0, handled = 0;
-
-       DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-
-       spin_lock(&i->lock);
-
-       l = i->head;
-       do {
-               struct uart_8250_port *up;
-               struct uart_port *port;
-
-               up = list_entry(l, struct uart_8250_port, list);
-               port = &up->port;
-
-               if (port->handle_irq(port)) {
-                       handled = 1;
-                       end = NULL;
-               } else if (end == NULL)
-                       end = l;
-
-               l = l->next;
-
-               if (l == i->head && pass_counter++ > PASS_LIMIT) {
-                       /* If we hit this, we're dead. */
-                       printk_ratelimited(KERN_ERR
-                               "serial8250: too much work for irq%d\n", irq);
-                       break;
-               }
-       } while (l != end);
-
-       spin_unlock(&i->lock);
-
-       DEBUG_INTR("end.\n");
-
-       return IRQ_RETVAL(handled);
-}
-
-/*
- * To support ISA shared interrupts, we need to have one interrupt
- * handler that ensures that the IRQ line has been deasserted
- * before returning.  Failing to do this will result in the IRQ
- * line being stuck active, and, since ISA irqs are edge triggered,
- * no more IRQs will be seen.
- */
-static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-{
-       spin_lock_irq(&i->lock);
-
-       if (!list_empty(i->head)) {
-               if (i->head == &up->list)
-                       i->head = i->head->next;
-               list_del(&up->list);
-       } else {
-               BUG_ON(i->head != &up->list);
-               i->head = NULL;
-       }
-       spin_unlock_irq(&i->lock);
-       /* List empty so throw away the hash node */
-       if (i->head == NULL) {
-               hlist_del(&i->node);
-               kfree(i);
-       }
-}
-
-static int serial_link_irq_chain(struct uart_8250_port *up)
-{
-       struct hlist_head *h;
-       struct hlist_node *n;
-       struct irq_info *i;
-       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
-
-       mutex_lock(&hash_mutex);
-
-       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
-       hlist_for_each(n, h) {
-               i = hlist_entry(n, struct irq_info, node);
-               if (i->irq == up->port.irq)
-                       break;
-       }
-
-       if (n == NULL) {
-               i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
-               if (i == NULL) {
-                       mutex_unlock(&hash_mutex);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&i->lock);
-               i->irq = up->port.irq;
-               hlist_add_head(&i->node, h);
-       }
-       mutex_unlock(&hash_mutex);
-
-       spin_lock_irq(&i->lock);
-
-       if (i->head) {
-               list_add(&up->list, i->head);
-               spin_unlock_irq(&i->lock);
-
-               ret = 0;
-       } else {
-               INIT_LIST_HEAD(&up->list);
-               i->head = &up->list;
-               spin_unlock_irq(&i->lock);
-               irq_flags |= up->port.irqflags;
-               ret = request_irq(up->port.irq, serial8250_interrupt,
-                                 irq_flags, "serial", i);
-               if (ret < 0)
-                       serial_do_unlink(i, up);
-       }
-
-       return ret;
-}
-
-static void serial_unlink_irq_chain(struct uart_8250_port *up)
-{
-       /*
-        * yes, some broken gcc emit "warning: 'i' may be used uninitialized"
-        * but no, we are not going to take a patch that assigns NULL below.
-        */
-       struct irq_info *i;
-       struct hlist_node *n;
-       struct hlist_head *h;
-
-       mutex_lock(&hash_mutex);
-
-       h = &irq_lists[up->port.irq % NR_IRQ_HASH];
-
-       hlist_for_each(n, h) {
-               i = hlist_entry(n, struct irq_info, node);
-               if (i->irq == up->port.irq)
-                       break;
-       }
-
-       BUG_ON(n == NULL);
-       BUG_ON(i->head == NULL);
-
-       if (list_empty(i->head))
-               free_irq(up->port.irq, i);
-
-       serial_do_unlink(i, up);
-       mutex_unlock(&hash_mutex);
-}
-
-/*
- * This function is used to handle ports that do not have an
- * interrupt.  This doesn't work very well for 16450's, but gives
- * barely passable results for a 16550A.  (Although at the expense
- * of much CPU overhead).
- */
-static void serial8250_timeout(unsigned long data)
-{
-       struct uart_8250_port *up = (struct uart_8250_port *)data;
-
-       up->port.handle_irq(&up->port);
-       mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
-}
-
-static void serial8250_backup_timeout(unsigned long data)
-{
-       struct uart_8250_port *up = (struct uart_8250_port *)data;
-       unsigned int iir, ier = 0, lsr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       /*
-        * Must disable interrupts or else we risk racing with the interrupt
-        * based handler.
-        */
-       if (up->port.irq) {
-               ier = serial_in(up, UART_IER);
-               serial_out(up, UART_IER, 0);
-       }
-
-       iir = serial_in(up, UART_IIR);
-
-       /*
-        * This should be a safe test for anyone who doesn't trust the
-        * IIR bits on their UART, but it's specifically designed for
-        * the "Diva" UART used on the management processor on many HP
-        * ia64 and parisc boxes.
-        */
-       lsr = serial_in(up, UART_LSR);
-       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-       if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
-           (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
-           (lsr & UART_LSR_THRE)) {
-               iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
-               iir |= UART_IIR_THRI;
-       }
-
-       if (!(iir & UART_IIR_NO_INT))
-               serial8250_tx_chars(up);
-
-       if (up->port.irq)
-               serial_out(up, UART_IER, ier);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /* Standard timer interval plus 0.2s to keep the port running */
-       mod_timer(&up->timer,
-               jiffies + uart_poll_timeout(&up->port) + HZ / 5);
-}
-
-static int univ8250_setup_irq(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-       int retval = 0;
-
-       /*
-        * The above check will only give an accurate result the first time
-        * the port is opened so this value needs to be preserved.
-        */
-       if (up->bugs & UART_BUG_THRE) {
-               pr_debug("ttyS%d - using backup timer\n", serial_index(port));
-
-               up->timer.function = serial8250_backup_timeout;
-               up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies +
-                         uart_poll_timeout(port) + HZ / 5);
-       }
-
-       /*
-        * If the "interrupt" for this port doesn't correspond with any
-        * hardware interrupt, we use a timer-based system.  The original
-        * driver used to do this with IRQ0.
-        */
-       if (!port->irq) {
-               up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
-       } else
-               retval = serial_link_irq_chain(up);
-
-       return retval;
-}
-
-static void univ8250_release_irq(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-
-       del_timer_sync(&up->timer);
-       up->timer.function = serial8250_timeout;
-       if (port->irq)
-               serial_unlink_irq_chain(up);
-}
-
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned long flags;
-       unsigned int lsr;
-
-       serial8250_rpm_get(up);
-
-       spin_lock_irqsave(&port->lock, flags);
-       lsr = serial_port_in(port, UART_LSR);
-       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-       spin_unlock_irqrestore(&port->lock, flags);
-
-       serial8250_rpm_put(up);
-
-       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned int status;
-       unsigned int ret;
-
-       serial8250_rpm_get(up);
-       status = serial8250_modem_status(up);
-       serial8250_rpm_put(up);
-
-       ret = 0;
-       if (status & UART_MSR_DCD)
-               ret |= TIOCM_CAR;
-       if (status & UART_MSR_RI)
-               ret |= TIOCM_RNG;
-       if (status & UART_MSR_DSR)
-               ret |= TIOCM_DSR;
-       if (status & UART_MSR_CTS)
-               ret |= TIOCM_CTS;
-       return ret;
-}
-
-void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned char mcr = 0;
-
-       if (mctrl & TIOCM_RTS)
-               mcr |= UART_MCR_RTS;
-       if (mctrl & TIOCM_DTR)
-               mcr |= UART_MCR_DTR;
-       if (mctrl & TIOCM_OUT1)
-               mcr |= UART_MCR_OUT1;
-       if (mctrl & TIOCM_OUT2)
-               mcr |= UART_MCR_OUT2;
-       if (mctrl & TIOCM_LOOP)
-               mcr |= UART_MCR_LOOP;
-
-       mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-
-       serial_port_out(port, UART_MCR, mcr);
-}
-EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-       if (port->set_mctrl)
-               port->set_mctrl(port, mctrl);
-       else
-               serial8250_do_set_mctrl(port, mctrl);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned long flags;
-
-       serial8250_rpm_get(up);
-       spin_lock_irqsave(&port->lock, flags);
-       if (break_state == -1)
-               up->lcr |= UART_LCR_SBC;
-       else
-               up->lcr &= ~UART_LCR_SBC;
-       serial_port_out(port, UART_LCR, up->lcr);
-       spin_unlock_irqrestore(&port->lock, flags);
-       serial8250_rpm_put(up);
-}
-
-/*
- *     Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
-       unsigned int status, tmout = 10000;
-
-       /* Wait up to 10ms for the character(s) to be sent. */
-       for (;;) {
-               status = serial_in(up, UART_LSR);
-
-               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
-
-               if ((status & bits) == bits)
-                       break;
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       }
-
-       /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & UPF_CONS_FLOW) {
-               unsigned int tmout;
-               for (tmout = 1000000; tmout; tmout--) {
-                       unsigned int msr = serial_in(up, UART_MSR);
-                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
-                       if (msr & UART_MSR_CTS)
-                               break;
-                       udelay(1);
-                       touch_nmi_watchdog();
-               }
-       }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial8250_get_poll_char(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned char lsr;
-       int status;
-
-       serial8250_rpm_get(up);
-
-       lsr = serial_port_in(port, UART_LSR);
-
-       if (!(lsr & UART_LSR_DR)) {
-               status = NO_POLL_CHAR;
-               goto out;
-       }
-
-       status = serial_port_in(port, UART_RX);
-out:
-       serial8250_rpm_put(up);
-       return status;
-}
-
-
-static void serial8250_put_poll_char(struct uart_port *port,
-                        unsigned char c)
-{
-       unsigned int ier;
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       serial8250_rpm_get(up);
-       /*
-        *      First save the IER then disable the interrupts
-        */
-       ier = serial_port_in(port, UART_IER);
-       if (up->capabilities & UART_CAP_UUE)
-               serial_port_out(port, UART_IER, UART_IER_UUE);
-       else
-               serial_port_out(port, UART_IER, 0);
-
-       wait_for_xmitr(up, BOTH_EMPTY);
-       /*
-        *      Send the character out.
-        */
-       serial_port_out(port, UART_TX, c);
-
-       /*
-        *      Finally, wait for transmitter to become empty
-        *      and restore the IER
-        */
-       wait_for_xmitr(up, BOTH_EMPTY);
-       serial_port_out(port, UART_IER, ier);
-       serial8250_rpm_put(up);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-int serial8250_do_startup(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned long flags;
-       unsigned char lsr, iir;
-       int retval;
-
-       if (port->type == PORT_8250_CIR)
-               return -ENODEV;
-
-       if (!port->fifosize)
-               port->fifosize = uart_config[port->type].fifo_size;
-       if (!up->tx_loadsz)
-               up->tx_loadsz = uart_config[port->type].tx_loadsz;
-       if (!up->capabilities)
-               up->capabilities = uart_config[port->type].flags;
-       up->mcr = 0;
-
-       if (port->iotype != up->cur_iotype)
-               set_io_from_upio(port);
-
-       serial8250_rpm_get(up);
-       if (port->type == PORT_16C950) {
-               /* Wake up and initialize UART */
-               up->acr = 0;
-               serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
-               serial_port_out(port, UART_EFR, UART_EFR_ECB);
-               serial_port_out(port, UART_IER, 0);
-               serial_port_out(port, UART_LCR, 0);
-               serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
-               serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
-               serial_port_out(port, UART_EFR, UART_EFR_ECB);
-               serial_port_out(port, UART_LCR, 0);
-       }
-
-#ifdef CONFIG_SERIAL_8250_RSA
-       /*
-        * If this is an RSA port, see if we can kick it up to the
-        * higher speed clock.
-        */
-       enable_rsa(up);
-#endif
-       /*
-        * Clear the FIFO buffers and disable them.
-        * (they will be reenabled in set_termios())
-        */
-       serial8250_clear_fifos(up);
-
-       /*
-        * Clear the interrupt registers.
-        */
-       serial_port_in(port, UART_LSR);
-       serial_port_in(port, UART_RX);
-       serial_port_in(port, UART_IIR);
-       serial_port_in(port, UART_MSR);
-
-       /*
-        * At this point, there's no way the LSR could still be 0xff;
-        * if it is, then bail out, because there's likely no UART
-        * here.
-        */
-       if (!(port->flags & UPF_BUGGY_UART) &&
-           (serial_port_in(port, UART_LSR) == 0xff)) {
-               printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
-                                  serial_index(port));
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /*
-        * For a XR16C850, we need to set the trigger levels
-        */
-       if (port->type == PORT_16850) {
-               unsigned char fctr;
-
-               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
-               fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
-               serial_port_out(port, UART_FCTR,
-                               fctr | UART_FCTR_TRGD | UART_FCTR_RX);
-               serial_port_out(port, UART_TRG, UART_TRG_96);
-               serial_port_out(port, UART_FCTR,
-                               fctr | UART_FCTR_TRGD | UART_FCTR_TX);
-               serial_port_out(port, UART_TRG, UART_TRG_96);
-
-               serial_port_out(port, UART_LCR, 0);
-       }
-
-       if (port->irq) {
-               unsigned char iir1;
-               /*
-                * Test for UARTs that do not reassert THRE when the
-                * transmitter is idle and the interrupt has already
-                * been cleared.  Real 16550s should always reassert
-                * this interrupt whenever the transmitter is idle and
-                * the interrupt is enabled.  Delays are necessary to
-                * allow register changes to become visible.
-                */
-               spin_lock_irqsave(&port->lock, flags);
-               if (up->port.irqflags & IRQF_SHARED)
-                       disable_irq_nosync(port->irq);
-
-               wait_for_xmitr(up, UART_LSR_THRE);
-               serial_port_out_sync(port, UART_IER, UART_IER_THRI);
-               udelay(1); /* allow THRE to set */
-               iir1 = serial_port_in(port, UART_IIR);
-               serial_port_out(port, UART_IER, 0);
-               serial_port_out_sync(port, UART_IER, UART_IER_THRI);
-               udelay(1); /* allow a working UART time to re-assert THRE */
-               iir = serial_port_in(port, UART_IIR);
-               serial_port_out(port, UART_IER, 0);
-
-               if (port->irqflags & IRQF_SHARED)
-                       enable_irq(port->irq);
-               spin_unlock_irqrestore(&port->lock, flags);
-
-               /*
-                * If the interrupt is not reasserted, or we otherwise
-                * don't trust the iir, setup a timer to kick the UART
-                * on a regular basis.
-                */
-               if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
-                   up->port.flags & UPF_BUG_THRE) {
-                       up->bugs |= UART_BUG_THRE;
-               }
-       }
-
-       retval = up->ops->setup_irq(up);
-       if (retval)
-               goto out;
-
-       /*
-        * Now, initialize the UART
-        */
-       serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
-
-       spin_lock_irqsave(&port->lock, flags);
-       if (up->port.flags & UPF_FOURPORT) {
-               if (!up->port.irq)
-                       up->port.mctrl |= TIOCM_OUT1;
-       } else
-               /*
-                * Most PC uarts need OUT2 raised to enable interrupts.
-                */
-               if (port->irq)
-                       up->port.mctrl |= TIOCM_OUT2;
-
-       serial8250_set_mctrl(port, port->mctrl);
-
-       /* Serial over Lan (SoL) hack:
-          Intel 8257x Gigabit ethernet chips have a
-          16550 emulation, to be used for Serial Over Lan.
-          Those chips take a longer time than a normal
-          serial device to signalize that a transmission
-          data was queued. Due to that, the above test generally
-          fails. One solution would be to delay the reading of
-          iir. However, this is not reliable, since the timeout
-          is variable. So, let's just don't test if we receive
-          TX irq. This way, we'll never enable UART_BUG_TXEN.
-        */
-       if (up->port.flags & UPF_NO_TXEN_TEST)
-               goto dont_test_tx_en;
-
-       /*
-        * Do a quick test to see if we receive an
-        * interrupt when we enable the TX irq.
-        */
-       serial_port_out(port, UART_IER, UART_IER_THRI);
-       lsr = serial_port_in(port, UART_LSR);
-       iir = serial_port_in(port, UART_IIR);
-       serial_port_out(port, UART_IER, 0);
-
-       if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
-               if (!(up->bugs & UART_BUG_TXEN)) {
-                       up->bugs |= UART_BUG_TXEN;
-                       pr_debug("ttyS%d - enabling bad tx status workarounds\n",
-                                serial_index(port));
-               }
-       } else {
-               up->bugs &= ~UART_BUG_TXEN;
-       }
-
-dont_test_tx_en:
-       spin_unlock_irqrestore(&port->lock, flags);
-
-       /*
-        * Clear the interrupt registers again for luck, and clear the
-        * saved flags to avoid getting false values from polling
-        * routines or the previous session.
-        */
-       serial_port_in(port, UART_LSR);
-       serial_port_in(port, UART_RX);
-       serial_port_in(port, UART_IIR);
-       serial_port_in(port, UART_MSR);
-       up->lsr_saved_flags = 0;
-       up->msr_saved_flags = 0;
-
-       /*
-        * Request DMA channels for both RX and TX.
-        */
-       if (up->dma) {
-               retval = serial8250_request_dma(up);
-               if (retval) {
-                       pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
-                                           serial_index(port));
-                       up->dma = NULL;
-               }
-       }
-
-       /*
-        * Finally, enable interrupts.  Note: Modem status interrupts
-        * are set via set_termios(), which will be occurring imminently
-        * anyway, so we don't enable them here.
-        */
-       up->ier = UART_IER_RLSI | UART_IER_RDI;
-       serial_port_out(port, UART_IER, up->ier);
-
-       if (port->flags & UPF_FOURPORT) {
-               unsigned int icp;
-               /*
-                * Enable interrupts on the AST Fourport board
-                */
-               icp = (port->iobase & 0xfe0) | 0x01f;
-               outb_p(0x80, icp);
-               inb_p(icp);
-       }
-       retval = 0;
-out:
-       serial8250_rpm_put(up);
-       return retval;
-}
-EXPORT_SYMBOL_GPL(serial8250_do_startup);
-
-static int serial8250_startup(struct uart_port *port)
-{
-       if (port->startup)
-               return port->startup(port);
-       return serial8250_do_startup(port);
-}
-
-void serial8250_do_shutdown(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned long flags;
-
-       serial8250_rpm_get(up);
-       /*
-        * Disable interrupts from this port
-        */
-       up->ier = 0;
-       serial_port_out(port, UART_IER, 0);
-
-       if (up->dma)
-               serial8250_release_dma(up);
-
-       spin_lock_irqsave(&port->lock, flags);
-       if (port->flags & UPF_FOURPORT) {
-               /* reset interrupts on the AST Fourport board */
-               inb((port->iobase & 0xfe0) | 0x1f);
-               port->mctrl |= TIOCM_OUT1;
-       } else
-               port->mctrl &= ~TIOCM_OUT2;
-
-       serial8250_set_mctrl(port, port->mctrl);
-       spin_unlock_irqrestore(&port->lock, flags);
-
-       /*
-        * Disable break condition and FIFOs
-        */
-       serial_port_out(port, UART_LCR,
-                       serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
-       serial8250_clear_fifos(up);
-
-#ifdef CONFIG_SERIAL_8250_RSA
-       /*
-        * Reset the RSA board back to 115kbps compat mode.
-        */
-       disable_rsa(up);
-#endif
-
-       /*
-        * Read data port to reset things, and then unlink from
-        * the IRQ chain.
-        */
-       serial_port_in(port, UART_RX);
-       serial8250_rpm_put(up);
-
-       up->ops->release_irq(up);
-}
-EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
-
-static void serial8250_shutdown(struct uart_port *port)
-{
-       if (port->shutdown)
-               port->shutdown(port);
-       else
-               serial8250_do_shutdown(port);
-}
-
-/*
- * XR17V35x UARTs have an extra fractional divisor register (DLD)
- * Calculate divisor with extra 4-bit fractional portion
- */
-static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
-                                        unsigned int baud,
-                                        unsigned int *frac)
-{
-       struct uart_port *port = &up->port;
-       unsigned int quot_16;
-
-       quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
-       *frac = quot_16 & 0x0f;
-
-       return quot_16 >> 4;
-}
-
-static unsigned int serial8250_get_divisor(struct uart_8250_port *up,
-                                          unsigned int baud,
-                                          unsigned int *frac)
-{
-       struct uart_port *port = &up->port;
-       unsigned int quot;
-
-       /*
-        * Handle magic divisors for baud rates above baud_base on
-        * SMSC SuperIO chips.
-        *
-        */
-       if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-           baud == (port->uartclk/4))
-               quot = 0x8001;
-       else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
-                baud == (port->uartclk/8))
-               quot = 0x8002;
-       else if (up->port.type == PORT_XR17V35X)
-               quot = xr17v35x_get_divisor(up, baud, frac);
-       else
-               quot = uart_get_divisor(port, baud);
-
-       /*
-        * Oxford Semi 952 rev B workaround
-        */
-       if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
-               quot++;
-
-       return quot;
-}
-
-static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
-                                           tcflag_t c_cflag)
-{
-       unsigned char cval;
-
-       switch (c_cflag & CSIZE) {
-       case CS5:
-               cval = UART_LCR_WLEN5;
-               break;
-       case CS6:
-               cval = UART_LCR_WLEN6;
-               break;
-       case CS7:
-               cval = UART_LCR_WLEN7;
-               break;
-       default:
-       case CS8:
-               cval = UART_LCR_WLEN8;
-               break;
-       }
-
-       if (c_cflag & CSTOPB)
-               cval |= UART_LCR_STOP;
-       if (c_cflag & PARENB) {
-               cval |= UART_LCR_PARITY;
-               if (up->bugs & UART_BUG_PARITY)
-                       up->fifo_bug = true;
-       }
-       if (!(c_cflag & PARODD))
-               cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
-       if (c_cflag & CMSPAR)
-               cval |= UART_LCR_SPAR;
-#endif
-
-       return cval;
-}
-
-static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
-                           unsigned int quot, unsigned int quot_frac)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
-       if (is_omap1510_8250(up)) {
-               if (baud == 115200) {
-                       quot = 1;
-                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
-               } else
-                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
-       }
-
-       /*
-        * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
-        * otherwise just set DLAB
-        */
-       if (up->capabilities & UART_NATSEMI)
-               serial_port_out(port, UART_LCR, 0xe0);
-       else
-               serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
-
-       serial_dl_write(up, quot);
-
-       /* XR17V35x UARTs have an extra fractional divisor register (DLD) */
-       if (up->port.type == PORT_XR17V35X)
-               serial_port_out(port, 0x2, quot_frac);
-}
-
-void
-serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
-                         struct ktermios *old)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       unsigned char cval;
-       unsigned long flags;
-       unsigned int baud, quot, frac = 0;
-
-       cval = serial8250_compute_lcr(up, termios->c_cflag);
-
-       /*
-        * Ask the core to calculate the divisor for us.
-        */
-       baud = uart_get_baud_rate(port, termios, old,
-                                 port->uartclk / 16 / 0xffff,
-                                 port->uartclk / 16);
-       quot = serial8250_get_divisor(up, baud, &frac);
-
-       /*
-        * Ok, we're now changing the port state.  Do it with
-        * interrupts disabled.
-        */
-       serial8250_rpm_get(up);
-       spin_lock_irqsave(&port->lock, flags);
-
-       up->lcr = cval;                                 /* Save computed LCR */
-
-       if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
-               /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
-               if ((baud < 2400 && !up->dma) || up->fifo_bug) {
-                       up->fcr &= ~UART_FCR_TRIGGER_MASK;
-                       up->fcr |= UART_FCR_TRIGGER_1;
-               }
-       }
-
-       /*
-        * MCR-based auto flow control.  When AFE is enabled, RTS will be
-        * deasserted when the receive FIFO contains more characters than
-        * the trigger, or the MCR RTS bit is cleared.  In the case where
-        * the remote UART is not using CTS auto flow control, we must
-        * have sufficient FIFO entries for the latency of the remote
-        * UART to respond.  IOW, at least 32 bytes of FIFO.
-        */
-       if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
-               up->mcr &= ~UART_MCR_AFE;
-               if (termios->c_cflag & CRTSCTS)
-                       up->mcr |= UART_MCR_AFE;
-       }
-
-       /*
-        * Update the per-port timeout.
-        */
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-       if (termios->c_iflag & INPCK)
-               port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-       if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-               port->read_status_mask |= UART_LSR_BI;
-
-       /*
-        * Characteres to ignore
-        */
-       port->ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-       if (termios->c_iflag & IGNBRK) {
-               port->ignore_status_mask |= UART_LSR_BI;
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns too (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       port->ignore_status_mask |= UART_LSR_OE;
-       }
-
-       /*
-        * ignore all characters if CREAD is not set
-        */
-       if ((termios->c_cflag & CREAD) == 0)
-               port->ignore_status_mask |= UART_LSR_DR;
-
-       /*
-        * CTS flow control flag and modem status interrupts
-        */
-       up->ier &= ~UART_IER_MSI;
-       if (!(up->bugs & UART_BUG_NOMSR) &&
-                       UART_ENABLE_MS(&up->port, termios->c_cflag))
-               up->ier |= UART_IER_MSI;
-       if (up->capabilities & UART_CAP_UUE)
-               up->ier |= UART_IER_UUE;
-       if (up->capabilities & UART_CAP_RTOIE)
-               up->ier |= UART_IER_RTOIE;
-
-       serial_port_out(port, UART_IER, up->ier);
-
-       if (up->capabilities & UART_CAP_EFR) {
-               unsigned char efr = 0;
-               /*
-                * TI16C752/Startech hardware flow control.  FIXME:
-                * - TI16C752 requires control thresholds to be set.
-                * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
-                */
-               if (termios->c_cflag & CRTSCTS)
-                       efr |= UART_EFR_CTS;
-
-               serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
-               if (port->flags & UPF_EXAR_EFR)
-                       serial_port_out(port, UART_XR_EFR, efr);
-               else
-                       serial_port_out(port, UART_EFR, efr);
-       }
-
-       serial8250_set_divisor(port, baud, quot, frac);
+       spin_lock_irqsave(&up->port.lock, flags);
 
        /*
-        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
-        * is written without DLAB set, this mode will be disabled.
+        * Must disable interrupts or else we risk racing with the interrupt
+        * based handler.
         */
-       if (port->type == PORT_16750)
-               serial_port_out(port, UART_FCR, up->fcr);
-
-       serial_port_out(port, UART_LCR, up->lcr);       /* reset DLAB */
-       if (port->type != PORT_16750) {
-               /* emulated UARTs (Lucent Venus 167x) need two steps */
-               if (up->fcr & UART_FCR_ENABLE_FIFO)
-                       serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
-               serial_port_out(port, UART_FCR, up->fcr);       /* set fcr */
-       }
-       serial8250_set_mctrl(port, port->mctrl);
-       spin_unlock_irqrestore(&port->lock, flags);
-       serial8250_rpm_put(up);
-
-       /* Don't rewrite B0 */
-       if (tty_termios_baud_rate(termios))
-               tty_termios_encode_baud_rate(termios, baud, baud);
-}
-EXPORT_SYMBOL(serial8250_do_set_termios);
-
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
-                      struct ktermios *old)
-{
-       if (port->set_termios)
-               port->set_termios(port, termios, old);
-       else
-               serial8250_do_set_termios(port, termios, old);
-}
-
-static void
-serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
-{
-       if (termios->c_line == N_PPS) {
-               port->flags |= UPF_HARDPPS_CD;
-               spin_lock_irq(&port->lock);
-               serial8250_enable_ms(port);
-               spin_unlock_irq(&port->lock);
-       } else {
-               port->flags &= ~UPF_HARDPPS_CD;
-               if (!UART_ENABLE_MS(port, termios->c_cflag)) {
-                       spin_lock_irq(&port->lock);
-                       serial8250_disable_ms(port);
-                       spin_unlock_irq(&port->lock);
-               }
+       if (up->port.irq) {
+               ier = serial_in(up, UART_IER);
+               serial_out(up, UART_IER, 0);
        }
-}
 
+       iir = serial_in(up, UART_IIR);
 
-void serial8250_do_pm(struct uart_port *port, unsigned int state,
-                     unsigned int oldstate)
-{
-       struct uart_8250_port *p = up_to_u8250p(port);
+       /*
+        * This should be a safe test for anyone who doesn't trust the
+        * IIR bits on their UART, but it's specifically designed for
+        * the "Diva" UART used on the management processor on many HP
+        * ia64 and parisc boxes.
+        */
+       lsr = serial_in(up, UART_LSR);
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+       if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+           (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
+           (lsr & UART_LSR_THRE)) {
+               iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+               iir |= UART_IIR_THRI;
+       }
 
-       serial8250_set_sleep(p, state != 0);
-}
-EXPORT_SYMBOL(serial8250_do_pm);
+       if (!(iir & UART_IIR_NO_INT))
+               serial8250_tx_chars(up);
 
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
-             unsigned int oldstate)
-{
-       if (port->pm)
-               port->pm(port, state, oldstate);
-       else
-               serial8250_do_pm(port, state, oldstate);
-}
+       if (up->port.irq)
+               serial_out(up, UART_IER, ier);
 
-static unsigned int serial8250_port_size(struct uart_8250_port *pt)
-{
-       if (pt->port.mapsize)
-               return pt->port.mapsize;
-       if (pt->port.iotype == UPIO_AU) {
-               if (pt->port.type == PORT_RT2880)
-                       return 0x100;
-               return 0x1000;
-       }
-       if (is_omap1_8250(pt))
-               return 0x16 << pt->port.regshift;
+       spin_unlock_irqrestore(&up->port.lock, flags);
 
-       return 8 << pt->port.regshift;
+       /* Standard timer interval plus 0.2s to keep the port running */
+       mod_timer(&up->timer,
+               jiffies + uart_poll_timeout(&up->port) + HZ / 5);
 }
 
-/*
- * Resource handling.
- */
-static int serial8250_request_std_resource(struct uart_8250_port *up)
+static int univ8250_setup_irq(struct uart_8250_port *up)
 {
-       unsigned int size = serial8250_port_size(up);
        struct uart_port *port = &up->port;
-       int ret = 0;
+       int retval = 0;
 
-       switch (port->iotype) {
-       case UPIO_AU:
-       case UPIO_TSI:
-       case UPIO_MEM32:
-       case UPIO_MEM32BE:
-       case UPIO_MEM:
-               if (!port->mapbase)
-                       break;
+       /*
+        * The above check will only give an accurate result the first time
+        * the port is opened so this value needs to be preserved.
+        */
+       if (up->bugs & UART_BUG_THRE) {
+               pr_debug("ttyS%d - using backup timer\n", serial_index(port));
 
-               if (!request_mem_region(port->mapbase, size, "serial")) {
-                       ret = -EBUSY;
-                       break;
-               }
+               up->timer.function = serial8250_backup_timeout;
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies +
+                         uart_poll_timeout(port) + HZ / 5);
+       }
 
-               if (port->flags & UPF_IOREMAP) {
-                       port->membase = ioremap_nocache(port->mapbase, size);
-                       if (!port->membase) {
-                               release_mem_region(port->mapbase, size);
-                               ret = -ENOMEM;
-                       }
-               }
-               break;
+       /*
+        * If the "interrupt" for this port doesn't correspond with any
+        * hardware interrupt, we use a timer-based system.  The original
+        * driver used to do this with IRQ0.
+        */
+       if (!port->irq) {
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+       } else
+               retval = serial_link_irq_chain(up);
 
-       case UPIO_HUB6:
-       case UPIO_PORT:
-               if (!request_region(port->iobase, size, "serial"))
-                       ret = -EBUSY;
-               break;
-       }
-       return ret;
+       return retval;
 }
 
-static void serial8250_release_std_resource(struct uart_8250_port *up)
+static void univ8250_release_irq(struct uart_8250_port *up)
 {
-       unsigned int size = serial8250_port_size(up);
        struct uart_port *port = &up->port;
 
-       switch (port->iotype) {
-       case UPIO_AU:
-       case UPIO_TSI:
-       case UPIO_MEM32:
-       case UPIO_MEM32BE:
-       case UPIO_MEM:
-               if (!port->mapbase)
-                       break;
-
-               if (port->flags & UPF_IOREMAP) {
-                       iounmap(port->membase);
-                       port->membase = NULL;
-               }
-
-               release_mem_region(port->mapbase, size);
-               break;
-
-       case UPIO_HUB6:
-       case UPIO_PORT:
-               release_region(port->iobase, size);
-               break;
-       }
+       del_timer_sync(&up->timer);
+       up->timer.function = serial8250_timeout;
+       if (port->irq)
+               serial_unlink_irq_chain(up);
 }
 
 #ifdef CONFIG_SERIAL_8250_RSA
@@ -2848,259 +396,6 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
 }
 #endif
 
-static void serial8250_release_port(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       serial8250_release_std_resource(up);
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       int ret;
-
-       if (port->type == PORT_8250_CIR)
-               return -ENODEV;
-
-       ret = serial8250_request_std_resource(up);
-
-       return ret;
-}
-
-static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
-{
-       const struct serial8250_config *conf_type = &uart_config[up->port.type];
-       unsigned char bytes;
-
-       bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
-
-       return bytes ? bytes : -EOPNOTSUPP;
-}
-
-static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
-{
-       const struct serial8250_config *conf_type = &uart_config[up->port.type];
-       int i;
-
-       if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
-               return -EOPNOTSUPP;
-
-       for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
-               if (bytes < conf_type->rxtrig_bytes[i])
-                       /* Use the nearest lower value */
-                       return (--i) << UART_FCR_R_TRIG_SHIFT;
-       }
-
-       return UART_FCR_R_TRIG_11;
-}
-
-static int do_get_rxtrig(struct tty_port *port)
-{
-       struct uart_state *state = container_of(port, struct uart_state, port);
-       struct uart_port *uport = state->uart_port;
-       struct uart_8250_port *up =
-               container_of(uport, struct uart_8250_port, port);
-
-       if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
-               return -EINVAL;
-
-       return fcr_get_rxtrig_bytes(up);
-}
-
-static int do_serial8250_get_rxtrig(struct tty_port *port)
-{
-       int rxtrig_bytes;
-
-       mutex_lock(&port->mutex);
-       rxtrig_bytes = do_get_rxtrig(port);
-       mutex_unlock(&port->mutex);
-
-       return rxtrig_bytes;
-}
-
-static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
-       struct device_attribute *attr, char *buf)
-{
-       struct tty_port *port = dev_get_drvdata(dev);
-       int rxtrig_bytes;
-
-       rxtrig_bytes = do_serial8250_get_rxtrig(port);
-       if (rxtrig_bytes < 0)
-               return rxtrig_bytes;
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
-}
-
-static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
-{
-       struct uart_state *state = container_of(port, struct uart_state, port);
-       struct uart_port *uport = state->uart_port;
-       struct uart_8250_port *up =
-               container_of(uport, struct uart_8250_port, port);
-       int rxtrig;
-
-       if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
-           up->fifo_bug)
-               return -EINVAL;
-
-       rxtrig = bytes_to_fcr_rxtrig(up, bytes);
-       if (rxtrig < 0)
-               return rxtrig;
-
-       serial8250_clear_fifos(up);
-       up->fcr &= ~UART_FCR_TRIGGER_MASK;
-       up->fcr |= (unsigned char)rxtrig;
-       serial_out(up, UART_FCR, up->fcr);
-       return 0;
-}
-
-static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
-{
-       int ret;
-
-       mutex_lock(&port->mutex);
-       ret = do_set_rxtrig(port, bytes);
-       mutex_unlock(&port->mutex);
-
-       return ret;
-}
-
-static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct tty_port *port = dev_get_drvdata(dev);
-       unsigned char bytes;
-       int ret;
-
-       if (!count)
-               return -EINVAL;
-
-       ret = kstrtou8(buf, 10, &bytes);
-       if (ret < 0)
-               return ret;
-
-       ret = do_serial8250_set_rxtrig(port, bytes);
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
-                  serial8250_get_attr_rx_trig_bytes,
-                  serial8250_set_attr_rx_trig_bytes);
-
-static struct attribute *serial8250_dev_attrs[] = {
-       &dev_attr_rx_trig_bytes.attr,
-       NULL,
-       };
-
-static struct attribute_group serial8250_dev_attr_group = {
-       .attrs = serial8250_dev_attrs,
-       };
-
-static void register_dev_spec_attr_grp(struct uart_8250_port *up)
-{
-       const struct serial8250_config *conf_type = &uart_config[up->port.type];
-
-       if (conf_type->rxtrig_bytes[0])
-               up->port.attr_group = &serial8250_dev_attr_group;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-       int ret;
-
-       if (port->type == PORT_8250_CIR)
-               return;
-
-       /*
-        * Find the region that we can probe for.  This in turn
-        * tells us whether we can probe for the type of port.
-        */
-       ret = serial8250_request_std_resource(up);
-       if (ret < 0)
-               return;
-
-       if (port->iotype != up->cur_iotype)
-               set_io_from_upio(port);
-
-       if (flags & UART_CONFIG_TYPE)
-               autoconfig(up);
-
-       /* if access method is AU, it is a 16550 with a quirk */
-       if (port->type == PORT_16550A && port->iotype == UPIO_AU)
-               up->bugs |= UART_BUG_NOMSR;
-
-       /* HW bugs may trigger IRQ while IIR == NO_INT */
-       if (port->type == PORT_TEGRA)
-               up->bugs |= UART_BUG_NOMSR;
-
-       if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-               autoconfig_irq(up);
-
-       if (port->type == PORT_UNKNOWN)
-               serial8250_release_std_resource(up);
-
-       /* Fixme: probably not the best place for this */
-       if ((port->type == PORT_XR17V35X) ||
-          (port->type == PORT_XR17D15X))
-               port->handle_irq = exar_handle_irq;
-
-       register_dev_spec_attr_grp(up);
-       up->fcr = uart_config[up->port.type].fcr;
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       if (ser->irq >= nr_irqs || ser->irq < 0 ||
-           ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-           ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
-           ser->type == PORT_STARTECH)
-               return -EINVAL;
-       return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
-       int type = port->type;
-
-       if (type >= ARRAY_SIZE(uart_config))
-               type = 0;
-       return uart_config[type].name;
-}
-
-static const struct uart_ops serial8250_pops = {
-       .tx_empty       = serial8250_tx_empty,
-       .set_mctrl      = serial8250_set_mctrl,
-       .get_mctrl      = serial8250_get_mctrl,
-       .stop_tx        = serial8250_stop_tx,
-       .start_tx       = serial8250_start_tx,
-       .throttle       = serial8250_throttle,
-       .unthrottle     = serial8250_unthrottle,
-       .stop_rx        = serial8250_stop_rx,
-       .enable_ms      = serial8250_enable_ms,
-       .break_ctl      = serial8250_break_ctl,
-       .startup        = serial8250_startup,
-       .shutdown       = serial8250_shutdown,
-       .set_termios    = serial8250_set_termios,
-       .set_ldisc      = serial8250_set_ldisc,
-       .pm             = serial8250_pm,
-       .type           = serial8250_type,
-       .release_port   = serial8250_release_port,
-       .request_port   = serial8250_request_port,
-       .config_port    = serial8250_config_port,
-       .verify_port    = serial8250_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
-       .poll_get_char = serial8250_get_poll_char,
-       .poll_put_char = serial8250_put_poll_char,
-#endif
-};
-
 static const struct uart_ops *base_ops;
 static struct uart_ops univ8250_port_ops;
 
@@ -3139,42 +434,6 @@ void serial8250_set_isa_configurator(
 }
 EXPORT_SYMBOL(serial8250_set_isa_configurator);
 
-static void serial8250_init_port(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-
-       spin_lock_init(&port->lock);
-       port->ops = &serial8250_pops;
-
-       up->cur_iotype = 0xFF;
-}
-
-static void serial8250_set_defaults(struct uart_8250_port *up)
-{
-       struct uart_port *port = &up->port;
-
-       if (up->port.flags & UPF_FIXED_TYPE) {
-               unsigned int type = up->port.type;
-
-               if (!up->port.fifosize)
-                       up->port.fifosize = uart_config[type].fifo_size;
-               if (!up->tx_loadsz)
-                       up->tx_loadsz = uart_config[type].tx_loadsz;
-               if (!up->capabilities)
-                       up->capabilities = uart_config[type].flags;
-       }
-
-       set_io_from_upio(port);
-
-       /* default dma handlers */
-       if (up->dma) {
-               if (!up->dma->tx_dma)
-                       up->dma->tx_dma = serial8250_tx_dma;
-               if (!up->dma->rx_dma)
-                       up->dma->rx_dma = serial8250_rx_dma;
-       }
-}
-
 #ifdef CONFIG_SERIAL_8250_RSA
 
 static void univ8250_config_port(struct uart_port *port, int flags)
@@ -3324,94 +583,6 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 
-static void serial8250_console_putchar(struct uart_port *port, int ch)
-{
-       struct uart_8250_port *up = up_to_u8250p(port);
-
-       wait_for_xmitr(up, UART_LSR_THRE);
-       serial_port_out(port, UART_TX, ch);
-}
-
-/*
- *     Print a string to the serial port trying not to disturb
- *     any possible real use of the port...
- *
- *     The console_lock must be held when we get here.
- */
-static void serial8250_console_write(struct uart_8250_port *up, const char *s,
-                                    unsigned int count)
-{
-       struct uart_port *port = &up->port;
-       unsigned long flags;
-       unsigned int ier;
-       int locked = 1;
-
-       touch_nmi_watchdog();
-
-       serial8250_rpm_get(up);
-
-       if (port->sysrq)
-               locked = 0;
-       else if (oops_in_progress)
-               locked = spin_trylock_irqsave(&port->lock, flags);
-       else
-               spin_lock_irqsave(&port->lock, flags);
-
-       /*
-        *      First save the IER then disable the interrupts
-        */
-       ier = serial_port_in(port, UART_IER);
-
-       if (up->capabilities & UART_CAP_UUE)
-               serial_port_out(port, UART_IER, UART_IER_UUE);
-       else
-               serial_port_out(port, UART_IER, 0);
-
-       /* check scratch reg to see if port powered off during system sleep */
-       if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
-               struct ktermios termios;
-               unsigned int baud, quot, frac = 0;
-
-               termios.c_cflag = port->cons->cflag;
-               if (port->state->port.tty && termios.c_cflag == 0)
-                       termios.c_cflag = port->state->port.tty->termios.c_cflag;
-
-               baud = uart_get_baud_rate(port, &termios, NULL,
-                                         port->uartclk / 16 / 0xffff,
-                                         port->uartclk / 16);
-               quot = serial8250_get_divisor(up, baud, &frac);
-
-               serial8250_set_divisor(port, baud, quot, frac);
-               serial_port_out(port, UART_LCR, up->lcr);
-               serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
-
-               up->canary = 0;
-       }
-
-       uart_console_write(port, s, count, serial8250_console_putchar);
-
-       /*
-        *      Finally, wait for transmitter to become empty
-        *      and restore the IER
-        */
-       wait_for_xmitr(up, BOTH_EMPTY);
-       serial_port_out(port, UART_IER, ier);
-
-       /*
-        *      The receive handling will happen properly because the
-        *      receive ready bit will still be set; it is not cleared
-        *      on read.  However, modem control will not, we must
-        *      call it if we have saved something in the saved flags
-        *      while processing with interrupts off.
-        */
-       if (up->msr_saved_flags)
-               serial8250_modem_status(up);
-
-       if (locked)
-               spin_unlock_irqrestore(&port->lock, flags);
-       serial8250_rpm_put(up);
-}
-
 static void univ8250_console_write(struct console *co, const char *s,
                                   unsigned int count)
 {
@@ -3420,39 +591,6 @@ static void univ8250_console_write(struct console *co, const char *s,
        serial8250_console_write(up, s, count);
 }
 
-static unsigned int probe_baud(struct uart_port *port)
-{
-       unsigned char lcr, dll, dlm;
-       unsigned int quot;
-
-       lcr = serial_port_in(port, UART_LCR);
-       serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
-       dll = serial_port_in(port, UART_DLL);
-       dlm = serial_port_in(port, UART_DLM);
-       serial_port_out(port, UART_LCR, lcr);
-
-       quot = (dlm << 8) | dll;
-       return (port->uartclk / 16) / quot;
-}
-
-static int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
-{
-       int baud = 9600;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       if (!port->iobase && !port->membase)
-               return -ENODEV;
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-       else if (probe)
-               baud = probe_baud(port);
-
-       return uart_set_options(port, port->cons, baud, parity, bits, flow);
-}
-
 static int univ8250_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
index d48b50641e9a6c63ed874399f6b587ccd844556d..06324f17a0cb1de308128573330373d073e78db3 100644 (file)
@@ -56,7 +56,6 @@
 
 struct dw8250_data {
        u8                      usr_reg;
-       int                     last_mcr;
        int                     line;
        int                     msr_mask_on;
        int                     msr_mask_off;
@@ -76,12 +75,6 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
 {
        struct dw8250_data *d = p->private_data;
 
-       /* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
-       if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
-               value |= UART_MSR_CTS;
-               value &= ~UART_MSR_DCTS;
-       }
-
        /* Override any modem control signals if needed */
        if (offset == UART_MSR) {
                value |= d->msr_mask_on;
@@ -101,11 +94,6 @@ static void dw8250_force_idle(struct uart_port *p)
 
 static void dw8250_serial_out(struct uart_port *p, int offset, int value)
 {
-       struct dw8250_data *d = p->private_data;
-
-       if (offset == UART_MCR)
-               d->last_mcr = value;
-
        writeb(value, p->membase + (offset << p->regshift));
 
        /* Make sure LCR write wasn't ignored */
@@ -144,11 +132,6 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset)
 
 static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
 {
-       struct dw8250_data *d = p->private_data;
-
-       if (offset == UART_MCR)
-               d->last_mcr = value;
-
        value &= 0xff;
        __raw_writeq(value, p->membase + (offset << p->regshift));
        /* Read back to ensure register write ordering. */
@@ -175,11 +158,6 @@ static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
 
 static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
 {
-       struct dw8250_data *d = p->private_data;
-
-       if (offset == UART_MCR)
-               d->last_mcr = value;
-
        writel(value, p->membase + (offset << p->regshift));
 
        /* Make sure LCR write wasn't ignored */
@@ -257,6 +235,11 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 
        if (!ret)
                p->uartclk = rate;
+
+       p->status &= ~UPSTAT_AUTOCTS;
+       if (termios->c_cflag & CRTSCTS)
+               p->status |= UPSTAT_AUTOCTS;
+
 out:
        serial8250_do_set_termios(p, termios, old);
 }
index 771dda29a0f89e352c0180572bf5a59acb0f824f..faed05f25bc2e148837518ad34958924c06eb90e 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 #include <asm/serial.h>
 
-unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
+static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
 {
        switch (port->iotype) {
        case UPIO_MEM:
@@ -51,7 +51,7 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse
        }
 }
 
-void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
+static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
 {
        switch (port->iotype) {
        case UPIO_MEM:
index 5815e81b5fc603cdad8463bcdd5cfe0880186376..89474399ab89b371be5599c33ca54aa555f2f0f5 100644 (file)
 #include <linux/serial_core.h>
 #include  "8250.h"
 
-#define ADDR_PORT 0x4E
-#define DATA_PORT 0x4F
-#define ENTRY_KEY 0x77
+#define ADDR_PORT 0
+#define DATA_PORT 1
 #define EXIT_KEY 0xAA
 #define CHIP_ID1  0x20
-#define CHIP_ID1_VAL 0x02
 #define CHIP_ID2  0x21
-#define CHIP_ID2_VAL 0x16
+#define CHIP_ID_0 0x1602
+#define CHIP_ID_1 0x0501
 #define VENDOR_ID1 0x23
 #define VENDOR_ID1_VAL 0x19
 #define VENDOR_ID2 0x24
 #define VENDOR_ID2_VAL 0x34
+#define IO_ADDR1 0x61
+#define IO_ADDR2 0x60
 #define LDN 0x7
 
 #define RS485  0xF0
 
 #define DRIVER_NAME "8250_fintek"
 
-static int fintek_8250_enter_key(void){
+struct fintek_8250 {
+       u16 base_port;
+       u8 index;
+       u8 key;
+       long line;
+};
+
+static int fintek_8250_enter_key(u16 base_port, u8 key)
+{
 
-       if (!request_muxed_region(ADDR_PORT, 2, DRIVER_NAME))
+       if (!request_muxed_region(base_port, 2, DRIVER_NAME))
                return -EBUSY;
 
-       outb(ENTRY_KEY, ADDR_PORT);
-       outb(ENTRY_KEY, ADDR_PORT);
+       outb(key, base_port + ADDR_PORT);
+       outb(key, base_port + ADDR_PORT);
        return 0;
 }
 
-static void fintek_8250_exit_key(void){
-
-       outb(EXIT_KEY, ADDR_PORT);
-       release_region(ADDR_PORT, 2);
-}
-
-static int fintek_8250_get_index(resource_size_t base_addr)
+static void fintek_8250_exit_key(u16 base_port)
 {
-       resource_size_t base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(base); i++)
-               if (base_addr == base[i])
-                       return i;
 
-       return -ENODEV;
+       outb(EXIT_KEY, base_port + ADDR_PORT);
+       release_region(base_port + ADDR_PORT, 2);
 }
 
-static int fintek_8250_check_id(void)
+static int fintek_8250_check_id(u16 base_port)
 {
+       u16 chip;
 
-       outb(CHIP_ID1, ADDR_PORT);
-       if (inb(DATA_PORT) != CHIP_ID1_VAL)
+       outb(VENDOR_ID1, base_port + ADDR_PORT);
+       if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL)
                return -ENODEV;
 
-       outb(CHIP_ID2, ADDR_PORT);
-       if (inb(DATA_PORT) != CHIP_ID2_VAL)
+       outb(VENDOR_ID2, base_port + ADDR_PORT);
+       if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL)
                return -ENODEV;
 
-       outb(VENDOR_ID1, ADDR_PORT);
-       if (inb(DATA_PORT) != VENDOR_ID1_VAL)
-               return -ENODEV;
+       outb(CHIP_ID1, base_port + ADDR_PORT);
+       chip = inb(base_port + DATA_PORT);
+       outb(CHIP_ID2, base_port + ADDR_PORT);
+       chip |= inb(base_port + DATA_PORT) << 8;
 
-       outb(VENDOR_ID2, ADDR_PORT);
-       if (inb(DATA_PORT) != VENDOR_ID2_VAL)
+       if (chip != CHIP_ID_0 && chip != CHIP_ID_1)
                return -ENODEV;
 
        return 0;
@@ -93,9 +92,9 @@ static int fintek_8250_rs485_config(struct uart_port *port,
                              struct serial_rs485 *rs485)
 {
        uint8_t config = 0;
-       int index = fintek_8250_get_index(port->iobase);
+       struct fintek_8250 *pdata = port->private_data;
 
-       if (index < 0)
+       if (!pdata)
                return -EINVAL;
 
        if (rs485->flags & SER_RS485_ENABLED)
@@ -125,44 +124,84 @@ static int fintek_8250_rs485_config(struct uart_port *port,
        if (rs485->flags & SER_RS485_RTS_ON_SEND)
                config |= RTS_INVERT;
 
-       if (fintek_8250_enter_key())
+       if (fintek_8250_enter_key(pdata->base_port, pdata->key))
                return -EBUSY;
 
-       outb(LDN, ADDR_PORT);
-       outb(index, DATA_PORT);
-       outb(RS485, ADDR_PORT);
-       outb(config, DATA_PORT);
-       fintek_8250_exit_key();
+       outb(LDN, pdata->base_port + ADDR_PORT);
+       outb(pdata->index, pdata->base_port + DATA_PORT);
+       outb(RS485, pdata->base_port + ADDR_PORT);
+       outb(config, pdata->base_port + DATA_PORT);
+       fintek_8250_exit_key(pdata->base_port);
 
        port->rs485 = *rs485;
 
        return 0;
 }
 
+static int fintek_8250_base_port(u16 io_address, u8 *key, u8 *index)
+{
+       static const u16 addr[] = {0x4e, 0x2e};
+       static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
+       int i, j, k;
+
+       for (i = 0; i < ARRAY_SIZE(addr); i++) {
+               for (j = 0; j < ARRAY_SIZE(keys); j++) {
+
+                       if (fintek_8250_enter_key(addr[i], keys[j]))
+                               continue;
+                       if (fintek_8250_check_id(addr[i])) {
+                               fintek_8250_exit_key(addr[i]);
+                               continue;
+                       }
+
+                       for (k = 0; k < 4; k++) {
+                               u16 aux;
+
+                               outb(LDN, addr[i] + ADDR_PORT);
+                               outb(k, addr[i] + DATA_PORT);
+
+                               outb(IO_ADDR1, addr[i] + ADDR_PORT);
+                               aux = inb(addr[i] + DATA_PORT);
+                               outb(IO_ADDR2, addr[i] + ADDR_PORT);
+                               aux |= inb(addr[i] + DATA_PORT) << 8;
+                               if (aux != io_address)
+                                       continue;
+
+                               fintek_8250_exit_key(addr[i]);
+                               *key = keys[j];
+                               *index = k;
+                               return addr[i];
+                       }
+                       fintek_8250_exit_key(addr[i]);
+               }
+       }
+
+       return -ENODEV;
+}
+
 static int
 fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
-       int line;
        struct uart_8250_port uart;
-       int ret;
+       struct fintek_8250 *pdata;
+       int base_port;
+       u8 key;
+       u8 index;
 
        if (!pnp_port_valid(dev, 0))
                return -ENODEV;
 
-       if (fintek_8250_get_index(pnp_port_start(dev, 0)) < 0)
+       base_port = fintek_8250_base_port(pnp_port_start(dev, 0), &key, &index);
+       if (base_port < 0)
                return -ENODEV;
 
-       /* Enable configuration registers*/
-       if (fintek_8250_enter_key())
-               return -EBUSY;
+       memset(&uart, 0, sizeof(uart));
 
-       /*Check ID*/
-       ret = fintek_8250_check_id();
-       fintek_8250_exit_key();
-       if (ret)
-               return ret;
+       pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+       uart.port.private_data = pdata;
 
-       memset(&uart, 0, sizeof(uart));
        if (!pnp_irq_valid(dev, 0))
                return -ENODEV;
        uart.port.irq = pnp_irq(dev, 0);
@@ -176,40 +215,43 @@ fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
        uart.port.uartclk = 1843200;
        uart.port.dev = &dev->dev;
 
-       line = serial8250_register_8250_port(&uart);
-       if (line < 0)
+       pdata->key = key;
+       pdata->base_port = base_port;
+       pdata->index = index;
+       pdata->line = serial8250_register_8250_port(&uart);
+       if (pdata->line < 0)
                return -ENODEV;
 
-       pnp_set_drvdata(dev, (void *)((long)line + 1));
+       pnp_set_drvdata(dev, pdata);
        return 0;
 }
 
 static void fintek_8250_remove(struct pnp_dev *dev)
 {
-       long line = (long)pnp_get_drvdata(dev);
+       struct fintek_8250 *pdata = pnp_get_drvdata(dev);
 
-       if (line)
-               serial8250_unregister_port(line - 1);
+       if (pdata)
+               serial8250_unregister_port(pdata->line);
 }
 
 #ifdef CONFIG_PM
 static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state)
 {
-       long line = (long)pnp_get_drvdata(dev);
+       struct fintek_8250 *pdata = pnp_get_drvdata(dev);
 
-       if (!line)
+       if (!pdata)
                return -ENODEV;
-       serial8250_suspend_port(line - 1);
+       serial8250_suspend_port(pdata->line);
        return 0;
 }
 
 static int fintek_8250_resume(struct pnp_dev *dev)
 {
-       long line = (long)pnp_get_drvdata(dev);
+       struct fintek_8250 *pdata = pnp_get_drvdata(dev);
 
-       if (!line)
+       if (!pdata)
                return -ENODEV;
-       serial8250_resume_port(line - 1);
+       serial8250_resume_port(pdata->line);
        return 0;
 }
 #else
index 21bf81fe794fae82026c52552d11442b3d7153e2..7c1e4be48e7b3b96b975b29ba4d2053083bd9700 100644 (file)
@@ -252,7 +252,6 @@ MODULE_DEVICE_TABLE(of, of_match);
 static struct platform_driver ingenic_uart_platform_driver = {
        .driver = {
                .name           = "ingenic-uart",
-               .owner          = THIS_MODULE,
                .of_match_table = of_match,
        },
        .probe                  = ingenic_uart_probe,
index d75a66c7275098184b53344d0729c9dd2ac50a85..826c5c4a2103be3ac9c5065eeb8274fd8ce8c75f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/delay.h>
 #define UART_ERRATA_i202_MDR1_ACCESS   (1 << 0)
 #define OMAP_UART_WER_HAS_TX_WAKEUP    (1 << 1)
 #define OMAP_DMA_TX_KICK               (1 << 2)
+/*
+ * See Advisory 21 in AM437x errata SPRZ408B, updated April 2015.
+ * The same errata is applicable to AM335x and DRA7x processors too.
+ */
+#define UART_ERRATA_CLOCK_DISABLE      (1 << 3)
 
 #define OMAP_UART_FCR_RX_TRIG          6
 #define OMAP_UART_FCR_TX_TRIG          4
 #define OMAP_UART_MVR_MAJ_SHIFT                8
 #define OMAP_UART_MVR_MIN_MASK         0x3f
 
+/* SYSC register bitmasks */
+#define OMAP_UART_SYSC_SOFTRESET       (1 << 1)
+
+/* SYSS register bitmasks */
+#define OMAP_UART_SYSS_RESETDONE       (1 << 0)
+
 #define UART_TI752_TLR_TX      0
 #define UART_TI752_TLR_RX      4
 
@@ -100,6 +112,7 @@ struct omap8250_priv {
        struct work_struct qos_work;
        struct uart_8250_dma omap8250_dma;
        spinlock_t rx_dma_lock;
+       bool rx_dma_broken;
 };
 
 static u32 uart_read(struct uart_8250_port *up, u32 reg)
@@ -232,6 +245,15 @@ static void omap8250_update_scr(struct uart_8250_port *up,
        serial_out(up, UART_OMAP_SCR, priv->scr);
 }
 
+static void omap8250_update_mdr1(struct uart_8250_port *up,
+                                struct omap8250_priv *priv)
+{
+       if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+               omap_8250_mdr1_errataset(up, priv);
+       else
+               serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+}
+
 static void omap8250_restore_regs(struct uart_8250_port *up)
 {
        struct omap8250_priv *priv = up->port.private_data;
@@ -282,11 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
        serial_out(up, UART_XOFF1, priv->xoff);
 
        serial_out(up, UART_LCR, up->lcr);
-       /* need mode A for FCR */
-       if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
-               omap_8250_mdr1_errataset(up, priv);
-       else
-               serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+
+       omap8250_update_mdr1(up, priv);
+
        up->port.ops->set_mctrl(&up->port, up->port.mctrl);
 }
 
@@ -428,12 +448,9 @@ static void omap_8250_set_termios(struct uart_port *port,
                priv->efr |= UART_EFR_CTS;
        } else  if (up->port.flags & UPF_SOFT_FLOW) {
                /*
-                * IXON Flag:
-                * Enable XON/XOFF flow control on input.
-                * Receiver compares XON1, XOFF1.
+                * OMAP rx s/w flow control is borked; the transmitter remains
+                * stuck off even if rx flow control is subsequently disabled
                 */
-               if (termios->c_iflag & IXON)
-                       priv->efr |= OMAP_UART_SW_RX;
 
                /*
                 * IXOFF Flag:
@@ -444,15 +461,6 @@ static void omap_8250_set_termios(struct uart_port *port,
                        up->port.status |= UPSTAT_AUTOXOFF;
                        priv->efr |= OMAP_UART_SW_TX;
                }
-
-               /*
-                * IXANY Flag:
-                * Enable any character to restart output.
-                * Operation resumes after receiving any
-                * character after recognition of the XOFF character
-                */
-               if (termios->c_iflag & IXANY)
-                       up->mcr |= UART_MCR_XONANY;
        }
        omap8250_restore_regs(up);
 
@@ -530,14 +538,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
 
        switch (revision) {
        case OMAP_UART_REV_46:
-               priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
+               priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
                break;
        case OMAP_UART_REV_52:
-               priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+               priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
                                OMAP_UART_WER_HAS_TX_WAKEUP;
                break;
        case OMAP_UART_REV_63:
-               priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+               priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
                        OMAP_UART_WER_HAS_TX_WAKEUP;
                break;
        default:
@@ -754,6 +762,7 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
        struct omap8250_priv    *priv = p->port.private_data;
        struct uart_8250_dma    *dma = p->dma;
        unsigned long           flags;
+       int ret;
 
        spin_lock_irqsave(&priv->rx_dma_lock, flags);
 
@@ -762,7 +771,9 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
                return;
        }
 
-       dmaengine_pause(dma->rxchan);
+       ret = dmaengine_pause(dma->rxchan);
+       if (WARN_ON_ONCE(ret))
+               priv->rx_dma_broken = true;
 
        spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
 
@@ -806,6 +817,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
                break;
        }
 
+       if (priv->rx_dma_broken)
+               return -EINVAL;
+
        spin_lock_irqsave(&priv->rx_dma_lock, flags);
 
        if (dma->rx_running)
@@ -1054,6 +1068,20 @@ static int omap8250_no_handle_irq(struct uart_port *port)
        return 0;
 }
 
+static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
+static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
+
+static const struct of_device_id omap8250_dt_ids[] = {
+       { .compatible = "ti,omap2-uart" },
+       { .compatible = "ti,omap3-uart" },
+       { .compatible = "ti,omap4-uart" },
+       { .compatible = "ti,am3352-uart", .data = &am3352_habit, },
+       { .compatible = "ti,am4372-uart", .data = &am4372_habit, },
+       { .compatible = "ti,dra742-uart", .data = &am4372_habit, },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
+
 static int omap8250_probe(struct platform_device *pdev)
 {
        struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1118,11 +1146,17 @@ static int omap8250_probe(struct platform_device *pdev)
        up.port.unthrottle = omap_8250_unthrottle;
 
        if (pdev->dev.of_node) {
+               const struct of_device_id *id;
+
                ret = of_alias_get_id(pdev->dev.of_node, "serial");
 
                of_property_read_u32(pdev->dev.of_node, "clock-frequency",
                                     &up.port.uartclk);
                priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
+               id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
+               if (id && id->data)
+                       priv->habit |= *(u8 *)id->data;
        } else {
                ret = pdev->id;
        }
@@ -1180,6 +1214,11 @@ static int omap8250_probe(struct platform_device *pdev)
 
                        if (of_machine_is_compatible("ti,am33xx"))
                                priv->habit |= OMAP_DMA_TX_KICK;
+                       /*
+                        * pause is currently not supported atleast on omap-sdma
+                        * and edma on most earlier kernels.
+                        */
+                       priv->rx_dma_broken = true;
                }
        }
 #endif
@@ -1257,17 +1296,46 @@ static int omap8250_lost_context(struct uart_8250_port *up)
 {
        u32 val;
 
-       val = serial_in(up, UART_OMAP_MDR1);
+       val = serial_in(up, UART_OMAP_SCR);
        /*
-        * If we lose context, then MDR1 is set to its reset value which is
-        * UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
-        * or 16x but never to disable again.
+        * If we lose context, then SCR is set to its reset value of zero.
+        * After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
+        * among other bits, to never set the register back to zero again.
         */
-       if (val == UART_OMAP_MDR1_DISABLE)
+       if (!val)
                return 1;
        return 0;
 }
 
+/* TODO: in future, this should happen via API in drivers/reset/ */
+static int omap8250_soft_reset(struct device *dev)
+{
+       struct omap8250_priv *priv = dev_get_drvdata(dev);
+       struct uart_8250_port *up = serial8250_get_port(priv->line);
+       int timeout = 100;
+       int sysc;
+       int syss;
+
+       sysc = serial_in(up, UART_OMAP_SYSC);
+
+       /* softreset the UART */
+       sysc |= OMAP_UART_SYSC_SOFTRESET;
+       serial_out(up, UART_OMAP_SYSC, sysc);
+
+       /* By experiments, 1us enough for reset complete on AM335x */
+       do {
+               udelay(1);
+               syss = serial_in(up, UART_OMAP_SYSS);
+       } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
+
+       if (!timeout) {
+               dev_err(dev, "timed out waiting for reset done\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 static int omap8250_runtime_suspend(struct device *dev)
 {
        struct omap8250_priv *priv = dev_get_drvdata(dev);
@@ -1285,7 +1353,18 @@ static int omap8250_runtime_suspend(struct device *dev)
                        return -EBUSY;
        }
 
-       if (up->dma)
+       if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
+               int ret;
+
+               ret = omap8250_soft_reset(dev);
+               if (ret)
+                       return ret;
+
+               /* Restore to UART mode after reset (for wakeup) */
+               omap8250_update_mdr1(up, priv);
+       }
+
+       if (up->dma && up->dma->rxchan)
                omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
 
        priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
@@ -1310,7 +1389,7 @@ static int omap8250_runtime_resume(struct device *dev)
        if (loss_cntx)
                omap8250_restore_regs(up);
 
-       if (up->dma)
+       if (up->dma && up->dma->rxchan)
                omap_8250_rx_dma(up, 0);
 
        priv->latency = priv->calc_latency;
@@ -1367,14 +1446,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = {
        .complete       = omap8250_complete,
 };
 
-static const struct of_device_id omap8250_dt_ids[] = {
-       { .compatible = "ti,omap2-uart" },
-       { .compatible = "ti,omap3-uart" },
-       { .compatible = "ti,omap4-uart" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
-
 static struct platform_driver omap8250_platform_driver = {
        .driver = {
                .name           = "omap8250",
index e55f18b93fe7e7334dce31ebab7e43aac1ad493e..68042dd1c525ee01519ca51701192ba840b6e55b 100644 (file)
@@ -1417,6 +1417,10 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
        reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
        writel(reg, p->membase + BYT_PRV_CLK);
 
+       p->status &= ~UPSTAT_AUTOCTS;
+       if (termios->c_cflag & CRTSCTS)
+               p->status |= UPSTAT_AUTOCTS;
+
        serial8250_do_set_termios(p, termios, old);
 }
 
@@ -1685,11 +1689,65 @@ pci_brcm_trumanage_setup(struct serial_private *priv,
        return ret;
 }
 
+/* RTS will control by MCR if this bit is 0 */
+#define FINTEK_RTS_CONTROL_BY_HW       BIT(4)
+/* only worked with FINTEK_RTS_CONTROL_BY_HW on */
+#define FINTEK_RTS_INVERT              BIT(5)
+
+/* We should do proper H/W transceiver setting before change to RS485 mode */
+static int pci_fintek_rs485_config(struct uart_port *port,
+                              struct serial_rs485 *rs485)
+{
+       u8 setting;
+       u8 *index = (u8 *) port->private_data;
+       struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev,
+                                               dev);
+
+       pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting);
+
+       if (!rs485)
+               rs485 = &port->rs485;
+       else if (rs485->flags & SER_RS485_ENABLED)
+               memset(rs485->padding, 0, sizeof(rs485->padding));
+       else
+               memset(rs485, 0, sizeof(*rs485));
+
+       /* F81504/508/512 not support RTS delay before or after send */
+       rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
+
+       if (rs485->flags & SER_RS485_ENABLED) {
+               /* Enable RTS H/W control mode */
+               setting |= FINTEK_RTS_CONTROL_BY_HW;
+
+               if (rs485->flags & SER_RS485_RTS_ON_SEND) {
+                       /* RTS driving high on TX */
+                       setting &= ~FINTEK_RTS_INVERT;
+               } else {
+                       /* RTS driving low on TX */
+                       setting |= FINTEK_RTS_INVERT;
+               }
+
+               rs485->delay_rts_after_send = 0;
+               rs485->delay_rts_before_send = 0;
+       } else {
+               /* Disable RTS H/W control mode */
+               setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT);
+       }
+
+       pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting);
+
+       if (rs485 != &port->rs485)
+               port->rs485 = *rs485;
+
+       return 0;
+}
+
 static int pci_fintek_setup(struct serial_private *priv,
                            const struct pciserial_board *board,
                            struct uart_8250_port *port, int idx)
 {
        struct pci_dev *pdev = priv->dev;
+       u8 *data;
        u8 config_base;
        u16 iobase;
 
@@ -1702,6 +1760,15 @@ static int pci_fintek_setup(struct serial_private *priv,
 
        port->port.iotype = UPIO_PORT;
        port->port.iobase = iobase;
+       port->port.rs485_config = pci_fintek_rs485_config;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       /* preserve index in PCI configuration space */
+       *data = idx;
+       port->port.private_data = data;
 
        return 0;
 }
@@ -1712,6 +1779,8 @@ static int pci_fintek_init(struct pci_dev *dev)
        u32 max_port, i;
        u32 bar_data[3];
        u8 config_base;
+       struct serial_private *priv = pci_get_drvdata(dev);
+       struct uart_8250_port *port;
 
        switch (dev->device) {
        case 0x1104: /* 4 ports */
@@ -1752,6 +1821,19 @@ static int pci_fintek_init(struct pci_dev *dev)
                                (u8)((iobase & 0xff00) >> 8));
 
                pci_write_config_byte(dev, config_base + 0x06, dev->irq);
+
+               if (priv) {
+                       /* re-apply RS232/485 mode when
+                        * pciserial_resume_ports()
+                        */
+                       port = serial8250_get_port(priv->line[i]);
+                       pci_fintek_rs485_config(&port->port, NULL);
+               } else {
+                       /* First init without port data
+                        * force init to RS232 Mode
+                        */
+                       pci_write_config_byte(dev, config_base + 0x07, 0x01);
+               }
        }
 
        return max_port;
@@ -2017,6 +2099,12 @@ pci_wch_ch38x_setup(struct serial_private *priv,
 #define PCIE_DEVICE_ID_WCH_CH382_2S1P  0x3250
 #define PCIE_DEVICE_ID_WCH_CH384_4S    0x3470
 
+#define PCI_VENDOR_ID_PERICOM                  0x12D8
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7951       0x7951
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7952       0x7952
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7954       0x7954
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7958       0x7958
+
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588        0x1588
@@ -2331,27 +2419,12 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
         * Pericom
         */
        {
-               .vendor         = 0x12d8,
-               .device         = 0x7952,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_pericom_setup,
-       },
-       {
-               .vendor         = 0x12d8,
-               .device         = 0x7954,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_pericom_setup,
-       },
-       {
-               .vendor         = 0x12d8,
-               .device         = 0x7958,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_pericom_setup,
+               .vendor         = PCI_VENDOR_ID_PERICOM,
+               .device         = PCI_ANY_ID,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_pericom_setup,
        },
-
        /*
         * PLX
         */
@@ -3056,6 +3129,10 @@ enum pci_board_num_t {
        pbn_fintek_8,
        pbn_fintek_12,
        pbn_wch384_4,
+       pbn_pericom_PI7C9X7951,
+       pbn_pericom_PI7C9X7952,
+       pbn_pericom_PI7C9X7954,
+       pbn_pericom_PI7C9X7958,
 };
 
 /*
@@ -3881,7 +3958,6 @@ static struct pciserial_board pci_boards[] = {
                .base_baud      = 115200,
                .first_offset   = 0x40,
        },
-
        [pbn_wch384_4] = {
                .flags          = FL_BASE0,
                .num_ports      = 4,
@@ -3889,6 +3965,33 @@ static struct pciserial_board pci_boards[] = {
                .uart_offset    = 8,
                .first_offset   = 0xC0,
        },
+       /*
+        * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
+        */
+       [pbn_pericom_PI7C9X7951] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 921600,
+               .uart_offset    = 0x8,
+       },
+       [pbn_pericom_PI7C9X7952] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 2,
+               .base_baud      = 921600,
+               .uart_offset    = 0x8,
+       },
+       [pbn_pericom_PI7C9X7954] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 4,
+               .base_baud      = 921600,
+               .uart_offset    = 0x8,
+       },
+       [pbn_pericom_PI7C9X7958] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 8,
+               .base_baud      = 921600,
+               .uart_offset    = 0x8,
+       },
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -5153,6 +5256,25 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID,
                0,
                0, pbn_exar_XR17V8358 },
+       /*
+        * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
+        */
+       {   PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_pericom_PI7C9X7951 },
+       {   PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_pericom_PI7C9X7952 },
+       {   PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_pericom_PI7C9X7954 },
+       {   PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_pericom_PI7C9X7958 },
        /*
         * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
         */
index 50a09cd76d50a1d0b4709f5e487361ab76ac0ded..658b392d1170d63dbb61e5c91348f8f2bcd2549f 100644 (file)
@@ -41,6 +41,12 @@ static const struct pnp_device_id pnp_dev_table[] = {
        {       "AEI1240",              0       },
        /* Rockwell 56K ACF II Fax+Data+Voice Modem */
        {       "AKY1021",              0 /*SPCI_FL_NO_SHIRQ*/  },
+       /*
+        * ALi Fast Infrared Controller
+        * Native driver (ali-ircc) is broken so at least
+        * it can be used with irtty-sir.
+        */
+       {       "ALI5123",              0       },
        /* AZT3005 PnP SOUND DEVICE */
        {       "AZT4001",              0       },
        /* Best Data Products Inc. Smart One 336F PnP Modem */
@@ -364,6 +370,11 @@ static const struct pnp_device_id pnp_dev_table[] = {
        /* Winbond CIR port, should not be probed. We should keep track
           of it to prevent the legacy serial driver from probing it */
        {       "WEC1022",              CIR_PORT        },
+       /*
+        * SMSC IrCC SIR/FIR port, should not be probed by serial driver
+        * as well so its own driver can bind to it.
+        */
+       {       "SMCF010",              CIR_PORT        },
        {       "",                     0       }
 };
 
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
new file mode 100644 (file)
index 0000000..54e6c8d
--- /dev/null
@@ -0,0 +1,2912 @@
+/*
+ *  Base port operations for 8250/16550-type serial ports
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *  Split from 8250_core.c, Copyright (C) 2001 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A note about mapbase / membase
+ *
+ *  mapbase is the physical address of the IO port.
+ *  membase is an 'ioremapped' cookie.
+ */
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/ratelimit.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/nmi.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "8250.h"
+
+/*
+ * Debugging.
+ */
+#if 0
+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
+#endif
+
+#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ * Here we define the default xmit fifo size used for each type of UART.
+ */
+static const struct serial8250_config uart_config[] = {
+       [PORT_UNKNOWN] = {
+               .name           = "unknown",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_8250] = {
+               .name           = "8250",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16450] = {
+               .name           = "16450",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16550] = {
+               .name           = "16550",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16550A] = {
+               .name           = "16550A",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .rxtrig_bytes   = {1, 4, 8, 14},
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_CIRRUS] = {
+               .name           = "Cirrus",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16650] = {
+               .name           = "ST16650",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_16650V2] = {
+               .name           = "ST16650V2",
+               .fifo_size      = 32,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_00,
+               .rxtrig_bytes   = {8, 16, 24, 28},
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_16750] = {
+               .name           = "TI16750",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+                                 UART_FCR7_64BYTE,
+               .rxtrig_bytes   = {1, 16, 32, 56},
+               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
+       },
+       [PORT_STARTECH] = {
+               .name           = "Startech",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1,
+       },
+       [PORT_16C950] = {
+               .name           = "16C950/954",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               /* UART_CAP_EFR breaks billionon CF bluetooth card. */
+               .flags          = UART_CAP_FIFO | UART_CAP_SLEEP,
+       },
+       [PORT_16654] = {
+               .name           = "ST16654",
+               .fifo_size      = 64,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_10,
+               .rxtrig_bytes   = {8, 16, 56, 60},
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_16850] = {
+               .name           = "XR16850",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+       },
+       [PORT_RSA] = {
+               .name           = "RSA",
+               .fifo_size      = 2048,
+               .tx_loadsz      = 2048,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_NS16550A] = {
+               .name           = "NS16550A",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_NATSEMI,
+       },
+       [PORT_XSCALE] = {
+               .name           = "XScale",
+               .fifo_size      = 32,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
+       },
+       [PORT_OCTEON] = {
+               .name           = "OCTEON",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_AR7] = {
+               .name           = "AR7",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_U6_16550A] = {
+               .name           = "U6_16550A",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_TEGRA] = {
+               .name           = "Tegra",
+               .fifo_size      = 32,
+               .tx_loadsz      = 8,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+                                 UART_FCR_T_TRIG_01,
+               .rxtrig_bytes   = {1, 4, 8, 14},
+               .flags          = UART_CAP_FIFO | UART_CAP_RTOIE,
+       },
+       [PORT_XR17D15X] = {
+               .name           = "XR17D15X",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+                                 UART_CAP_SLEEP,
+       },
+       [PORT_XR17V35X] = {
+               .name           = "XR17V35X",
+               .fifo_size      = 256,
+               .tx_loadsz      = 256,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
+                                 UART_FCR_T_TRIG_11,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+                                 UART_CAP_SLEEP,
+       },
+       [PORT_LPC3220] = {
+               .name           = "LPC3220",
+               .fifo_size      = 64,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
+                                 UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
+               .flags          = UART_CAP_FIFO,
+       },
+       [PORT_BRCM_TRUMANAGE] = {
+               .name           = "TruManage",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1024,
+               .flags          = UART_CAP_HFIFO,
+       },
+       [PORT_8250_CIR] = {
+               .name           = "CIR port"
+       },
+       [PORT_ALTR_16550_F32] = {
+               .name           = "Altera 16550 FIFO32",
+               .fifo_size      = 32,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_ALTR_16550_F64] = {
+               .name           = "Altera 16550 FIFO64",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_ALTR_16550_F128] = {
+               .name           = "Altera 16550 FIFO128",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
+workaround of errata A-008006 which states that tx_loadsz should  be
+configured less than Maximum supported fifo bytes */
+       [PORT_16550A_FSL64] = {
+               .name           = "16550A_FSL64",
+               .fifo_size      = 64,
+               .tx_loadsz      = 63,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+                                 UART_FCR7_64BYTE,
+               .flags          = UART_CAP_FIFO,
+       },
+};
+
+/* Uart divisor latch read */
+static int default_serial_dl_read(struct uart_8250_port *up)
+{
+       return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static void default_serial_dl_write(struct uart_8250_port *up, int value)
+{
+       serial_out(up, UART_DLL, value & 0xff);
+       serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+
+/* Au1x00/RT288x UART hardware has a weird register layout */
+static const s8 au_io_in_map[8] = {
+        0,     /* UART_RX  */
+        2,     /* UART_IER */
+        3,     /* UART_IIR */
+        5,     /* UART_LCR */
+        6,     /* UART_MCR */
+        7,     /* UART_LSR */
+        8,     /* UART_MSR */
+       -1,     /* UART_SCR (unmapped) */
+};
+
+static const s8 au_io_out_map[8] = {
+        1,     /* UART_TX  */
+        2,     /* UART_IER */
+        4,     /* UART_FCR */
+        5,     /* UART_LCR */
+        6,     /* UART_MCR */
+       -1,     /* UART_LSR (unmapped) */
+       -1,     /* UART_MSR (unmapped) */
+       -1,     /* UART_SCR (unmapped) */
+};
+
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+       if (offset >= ARRAY_SIZE(au_io_in_map))
+               return UINT_MAX;
+       offset = au_io_in_map[offset];
+       if (offset < 0)
+               return UINT_MAX;
+       return __raw_readl(p->membase + (offset << p->regshift));
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+       if (offset >= ARRAY_SIZE(au_io_out_map))
+               return;
+       offset = au_io_out_map[offset];
+       if (offset < 0)
+               return;
+       __raw_writel(value, p->membase + (offset << p->regshift));
+}
+
+/* Au1x00 haven't got a standard divisor latch */
+static int au_serial_dl_read(struct uart_8250_port *up)
+{
+       return __raw_readl(up->port.membase + 0x28);
+}
+
+static void au_serial_dl_write(struct uart_8250_port *up, int value)
+{
+       __raw_writel(value, up->port.membase + 0x28);
+}
+
+#endif
+
+static unsigned int hub6_serial_in(struct uart_port *p, int offset)
+{
+       offset = offset << p->regshift;
+       outb(p->hub6 - 1 + offset, p->iobase);
+       return inb(p->iobase + 1);
+}
+
+static void hub6_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       outb(p->hub6 - 1 + offset, p->iobase);
+       outb(value, p->iobase + 1);
+}
+
+static unsigned int mem_serial_in(struct uart_port *p, int offset)
+{
+       offset = offset << p->regshift;
+       return readb(p->membase + offset);
+}
+
+static void mem_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+{
+       offset = offset << p->regshift;
+       return readl(p->membase + offset);
+}
+
+static void mem32be_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       iowrite32be(value, p->membase + offset);
+}
+
+static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
+{
+       offset = offset << p->regshift;
+       return ioread32be(p->membase + offset);
+}
+
+static unsigned int io_serial_in(struct uart_port *p, int offset)
+{
+       offset = offset << p->regshift;
+       return inb(p->iobase + offset);
+}
+
+static void io_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       outb(value, p->iobase + offset);
+}
+
+static int serial8250_default_handle_irq(struct uart_port *port);
+static int exar_handle_irq(struct uart_port *port);
+
+static void set_io_from_upio(struct uart_port *p)
+{
+       struct uart_8250_port *up = up_to_u8250p(p);
+
+       up->dl_read = default_serial_dl_read;
+       up->dl_write = default_serial_dl_write;
+
+       switch (p->iotype) {
+       case UPIO_HUB6:
+               p->serial_in = hub6_serial_in;
+               p->serial_out = hub6_serial_out;
+               break;
+
+       case UPIO_MEM:
+               p->serial_in = mem_serial_in;
+               p->serial_out = mem_serial_out;
+               break;
+
+       case UPIO_MEM32:
+               p->serial_in = mem32_serial_in;
+               p->serial_out = mem32_serial_out;
+               break;
+
+       case UPIO_MEM32BE:
+               p->serial_in = mem32be_serial_in;
+               p->serial_out = mem32be_serial_out;
+               break;
+
+#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+       case UPIO_AU:
+               p->serial_in = au_serial_in;
+               p->serial_out = au_serial_out;
+               up->dl_read = au_serial_dl_read;
+               up->dl_write = au_serial_dl_write;
+               break;
+#endif
+
+       default:
+               p->serial_in = io_serial_in;
+               p->serial_out = io_serial_out;
+               break;
+       }
+       /* Remember loaded iotype */
+       up->cur_iotype = p->iotype;
+       p->handle_irq = serial8250_default_handle_irq;
+}
+
+static void
+serial_port_out_sync(struct uart_port *p, int offset, int value)
+{
+       switch (p->iotype) {
+       case UPIO_MEM:
+       case UPIO_MEM32:
+       case UPIO_MEM32BE:
+       case UPIO_AU:
+               p->serial_out(p, offset, value);
+               p->serial_in(p, UART_LCR);      /* safe, no side-effects */
+               break;
+       default:
+               p->serial_out(p, offset, value);
+       }
+}
+
+/*
+ * For the 16C950
+ */
+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
+{
+       serial_out(up, UART_SCR, offset);
+       serial_out(up, UART_ICR, value);
+}
+
+static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+{
+       unsigned int value;
+
+       serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
+       serial_out(up, UART_SCR, offset);
+       value = serial_in(up, UART_ICR);
+       serial_icr_write(up, UART_ACR, up->acr);
+
+       return value;
+}
+
+/*
+ * FIFO support.
+ */
+static void serial8250_clear_fifos(struct uart_8250_port *p)
+{
+       if (p->capabilities & UART_CAP_FIFO) {
+               serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+               serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+                              UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+               serial_out(p, UART_FCR, 0);
+       }
+}
+
+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
+{
+       serial8250_clear_fifos(p);
+       serial_out(p, UART_FCR, p->fcr);
+}
+EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+
+void serial8250_rpm_get(struct uart_8250_port *p)
+{
+       if (!(p->capabilities & UART_CAP_RPM))
+               return;
+       pm_runtime_get_sync(p->port.dev);
+}
+EXPORT_SYMBOL_GPL(serial8250_rpm_get);
+
+void serial8250_rpm_put(struct uart_8250_port *p)
+{
+       if (!(p->capabilities & UART_CAP_RPM))
+               return;
+       pm_runtime_mark_last_busy(p->port.dev);
+       pm_runtime_put_autosuspend(p->port.dev);
+}
+EXPORT_SYMBOL_GPL(serial8250_rpm_put);
+
+/*
+ * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
+ * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
+ * empty and the HW can idle again.
+ */
+static void serial8250_rpm_get_tx(struct uart_8250_port *p)
+{
+       unsigned char rpm_active;
+
+       if (!(p->capabilities & UART_CAP_RPM))
+               return;
+
+       rpm_active = xchg(&p->rpm_tx_active, 1);
+       if (rpm_active)
+               return;
+       pm_runtime_get_sync(p->port.dev);
+}
+
+static void serial8250_rpm_put_tx(struct uart_8250_port *p)
+{
+       unsigned char rpm_active;
+
+       if (!(p->capabilities & UART_CAP_RPM))
+               return;
+
+       rpm_active = xchg(&p->rpm_tx_active, 0);
+       if (!rpm_active)
+               return;
+       pm_runtime_mark_last_busy(p->port.dev);
+       pm_runtime_put_autosuspend(p->port.dev);
+}
+
+/*
+ * IER sleep support.  UARTs which have EFRs need the "extended
+ * capability" bit enabled.  Note that on XR16C850s, we need to
+ * reset LCR to write to IER.
+ */
+static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+{
+       unsigned char lcr = 0, efr = 0;
+       /*
+        * Exar UARTs have a SLEEP register that enables or disables
+        * each UART to enter sleep mode separately.  On the XR17V35x the
+        * register is accessible to each UART at the UART_EXAR_SLEEP
+        * offset but the UART channel may only write to the corresponding
+        * bit.
+        */
+       serial8250_rpm_get(p);
+       if ((p->port.type == PORT_XR17V35X) ||
+          (p->port.type == PORT_XR17D15X)) {
+               serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
+               goto out;
+       }
+
+       if (p->capabilities & UART_CAP_SLEEP) {
+               if (p->capabilities & UART_CAP_EFR) {
+                       lcr = serial_in(p, UART_LCR);
+                       efr = serial_in(p, UART_EFR);
+                       serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
+                       serial_out(p, UART_EFR, UART_EFR_ECB);
+                       serial_out(p, UART_LCR, 0);
+               }
+               serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+               if (p->capabilities & UART_CAP_EFR) {
+                       serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
+                       serial_out(p, UART_EFR, efr);
+                       serial_out(p, UART_LCR, lcr);
+               }
+       }
+out:
+       serial8250_rpm_put(p);
+}
+
+#ifdef CONFIG_SERIAL_8250_RSA
+/*
+ * Attempts to turn on the RSA FIFO.  Returns zero on failure.
+ * We set the port uart clock rate if we succeed.
+ */
+static int __enable_rsa(struct uart_8250_port *up)
+{
+       unsigned char mode;
+       int result;
+
+       mode = serial_in(up, UART_RSA_MSR);
+       result = mode & UART_RSA_MSR_FIFO;
+
+       if (!result) {
+               serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
+               mode = serial_in(up, UART_RSA_MSR);
+               result = mode & UART_RSA_MSR_FIFO;
+       }
+
+       if (result)
+               up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
+
+       return result;
+}
+
+static void enable_rsa(struct uart_8250_port *up)
+{
+       if (up->port.type == PORT_RSA) {
+               if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
+                       spin_lock_irq(&up->port.lock);
+                       __enable_rsa(up);
+                       spin_unlock_irq(&up->port.lock);
+               }
+               if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+                       serial_out(up, UART_RSA_FRR, 0);
+       }
+}
+
+/*
+ * Attempts to turn off the RSA FIFO.  Returns zero on failure.
+ * It is unknown why interrupts were disabled in here.  However,
+ * the caller is expected to preserve this behaviour by grabbing
+ * the spinlock before calling this function.
+ */
+static void disable_rsa(struct uart_8250_port *up)
+{
+       unsigned char mode;
+       int result;
+
+       if (up->port.type == PORT_RSA &&
+           up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+               spin_lock_irq(&up->port.lock);
+
+               mode = serial_in(up, UART_RSA_MSR);
+               result = !(mode & UART_RSA_MSR_FIFO);
+
+               if (!result) {
+                       serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
+                       mode = serial_in(up, UART_RSA_MSR);
+                       result = !(mode & UART_RSA_MSR_FIFO);
+               }
+
+               if (result)
+                       up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
+               spin_unlock_irq(&up->port.lock);
+       }
+}
+#endif /* CONFIG_SERIAL_8250_RSA */
+
+/*
+ * This is a quickie test to see how big the FIFO is.
+ * It doesn't work at all the time, more's the pity.
+ */
+static int size_fifo(struct uart_8250_port *up)
+{
+       unsigned char old_fcr, old_mcr, old_lcr;
+       unsigned short old_dl;
+       int count;
+
+       old_lcr = serial_in(up, UART_LCR);
+       serial_out(up, UART_LCR, 0);
+       old_fcr = serial_in(up, UART_FCR);
+       old_mcr = serial_in(up, UART_MCR);
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+                   UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+       serial_out(up, UART_MCR, UART_MCR_LOOP);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       old_dl = serial_dl_read(up);
+       serial_dl_write(up, 0x0001);
+       serial_out(up, UART_LCR, 0x03);
+       for (count = 0; count < 256; count++)
+               serial_out(up, UART_TX, count);
+       mdelay(20);/* FIXME - schedule_timeout */
+       for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
+            (count < 256); count++)
+               serial_in(up, UART_RX);
+       serial_out(up, UART_FCR, old_fcr);
+       serial_out(up, UART_MCR, old_mcr);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       serial_dl_write(up, old_dl);
+       serial_out(up, UART_LCR, old_lcr);
+
+       return count;
+}
+
+/*
+ * Read UART ID using the divisor method - set DLL and DLM to zero
+ * and the revision will be in DLL and device type in DLM.  We
+ * preserve the device state across this.
+ */
+static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+{
+       unsigned char old_dll, old_dlm, old_lcr;
+       unsigned int id;
+
+       old_lcr = serial_in(p, UART_LCR);
+       serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
+
+       old_dll = serial_in(p, UART_DLL);
+       old_dlm = serial_in(p, UART_DLM);
+
+       serial_out(p, UART_DLL, 0);
+       serial_out(p, UART_DLM, 0);
+
+       id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
+
+       serial_out(p, UART_DLL, old_dll);
+       serial_out(p, UART_DLM, old_dlm);
+       serial_out(p, UART_LCR, old_lcr);
+
+       return id;
+}
+
+/*
+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+ * When this function is called we know it is at least a StarTech
+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
+ * its clones.  (We treat the broken original StarTech 16650 V1 as a
+ * 16550, and why not?  Startech doesn't seem to even acknowledge its
+ * existence.)
+ *
+ * What evil have men's minds wrought...
+ */
+static void autoconfig_has_efr(struct uart_8250_port *up)
+{
+       unsigned int id1, id2, id3, rev;
+
+       /*
+        * Everything with an EFR has SLEEP
+        */
+       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+
+       /*
+        * First we check to see if it's an Oxford Semiconductor UART.
+        *
+        * If we have to do this here because some non-National
+        * Semiconductor clone chips lock up if you try writing to the
+        * LSR register (which serial_icr_read does)
+        */
+
+       /*
+        * Check for Oxford Semiconductor 16C950.
+        *
+        * EFR [4] must be set else this test fails.
+        *
+        * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
+        * claims that it's needed for 952 dual UART's (which are not
+        * recommended for new designs).
+        */
+       up->acr = 0;
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       serial_out(up, UART_EFR, UART_EFR_ECB);
+       serial_out(up, UART_LCR, 0x00);
+       id1 = serial_icr_read(up, UART_ID1);
+       id2 = serial_icr_read(up, UART_ID2);
+       id3 = serial_icr_read(up, UART_ID3);
+       rev = serial_icr_read(up, UART_REV);
+
+       DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
+
+       if (id1 == 0x16 && id2 == 0xC9 &&
+           (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
+               up->port.type = PORT_16C950;
+
+               /*
+                * Enable work around for the Oxford Semiconductor 952 rev B
+                * chip which causes it to seriously miscalculate baud rates
+                * when DLL is 0.
+                */
+               if (id3 == 0x52 && rev == 0x01)
+                       up->bugs |= UART_BUG_QUOT;
+               return;
+       }
+
+       /*
+        * We check for a XR16C850 by setting DLL and DLM to 0, and then
+        * reading back DLL and DLM.  The chip type depends on the DLM
+        * value read back:
+        *  0x10 - XR16C850 and the DLL contains the chip revision.
+        *  0x12 - XR16C2850.
+        *  0x14 - XR16C854.
+        */
+       id1 = autoconfig_read_divisor_id(up);
+       DEBUG_AUTOCONF("850id=%04x ", id1);
+
+       id2 = id1 >> 8;
+       if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
+               up->port.type = PORT_16850;
+               return;
+       }
+
+       /*
+        * It wasn't an XR16C850.
+        *
+        * We distinguish between the '654 and the '650 by counting
+        * how many bytes are in the FIFO.  I'm using this for now,
+        * since that's the technique that was sent to me in the
+        * serial driver update, but I'm not convinced this works.
+        * I've had problems doing this in the past.  -TYT
+        */
+       if (size_fifo(up) == 64)
+               up->port.type = PORT_16654;
+       else
+               up->port.type = PORT_16650V2;
+}
+
+/*
+ * We detected a chip without a FIFO.  Only two fall into
+ * this category - the original 8250 and the 16450.  The
+ * 16450 has a scratch register (accessible with LCR=0)
+ */
+static void autoconfig_8250(struct uart_8250_port *up)
+{
+       unsigned char scratch, status1, status2;
+
+       up->port.type = PORT_8250;
+
+       scratch = serial_in(up, UART_SCR);
+       serial_out(up, UART_SCR, 0xa5);
+       status1 = serial_in(up, UART_SCR);
+       serial_out(up, UART_SCR, 0x5a);
+       status2 = serial_in(up, UART_SCR);
+       serial_out(up, UART_SCR, scratch);
+
+       if (status1 == 0xa5 && status2 == 0x5a)
+               up->port.type = PORT_16450;
+}
+
+static int broken_efr(struct uart_8250_port *up)
+{
+       /*
+        * Exar ST16C2550 "A2" devices incorrectly detect as
+        * having an EFR, and report an ID of 0x0201.  See
+        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
+        */
+       if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
+               return 1;
+
+       return 0;
+}
+
+/*
+ * We know that the chip has FIFOs.  Does it have an EFR?  The
+ * EFR is located in the same register position as the IIR and
+ * we know the top two bits of the IIR are currently set.  The
+ * EFR should contain zero.  Try to read the EFR.
+ */
+static void autoconfig_16550a(struct uart_8250_port *up)
+{
+       unsigned char status1, status2;
+       unsigned int iersave;
+
+       up->port.type = PORT_16550A;
+       up->capabilities |= UART_CAP_FIFO;
+
+       /*
+        * XR17V35x UARTs have an extra divisor register, DLD
+        * that gets enabled with when DLAB is set which will
+        * cause the device to incorrectly match and assign
+        * port type to PORT_16650.  The EFR for this UART is
+        * found at offset 0x09. Instead check the Deice ID (DVID)
+        * register for a 2, 4 or 8 port UART.
+        */
+       if (up->port.flags & UPF_EXAR_EFR) {
+               status1 = serial_in(up, UART_EXAR_DVID);
+               if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
+                       DEBUG_AUTOCONF("Exar XR17V35x ");
+                       up->port.type = PORT_XR17V35X;
+                       up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+                                               UART_CAP_SLEEP;
+
+                       return;
+               }
+
+       }
+
+       /*
+        * Check for presence of the EFR when DLAB is set.
+        * Only ST16C650V1 UARTs pass this test.
+        */
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       if (serial_in(up, UART_EFR) == 0) {
+               serial_out(up, UART_EFR, 0xA8);
+               if (serial_in(up, UART_EFR) != 0) {
+                       DEBUG_AUTOCONF("EFRv1 ");
+                       up->port.type = PORT_16650;
+                       up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+               } else {
+                       serial_out(up, UART_LCR, 0);
+                       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+                                  UART_FCR7_64BYTE);
+                       status1 = serial_in(up, UART_IIR) >> 5;
+                       serial_out(up, UART_FCR, 0);
+                       serial_out(up, UART_LCR, 0);
+
+                       if (status1 == 7)
+                               up->port.type = PORT_16550A_FSL64;
+                       else
+                               DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+               }
+               serial_out(up, UART_EFR, 0);
+               return;
+       }
+
+       /*
+        * Maybe it requires 0xbf to be written to the LCR.
+        * (other ST16C650V2 UARTs, TI16C752A, etc)
+        */
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
+               DEBUG_AUTOCONF("EFRv2 ");
+               autoconfig_has_efr(up);
+               return;
+       }
+
+       /*
+        * Check for a National Semiconductor SuperIO chip.
+        * Attempt to switch to bank 2, read the value of the LOOP bit
+        * from EXCR1. Switch back to bank 0, change it in MCR. Then
+        * switch back to bank 2, read it from EXCR1 again and check
+        * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
+        */
+       serial_out(up, UART_LCR, 0);
+       status1 = serial_in(up, UART_MCR);
+       serial_out(up, UART_LCR, 0xE0);
+       status2 = serial_in(up, 0x02); /* EXCR1 */
+
+       if (!((status2 ^ status1) & UART_MCR_LOOP)) {
+               serial_out(up, UART_LCR, 0);
+               serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
+               serial_out(up, UART_LCR, 0xE0);
+               status2 = serial_in(up, 0x02); /* EXCR1 */
+               serial_out(up, UART_LCR, 0);
+               serial_out(up, UART_MCR, status1);
+
+               if ((status2 ^ status1) & UART_MCR_LOOP) {
+                       unsigned short quot;
+
+                       serial_out(up, UART_LCR, 0xE0);
+
+                       quot = serial_dl_read(up);
+                       quot <<= 3;
+
+                       if (ns16550a_goto_highspeed(up))
+                               serial_dl_write(up, quot);
+
+                       serial_out(up, UART_LCR, 0);
+
+                       up->port.uartclk = 921600*16;
+                       up->port.type = PORT_NS16550A;
+                       up->capabilities |= UART_NATSEMI;
+                       return;
+               }
+       }
+
+       /*
+        * No EFR.  Try to detect a TI16750, which only sets bit 5 of
+        * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
+        * Try setting it with and without DLAB set.  Cheap clones
+        * set bit 5 without DLAB set.
+        */
+       serial_out(up, UART_LCR, 0);
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+       status1 = serial_in(up, UART_IIR) >> 5;
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+       status2 = serial_in(up, UART_IIR) >> 5;
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       serial_out(up, UART_LCR, 0);
+
+       DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
+
+       if (status1 == 6 && status2 == 7) {
+               up->port.type = PORT_16750;
+               up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
+               return;
+       }
+
+       /*
+        * Try writing and reading the UART_IER_UUE bit (b6).
+        * If it works, this is probably one of the Xscale platform's
+        * internal UARTs.
+        * We're going to explicitly set the UUE bit to 0 before
+        * trying to write and read a 1 just to make sure it's not
+        * already a 1 and maybe locked there before we even start start.
+        */
+       iersave = serial_in(up, UART_IER);
+       serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
+       if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+               /*
+                * OK it's in a known zero state, try writing and reading
+                * without disturbing the current state of the other bits.
+                */
+               serial_out(up, UART_IER, iersave | UART_IER_UUE);
+               if (serial_in(up, UART_IER) & UART_IER_UUE) {
+                       /*
+                        * It's an Xscale.
+                        * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+                        */
+                       DEBUG_AUTOCONF("Xscale ");
+                       up->port.type = PORT_XSCALE;
+                       up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
+                       return;
+               }
+       } else {
+               /*
+                * If we got here we couldn't force the IER_UUE bit to 0.
+                * Log it and continue.
+                */
+               DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+       }
+       serial_out(up, UART_IER, iersave);
+
+       /*
+        * Exar uarts have EFR in a weird location
+        */
+       if (up->port.flags & UPF_EXAR_EFR) {
+               DEBUG_AUTOCONF("Exar XR17D15x ");
+               up->port.type = PORT_XR17D15X;
+               up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+                                   UART_CAP_SLEEP;
+
+               return;
+       }
+
+       /*
+        * We distinguish between 16550A and U6 16550A by counting
+        * how many bytes are in the FIFO.
+        */
+       if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
+               up->port.type = PORT_U6_16550A;
+               up->capabilities |= UART_CAP_AFE;
+       }
+}
+
+/*
+ * This routine is called by rs_init() to initialize a specific serial
+ * port.  It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A.  The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void autoconfig(struct uart_8250_port *up)
+{
+       unsigned char status1, scratch, scratch2, scratch3;
+       unsigned char save_lcr, save_mcr;
+       struct uart_port *port = &up->port;
+       unsigned long flags;
+       unsigned int old_capabilities;
+
+       if (!port->iobase && !port->mapbase && !port->membase)
+               return;
+
+       DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
+                      serial_index(port), port->iobase, port->membase);
+
+       /*
+        * We really do need global IRQs disabled here - we're going to
+        * be frobbing the chips IRQ enable register to see if it exists.
+        */
+       spin_lock_irqsave(&port->lock, flags);
+
+       up->capabilities = 0;
+       up->bugs = 0;
+
+       if (!(port->flags & UPF_BUGGY_UART)) {
+               /*
+                * Do a simple existence test first; if we fail this,
+                * there's no point trying anything else.
+                *
+                * 0x80 is used as a nonsense port to prevent against
+                * false positives due to ISA bus float.  The
+                * assumption is that 0x80 is a non-existent port;
+                * which should be safe since include/asm/io.h also
+                * makes this assumption.
+                *
+                * Note: this is safe as long as MCR bit 4 is clear
+                * and the device is in "PC" mode.
+                */
+               scratch = serial_in(up, UART_IER);
+               serial_out(up, UART_IER, 0);
+#ifdef __i386__
+               outb(0xff, 0x080);
+#endif
+               /*
+                * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+                * 16C754B) allow only to modify them if an EFR bit is set.
+                */
+               scratch2 = serial_in(up, UART_IER) & 0x0f;
+               serial_out(up, UART_IER, 0x0F);
+#ifdef __i386__
+               outb(0, 0x080);
+#endif
+               scratch3 = serial_in(up, UART_IER) & 0x0f;
+               serial_out(up, UART_IER, scratch);
+               if (scratch2 != 0 || scratch3 != 0x0F) {
+                       /*
+                        * We failed; there's nothing here
+                        */
+                       spin_unlock_irqrestore(&port->lock, flags);
+                       DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
+                                      scratch2, scratch3);
+                       goto out;
+               }
+       }
+
+       save_mcr = serial_in(up, UART_MCR);
+       save_lcr = serial_in(up, UART_LCR);
+
+       /*
+        * Check to see if a UART is really there.  Certain broken
+        * internal modems based on the Rockwell chipset fail this
+        * test, because they apparently don't implement the loopback
+        * test mode.  So this test is skipped on the COM 1 through
+        * COM 4 ports.  This *should* be safe, since no board
+        * manufacturer would be stupid enough to design a board
+        * that conflicts with COM 1-4 --- we hope!
+        */
+       if (!(port->flags & UPF_SKIP_TEST)) {
+               serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
+               status1 = serial_in(up, UART_MSR) & 0xF0;
+               serial_out(up, UART_MCR, save_mcr);
+               if (status1 != 0x90) {
+                       spin_unlock_irqrestore(&port->lock, flags);
+                       DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+                                      status1);
+                       goto out;
+               }
+       }
+
+       /*
+        * We're pretty sure there's a port here.  Lets find out what
+        * type of port it is.  The IIR top two bits allows us to find
+        * out if it's 8250 or 16450, 16550, 16550A or later.  This
+        * determines what we test for next.
+        *
+        * We also initialise the EFR (if any) to zero for later.  The
+        * EFR occupies the same register location as the FCR and IIR.
+        */
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       serial_out(up, UART_EFR, 0);
+       serial_out(up, UART_LCR, 0);
+
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       scratch = serial_in(up, UART_IIR) >> 6;
+
+       switch (scratch) {
+       case 0:
+               autoconfig_8250(up);
+               break;
+       case 1:
+               port->type = PORT_UNKNOWN;
+               break;
+       case 2:
+               port->type = PORT_16550;
+               break;
+       case 3:
+               autoconfig_16550a(up);
+               break;
+       }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+       /*
+        * Only probe for RSA ports if we got the region.
+        */
+       if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
+           __enable_rsa(up))
+               port->type = PORT_RSA;
+#endif
+
+       serial_out(up, UART_LCR, save_lcr);
+
+       port->fifosize = uart_config[up->port.type].fifo_size;
+       old_capabilities = up->capabilities;
+       up->capabilities = uart_config[port->type].flags;
+       up->tx_loadsz = uart_config[port->type].tx_loadsz;
+
+       if (port->type == PORT_UNKNOWN)
+               goto out_lock;
+
+       /*
+        * Reset the UART.
+        */
+#ifdef CONFIG_SERIAL_8250_RSA
+       if (port->type == PORT_RSA)
+               serial_out(up, UART_RSA_FRR, 0);
+#endif
+       serial_out(up, UART_MCR, save_mcr);
+       serial8250_clear_fifos(up);
+       serial_in(up, UART_RX);
+       if (up->capabilities & UART_CAP_UUE)
+               serial_out(up, UART_IER, UART_IER_UUE);
+       else
+               serial_out(up, UART_IER, 0);
+
+out_lock:
+       spin_unlock_irqrestore(&port->lock, flags);
+       if (up->capabilities != old_capabilities) {
+               printk(KERN_WARNING
+                      "ttyS%d: detected caps %08x should be %08x\n",
+                      serial_index(port), old_capabilities,
+                      up->capabilities);
+       }
+out:
+       DEBUG_AUTOCONF("iir=%d ", scratch);
+       DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
+}
+
+static void autoconfig_irq(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+       unsigned char save_mcr, save_ier;
+       unsigned char save_ICP = 0;
+       unsigned int ICP = 0;
+       unsigned long irqs;
+       int irq;
+
+       if (port->flags & UPF_FOURPORT) {
+               ICP = (port->iobase & 0xfe0) | 0x1f;
+               save_ICP = inb_p(ICP);
+               outb_p(0x80, ICP);
+               inb_p(ICP);
+       }
+
+       /* forget possible initially masked and pending IRQ */
+       probe_irq_off(probe_irq_on());
+       save_mcr = serial_in(up, UART_MCR);
+       save_ier = serial_in(up, UART_IER);
+       serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+       irqs = probe_irq_on();
+       serial_out(up, UART_MCR, 0);
+       udelay(10);
+       if (port->flags & UPF_FOURPORT) {
+               serial_out(up, UART_MCR,
+                           UART_MCR_DTR | UART_MCR_RTS);
+       } else {
+               serial_out(up, UART_MCR,
+                           UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+       }
+       serial_out(up, UART_IER, 0x0f); /* enable all intrs */
+       serial_in(up, UART_LSR);
+       serial_in(up, UART_RX);
+       serial_in(up, UART_IIR);
+       serial_in(up, UART_MSR);
+       serial_out(up, UART_TX, 0xFF);
+       udelay(20);
+       irq = probe_irq_off(irqs);
+
+       serial_out(up, UART_MCR, save_mcr);
+       serial_out(up, UART_IER, save_ier);
+
+       if (port->flags & UPF_FOURPORT)
+               outb_p(save_ICP, ICP);
+
+       port->irq = (irq > 0) ? irq : 0;
+}
+
+static inline void __stop_tx(struct uart_8250_port *p)
+{
+       if (p->ier & UART_IER_THRI) {
+               p->ier &= ~UART_IER_THRI;
+               serial_out(p, UART_IER, p->ier);
+               serial8250_rpm_put_tx(p);
+       }
+}
+
+static void serial8250_stop_tx(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       serial8250_rpm_get(up);
+       __stop_tx(up);
+
+       /*
+        * We really want to stop the transmitter from sending.
+        */
+       if (port->type == PORT_16C950) {
+               up->acr |= UART_ACR_TXDIS;
+               serial_icr_write(up, UART_ACR, up->acr);
+       }
+       serial8250_rpm_put(up);
+}
+
+static void serial8250_start_tx(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       serial8250_rpm_get_tx(up);
+
+       if (up->dma && !up->dma->tx_dma(up))
+               return;
+
+       if (!(up->ier & UART_IER_THRI)) {
+               up->ier |= UART_IER_THRI;
+               serial_port_out(port, UART_IER, up->ier);
+
+               if (up->bugs & UART_BUG_TXEN) {
+                       unsigned char lsr;
+                       lsr = serial_in(up, UART_LSR);
+                       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+                       if (lsr & UART_LSR_THRE)
+                               serial8250_tx_chars(up);
+               }
+       }
+
+       /*
+        * Re-enable the transmitter if we disabled it.
+        */
+       if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
+               up->acr &= ~UART_ACR_TXDIS;
+               serial_icr_write(up, UART_ACR, up->acr);
+       }
+}
+
+static void serial8250_throttle(struct uart_port *port)
+{
+       port->throttle(port);
+}
+
+static void serial8250_unthrottle(struct uart_port *port)
+{
+       port->unthrottle(port);
+}
+
+static void serial8250_stop_rx(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       serial8250_rpm_get(up);
+
+       up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+       up->port.read_status_mask &= ~UART_LSR_DR;
+       serial_port_out(port, UART_IER, up->ier);
+
+       serial8250_rpm_put(up);
+}
+
+static void serial8250_disable_ms(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       /* no MSR capabilities */
+       if (up->bugs & UART_BUG_NOMSR)
+               return;
+
+       up->ier &= ~UART_IER_MSI;
+       serial_port_out(port, UART_IER, up->ier);
+}
+
+static void serial8250_enable_ms(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       /* no MSR capabilities */
+       if (up->bugs & UART_BUG_NOMSR)
+               return;
+
+       up->ier |= UART_IER_MSI;
+
+       serial8250_rpm_get(up);
+       serial_port_out(port, UART_IER, up->ier);
+       serial8250_rpm_put(up);
+}
+
+/*
+ * serial8250_rx_chars: processes according to the passed in LSR
+ * value, and returns the remaining LSR bits not handled
+ * by this Rx routine.
+ */
+unsigned char
+serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+{
+       struct uart_port *port = &up->port;
+       unsigned char ch;
+       int max_count = 256;
+       char flag;
+
+       do {
+               if (likely(lsr & UART_LSR_DR))
+                       ch = serial_in(up, UART_RX);
+               else
+                       /*
+                        * Intel 82571 has a Serial Over Lan device that will
+                        * set UART_LSR_BI without setting UART_LSR_DR when
+                        * it receives a break. To avoid reading from the
+                        * receive buffer without UART_LSR_DR bit set, we
+                        * just force the read character to be 0
+                        */
+                       ch = 0;
+
+               flag = TTY_NORMAL;
+               port->icount.rx++;
+
+               lsr |= up->lsr_saved_flags;
+               up->lsr_saved_flags = 0;
+
+               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+                       if (lsr & UART_LSR_BI) {
+                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+                               port->icount.brk++;
+                               /*
+                                * We do the SysRQ and SAK checking
+                                * here because otherwise the break
+                                * may get masked by ignore_status_mask
+                                * or read_status_mask.
+                                */
+                               if (uart_handle_break(port))
+                                       goto ignore_char;
+                       } else if (lsr & UART_LSR_PE)
+                               port->icount.parity++;
+                       else if (lsr & UART_LSR_FE)
+                               port->icount.frame++;
+                       if (lsr & UART_LSR_OE)
+                               port->icount.overrun++;
+
+                       /*
+                        * Mask off conditions which should be ignored.
+                        */
+                       lsr &= port->read_status_mask;
+
+                       if (lsr & UART_LSR_BI) {
+                               DEBUG_INTR("handling break....");
+                               flag = TTY_BREAK;
+                       } else if (lsr & UART_LSR_PE)
+                               flag = TTY_PARITY;
+                       else if (lsr & UART_LSR_FE)
+                               flag = TTY_FRAME;
+               }
+               if (uart_handle_sysrq_char(port, ch))
+                       goto ignore_char;
+
+               uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
+
+ignore_char:
+               lsr = serial_in(up, UART_LSR);
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
+       spin_unlock(&port->lock);
+       tty_flip_buffer_push(&port->state->port);
+       spin_lock(&port->lock);
+       return lsr;
+}
+EXPORT_SYMBOL_GPL(serial8250_rx_chars);
+
+void serial8250_tx_chars(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+       struct circ_buf *xmit = &port->state->xmit;
+       int count;
+
+       if (port->x_char) {
+               serial_out(up, UART_TX, port->x_char);
+               port->icount.tx++;
+               port->x_char = 0;
+               return;
+       }
+       if (uart_tx_stopped(port)) {
+               serial8250_stop_tx(port);
+               return;
+       }
+       if (uart_circ_empty(xmit)) {
+               __stop_tx(up);
+               return;
+       }
+
+       count = up->tx_loadsz;
+       do {
+               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               port->icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+               if (up->capabilities & UART_CAP_HFIFO) {
+                       if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
+                           BOTH_EMPTY)
+                               break;
+               }
+       } while (--count > 0);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+
+       DEBUG_INTR("THRE...");
+
+       /*
+        * With RPM enabled, we have to wait until the FIFO is empty before the
+        * HW can go idle. So we get here once again with empty FIFO and disable
+        * the interrupt and RPM in __stop_tx()
+        */
+       if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
+               __stop_tx(up);
+}
+EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+
+/* Caller holds uart port lock */
+unsigned int serial8250_modem_status(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+       unsigned int status = serial_in(up, UART_MSR);
+
+       status |= up->msr_saved_flags;
+       up->msr_saved_flags = 0;
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+           port->state != NULL) {
+               if (status & UART_MSR_TERI)
+                       port->icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       port->icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       uart_handle_dcd_change(port, status & UART_MSR_DCD);
+               if (status & UART_MSR_DCTS)
+                       uart_handle_cts_change(port, status & UART_MSR_CTS);
+
+               wake_up_interruptible(&port->state->port.delta_msr_wait);
+       }
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(serial8250_modem_status);
+
+/*
+ * This handles the interrupt from one port.
+ */
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+       unsigned char status;
+       unsigned long flags;
+       struct uart_8250_port *up = up_to_u8250p(port);
+       int dma_err = 0;
+
+       if (iir & UART_IIR_NO_INT)
+               return 0;
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       status = serial_port_in(port, UART_LSR);
+
+       DEBUG_INTR("status = %x...", status);
+
+       if (status & (UART_LSR_DR | UART_LSR_BI)) {
+               if (up->dma)
+                       dma_err = up->dma->rx_dma(up, iir);
+
+               if (!up->dma || dma_err)
+                       status = serial8250_rx_chars(up, status);
+       }
+       serial8250_modem_status(up);
+       if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+           (status & UART_LSR_THRE))
+               serial8250_tx_chars(up);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+static int serial8250_default_handle_irq(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned int iir;
+       int ret;
+
+       serial8250_rpm_get(up);
+
+       iir = serial_port_in(port, UART_IIR);
+       ret = serial8250_handle_irq(port, iir);
+
+       serial8250_rpm_put(up);
+       return ret;
+}
+
+/*
+ * These Exar UARTs have an extra interrupt indicator that could
+ * fire for a few unimplemented interrupts.  One of which is a
+ * wakeup event when coming out of sleep.  Put this here just
+ * to be on the safe side that these interrupts don't go unhandled.
+ */
+static int exar_handle_irq(struct uart_port *port)
+{
+       unsigned char int0, int1, int2, int3;
+       unsigned int iir = serial_port_in(port, UART_IIR);
+       int ret;
+
+       ret = serial8250_handle_irq(port, iir);
+
+       if ((port->type == PORT_XR17V35X) ||
+          (port->type == PORT_XR17D15X)) {
+               int0 = serial_port_in(port, 0x80);
+               int1 = serial_port_in(port, 0x81);
+               int2 = serial_port_in(port, 0x82);
+               int3 = serial_port_in(port, 0x83);
+       }
+
+       return ret;
+}
+
+static unsigned int serial8250_tx_empty(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned long flags;
+       unsigned int lsr;
+
+       serial8250_rpm_get(up);
+
+       spin_lock_irqsave(&port->lock, flags);
+       lsr = serial_port_in(port, UART_LSR);
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       serial8250_rpm_put(up);
+
+       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int serial8250_get_mctrl(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned int status;
+       unsigned int ret;
+
+       serial8250_rpm_get(up);
+       status = serial8250_modem_status(up);
+       serial8250_rpm_put(up);
+
+       ret = 0;
+       if (status & UART_MSR_DCD)
+               ret |= TIOCM_CAR;
+       if (status & UART_MSR_RI)
+               ret |= TIOCM_RNG;
+       if (status & UART_MSR_DSR)
+               ret |= TIOCM_DSR;
+       if (status & UART_MSR_CTS)
+               ret |= TIOCM_CTS;
+       return ret;
+}
+
+void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned char mcr = 0;
+
+       if (mctrl & TIOCM_RTS)
+               mcr |= UART_MCR_RTS;
+       if (mctrl & TIOCM_DTR)
+               mcr |= UART_MCR_DTR;
+       if (mctrl & TIOCM_OUT1)
+               mcr |= UART_MCR_OUT1;
+       if (mctrl & TIOCM_OUT2)
+               mcr |= UART_MCR_OUT2;
+       if (mctrl & TIOCM_LOOP)
+               mcr |= UART_MCR_LOOP;
+
+       mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
+
+       serial_port_out(port, UART_MCR, mcr);
+}
+EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       if (port->set_mctrl)
+               port->set_mctrl(port, mctrl);
+       else
+               serial8250_do_set_mctrl(port, mctrl);
+}
+
+static void serial8250_break_ctl(struct uart_port *port, int break_state)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned long flags;
+
+       serial8250_rpm_get(up);
+       spin_lock_irqsave(&port->lock, flags);
+       if (break_state == -1)
+               up->lcr |= UART_LCR_SBC;
+       else
+               up->lcr &= ~UART_LCR_SBC;
+       serial_port_out(port, UART_LCR, up->lcr);
+       spin_unlock_irqrestore(&port->lock, flags);
+       serial8250_rpm_put(up);
+}
+
+/*
+ *     Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+       unsigned int status, tmout = 10000;
+
+       /* Wait up to 10ms for the character(s) to be sent. */
+       for (;;) {
+               status = serial_in(up, UART_LSR);
+
+               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
+
+               if ((status & bits) == bits)
+                       break;
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       }
+
+       /* Wait up to 1s for flow control if necessary */
+       if (up->port.flags & UPF_CONS_FLOW) {
+               unsigned int tmout;
+               for (tmout = 1000000; tmout; tmout--) {
+                       unsigned int msr = serial_in(up, UART_MSR);
+                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+                       if (msr & UART_MSR_CTS)
+                               break;
+                       udelay(1);
+                       touch_nmi_watchdog();
+               }
+       }
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial8250_get_poll_char(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned char lsr;
+       int status;
+
+       serial8250_rpm_get(up);
+
+       lsr = serial_port_in(port, UART_LSR);
+
+       if (!(lsr & UART_LSR_DR)) {
+               status = NO_POLL_CHAR;
+               goto out;
+       }
+
+       status = serial_port_in(port, UART_RX);
+out:
+       serial8250_rpm_put(up);
+       return status;
+}
+
+
+static void serial8250_put_poll_char(struct uart_port *port,
+                        unsigned char c)
+{
+       unsigned int ier;
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       serial8250_rpm_get(up);
+       /*
+        *      First save the IER then disable the interrupts
+        */
+       ier = serial_port_in(port, UART_IER);
+       if (up->capabilities & UART_CAP_UUE)
+               serial_port_out(port, UART_IER, UART_IER_UUE);
+       else
+               serial_port_out(port, UART_IER, 0);
+
+       wait_for_xmitr(up, BOTH_EMPTY);
+       /*
+        *      Send the character out.
+        */
+       serial_port_out(port, UART_TX, c);
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore the IER
+        */
+       wait_for_xmitr(up, BOTH_EMPTY);
+       serial_port_out(port, UART_IER, ier);
+       serial8250_rpm_put(up);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+int serial8250_do_startup(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned long flags;
+       unsigned char lsr, iir;
+       int retval;
+
+       if (port->type == PORT_8250_CIR)
+               return -ENODEV;
+
+       if (!port->fifosize)
+               port->fifosize = uart_config[port->type].fifo_size;
+       if (!up->tx_loadsz)
+               up->tx_loadsz = uart_config[port->type].tx_loadsz;
+       if (!up->capabilities)
+               up->capabilities = uart_config[port->type].flags;
+       up->mcr = 0;
+
+       if (port->iotype != up->cur_iotype)
+               set_io_from_upio(port);
+
+       serial8250_rpm_get(up);
+       if (port->type == PORT_16C950) {
+               /* Wake up and initialize UART */
+               up->acr = 0;
+               serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+               serial_port_out(port, UART_EFR, UART_EFR_ECB);
+               serial_port_out(port, UART_IER, 0);
+               serial_port_out(port, UART_LCR, 0);
+               serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+               serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+               serial_port_out(port, UART_EFR, UART_EFR_ECB);
+               serial_port_out(port, UART_LCR, 0);
+       }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+       /*
+        * If this is an RSA port, see if we can kick it up to the
+        * higher speed clock.
+        */
+       enable_rsa(up);
+#endif
+
+       if (port->type == PORT_XR17V35X) {
+               /*
+                * First enable access to IER [7:5], ISR [5:4], FCR [5:4],
+                * MCR [7:5] and MSR [7:0]
+                */
+               serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
+
+               /*
+                * Make sure all interrups are masked until initialization is
+                * complete and the FIFOs are cleared
+                */
+               serial_port_out(port, UART_IER, 0);
+       }
+
+       /*
+        * Clear the FIFO buffers and disable them.
+        * (they will be reenabled in set_termios())
+        */
+       serial8250_clear_fifos(up);
+
+       /*
+        * Clear the interrupt registers.
+        */
+       serial_port_in(port, UART_LSR);
+       serial_port_in(port, UART_RX);
+       serial_port_in(port, UART_IIR);
+       serial_port_in(port, UART_MSR);
+
+       /*
+        * At this point, there's no way the LSR could still be 0xff;
+        * if it is, then bail out, because there's likely no UART
+        * here.
+        */
+       if (!(port->flags & UPF_BUGGY_UART) &&
+           (serial_port_in(port, UART_LSR) == 0xff)) {
+               printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+                                  serial_index(port));
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /*
+        * For a XR16C850, we need to set the trigger levels
+        */
+       if (port->type == PORT_16850) {
+               unsigned char fctr;
+
+               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+               fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+               serial_port_out(port, UART_FCTR,
+                               fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+               serial_port_out(port, UART_TRG, UART_TRG_96);
+               serial_port_out(port, UART_FCTR,
+                               fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+               serial_port_out(port, UART_TRG, UART_TRG_96);
+
+               serial_port_out(port, UART_LCR, 0);
+       }
+
+       if (port->irq) {
+               unsigned char iir1;
+               /*
+                * Test for UARTs that do not reassert THRE when the
+                * transmitter is idle and the interrupt has already
+                * been cleared.  Real 16550s should always reassert
+                * this interrupt whenever the transmitter is idle and
+                * the interrupt is enabled.  Delays are necessary to
+                * allow register changes to become visible.
+                */
+               spin_lock_irqsave(&port->lock, flags);
+               if (up->port.irqflags & IRQF_SHARED)
+                       disable_irq_nosync(port->irq);
+
+               wait_for_xmitr(up, UART_LSR_THRE);
+               serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow THRE to set */
+               iir1 = serial_port_in(port, UART_IIR);
+               serial_port_out(port, UART_IER, 0);
+               serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+               udelay(1); /* allow a working UART time to re-assert THRE */
+               iir = serial_port_in(port, UART_IIR);
+               serial_port_out(port, UART_IER, 0);
+
+               if (port->irqflags & IRQF_SHARED)
+                       enable_irq(port->irq);
+               spin_unlock_irqrestore(&port->lock, flags);
+
+               /*
+                * If the interrupt is not reasserted, or we otherwise
+                * don't trust the iir, setup a timer to kick the UART
+                * on a regular basis.
+                */
+               if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
+                   up->port.flags & UPF_BUG_THRE) {
+                       up->bugs |= UART_BUG_THRE;
+               }
+       }
+
+       retval = up->ops->setup_irq(up);
+       if (retval)
+               goto out;
+
+       /*
+        * Now, initialize the UART
+        */
+       serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
+
+       spin_lock_irqsave(&port->lock, flags);
+       if (up->port.flags & UPF_FOURPORT) {
+               if (!up->port.irq)
+                       up->port.mctrl |= TIOCM_OUT1;
+       } else
+               /*
+                * Most PC uarts need OUT2 raised to enable interrupts.
+                */
+               if (port->irq)
+                       up->port.mctrl |= TIOCM_OUT2;
+
+       serial8250_set_mctrl(port, port->mctrl);
+
+       /* Serial over Lan (SoL) hack:
+          Intel 8257x Gigabit ethernet chips have a
+          16550 emulation, to be used for Serial Over Lan.
+          Those chips take a longer time than a normal
+          serial device to signalize that a transmission
+          data was queued. Due to that, the above test generally
+          fails. One solution would be to delay the reading of
+          iir. However, this is not reliable, since the timeout
+          is variable. So, let's just don't test if we receive
+          TX irq. This way, we'll never enable UART_BUG_TXEN.
+        */
+       if (up->port.flags & UPF_NO_TXEN_TEST)
+               goto dont_test_tx_en;
+
+       /*
+        * Do a quick test to see if we receive an
+        * interrupt when we enable the TX irq.
+        */
+       serial_port_out(port, UART_IER, UART_IER_THRI);
+       lsr = serial_port_in(port, UART_LSR);
+       iir = serial_port_in(port, UART_IIR);
+       serial_port_out(port, UART_IER, 0);
+
+       if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+               if (!(up->bugs & UART_BUG_TXEN)) {
+                       up->bugs |= UART_BUG_TXEN;
+                       pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+                                serial_index(port));
+               }
+       } else {
+               up->bugs &= ~UART_BUG_TXEN;
+       }
+
+dont_test_tx_en:
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       /*
+        * Clear the interrupt registers again for luck, and clear the
+        * saved flags to avoid getting false values from polling
+        * routines or the previous session.
+        */
+       serial_port_in(port, UART_LSR);
+       serial_port_in(port, UART_RX);
+       serial_port_in(port, UART_IIR);
+       serial_port_in(port, UART_MSR);
+       up->lsr_saved_flags = 0;
+       up->msr_saved_flags = 0;
+
+       /*
+        * Request DMA channels for both RX and TX.
+        */
+       if (up->dma) {
+               retval = serial8250_request_dma(up);
+               if (retval) {
+                       pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
+                                           serial_index(port));
+                       up->dma = NULL;
+               }
+       }
+
+       /*
+        * Set the IER shadow for rx interrupts but defer actual interrupt
+        * enable until after the FIFOs are enabled; otherwise, an already-
+        * active sender can swamp the interrupt handler with "too much work".
+        */
+       up->ier = UART_IER_RLSI | UART_IER_RDI;
+
+       if (port->flags & UPF_FOURPORT) {
+               unsigned int icp;
+               /*
+                * Enable interrupts on the AST Fourport board
+                */
+               icp = (port->iobase & 0xfe0) | 0x01f;
+               outb_p(0x80, icp);
+               inb_p(icp);
+       }
+       retval = 0;
+out:
+       serial8250_rpm_put(up);
+       return retval;
+}
+EXPORT_SYMBOL_GPL(serial8250_do_startup);
+
+static int serial8250_startup(struct uart_port *port)
+{
+       if (port->startup)
+               return port->startup(port);
+       return serial8250_do_startup(port);
+}
+
+void serial8250_do_shutdown(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned long flags;
+
+       serial8250_rpm_get(up);
+       /*
+        * Disable interrupts from this port
+        */
+       up->ier = 0;
+       serial_port_out(port, UART_IER, 0);
+
+       if (up->dma)
+               serial8250_release_dma(up);
+
+       spin_lock_irqsave(&port->lock, flags);
+       if (port->flags & UPF_FOURPORT) {
+               /* reset interrupts on the AST Fourport board */
+               inb((port->iobase & 0xfe0) | 0x1f);
+               port->mctrl |= TIOCM_OUT1;
+       } else
+               port->mctrl &= ~TIOCM_OUT2;
+
+       serial8250_set_mctrl(port, port->mctrl);
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       /*
+        * Disable break condition and FIFOs
+        */
+       serial_port_out(port, UART_LCR,
+                       serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
+       serial8250_clear_fifos(up);
+
+#ifdef CONFIG_SERIAL_8250_RSA
+       /*
+        * Reset the RSA board back to 115kbps compat mode.
+        */
+       disable_rsa(up);
+#endif
+
+       /*
+        * Read data port to reset things, and then unlink from
+        * the IRQ chain.
+        */
+       serial_port_in(port, UART_RX);
+       serial8250_rpm_put(up);
+
+       up->ops->release_irq(up);
+}
+EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+       if (port->shutdown)
+               port->shutdown(port);
+       else
+               serial8250_do_shutdown(port);
+}
+
+/*
+ * XR17V35x UARTs have an extra fractional divisor register (DLD)
+ * Calculate divisor with extra 4-bit fractional portion
+ */
+static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
+                                        unsigned int baud,
+                                        unsigned int *frac)
+{
+       struct uart_port *port = &up->port;
+       unsigned int quot_16;
+
+       quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
+       *frac = quot_16 & 0x0f;
+
+       return quot_16 >> 4;
+}
+
+static unsigned int serial8250_get_divisor(struct uart_8250_port *up,
+                                          unsigned int baud,
+                                          unsigned int *frac)
+{
+       struct uart_port *port = &up->port;
+       unsigned int quot;
+
+       /*
+        * Handle magic divisors for baud rates above baud_base on
+        * SMSC SuperIO chips.
+        *
+        */
+       if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+           baud == (port->uartclk/4))
+               quot = 0x8001;
+       else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+                baud == (port->uartclk/8))
+               quot = 0x8002;
+       else if (up->port.type == PORT_XR17V35X)
+               quot = xr17v35x_get_divisor(up, baud, frac);
+       else
+               quot = uart_get_divisor(port, baud);
+
+       /*
+        * Oxford Semi 952 rev B workaround
+        */
+       if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
+               quot++;
+
+       return quot;
+}
+
+static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
+                                           tcflag_t c_cflag)
+{
+       unsigned char cval;
+
+       switch (c_cflag & CSIZE) {
+       case CS5:
+               cval = UART_LCR_WLEN5;
+               break;
+       case CS6:
+               cval = UART_LCR_WLEN6;
+               break;
+       case CS7:
+               cval = UART_LCR_WLEN7;
+               break;
+       default:
+       case CS8:
+               cval = UART_LCR_WLEN8;
+               break;
+       }
+
+       if (c_cflag & CSTOPB)
+               cval |= UART_LCR_STOP;
+       if (c_cflag & PARENB) {
+               cval |= UART_LCR_PARITY;
+               if (up->bugs & UART_BUG_PARITY)
+                       up->fifo_bug = true;
+       }
+       if (!(c_cflag & PARODD))
+               cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+       if (c_cflag & CMSPAR)
+               cval |= UART_LCR_SPAR;
+#endif
+
+       return cval;
+}
+
+static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
+                           unsigned int quot, unsigned int quot_frac)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+       if (is_omap1510_8250(up)) {
+               if (baud == 115200) {
+                       quot = 1;
+                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
+               } else
+                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
+       }
+
+       /*
+        * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
+        * otherwise just set DLAB
+        */
+       if (up->capabilities & UART_NATSEMI)
+               serial_port_out(port, UART_LCR, 0xe0);
+       else
+               serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
+
+       serial_dl_write(up, quot);
+
+       /* XR17V35x UARTs have an extra fractional divisor register (DLD) */
+       if (up->port.type == PORT_XR17V35X)
+               serial_port_out(port, 0x2, quot_frac);
+}
+
+void
+serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+                         struct ktermios *old)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       unsigned char cval;
+       unsigned long flags;
+       unsigned int baud, quot, frac = 0;
+
+       cval = serial8250_compute_lcr(up, termios->c_cflag);
+
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+       baud = uart_get_baud_rate(port, termios, old,
+                                 port->uartclk / 16 / 0xffff,
+                                 port->uartclk / 16);
+       quot = serial8250_get_divisor(up, baud, &frac);
+
+       /*
+        * Ok, we're now changing the port state.  Do it with
+        * interrupts disabled.
+        */
+       serial8250_rpm_get(up);
+       spin_lock_irqsave(&port->lock, flags);
+
+       up->lcr = cval;                                 /* Save computed LCR */
+
+       if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
+               /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
+               if ((baud < 2400 && !up->dma) || up->fifo_bug) {
+                       up->fcr &= ~UART_FCR_TRIGGER_MASK;
+                       up->fcr |= UART_FCR_TRIGGER_1;
+               }
+       }
+
+       /*
+        * MCR-based auto flow control.  When AFE is enabled, RTS will be
+        * deasserted when the receive FIFO contains more characters than
+        * the trigger, or the MCR RTS bit is cleared.  In the case where
+        * the remote UART is not using CTS auto flow control, we must
+        * have sufficient FIFO entries for the latency of the remote
+        * UART to respond.  IOW, at least 32 bytes of FIFO.
+        */
+       if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
+               up->mcr &= ~UART_MCR_AFE;
+               if (termios->c_cflag & CRTSCTS)
+                       up->mcr |= UART_MCR_AFE;
+       }
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+       if (termios->c_iflag & INPCK)
+               port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+       if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+               port->read_status_mask |= UART_LSR_BI;
+
+       /*
+        * Characteres to ignore
+        */
+       port->ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+       if (termios->c_iflag & IGNBRK) {
+               port->ignore_status_mask |= UART_LSR_BI;
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       port->ignore_status_mask |= UART_LSR_OE;
+       }
+
+       /*
+        * ignore all characters if CREAD is not set
+        */
+       if ((termios->c_cflag & CREAD) == 0)
+               port->ignore_status_mask |= UART_LSR_DR;
+
+       /*
+        * CTS flow control flag and modem status interrupts
+        */
+       up->ier &= ~UART_IER_MSI;
+       if (!(up->bugs & UART_BUG_NOMSR) &&
+                       UART_ENABLE_MS(&up->port, termios->c_cflag))
+               up->ier |= UART_IER_MSI;
+       if (up->capabilities & UART_CAP_UUE)
+               up->ier |= UART_IER_UUE;
+       if (up->capabilities & UART_CAP_RTOIE)
+               up->ier |= UART_IER_RTOIE;
+
+       serial_port_out(port, UART_IER, up->ier);
+
+       if (up->capabilities & UART_CAP_EFR) {
+               unsigned char efr = 0;
+               /*
+                * TI16C752/Startech hardware flow control.  FIXME:
+                * - TI16C752 requires control thresholds to be set.
+                * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
+                */
+               if (termios->c_cflag & CRTSCTS)
+                       efr |= UART_EFR_CTS;
+
+               serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+               if (port->flags & UPF_EXAR_EFR)
+                       serial_port_out(port, UART_XR_EFR, efr);
+               else
+                       serial_port_out(port, UART_EFR, efr);
+       }
+
+       serial8250_set_divisor(port, baud, quot, frac);
+
+       /*
+        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+        * is written without DLAB set, this mode will be disabled.
+        */
+       if (port->type == PORT_16750)
+               serial_port_out(port, UART_FCR, up->fcr);
+
+       serial_port_out(port, UART_LCR, up->lcr);       /* reset DLAB */
+       if (port->type != PORT_16750) {
+               /* emulated UARTs (Lucent Venus 167x) need two steps */
+               if (up->fcr & UART_FCR_ENABLE_FIFO)
+                       serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
+               serial_port_out(port, UART_FCR, up->fcr);       /* set fcr */
+       }
+       serial8250_set_mctrl(port, port->mctrl);
+       spin_unlock_irqrestore(&port->lock, flags);
+       serial8250_rpm_put(up);
+
+       /* Don't rewrite B0 */
+       if (tty_termios_baud_rate(termios))
+               tty_termios_encode_baud_rate(termios, baud, baud);
+}
+EXPORT_SYMBOL(serial8250_do_set_termios);
+
+static void
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+                      struct ktermios *old)
+{
+       if (port->set_termios)
+               port->set_termios(port, termios, old);
+       else
+               serial8250_do_set_termios(port, termios, old);
+}
+
+static void
+serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
+{
+       if (termios->c_line == N_PPS) {
+               port->flags |= UPF_HARDPPS_CD;
+               spin_lock_irq(&port->lock);
+               serial8250_enable_ms(port);
+               spin_unlock_irq(&port->lock);
+       } else {
+               port->flags &= ~UPF_HARDPPS_CD;
+               if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+                       spin_lock_irq(&port->lock);
+                       serial8250_disable_ms(port);
+                       spin_unlock_irq(&port->lock);
+               }
+       }
+}
+
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+                     unsigned int oldstate)
+{
+       struct uart_8250_port *p = up_to_u8250p(port);
+
+       serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
+
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+             unsigned int oldstate)
+{
+       if (port->pm)
+               port->pm(port, state, oldstate);
+       else
+               serial8250_do_pm(port, state, oldstate);
+}
+
+static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+{
+       if (pt->port.mapsize)
+               return pt->port.mapsize;
+       if (pt->port.iotype == UPIO_AU) {
+               if (pt->port.type == PORT_RT2880)
+                       return 0x100;
+               return 0x1000;
+       }
+       if (is_omap1_8250(pt))
+               return 0x16 << pt->port.regshift;
+
+       return 8 << pt->port.regshift;
+}
+
+/*
+ * Resource handling.
+ */
+static int serial8250_request_std_resource(struct uart_8250_port *up)
+{
+       unsigned int size = serial8250_port_size(up);
+       struct uart_port *port = &up->port;
+       int ret = 0;
+
+       switch (port->iotype) {
+       case UPIO_AU:
+       case UPIO_TSI:
+       case UPIO_MEM32:
+       case UPIO_MEM32BE:
+       case UPIO_MEM:
+               if (!port->mapbase)
+                       break;
+
+               if (!request_mem_region(port->mapbase, size, "serial")) {
+                       ret = -EBUSY;
+                       break;
+               }
+
+               if (port->flags & UPF_IOREMAP) {
+                       port->membase = ioremap_nocache(port->mapbase, size);
+                       if (!port->membase) {
+                               release_mem_region(port->mapbase, size);
+                               ret = -ENOMEM;
+                       }
+               }
+               break;
+
+       case UPIO_HUB6:
+       case UPIO_PORT:
+               if (!request_region(port->iobase, size, "serial"))
+                       ret = -EBUSY;
+               break;
+       }
+       return ret;
+}
+
+static void serial8250_release_std_resource(struct uart_8250_port *up)
+{
+       unsigned int size = serial8250_port_size(up);
+       struct uart_port *port = &up->port;
+
+       switch (port->iotype) {
+       case UPIO_AU:
+       case UPIO_TSI:
+       case UPIO_MEM32:
+       case UPIO_MEM32BE:
+       case UPIO_MEM:
+               if (!port->mapbase)
+                       break;
+
+               if (port->flags & UPF_IOREMAP) {
+                       iounmap(port->membase);
+                       port->membase = NULL;
+               }
+
+               release_mem_region(port->mapbase, size);
+               break;
+
+       case UPIO_HUB6:
+       case UPIO_PORT:
+               release_region(port->iobase, size);
+               break;
+       }
+}
+
+static void serial8250_release_port(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       serial8250_release_std_resource(up);
+}
+
+static int serial8250_request_port(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       int ret;
+
+       if (port->type == PORT_8250_CIR)
+               return -ENODEV;
+
+       ret = serial8250_request_std_resource(up);
+
+       return ret;
+}
+
+static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
+{
+       const struct serial8250_config *conf_type = &uart_config[up->port.type];
+       unsigned char bytes;
+
+       bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
+
+       return bytes ? bytes : -EOPNOTSUPP;
+}
+
+static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
+{
+       const struct serial8250_config *conf_type = &uart_config[up->port.type];
+       int i;
+
+       if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
+               return -EOPNOTSUPP;
+
+       for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
+               if (bytes < conf_type->rxtrig_bytes[i])
+                       /* Use the nearest lower value */
+                       return (--i) << UART_FCR_R_TRIG_SHIFT;
+       }
+
+       return UART_FCR_R_TRIG_11;
+}
+
+static int do_get_rxtrig(struct tty_port *port)
+{
+       struct uart_state *state = container_of(port, struct uart_state, port);
+       struct uart_port *uport = state->uart_port;
+       struct uart_8250_port *up =
+               container_of(uport, struct uart_8250_port, port);
+
+       if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
+               return -EINVAL;
+
+       return fcr_get_rxtrig_bytes(up);
+}
+
+static int do_serial8250_get_rxtrig(struct tty_port *port)
+{
+       int rxtrig_bytes;
+
+       mutex_lock(&port->mutex);
+       rxtrig_bytes = do_get_rxtrig(port);
+       mutex_unlock(&port->mutex);
+
+       return rxtrig_bytes;
+}
+
+static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct tty_port *port = dev_get_drvdata(dev);
+       int rxtrig_bytes;
+
+       rxtrig_bytes = do_serial8250_get_rxtrig(port);
+       if (rxtrig_bytes < 0)
+               return rxtrig_bytes;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
+}
+
+static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
+{
+       struct uart_state *state = container_of(port, struct uart_state, port);
+       struct uart_port *uport = state->uart_port;
+       struct uart_8250_port *up =
+               container_of(uport, struct uart_8250_port, port);
+       int rxtrig;
+
+       if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
+           up->fifo_bug)
+               return -EINVAL;
+
+       rxtrig = bytes_to_fcr_rxtrig(up, bytes);
+       if (rxtrig < 0)
+               return rxtrig;
+
+       serial8250_clear_fifos(up);
+       up->fcr &= ~UART_FCR_TRIGGER_MASK;
+       up->fcr |= (unsigned char)rxtrig;
+       serial_out(up, UART_FCR, up->fcr);
+       return 0;
+}
+
+static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
+{
+       int ret;
+
+       mutex_lock(&port->mutex);
+       ret = do_set_rxtrig(port, bytes);
+       mutex_unlock(&port->mutex);
+
+       return ret;
+}
+
+static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct tty_port *port = dev_get_drvdata(dev);
+       unsigned char bytes;
+       int ret;
+
+       if (!count)
+               return -EINVAL;
+
+       ret = kstrtou8(buf, 10, &bytes);
+       if (ret < 0)
+               return ret;
+
+       ret = do_serial8250_set_rxtrig(port, bytes);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
+                  serial8250_get_attr_rx_trig_bytes,
+                  serial8250_set_attr_rx_trig_bytes);
+
+static struct attribute *serial8250_dev_attrs[] = {
+       &dev_attr_rx_trig_bytes.attr,
+       NULL,
+       };
+
+static struct attribute_group serial8250_dev_attr_group = {
+       .attrs = serial8250_dev_attrs,
+       };
+
+static void register_dev_spec_attr_grp(struct uart_8250_port *up)
+{
+       const struct serial8250_config *conf_type = &uart_config[up->port.type];
+
+       if (conf_type->rxtrig_bytes[0])
+               up->port.attr_group = &serial8250_dev_attr_group;
+}
+
+static void serial8250_config_port(struct uart_port *port, int flags)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       int ret;
+
+       if (port->type == PORT_8250_CIR)
+               return;
+
+       /*
+        * Find the region that we can probe for.  This in turn
+        * tells us whether we can probe for the type of port.
+        */
+       ret = serial8250_request_std_resource(up);
+       if (ret < 0)
+               return;
+
+       if (port->iotype != up->cur_iotype)
+               set_io_from_upio(port);
+
+       if (flags & UART_CONFIG_TYPE)
+               autoconfig(up);
+
+       /* if access method is AU, it is a 16550 with a quirk */
+       if (port->type == PORT_16550A && port->iotype == UPIO_AU)
+               up->bugs |= UART_BUG_NOMSR;
+
+       /* HW bugs may trigger IRQ while IIR == NO_INT */
+       if (port->type == PORT_TEGRA)
+               up->bugs |= UART_BUG_NOMSR;
+
+       if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
+               autoconfig_irq(up);
+
+       if (port->type == PORT_UNKNOWN)
+               serial8250_release_std_resource(up);
+
+       /* Fixme: probably not the best place for this */
+       if ((port->type == PORT_XR17V35X) ||
+          (port->type == PORT_XR17D15X))
+               port->handle_irq = exar_handle_irq;
+
+       register_dev_spec_attr_grp(up);
+       up->fcr = uart_config[up->port.type].fcr;
+}
+
+static int
+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       if (ser->irq >= nr_irqs || ser->irq < 0 ||
+           ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+           ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
+           ser->type == PORT_STARTECH)
+               return -EINVAL;
+       return 0;
+}
+
+static const char *
+serial8250_type(struct uart_port *port)
+{
+       int type = port->type;
+
+       if (type >= ARRAY_SIZE(uart_config))
+               type = 0;
+       return uart_config[type].name;
+}
+
+static const struct uart_ops serial8250_pops = {
+       .tx_empty       = serial8250_tx_empty,
+       .set_mctrl      = serial8250_set_mctrl,
+       .get_mctrl      = serial8250_get_mctrl,
+       .stop_tx        = serial8250_stop_tx,
+       .start_tx       = serial8250_start_tx,
+       .throttle       = serial8250_throttle,
+       .unthrottle     = serial8250_unthrottle,
+       .stop_rx        = serial8250_stop_rx,
+       .enable_ms      = serial8250_enable_ms,
+       .break_ctl      = serial8250_break_ctl,
+       .startup        = serial8250_startup,
+       .shutdown       = serial8250_shutdown,
+       .set_termios    = serial8250_set_termios,
+       .set_ldisc      = serial8250_set_ldisc,
+       .pm             = serial8250_pm,
+       .type           = serial8250_type,
+       .release_port   = serial8250_release_port,
+       .request_port   = serial8250_request_port,
+       .config_port    = serial8250_config_port,
+       .verify_port    = serial8250_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = serial8250_get_poll_char,
+       .poll_put_char = serial8250_put_poll_char,
+#endif
+};
+
+void serial8250_init_port(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+
+       spin_lock_init(&port->lock);
+       port->ops = &serial8250_pops;
+
+       up->cur_iotype = 0xFF;
+}
+EXPORT_SYMBOL_GPL(serial8250_init_port);
+
+void serial8250_set_defaults(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+
+       if (up->port.flags & UPF_FIXED_TYPE) {
+               unsigned int type = up->port.type;
+
+               if (!up->port.fifosize)
+                       up->port.fifosize = uart_config[type].fifo_size;
+               if (!up->tx_loadsz)
+                       up->tx_loadsz = uart_config[type].tx_loadsz;
+               if (!up->capabilities)
+                       up->capabilities = uart_config[type].flags;
+       }
+
+       set_io_from_upio(port);
+
+       /* default dma handlers */
+       if (up->dma) {
+               if (!up->dma->tx_dma)
+                       up->dma->tx_dma = serial8250_tx_dma;
+               if (!up->dma->rx_dma)
+                       up->dma->rx_dma = serial8250_rx_dma;
+       }
+}
+EXPORT_SYMBOL_GPL(serial8250_set_defaults);
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+
+static void serial8250_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       wait_for_xmitr(up, UART_LSR_THRE);
+       serial_port_out(port, UART_TX, ch);
+}
+
+/*
+ *     Print a string to the serial port trying not to disturb
+ *     any possible real use of the port...
+ *
+ *     The console_lock must be held when we get here.
+ */
+void serial8250_console_write(struct uart_8250_port *up, const char *s,
+                             unsigned int count)
+{
+       struct uart_port *port = &up->port;
+       unsigned long flags;
+       unsigned int ier;
+       int locked = 1;
+
+       touch_nmi_watchdog();
+
+       serial8250_rpm_get(up);
+
+       if (port->sysrq)
+               locked = 0;
+       else if (oops_in_progress)
+               locked = spin_trylock_irqsave(&port->lock, flags);
+       else
+               spin_lock_irqsave(&port->lock, flags);
+
+       /*
+        *      First save the IER then disable the interrupts
+        */
+       ier = serial_port_in(port, UART_IER);
+
+       if (up->capabilities & UART_CAP_UUE)
+               serial_port_out(port, UART_IER, UART_IER_UUE);
+       else
+               serial_port_out(port, UART_IER, 0);
+
+       /* check scratch reg to see if port powered off during system sleep */
+       if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
+               struct ktermios termios;
+               unsigned int baud, quot, frac = 0;
+
+               termios.c_cflag = port->cons->cflag;
+               if (port->state->port.tty && termios.c_cflag == 0)
+                       termios.c_cflag = port->state->port.tty->termios.c_cflag;
+
+               baud = uart_get_baud_rate(port, &termios, NULL,
+                                         port->uartclk / 16 / 0xffff,
+                                         port->uartclk / 16);
+               quot = serial8250_get_divisor(up, baud, &frac);
+
+               serial8250_set_divisor(port, baud, quot, frac);
+               serial_port_out(port, UART_LCR, up->lcr);
+               serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+
+               up->canary = 0;
+       }
+
+       uart_console_write(port, s, count, serial8250_console_putchar);
+
+       /*
+        *      Finally, wait for transmitter to become empty
+        *      and restore the IER
+        */
+       wait_for_xmitr(up, BOTH_EMPTY);
+       serial_port_out(port, UART_IER, ier);
+
+       /*
+        *      The receive handling will happen properly because the
+        *      receive ready bit will still be set; it is not cleared
+        *      on read.  However, modem control will not, we must
+        *      call it if we have saved something in the saved flags
+        *      while processing with interrupts off.
+        */
+       if (up->msr_saved_flags)
+               serial8250_modem_status(up);
+
+       if (locked)
+               spin_unlock_irqrestore(&port->lock, flags);
+       serial8250_rpm_put(up);
+}
+
+static unsigned int probe_baud(struct uart_port *port)
+{
+       unsigned char lcr, dll, dlm;
+       unsigned int quot;
+
+       lcr = serial_port_in(port, UART_LCR);
+       serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+       dll = serial_port_in(port, UART_DLL);
+       dlm = serial_port_in(port, UART_DLM);
+       serial_port_out(port, UART_LCR, lcr);
+
+       quot = (dlm << 8) | dll;
+       return (port->uartclk / 16) / quot;
+}
+
+int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
+{
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       if (!port->iobase && !port->membase)
+               return -ENODEV;
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       else if (probe)
+               baud = probe_baud(port);
+
+       return uart_set_options(port, port->cons, baud, parity, bits, flow);
+}
+
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
index 7d79425c2b09377f76282b917c5560511c27940f..d11621e2cf1df083ca4c58309ef610df6c9c70fa 100644 (file)
@@ -218,6 +218,7 @@ static int uniphier_uart_probe(struct platform_device *pdev)
        ret = serial8250_register_8250_port(&up);
        if (ret < 0) {
                dev_err(dev, "failed to register 8250 port\n");
+               clk_disable_unprepare(priv->clk);
                return ret;
        }
 
index 706295913c3451e0bea1ce20081e1d0b009ca682..39c6d2277570bcacef38c09fd8203ae8b6793ccd 100644 (file)
@@ -2,10 +2,11 @@
 # Makefile for the 8250 serial device drivers.
 #
 
-obj-$(CONFIG_SERIAL_8250)              += 8250.o
+obj-$(CONFIG_SERIAL_8250)              += 8250.o 8250_base.o
 8250-y                                 := 8250_core.o
 8250-$(CONFIG_SERIAL_8250_PNP)         += 8250_pnp.o
-8250-$(CONFIG_SERIAL_8250_DMA)         += 8250_dma.o
+8250_base-y                            := 8250_port.o
+8250_base-$(CONFIG_SERIAL_8250_DMA)    += 8250_dma.o
 obj-$(CONFIG_SERIAL_8250_GSC)          += 8250_gsc.o
 obj-$(CONFIG_SERIAL_8250_PCI)          += 8250_pci.o
 obj-$(CONFIG_SERIAL_8250_HP300)                += 8250_hp300.o
index 15b4079a335e886ca62c422970c80ba8c93f9dfb..ed299b9e63752b4ec9d319a7e989fe3307433a77 100644 (file)
@@ -47,12 +47,12 @@ config SERIAL_AMBA_PL010_CONSOLE
 
 config SERIAL_AMBA_PL011
        tristate "ARM AMBA PL011 serial port support"
-       depends on ARM_AMBA
+       depends on ARM_AMBA || SOC_ZX296702
        select SERIAL_CORE
        help
          This selects the ARM(R) AMBA(R) PrimeCell PL011 UART.  If you have
          an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
-         here.
+         here. Say Y or M if you have SOC_ZX296702.
 
          If unsure, say N.
 
@@ -594,7 +594,7 @@ config SERIAL_IMX_CONSOLE
 
 config SERIAL_UARTLITE
        tristate "Xilinx uartlite serial port support"
-       depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ
+       depends on HAS_IOMEM
        select SERIAL_CORE
        help
          Say Y here if you want to use the Xilinx uartlite serial controller.
@@ -1067,6 +1067,7 @@ config SERIAL_ETRAXFS
        bool "ETRAX FS serial port support"
        depends on ETRAX_ARCH_V32 && OF
        select SERIAL_CORE
+       select SERIAL_MCTRL_GPIO if GPIOLIB
 
 config SERIAL_ETRAXFS_CONSOLE
        bool "ETRAX FS serial console support"
@@ -1376,7 +1377,8 @@ config SERIAL_ALTERA_UART_CONSOLE
 
 config SERIAL_IFX6X60
         tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
-       depends on GPIOLIB && SPI && HAS_DMA
+       depends on GPIOLIB || COMPILE_TEST
+       depends on SPI && HAS_DMA
        help
          Support for the IFX6x60 modem devices on Intel MID platforms.
 
index fd27e986b1dd3437dfd2560ec11efd8def7bf254..2af09ab153b6db628c09bf248219a65a0e40387d 100644 (file)
 /* There is by now at least one vendor with differing details, so handle it */
 struct vendor_data {
        unsigned int            ifls;
+       unsigned int            fr_busy;
+       unsigned int            fr_dsr;
+       unsigned int            fr_cts;
+       unsigned int            fr_ri;
        unsigned int            lcrh_tx;
        unsigned int            lcrh_rx;
+       u16                     *reg_lut;
        bool                    oversampling;
        bool                    dma_threshold;
        bool                    cts_event_workaround;
@@ -85,6 +90,48 @@ struct vendor_data {
        unsigned int (*get_fifosize)(struct amba_device *dev);
 };
 
+/* Max address offset of register in use is 0x48 */
+#define REG_NR         (0x48 >> 2)
+#define IDX(x)         (x >> 2)
+enum reg_idx {
+       REG_DR          = IDX(UART01x_DR),
+       REG_RSR         = IDX(UART01x_RSR),
+       REG_ST_DMAWM    = IDX(ST_UART011_DMAWM),
+       REG_FR          = IDX(UART01x_FR),
+       REG_ST_LCRH_RX  = IDX(ST_UART011_LCRH_RX),
+       REG_ILPR        = IDX(UART01x_ILPR),
+       REG_IBRD        = IDX(UART011_IBRD),
+       REG_FBRD        = IDX(UART011_FBRD),
+       REG_LCRH        = IDX(UART011_LCRH),
+       REG_CR          = IDX(UART011_CR),
+       REG_IFLS        = IDX(UART011_IFLS),
+       REG_IMSC        = IDX(UART011_IMSC),
+       REG_RIS         = IDX(UART011_RIS),
+       REG_MIS         = IDX(UART011_MIS),
+       REG_ICR         = IDX(UART011_ICR),
+       REG_DMACR       = IDX(UART011_DMACR),
+};
+
+static u16 arm_reg[] = {
+       [REG_DR]                = UART01x_DR,
+       [REG_RSR]               = UART01x_RSR,
+       [REG_ST_DMAWM]          = ~0,
+       [REG_FR]                = UART01x_FR,
+       [REG_ST_LCRH_RX]        = ~0,
+       [REG_ILPR]              = UART01x_ILPR,
+       [REG_IBRD]              = UART011_IBRD,
+       [REG_FBRD]              = UART011_FBRD,
+       [REG_LCRH]              = UART011_LCRH,
+       [REG_CR]                = UART011_CR,
+       [REG_IFLS]              = UART011_IFLS,
+       [REG_IMSC]              = UART011_IMSC,
+       [REG_RIS]               = UART011_RIS,
+       [REG_MIS]               = UART011_MIS,
+       [REG_ICR]               = UART011_ICR,
+       [REG_DMACR]             = UART011_DMACR,
+};
+
+#ifdef CONFIG_ARM_AMBA
 static unsigned int get_fifosize_arm(struct amba_device *dev)
 {
        return amba_rev(dev) < 3 ? 16 : 32;
@@ -92,8 +139,13 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
 
 static struct vendor_data vendor_arm = {
        .ifls                   = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
-       .lcrh_tx                = UART011_LCRH,
-       .lcrh_rx                = UART011_LCRH,
+       .fr_busy                = UART01x_FR_BUSY,
+       .fr_dsr                 = UART01x_FR_DSR,
+       .fr_cts                 = UART01x_FR_CTS,
+       .fr_ri                  = UART011_FR_RI,
+       .lcrh_tx                = REG_LCRH,
+       .lcrh_rx                = REG_LCRH,
+       .reg_lut                = arm_reg,
        .oversampling           = false,
        .dma_threshold          = false,
        .cts_event_workaround   = false,
@@ -101,8 +153,14 @@ static struct vendor_data vendor_arm = {
        .fixed_options          = false,
        .get_fifosize           = get_fifosize_arm,
 };
+#endif
 
 static struct vendor_data vendor_sbsa = {
+       .fr_busy                = UART01x_FR_BUSY,
+       .fr_dsr                 = UART01x_FR_DSR,
+       .fr_cts                 = UART01x_FR_CTS,
+       .fr_ri                  = UART011_FR_RI,
+       .reg_lut                = arm_reg,
        .oversampling           = false,
        .dma_threshold          = false,
        .cts_event_workaround   = false,
@@ -110,6 +168,26 @@ static struct vendor_data vendor_sbsa = {
        .fixed_options          = true,
 };
 
+#ifdef CONFIG_ARM_AMBA
+static u16 st_reg[] = {
+       [REG_DR]                = UART01x_DR,
+       [REG_RSR]               = UART01x_RSR,
+       [REG_ST_DMAWM]          = ST_UART011_DMAWM,
+       [REG_FR]                = UART01x_FR,
+       [REG_ST_LCRH_RX]        = ST_UART011_LCRH_RX,
+       [REG_ILPR]              = UART01x_ILPR,
+       [REG_IBRD]              = UART011_IBRD,
+       [REG_FBRD]              = UART011_FBRD,
+       [REG_LCRH]              = UART011_LCRH,
+       [REG_CR]                = UART011_CR,
+       [REG_IFLS]              = UART011_IFLS,
+       [REG_IMSC]              = UART011_IMSC,
+       [REG_RIS]               = UART011_RIS,
+       [REG_MIS]               = UART011_MIS,
+       [REG_ICR]               = UART011_ICR,
+       [REG_DMACR]             = UART011_DMACR,
+};
+
 static unsigned int get_fifosize_st(struct amba_device *dev)
 {
        return 64;
@@ -117,8 +195,13 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
 
 static struct vendor_data vendor_st = {
        .ifls                   = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
-       .lcrh_tx                = ST_UART011_LCRH_TX,
-       .lcrh_rx                = ST_UART011_LCRH_RX,
+       .fr_busy                = UART01x_FR_BUSY,
+       .fr_dsr                 = UART01x_FR_DSR,
+       .fr_cts                 = UART01x_FR_CTS,
+       .fr_ri                  = UART011_FR_RI,
+       .lcrh_tx                = REG_LCRH,
+       .lcrh_rx                = REG_ST_LCRH_RX,
+       .reg_lut                = st_reg,
        .oversampling           = true,
        .dma_threshold          = true,
        .cts_event_workaround   = true,
@@ -126,6 +209,43 @@ static struct vendor_data vendor_st = {
        .fixed_options          = false,
        .get_fifosize           = get_fifosize_st,
 };
+#endif
+
+#ifdef CONFIG_SOC_ZX296702
+static u16 zte_reg[] = {
+       [REG_DR]                = ZX_UART01x_DR,
+       [REG_RSR]               = UART01x_RSR,
+       [REG_ST_DMAWM]          = ST_UART011_DMAWM,
+       [REG_FR]                = ZX_UART01x_FR,
+       [REG_ST_LCRH_RX]        = ST_UART011_LCRH_RX,
+       [REG_ILPR]              = UART01x_ILPR,
+       [REG_IBRD]              = UART011_IBRD,
+       [REG_FBRD]              = UART011_FBRD,
+       [REG_LCRH]              = ZX_UART011_LCRH_TX,
+       [REG_CR]                = ZX_UART011_CR,
+       [REG_IFLS]              = ZX_UART011_IFLS,
+       [REG_IMSC]              = ZX_UART011_IMSC,
+       [REG_RIS]               = ZX_UART011_RIS,
+       [REG_MIS]               = ZX_UART011_MIS,
+       [REG_ICR]               = ZX_UART011_ICR,
+       [REG_DMACR]             = ZX_UART011_DMACR,
+};
+
+static struct vendor_data vendor_zte = {
+       .ifls                   = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+       .fr_busy                = ZX_UART01x_FR_BUSY,
+       .fr_dsr                 = ZX_UART01x_FR_DSR,
+       .fr_cts                 = ZX_UART01x_FR_CTS,
+       .fr_ri                  = ZX_UART011_FR_RI,
+       .lcrh_tx                = REG_LCRH,
+       .lcrh_rx                = REG_ST_LCRH_RX,
+       .reg_lut                = zte_reg,
+       .oversampling           = false,
+       .dma_threshold          = false,
+       .cts_event_workaround   = false,
+       .fixed_options          = false,
+};
+#endif
 
 /* Deals with DMA transactions */
 
@@ -164,10 +284,15 @@ struct uart_amba_port {
        struct uart_port        port;
        struct clk              *clk;
        const struct vendor_data *vendor;
+       u16                     *reg_lut;
        unsigned int            dmacr;          /* dma control reg */
        unsigned int            im;             /* interrupt mask */
        unsigned int            old_status;
        unsigned int            fifosize;       /* vendor-specific */
+       unsigned int            fr_busy;        /* vendor-specific */
+       unsigned int            fr_dsr;         /* vendor-specific */
+       unsigned int            fr_cts;         /* vendor-specific */
+       unsigned int            fr_ri;          /* vendor-specific */
        unsigned int            lcrh_tx;        /* vendor-specific */
        unsigned int            lcrh_rx;        /* vendor-specific */
        unsigned int            old_cr;         /* state during shutdown */
@@ -184,6 +309,29 @@ struct uart_amba_port {
 #endif
 };
 
+static bool is_implemented(struct uart_amba_port *uap, unsigned int reg)
+{
+       return uap->reg_lut[reg] != (u16)~0;
+}
+
+static unsigned int pl011_readw(struct uart_amba_port *uap, int index)
+{
+       WARN_ON(index > REG_NR);
+       return readw_relaxed(uap->port.membase + uap->reg_lut[index]);
+}
+
+static void pl011_writew(struct uart_amba_port *uap, int val, int index)
+{
+       WARN_ON(index > REG_NR);
+       writew_relaxed(val, uap->port.membase + uap->reg_lut[index]);
+}
+
+static void pl011_writeb(struct uart_amba_port *uap, u8 val, int index)
+{
+       WARN_ON(index > REG_NR);
+       writeb_relaxed(val, uap->port.membase + uap->reg_lut[index]);
+}
+
 /*
  * Reads up to 256 characters from the FIFO or until it's empty and
  * inserts them into the TTY layer. Returns the number of characters
@@ -196,12 +344,12 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
        int fifotaken = 0;
 
        while (max_count--) {
-               status = readw(uap->port.membase + UART01x_FR);
+               status = pl011_readw(uap, REG_FR);
                if (status & UART01x_FR_RXFE)
                        break;
 
                /* Take chars from the FIFO and update status */
-               ch = readw(uap->port.membase + UART01x_DR) |
+               ch = pl011_readw(uap, REG_DR) |
                        UART_DUMMY_DR_RX;
                flag = TTY_NORMAL;
                uap->port.icount.rx++;
@@ -284,7 +432,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
        struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
        struct device *dev = uap->port.dev;
        struct dma_slave_config tx_conf = {
-               .dst_addr = uap->port.mapbase + UART01x_DR,
+               .dst_addr = uap->port.mapbase + uap->reg_lut[REG_DR],
                .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
                .direction = DMA_MEM_TO_DEV,
                .dst_maxburst = uap->fifosize >> 1,
@@ -339,7 +487,7 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
 
        if (chan) {
                struct dma_slave_config rx_conf = {
-                       .src_addr = uap->port.mapbase + UART01x_DR,
+                       .src_addr = uap->port.mapbase + uap->reg_lut[REG_DR],
                        .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
                        .direction = DMA_DEV_TO_MEM,
                        .src_maxburst = uap->fifosize >> 2,
@@ -438,7 +586,7 @@ static void pl011_dma_tx_callback(void *data)
 
        dmacr = uap->dmacr;
        uap->dmacr = dmacr & ~UART011_TXDMAE;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
 
        /*
         * If TX DMA was disabled, it means that we've stopped the DMA for
@@ -552,7 +700,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
        dma_dev->device_issue_pending(chan);
 
        uap->dmacr |= UART011_TXDMAE;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
        uap->dmatx.queued = true;
 
        /*
@@ -588,9 +736,9 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
         */
        if (uap->dmatx.queued) {
                uap->dmacr |= UART011_TXDMAE;
-               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+               pl011_writew(uap, uap->dmacr, REG_DMACR);
                uap->im &= ~UART011_TXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
+               pl011_writew(uap, uap->im, REG_IMSC);
                return true;
        }
 
@@ -600,7 +748,7 @@ static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
         */
        if (pl011_dma_tx_refill(uap) > 0) {
                uap->im &= ~UART011_TXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
+               pl011_writew(uap, uap->im, REG_IMSC);
                return true;
        }
        return false;
@@ -614,7 +762,7 @@ static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
 {
        if (uap->dmatx.queued) {
                uap->dmacr &= ~UART011_TXDMAE;
-               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+               pl011_writew(uap, uap->dmacr, REG_DMACR);
        }
 }
 
@@ -640,14 +788,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
                if (!uap->dmatx.queued) {
                        if (pl011_dma_tx_refill(uap) > 0) {
                                uap->im &= ~UART011_TXIM;
-                               writew(uap->im, uap->port.membase +
-                                      UART011_IMSC);
+                               pl011_writew(uap, uap->im, REG_IMSC);
                        } else
                                ret = false;
                } else if (!(uap->dmacr & UART011_TXDMAE)) {
                        uap->dmacr |= UART011_TXDMAE;
-                       writew(uap->dmacr,
-                                      uap->port.membase + UART011_DMACR);
+                       pl011_writew(uap, uap->dmacr, REG_DMACR);
                }
                return ret;
        }
@@ -658,9 +804,9 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
         */
        dmacr = uap->dmacr;
        uap->dmacr &= ~UART011_TXDMAE;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
 
-       if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+       if (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) {
                /*
                 * No space in the FIFO, so enable the transmit interrupt
                 * so we know when there is space.  Note that once we've
@@ -669,13 +815,13 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
                return false;
        }
 
-       writew(uap->port.x_char, uap->port.membase + UART01x_DR);
+       pl011_writew(uap, uap->port.x_char, REG_DR);
        uap->port.icount.tx++;
        uap->port.x_char = 0;
 
        /* Success - restore the DMA state */
        uap->dmacr = dmacr;
-       writew(dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, dmacr, REG_DMACR);
 
        return true;
 }
@@ -703,7 +849,7 @@ __acquires(&uap->port.lock)
                             DMA_TO_DEVICE);
                uap->dmatx.queued = false;
                uap->dmacr &= ~UART011_TXDMAE;
-               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+               pl011_writew(uap, uap->dmacr, REG_DMACR);
        }
 }
 
@@ -743,11 +889,11 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
        dma_async_issue_pending(rxchan);
 
        uap->dmacr |= UART011_RXDMAE;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
        uap->dmarx.running = true;
 
        uap->im &= ~UART011_RXIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
 
        return 0;
 }
@@ -805,8 +951,9 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
         */
        if (dma_count == pending && readfifo) {
                /* Clear any error flags */
-               writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
-                      uap->port.membase + UART011_ICR);
+               pl011_writew(uap,
+                            UART011_OEIS | UART011_BEIS | UART011_PEIS
+                            | UART011_FEIS, REG_ICR);
 
                /*
                 * If we read all the DMA'd characters, and we had an
@@ -854,7 +1001,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
 
        /* Disable RX DMA - incoming data will wait in the FIFO */
        uap->dmacr &= ~UART011_RXDMAE;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
        uap->dmarx.running = false;
 
        pending = sgbuf->sg.length - state.residue;
@@ -874,7 +1021,7 @@ static void pl011_dma_rx_irq(struct uart_amba_port *uap)
                dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
                        "fall back to interrupt mode\n");
                uap->im |= UART011_RXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
+               pl011_writew(uap, uap->im, REG_IMSC);
        }
 }
 
@@ -922,7 +1069,7 @@ static void pl011_dma_rx_callback(void *data)
                dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
                        "fall back to interrupt mode\n");
                uap->im |= UART011_RXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
+               pl011_writew(uap, uap->im, REG_IMSC);
        }
 }
 
@@ -935,7 +1082,7 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
 {
        /* FIXME.  Just disable the DMA enable */
        uap->dmacr &= ~UART011_RXDMAE;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
 }
 
 /*
@@ -979,7 +1126,7 @@ static void pl011_dma_rx_poll(unsigned long args)
                spin_lock_irqsave(&uap->port.lock, flags);
                pl011_dma_rx_stop(uap);
                uap->im |= UART011_RXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
+               pl011_writew(uap, uap->im, REG_IMSC);
                spin_unlock_irqrestore(&uap->port.lock, flags);
 
                uap->dmarx.running = false;
@@ -1041,7 +1188,7 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 skip_rx:
        /* Turn on DMA error (RX/TX will be enabled on demand) */
        uap->dmacr |= UART011_DMAONERR;
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
 
        /*
         * ST Micro variants has some specific dma burst threshold
@@ -1049,8 +1196,9 @@ skip_rx:
         * be issued above/below 16 bytes.
         */
        if (uap->vendor->dma_threshold)
-               writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
-                              uap->port.membase + ST_UART011_DMAWM);
+               pl011_writew(uap,
+                            ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
+                            REG_ST_DMAWM);
 
        if (uap->using_rx_dma) {
                if (pl011_dma_rx_trigger_dma(uap))
@@ -1075,12 +1223,12 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
                return;
 
        /* Disable RX and TX DMA */
-       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
+       while (pl011_readw(uap, REG_FR) & uap->fr_busy)
                barrier();
 
        spin_lock_irq(&uap->port.lock);
        uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
-       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       pl011_writew(uap, uap->dmacr, REG_DMACR);
        spin_unlock_irq(&uap->port.lock);
 
        if (uap->using_tx_dma) {
@@ -1181,7 +1329,7 @@ static void pl011_stop_tx(struct uart_port *port)
            container_of(port, struct uart_amba_port, port);
 
        uap->im &= ~UART011_TXIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
        pl011_dma_tx_stop(uap);
 }
 
@@ -1191,7 +1339,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
        uap->im |= UART011_TXIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
        pl011_tx_chars(uap, false);
 }
 
@@ -1211,7 +1359,7 @@ static void pl011_stop_rx(struct uart_port *port)
 
        uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
                     UART011_PEIM|UART011_BEIM|UART011_OEIM);
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
 
        pl011_dma_rx_stop(uap);
 }
@@ -1222,7 +1370,7 @@ static void pl011_enable_ms(struct uart_port *port)
            container_of(port, struct uart_amba_port, port);
 
        uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
 }
 
 static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1242,7 +1390,7 @@ __acquires(&uap->port.lock)
                        dev_dbg(uap->port.dev, "could not trigger RX DMA job "
                                "fall back to interrupt mode again\n");
                        uap->im |= UART011_RXIM;
-                       writew(uap->im, uap->port.membase + UART011_IMSC);
+                       pl011_writew(uap, uap->im, REG_IMSC);
                } else {
 #ifdef CONFIG_DMA_ENGINE
                        /* Start Rx DMA poll */
@@ -1263,10 +1411,10 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
                          bool from_irq)
 {
        if (unlikely(!from_irq) &&
-           readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+           pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
                return false; /* unable to transmit character */
 
-       writew(c, uap->port.membase + UART01x_DR);
+       pl011_writew(uap, c, REG_DR);
        uap->port.icount.tx++;
 
        return true;
@@ -1313,7 +1461,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 {
        unsigned int status, delta;
 
-       status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
+       status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY;
 
        delta = status ^ uap->old_status;
        uap->old_status = status;
@@ -1324,11 +1472,11 @@ static void pl011_modem_status(struct uart_amba_port *uap)
        if (delta & UART01x_FR_DCD)
                uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
 
-       if (delta & UART01x_FR_DSR)
+       if (delta & uap->fr_dsr)
                uap->port.icount.dsr++;
 
-       if (delta & UART01x_FR_CTS)
-               uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
+       if (delta & uap->fr_cts)
+               uart_handle_cts_change(&uap->port, status & uap->fr_cts);
 
        wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 }
@@ -1341,15 +1489,15 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
                return;
 
        /* workaround to make sure that all bits are unlocked.. */
-       writew(0x00, uap->port.membase + UART011_ICR);
+       pl011_writew(uap, 0x00, REG_ICR);
 
        /*
         * WA: introduce 26ns(1 uart clk) delay before W1C;
         * single apb access will incur 2 pclk(133.12Mhz) delay,
         * so add 2 dummy reads
         */
-       dummy_read = readw(uap->port.membase + UART011_ICR);
-       dummy_read = readw(uap->port.membase + UART011_ICR);
+       dummy_read = pl011_readw(uap, REG_ICR);
+       dummy_read = pl011_readw(uap, REG_ICR);
 }
 
 static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1361,15 +1509,13 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
        int handled = 0;
 
        spin_lock_irqsave(&uap->port.lock, flags);
-       imsc = readw(uap->port.membase + UART011_IMSC);
-       status = readw(uap->port.membase + UART011_RIS) & imsc;
+       imsc = pl011_readw(uap, REG_IMSC);
+       status = pl011_readw(uap, REG_RIS) & imsc;
        if (status) {
                do {
                        check_apply_cts_event_workaround(uap);
-
-                       writew(status & ~(UART011_TXIS|UART011_RTIS|
-                                         UART011_RXIS),
-                              uap->port.membase + UART011_ICR);
+                       pl011_writew(uap, status & ~(UART011_TXIS|UART011_RTIS|
+                                    UART011_RXIS), REG_ICR);
 
                        if (status & (UART011_RTIS|UART011_RXIS)) {
                                if (pl011_dma_rx_running(uap))
@@ -1386,7 +1532,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
                        if (pass_counter-- == 0)
                                break;
 
-                       status = readw(uap->port.membase + UART011_RIS) & imsc;
+                       status = pl011_readw(uap, REG_RIS) & imsc;
                } while (status != 0);
                handled = 1;
        }
@@ -1400,8 +1546,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
-       unsigned int status = readw(uap->port.membase + UART01x_FR);
-       return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
+       unsigned int status = pl011_readw(uap, REG_FR);
+       return status & (uap->fr_busy|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
 }
 
 static unsigned int pl011_get_mctrl(struct uart_port *port)
@@ -1409,16 +1555,16 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
        unsigned int result = 0;
-       unsigned int status = readw(uap->port.membase + UART01x_FR);
+       unsigned int status = pl011_readw(uap, REG_FR);
 
 #define TIOCMBIT(uartbit, tiocmbit)    \
        if (status & uartbit)           \
                result |= tiocmbit
 
        TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
-       TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
-       TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
-       TIOCMBIT(UART011_FR_RI, TIOCM_RNG);
+       TIOCMBIT(uap->fr_dsr, TIOCM_DSR);
+       TIOCMBIT(uap->fr_cts, TIOCM_CTS);
+       TIOCMBIT(uap->fr_ri, TIOCM_RNG);
 #undef TIOCMBIT
        return result;
 }
@@ -1429,7 +1575,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
            container_of(port, struct uart_amba_port, port);
        unsigned int cr;
 
-       cr = readw(uap->port.membase + UART011_CR);
+       cr = pl011_readw(uap, REG_CR);
 
 #define        TIOCMBIT(tiocmbit, uartbit)             \
        if (mctrl & tiocmbit)           \
@@ -1449,7 +1595,7 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
        }
 #undef TIOCMBIT
 
-       writew(cr, uap->port.membase + UART011_CR);
+       pl011_writew(uap, cr, REG_CR);
 }
 
 static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1460,12 +1606,12 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
        unsigned int lcr_h;
 
        spin_lock_irqsave(&uap->port.lock, flags);
-       lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+       lcr_h = pl011_readw(uap, uap->lcrh_tx);
        if (break_state == -1)
                lcr_h |= UART01x_LCRH_BRK;
        else
                lcr_h &= ~UART01x_LCRH_BRK;
-       writew(lcr_h, uap->port.membase + uap->lcrh_tx);
+       pl011_writew(uap, lcr_h, uap->lcrh_tx);
        spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -1475,9 +1621,8 @@ static void pl011_quiesce_irqs(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
-       unsigned char __iomem *regs = uap->port.membase;
 
-       writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+       pl011_writew(uap, pl011_readw(uap, REG_MIS), REG_ICR);
        /*
         * There is no way to clear TXIM as this is "ready to transmit IRQ", so
         * we simply mask it. start_tx() will unmask it.
@@ -1491,7 +1636,7 @@ static void pl011_quiesce_irqs(struct uart_port *port)
         * (including tx queue), so we're also fine with start_tx()'s caller
         * side.
         */
-       writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC);
+       pl011_writew(uap, pl011_readw(uap, REG_IMSC) & ~UART011_TXIM, REG_IMSC);
 }
 
 static int pl011_get_poll_char(struct uart_port *port)
@@ -1506,11 +1651,11 @@ static int pl011_get_poll_char(struct uart_port *port)
         */
        pl011_quiesce_irqs(port);
 
-       status = readw(uap->port.membase + UART01x_FR);
+       status = pl011_readw(uap, REG_FR);
        if (status & UART01x_FR_RXFE)
                return NO_POLL_CHAR;
 
-       return readw(uap->port.membase + UART01x_DR);
+       return pl011_readw(uap, REG_DR);
 }
 
 static void pl011_put_poll_char(struct uart_port *port,
@@ -1519,10 +1664,10 @@ static void pl011_put_poll_char(struct uart_port *port,
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
 
-       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+       while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
                barrier();
 
-       writew(ch, uap->port.membase + UART01x_DR);
+       pl011_writew(uap, ch, REG_DR);
 }
 
 #endif /* CONFIG_CONSOLE_POLL */
@@ -1546,15 +1691,15 @@ static int pl011_hwinit(struct uart_port *port)
        uap->port.uartclk = clk_get_rate(uap->clk);
 
        /* Clear pending error and receive interrupts */
-       writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
-              UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+       pl011_writew(uap, UART011_OEIS | UART011_BEIS | UART011_PEIS |
+                    UART011_FEIS | UART011_RTIS | UART011_RXIS, REG_ICR);
 
        /*
         * Save interrupts enable mask, and enable RX interrupts in case if
         * the interrupt is used for NMI entry.
         */
-       uap->im = readw(uap->port.membase + UART011_IMSC);
-       writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
+       uap->im = pl011_readw(uap, REG_IMSC);
+       pl011_writew(uap, UART011_RTIM | UART011_RXIM, REG_IMSC);
 
        if (dev_get_platdata(uap->port.dev)) {
                struct amba_pl011_data *plat;
@@ -1568,22 +1713,22 @@ static int pl011_hwinit(struct uart_port *port)
 
 static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
 {
-       writew(lcr_h, uap->port.membase + uap->lcrh_rx);
-       if (uap->lcrh_rx != uap->lcrh_tx) {
+       pl011_writew(uap, lcr_h, uap->lcrh_rx);
+       if (is_implemented(uap, REG_ST_LCRH_RX)) {
                int i;
                /*
                 * Wait 10 PCLKs before writing LCRH_TX register,
                 * to get this delay write read only register 10 times
                 */
                for (i = 0; i < 10; ++i)
-                       writew(0xff, uap->port.membase + UART011_MIS);
-               writew(lcr_h, uap->port.membase + uap->lcrh_tx);
+                       pl011_writew(uap, 0xff, REG_MIS);
+               pl011_writew(uap, lcr_h, uap->lcrh_tx);
        }
 }
 
 static int pl011_allocate_irq(struct uart_amba_port *uap)
 {
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
 
        return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
 }
@@ -1598,12 +1743,11 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
        spin_lock_irq(&uap->port.lock);
 
        /* Clear out any spuriously appearing RX interrupts */
-       writew(UART011_RTIS | UART011_RXIS,
-              uap->port.membase + UART011_ICR);
+       pl011_writew(uap, UART011_RTIS | UART011_RXIS, REG_ICR);
        uap->im = UART011_RTIM;
        if (!pl011_dma_rx_running(uap))
                uap->im |= UART011_RXIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_writew(uap, uap->im, REG_IMSC);
        spin_unlock_irq(&uap->port.lock);
 }
 
@@ -1622,21 +1766,21 @@ static int pl011_startup(struct uart_port *port)
        if (retval)
                goto clk_dis;
 
-       writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+       pl011_writew(uap, uap->vendor->ifls, REG_IFLS);
 
        spin_lock_irq(&uap->port.lock);
 
        /* restore RTS and DTR */
        cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
        cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
-       writew(cr, uap->port.membase + UART011_CR);
+       pl011_writew(uap, cr, REG_CR);
 
        spin_unlock_irq(&uap->port.lock);
 
        /*
         * initialise the old status of the modem signals
         */
-       uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
+       uap->old_status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY;
 
        /* Startup DMA */
        pl011_dma_startup(uap);
@@ -1675,11 +1819,11 @@ static int sbsa_uart_startup(struct uart_port *port)
 static void pl011_shutdown_channel(struct uart_amba_port *uap,
                                        unsigned int lcrh)
 {
-      unsigned long val;
+       unsigned long val;
 
-      val = readw(uap->port.membase + lcrh);
-      val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
-      writew(val, uap->port.membase + lcrh);
+       val = pl011_readw(uap, lcrh);
+       val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
+       pl011_writew(uap, val, lcrh);
 }
 
 /*
@@ -1693,18 +1837,18 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
 
        uap->autorts = false;
        spin_lock_irq(&uap->port.lock);
-       cr = readw(uap->port.membase + UART011_CR);
+       cr = pl011_readw(uap, REG_CR);
        uap->old_cr = cr;
        cr &= UART011_CR_RTS | UART011_CR_DTR;
        cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-       writew(cr, uap->port.membase + UART011_CR);
+       pl011_writew(uap, cr, REG_CR);
        spin_unlock_irq(&uap->port.lock);
 
        /*
         * disable break condition and fifos
         */
        pl011_shutdown_channel(uap, uap->lcrh_rx);
-       if (uap->lcrh_rx != uap->lcrh_tx)
+       if (is_implemented(uap, REG_ST_LCRH_RX))
                pl011_shutdown_channel(uap, uap->lcrh_tx);
 }
 
@@ -1714,8 +1858,8 @@ static void pl011_disable_interrupts(struct uart_amba_port *uap)
 
        /* mask all interrupts and clear all pending ones */
        uap->im = 0;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
-       writew(0xffff, uap->port.membase + UART011_ICR);
+       pl011_writew(uap, uap->im, REG_IMSC);
+       pl011_writew(uap, 0xffff, REG_ICR);
 
        spin_unlock_irq(&uap->port.lock);
 }
@@ -1867,8 +2011,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
                pl011_enable_ms(port);
 
        /* first, disable everything */
-       old_cr = readw(port->membase + UART011_CR);
-       writew(0, port->membase + UART011_CR);
+       old_cr = pl011_readw(uap, REG_CR);
+       pl011_writew(uap, 0, REG_CR);
 
        if (termios->c_cflag & CRTSCTS) {
                if (old_cr & UART011_CR_RTS)
@@ -1901,17 +2045,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
                        quot -= 2;
        }
        /* Set baud rate */
-       writew(quot & 0x3f, port->membase + UART011_FBRD);
-       writew(quot >> 6, port->membase + UART011_IBRD);
+       pl011_writew(uap, quot & 0x3f, REG_FBRD);
+       pl011_writew(uap, quot >> 6, REG_IBRD);
 
        /*
         * ----------v----------v----------v----------v-----
         * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
-        * UART011_FBRD & UART011_IBRD.
+        * REG_FBRD & REG_IBRD.
         * ----------^----------^----------^----------^-----
         */
        pl011_write_lcr_h(uap, lcr_h);
-       writew(old_cr, port->membase + UART011_CR);
+       pl011_writew(uap, old_cr, REG_CR);
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -2052,9 +2196,9 @@ static void pl011_console_putchar(struct uart_port *port, int ch)
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
 
-       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+       while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
                barrier();
-       writew(ch, uap->port.membase + UART01x_DR);
+       pl011_writew(uap, ch, REG_DR);
 }
 
 static void
@@ -2079,10 +2223,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
         *      First save the CR then disable the interrupts
         */
        if (!uap->vendor->always_enabled) {
-               old_cr = readw(uap->port.membase + UART011_CR);
+               old_cr = pl011_readw(uap, REG_CR);
                new_cr = old_cr & ~UART011_CR_CTSEN;
                new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
-               writew(new_cr, uap->port.membase + UART011_CR);
+               pl011_writew(uap, new_cr, REG_CR);
        }
 
        uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2092,10 +2236,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
         *      and restore the TCR
         */
        do {
-               status = readw(uap->port.membase + UART01x_FR);
-       } while (status & UART01x_FR_BUSY);
+               status = pl011_readw(uap, REG_FR);
+       } while (status & uap->fr_busy);
        if (!uap->vendor->always_enabled)
-               writew(old_cr, uap->port.membase + UART011_CR);
+               pl011_writew(uap, old_cr, REG_CR);
 
        if (locked)
                spin_unlock(&uap->port.lock);
@@ -2108,10 +2252,10 @@ static void __init
 pl011_console_get_options(struct uart_amba_port *uap, int *baud,
                             int *parity, int *bits)
 {
-       if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
+       if (pl011_readw(uap, REG_CR) & UART01x_CR_UARTEN) {
                unsigned int lcr_h, ibrd, fbrd;
 
-               lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+               lcr_h = pl011_readw(uap, uap->lcrh_tx);
 
                *parity = 'n';
                if (lcr_h & UART01x_LCRH_PEN) {
@@ -2126,13 +2270,13 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
                else
                        *bits = 8;
 
-               ibrd = readw(uap->port.membase + UART011_IBRD);
-               fbrd = readw(uap->port.membase + UART011_FBRD);
+               ibrd = pl011_readw(uap, REG_IBRD);
+               fbrd = pl011_readw(uap, REG_FBRD);
 
                *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
                if (uap->vendor->oversampling) {
-                       if (readw(uap->port.membase + UART011_CR)
+                       if (pl011_readw(uap, REG_CR)
                                  & ST_UART011_CR_OVSFACT)
                                *baud *= 2;
                }
@@ -2204,10 +2348,13 @@ static struct console amba_console = {
 
 static void pl011_putc(struct uart_port *port, int c)
 {
-       while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
+       struct uart_amba_port *uap =
+           container_of(port, struct uart_amba_port, port);
+
+       while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
                ;
-       writeb(c, port->membase + UART01x_DR);
-       while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
+       pl011_writeb(uap, c, REG_DR);
+       while (pl011_readw(uap, REG_FR) & uap->fr_busy)
                ;
 }
 
@@ -2334,8 +2481,8 @@ static int pl011_register_port(struct uart_amba_port *uap)
        int ret;
 
        /* Ensure interrupts from this UART are masked and cleared */
-       writew(0, uap->port.membase + UART011_IMSC);
-       writew(0xffff, uap->port.membase + UART011_ICR);
+       pl011_writew(uap, 0, REG_IMSC);
+       pl011_writew(uap, 0xffff, REG_ICR);
 
        if (!amba_reg.state) {
                ret = uart_register_driver(&amba_reg);
@@ -2353,6 +2500,7 @@ static int pl011_register_port(struct uart_amba_port *uap)
        return ret;
 }
 
+#ifdef CONFIG_ARM_AMBA
 static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 {
        struct uart_amba_port *uap;
@@ -2373,8 +2521,13 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
                return PTR_ERR(uap->clk);
 
        uap->vendor = vendor;
+       uap->reg_lut = vendor->reg_lut;
        uap->lcrh_rx = vendor->lcrh_rx;
        uap->lcrh_tx = vendor->lcrh_tx;
+       uap->fr_busy = vendor->fr_busy;
+       uap->fr_dsr = vendor->fr_dsr;
+       uap->fr_cts = vendor->fr_cts;
+       uap->fr_ri = vendor->fr_ri;
        uap->fifosize = vendor->get_fifosize(dev);
        uap->port.irq = dev->irq[0];
        uap->port.ops = &amba_pl011_pops;
@@ -2398,6 +2551,67 @@ static int pl011_remove(struct amba_device *dev)
        pl011_unregister_port(uap);
        return 0;
 }
+#endif
+
+#ifdef CONFIG_SOC_ZX296702
+static int zx_uart_probe(struct platform_device *pdev)
+{
+       struct uart_amba_port *uap;
+       struct vendor_data *vendor = &vendor_zte;
+       struct resource *res;
+       int portnr, ret;
+
+       portnr = pl011_find_free_port();
+       if (portnr < 0)
+               return portnr;
+
+       uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port),
+                       GFP_KERNEL);
+       if (!uap) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       uap->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(uap->clk)) {
+               ret = PTR_ERR(uap->clk);
+               goto out;
+       }
+
+       uap->vendor     = vendor;
+       uap->reg_lut    = vendor->reg_lut;
+       uap->lcrh_rx    = vendor->lcrh_rx;
+       uap->lcrh_tx    = vendor->lcrh_tx;
+       uap->fr_busy    = vendor->fr_busy;
+       uap->fr_dsr     = vendor->fr_dsr;
+       uap->fr_cts     = vendor->fr_cts;
+       uap->fr_ri      = vendor->fr_ri;
+       uap->fifosize   = 16;
+       uap->port.irq   = platform_get_irq(pdev, 0);
+       uap->port.ops   = &amba_pl011_pops;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       ret = pl011_setup_port(&pdev->dev, uap, res, portnr);
+       if (ret)
+               return ret;
+
+       platform_set_drvdata(pdev, uap);
+
+       return pl011_register_port(uap);
+out:
+       return ret;
+}
+
+static int zx_uart_remove(struct platform_device *pdev)
+{
+       struct uart_amba_port *uap = platform_get_drvdata(pdev);
+
+       uart_remove_one_port(&amba_reg, &uap->port);
+       pl011_unregister_port(uap);
+       return 0;
+}
+#endif
 
 #ifdef CONFIG_PM_SLEEP
 static int pl011_suspend(struct device *dev)
@@ -2454,6 +2668,11 @@ static int sbsa_uart_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        uap->vendor     = &vendor_sbsa;
+       uap->reg_lut    = vendor_sbsa.reg_lut;
+       uap->fr_busy    = vendor_sbsa.fr_busy;
+       uap->fr_dsr     = vendor_sbsa.fr_dsr;
+       uap->fr_cts     = vendor_sbsa.fr_cts;
+       uap->fr_ri      = vendor_sbsa.fr_ri;
        uap->fifosize   = 32;
        uap->port.irq   = platform_get_irq(pdev, 0);
        uap->port.ops   = &sbsa_uart_pops;
@@ -2503,6 +2722,7 @@ static struct platform_driver arm_sbsa_uart_platform_driver = {
        },
 };
 
+#ifdef CONFIG_ARM_AMBA
 static struct amba_id pl011_ids[] = {
        {
                .id     = 0x00041011,
@@ -2528,20 +2748,57 @@ static struct amba_driver pl011_driver = {
        .probe          = pl011_probe,
        .remove         = pl011_remove,
 };
+#endif
+
+#ifdef CONFIG_SOC_ZX296702
+static const struct of_device_id zx_uart_dt_ids[] = {
+       { .compatible = "zte,zx296702-uart", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, zx_uart_dt_ids);
+
+static struct platform_driver zx_uart_driver = {
+       .driver = {
+               .name   = "zx-uart",
+               .owner  = THIS_MODULE,
+               .pm     = &pl011_dev_pm_ops,
+               .of_match_table = zx_uart_dt_ids,
+       },
+       .probe          = zx_uart_probe,
+       .remove         = zx_uart_remove,
+};
+#endif
+
 
 static int __init pl011_init(void)
 {
+       int ret;
        printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
 
        if (platform_driver_register(&arm_sbsa_uart_platform_driver))
                pr_warn("could not register SBSA UART platform driver\n");
-       return amba_driver_register(&pl011_driver);
+
+#ifdef CONFIG_SOC_ZX296702
+       ret = platform_driver_register(&zx_uart_driver);
+       if (ret)
+               pr_warn("could not register ZX UART platform driver\n");
+#endif
+
+#ifdef CONFIG_ARM_AMBA
+       ret = amba_driver_register(&pl011_driver);
+#endif
+       return ret;
 }
 
 static void __exit pl011_exit(void)
 {
        platform_driver_unregister(&arm_sbsa_uart_platform_driver);
+#ifdef CONFIG_SOC_ZX296702
+       platform_driver_unregister(&zx_uart_driver);
+#endif
+#ifdef CONFIG_ARM_AMBA
        amba_driver_unregister(&pl011_driver);
+#endif
 }
 
 /*
index 2a8f528153e7cf51d7ff947592b4a607a70d6304..5ca5cf3e9359cf17f9a3aaebbff028ecada3a910 100644 (file)
 /* Revisit: We should calculate this based on the actual port settings */
 #define PDC_RX_TIMEOUT         (3 * 10)                /* 3 bytes */
 
+/* The minium number of data FIFOs should be able to contain */
+#define ATMEL_MIN_FIFO_SIZE    8
+/*
+ * These two offsets are substracted from the RX FIFO size to define the RTS
+ * high and low thresholds
+ */
+#define ATMEL_RTS_HIGH_OFFSET  16
+#define ATMEL_RTS_LOW_OFFSET   20
+
 #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -88,37 +97,6 @@ static void atmel_stop_rx(struct uart_port *port);
 
 #define ATMEL_ISR_PASS_LIMIT   256
 
-/* UART registers. CR is write-only, hence no GET macro */
-#define UART_PUT_CR(port,v)    __raw_writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port)      __raw_readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v)    __raw_writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v)   __raw_writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v)   __raw_writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port)     __raw_readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port)     __raw_readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port)    __raw_readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v)  __raw_writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port)    __raw_readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v)  __raw_writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v)  __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
-#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
-#define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME)
-#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
-
- /* PDC registers */
-#define UART_PUT_PTCR(port,v)  __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port)    __raw_readl((port)->membase + ATMEL_PDC_PTSR)
-
-#define UART_PUT_RPR(port,v)   __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port)     __raw_readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v)   __raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v)  __raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v)  __raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
-
-#define UART_PUT_TPR(port,v)   __raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v)   __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
-#define UART_GET_TCR(port)     __raw_readl((port)->membase + ATMEL_PDC_TCR)
-
 struct atmel_dma_buffer {
        unsigned char   *buf;
        dma_addr_t      dma_addr;
@@ -166,12 +144,16 @@ struct atmel_uart_port {
        unsigned int            irq_status;
        unsigned int            irq_status_prev;
        unsigned int            status_change;
+       unsigned int            tx_len;
 
        struct circ_buf         rx_ring;
 
        struct mctrl_gpios      *gpios;
        int                     gpio_irq[UART_GPIO_MAX];
        unsigned int            tx_done_mask;
+       u32                     fifo_size;
+       u32                     rts_high;
+       u32                     rts_low;
        bool                    ms_irq_enabled;
        bool                    is_usart;       /* usart or uart */
        struct timer_list       uart_timer;     /* uart timer */
@@ -212,6 +194,43 @@ to_atmel_uart_port(struct uart_port *uart)
        return container_of(uart, struct atmel_uart_port, uart);
 }
 
+static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
+{
+       return __raw_readl(port->membase + reg);
+}
+
+static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
+{
+       __raw_writel(value, port->membase + reg);
+}
+
+#ifdef CONFIG_AVR32
+
+/* AVR32 cannot handle 8 or 16bit I/O accesses but only 32bit I/O accesses */
+static inline u8 atmel_uart_read_char(struct uart_port *port)
+{
+       return __raw_readl(port->membase + ATMEL_US_RHR);
+}
+
+static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
+{
+       __raw_writel(value, port->membase + ATMEL_US_THR);
+}
+
+#else
+
+static inline u8 atmel_uart_read_char(struct uart_port *port)
+{
+       return __raw_readb(port->membase + ATMEL_US_RHR);
+}
+
+static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
+{
+       __raw_writeb(value, port->membase + ATMEL_US_THR);
+}
+
+#endif
+
 #ifdef CONFIG_SERIAL_ATMEL_PDC
 static bool atmel_use_pdc_rx(struct uart_port *port)
 {
@@ -257,7 +276,7 @@ static unsigned int atmel_get_lines_status(struct uart_port *port)
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
        unsigned int status, ret = 0;
 
-       status = UART_GET_CSR(port);
+       status = atmel_uart_readl(port, ATMEL_US_CSR);
 
        mctrl_gpio_get(atmel_port->gpios, &ret);
 
@@ -304,9 +323,9 @@ static int atmel_config_rs485(struct uart_port *port,
        unsigned int mode;
 
        /* Disable interrupts */
-       UART_PUT_IDR(port, atmel_port->tx_done_mask);
+       atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
-       mode = UART_GET_MR(port);
+       mode = atmel_uart_readl(port, ATMEL_US_MR);
 
        /* Resetting serial mode to RS232 (0x0) */
        mode &= ~ATMEL_US_USMODE;
@@ -316,7 +335,8 @@ static int atmel_config_rs485(struct uart_port *port,
        if (rs485conf->flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
                atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-               UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+               atmel_uart_writel(port, ATMEL_US_TTGR,
+                                 rs485conf->delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else {
                dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -326,10 +346,10 @@ static int atmel_config_rs485(struct uart_port *port,
                else
                        atmel_port->tx_done_mask = ATMEL_US_TXRDY;
        }
-       UART_PUT_MR(port, mode);
+       atmel_uart_writel(port, ATMEL_US_MR, mode);
 
        /* Enable interrupts */
-       UART_PUT_IER(port, atmel_port->tx_done_mask);
+       atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 
        return 0;
 }
@@ -339,7 +359,9 @@ static int atmel_config_rs485(struct uart_port *port,
  */
 static u_int atmel_tx_empty(struct uart_port *port)
 {
-       return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+       return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
+               TIOCSER_TEMT :
+               0;
 }
 
 /*
@@ -348,13 +370,14 @@ static u_int atmel_tx_empty(struct uart_port *port)
 static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 {
        unsigned int control = 0;
-       unsigned int mode = UART_GET_MR(port);
+       unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
        unsigned int rts_paused, rts_ready;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
        /* override mode to RS485 if needed, otherwise keep the current mode */
        if (port->rs485.flags & SER_RS485_ENABLED) {
-               UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+               atmel_uart_writel(port, ATMEL_US_TTGR,
+                                 port->rs485.delay_rts_after_send);
                mode &= ~ATMEL_US_USMODE;
                mode |= ATMEL_US_USMODE_RS485;
        }
@@ -384,7 +407,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
        else
                control |= ATMEL_US_DTRDIS;
 
-       UART_PUT_CR(port, control);
+       atmel_uart_writel(port, ATMEL_US_CR, control);
 
        mctrl_gpio_set(atmel_port->gpios, mctrl);
 
@@ -395,7 +418,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
        else
                mode |= ATMEL_US_CHMODE_NORMAL;
 
-       UART_PUT_MR(port, mode);
+       atmel_uart_writel(port, ATMEL_US_MR, mode);
 }
 
 /*
@@ -406,7 +429,7 @@ static u_int atmel_get_mctrl(struct uart_port *port)
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
        unsigned int ret = 0, status;
 
-       status = UART_GET_CSR(port);
+       status = atmel_uart_readl(port, ATMEL_US_CSR);
 
        /*
         * The control signals are active low.
@@ -432,10 +455,10 @@ static void atmel_stop_tx(struct uart_port *port)
 
        if (atmel_use_pdc_tx(port)) {
                /* disable PDC transmit */
-               UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
        }
        /* Disable interrupts */
-       UART_PUT_IDR(port, atmel_port->tx_done_mask);
+       atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
        if ((port->rs485.flags & SER_RS485_ENABLED) &&
            !(port->rs485.flags & SER_RS485_RX_DURING_TX))
@@ -450,7 +473,7 @@ static void atmel_start_tx(struct uart_port *port)
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
        if (atmel_use_pdc_tx(port)) {
-               if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+               if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
                        /* The transmitter is already running.  Yes, we
                           really need this.*/
                        return;
@@ -460,10 +483,10 @@ static void atmel_start_tx(struct uart_port *port)
                        atmel_stop_rx(port);
 
                /* re-enable PDC transmit */
-               UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
        }
        /* Enable interrupts */
-       UART_PUT_IER(port, atmel_port->tx_done_mask);
+       atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 }
 
 /*
@@ -471,17 +494,19 @@ static void atmel_start_tx(struct uart_port *port)
  */
 static void atmel_start_rx(struct uart_port *port)
 {
-       UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
+       /* reset status and receiver */
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
-       UART_PUT_CR(port, ATMEL_US_RXEN);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
 
        if (atmel_use_pdc_rx(port)) {
                /* enable PDC controller */
-               UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-                       port->read_status_mask);
-               UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+               atmel_uart_writel(port, ATMEL_US_IER,
+                                 ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+                                 port->read_status_mask);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
        } else {
-               UART_PUT_IER(port, ATMEL_US_RXRDY);
+               atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
        }
 }
 
@@ -490,15 +515,16 @@ static void atmel_start_rx(struct uart_port *port)
  */
 static void atmel_stop_rx(struct uart_port *port)
 {
-       UART_PUT_CR(port, ATMEL_US_RXDIS);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
 
        if (atmel_use_pdc_rx(port)) {
                /* disable PDC receive */
-               UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
-               UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
-                       port->read_status_mask);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
+               atmel_uart_writel(port, ATMEL_US_IDR,
+                                 ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+                                 port->read_status_mask);
        } else {
-               UART_PUT_IDR(port, ATMEL_US_RXRDY);
+               atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
        }
 }
 
@@ -538,7 +564,7 @@ static void atmel_enable_ms(struct uart_port *port)
        else
                ier |= ATMEL_US_DCDIC;
 
-       UART_PUT_IER(port, ier);
+       atmel_uart_writel(port, ATMEL_US_IER, ier);
 }
 
 /*
@@ -577,7 +603,7 @@ static void atmel_disable_ms(struct uart_port *port)
        else
                idr |= ATMEL_US_DCDIC;
 
-       UART_PUT_IDR(port, idr);
+       atmel_uart_writel(port, ATMEL_US_IDR, idr);
 }
 
 /*
@@ -586,9 +612,11 @@ static void atmel_disable_ms(struct uart_port *port)
 static void atmel_break_ctl(struct uart_port *port, int break_state)
 {
        if (break_state != 0)
-               UART_PUT_CR(port, ATMEL_US_STTBRK);     /* start break */
+               /* start break */
+               atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
        else
-               UART_PUT_CR(port, ATMEL_US_STPBRK);     /* stop break */
+               /* stop break */
+               atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
 }
 
 /*
@@ -622,7 +650,7 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
 static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
 {
        /* clear error */
-       UART_PUT_CR(port, ATMEL_US_RSTSTA);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
        if (status & ATMEL_US_RXBRK) {
                /* ignore side-effect */
@@ -645,9 +673,9 @@ static void atmel_rx_chars(struct uart_port *port)
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
        unsigned int status, ch;
 
-       status = UART_GET_CSR(port);
+       status = atmel_uart_readl(port, ATMEL_US_CSR);
        while (status & ATMEL_US_RXRDY) {
-               ch = UART_GET_CHAR(port);
+               ch = atmel_uart_read_char(port);
 
                /*
                 * note that the error handling code is
@@ -658,12 +686,13 @@ static void atmel_rx_chars(struct uart_port *port)
                             || atmel_port->break_active)) {
 
                        /* clear error */
-                       UART_PUT_CR(port, ATMEL_US_RSTSTA);
+                       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
 
                        if (status & ATMEL_US_RXBRK
                            && !atmel_port->break_active) {
                                atmel_port->break_active = 1;
-                               UART_PUT_IER(port, ATMEL_US_RXBRK);
+                               atmel_uart_writel(port, ATMEL_US_IER,
+                                                 ATMEL_US_RXBRK);
                        } else {
                                /*
                                 * This is either the end-of-break
@@ -672,14 +701,15 @@ static void atmel_rx_chars(struct uart_port *port)
                                 * being set. In both cases, the next
                                 * RXBRK will indicate start-of-break.
                                 */
-                               UART_PUT_IDR(port, ATMEL_US_RXBRK);
+                               atmel_uart_writel(port, ATMEL_US_IDR,
+                                                 ATMEL_US_RXBRK);
                                status &= ~ATMEL_US_RXBRK;
                                atmel_port->break_active = 0;
                        }
                }
 
                atmel_buffer_rx_char(port, status, ch);
-               status = UART_GET_CSR(port);
+               status = atmel_uart_readl(port, ATMEL_US_CSR);
        }
 
        tasklet_schedule(&atmel_port->tasklet);
@@ -694,16 +724,18 @@ static void atmel_tx_chars(struct uart_port *port)
        struct circ_buf *xmit = &port->state->xmit;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-       if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-               UART_PUT_CHAR(port, port->x_char);
+       if (port->x_char &&
+           (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
+               atmel_uart_write_char(port, port->x_char);
                port->icount.tx++;
                port->x_char = 0;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(port))
                return;
 
-       while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
-               UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+       while (atmel_uart_readl(port, ATMEL_US_CSR) &
+              atmel_port->tx_done_mask) {
+               atmel_uart_write_char(port, xmit->buf[xmit->tail]);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                port->icount.tx++;
                if (uart_circ_empty(xmit))
@@ -715,7 +747,8 @@ static void atmel_tx_chars(struct uart_port *port)
 
        if (!uart_circ_empty(xmit))
                /* Enable interrupts */
-               UART_PUT_IER(port, atmel_port->tx_done_mask);
+               atmel_uart_writel(port, ATMEL_US_IER,
+                                 atmel_port->tx_done_mask);
 }
 
 static void atmel_complete_tx_dma(void *arg)
@@ -730,10 +763,10 @@ static void atmel_complete_tx_dma(void *arg)
 
        if (chan)
                dmaengine_terminate_all(chan);
-       xmit->tail += sg_dma_len(&atmel_port->sg_tx);
+       xmit->tail += atmel_port->tx_len;
        xmit->tail &= UART_XMIT_SIZE - 1;
 
-       port->icount.tx += sg_dma_len(&atmel_port->sg_tx);
+       port->icount.tx += atmel_port->tx_len;
 
        spin_lock_irq(&atmel_port->lock_tx);
        async_tx_ack(atmel_port->desc_tx);
@@ -781,7 +814,9 @@ static void atmel_tx_dma(struct uart_port *port)
        struct circ_buf *xmit = &port->state->xmit;
        struct dma_chan *chan = atmel_port->chan_tx;
        struct dma_async_tx_descriptor *desc;
-       struct scatterlist *sg = &atmel_port->sg_tx;
+       struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
+       unsigned int tx_len, part1_len, part2_len, sg_len;
+       dma_addr_t phys_addr;
 
        /* Make sure we have an idle channel */
        if (atmel_port->desc_tx != NULL)
@@ -797,18 +832,46 @@ static void atmel_tx_dma(struct uart_port *port)
                 * Take the port lock to get a
                 * consistent xmit buffer state.
                 */
-               sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-               sg_dma_address(sg) = (sg_dma_address(sg) &
-                                       ~(UART_XMIT_SIZE - 1))
-                                       + sg->offset;
-               sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head,
-                                               xmit->tail,
-                                               UART_XMIT_SIZE);
-               BUG_ON(!sg_dma_len(sg));
+               tx_len = CIRC_CNT_TO_END(xmit->head,
+                                        xmit->tail,
+                                        UART_XMIT_SIZE);
+
+               if (atmel_port->fifo_size) {
+                       /* multi data mode */
+                       part1_len = (tx_len & ~0x3); /* DWORD access */
+                       part2_len = (tx_len & 0x3); /* BYTE access */
+               } else {
+                       /* single data (legacy) mode */
+                       part1_len = 0;
+                       part2_len = tx_len; /* BYTE access only */
+               }
+
+               sg_init_table(sgl, 2);
+               sg_len = 0;
+               phys_addr = sg_dma_address(sg_tx) + xmit->tail;
+               if (part1_len) {
+                       sg = &sgl[sg_len++];
+                       sg_dma_address(sg) = phys_addr;
+                       sg_dma_len(sg) = part1_len;
+
+                       phys_addr += part1_len;
+               }
+
+               if (part2_len) {
+                       sg = &sgl[sg_len++];
+                       sg_dma_address(sg) = phys_addr;
+                       sg_dma_len(sg) = part2_len;
+               }
+
+               /*
+                * save tx_len so atmel_complete_tx_dma() will increase
+                * xmit->tail correctly
+                */
+               atmel_port->tx_len = tx_len;
 
                desc = dmaengine_prep_slave_sg(chan,
-                                              sg,
-                                              1,
+                                              sgl,
+                                              sg_len,
                                               DMA_MEM_TO_DEV,
                                               DMA_PREP_INTERRUPT |
                                               DMA_CTRL_ACK);
@@ -817,7 +880,7 @@ static void atmel_tx_dma(struct uart_port *port)
                        return;
                }
 
-               dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+               dma_sync_sg_for_device(port->dev, sg_tx, 1, DMA_TO_DEVICE);
 
                atmel_port->desc_tx = desc;
                desc->callback = atmel_complete_tx_dma;
@@ -877,7 +940,9 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
        /* Configure the slave DMA */
        memset(&config, 0, sizeof(config));
        config.direction = DMA_MEM_TO_DEV;
-       config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+       config.dst_addr_width = (atmel_port->fifo_size) ?
+                               DMA_SLAVE_BUSWIDTH_4_BYTES :
+                               DMA_SLAVE_BUSWIDTH_1_BYTE;
        config.dst_addr = port->mapbase + ATMEL_US_THR;
        config.dst_maxburst = 1;
 
@@ -935,14 +1000,14 @@ static void atmel_rx_from_dma(struct uart_port *port)
 
 
        /* Reset the UART timeout early so that we don't miss one */
-       UART_PUT_CR(port, ATMEL_US_STTTO);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
        dmastat = dmaengine_tx_status(chan,
                                atmel_port->cookie_rx,
                                &state);
        /* Restart a new tasklet if DMA status is error */
        if (dmastat == DMA_ERROR) {
                dev_dbg(port->dev, "Get residue error, restart tasklet\n");
-               UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+               atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
                tasklet_schedule(&atmel_port->tasklet);
                return;
        }
@@ -1008,7 +1073,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
        tty_flip_buffer_push(tport);
        spin_lock(&port->lock);
 
-       UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+       atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_dma(struct uart_port *port)
@@ -1118,8 +1183,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
                 * the moment.
                 */
                if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
-                       UART_PUT_IDR(port, (ATMEL_US_ENDRX
-                                               | ATMEL_US_TIMEOUT));
+                       atmel_uart_writel(port, ATMEL_US_IDR,
+                                         (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
                        tasklet_schedule(&atmel_port->tasklet);
                }
 
@@ -1130,7 +1195,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 
        if (atmel_use_dma_rx(port)) {
                if (pending & ATMEL_US_TIMEOUT) {
-                       UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
+                       atmel_uart_writel(port, ATMEL_US_IDR,
+                                         ATMEL_US_TIMEOUT);
                        tasklet_schedule(&atmel_port->tasklet);
                }
        }
@@ -1143,8 +1209,8 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
                 * End of break detected. If it came along with a
                 * character, atmel_rx_chars will handle it.
                 */
-               UART_PUT_CR(port, ATMEL_US_RSTSTA);
-               UART_PUT_IDR(port, ATMEL_US_RXBRK);
+               atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+               atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
                atmel_port->break_active = 0;
        }
 }
@@ -1159,7 +1225,8 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
 
        if (pending & atmel_port->tx_done_mask) {
                /* Either PDC or interrupt transmission */
-               UART_PUT_IDR(port, atmel_port->tx_done_mask);
+               atmel_uart_writel(port, ATMEL_US_IDR,
+                                 atmel_port->tx_done_mask);
                tasklet_schedule(&atmel_port->tasklet);
        }
 }
@@ -1197,7 +1264,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
 
        do {
                status = atmel_get_lines_status(port);
-               mask = UART_GET_IMR(port);
+               mask = atmel_uart_readl(port, ATMEL_US_IMR);
                pending = status & mask;
                if (!gpio_handled) {
                        /*
@@ -1223,7 +1290,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
                if (atmel_port->suspended) {
                        atmel_port->pending |= pending;
                        atmel_port->pending_status = status;
-                       UART_PUT_IDR(port, mask);
+                       atmel_uart_writel(port, ATMEL_US_IDR, mask);
                        pm_system_wakeup();
                        break;
                }
@@ -1260,7 +1327,7 @@ static void atmel_tx_pdc(struct uart_port *port)
        int count;
 
        /* nothing left to transmit? */
-       if (UART_GET_TCR(port))
+       if (atmel_uart_readl(port, ATMEL_PDC_TCR))
                return;
 
        xmit->tail += pdc->ofs;
@@ -1272,7 +1339,7 @@ static void atmel_tx_pdc(struct uart_port *port)
        /* more to transmit - setup next transfer */
 
        /* disable PDC transmit */
-       UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+       atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
        if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
                dma_sync_single_for_device(port->dev,
@@ -1283,12 +1350,14 @@ static void atmel_tx_pdc(struct uart_port *port)
                count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
                pdc->ofs = count;
 
-               UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
-               UART_PUT_TCR(port, count);
+               atmel_uart_writel(port, ATMEL_PDC_TPR,
+                                 pdc->dma_addr + xmit->tail);
+               atmel_uart_writel(port, ATMEL_PDC_TCR, count);
                /* re-enable PDC transmit */
-               UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
                /* Enable interrupts */
-               UART_PUT_IER(port, atmel_port->tx_done_mask);
+               atmel_uart_writel(port, ATMEL_US_IER,
+                                 atmel_port->tx_done_mask);
        } else {
                if ((port->rs485.flags & SER_RS485_ENABLED) &&
                    !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -1414,10 +1483,10 @@ static void atmel_rx_from_pdc(struct uart_port *port)
 
        do {
                /* Reset the UART timeout early so that we don't miss one */
-               UART_PUT_CR(port, ATMEL_US_STTTO);
+               atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
                pdc = &atmel_port->pdc_rx[rx_idx];
-               head = UART_GET_RPR(port) - pdc->dma_addr;
+               head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
                tail = pdc->ofs;
 
                /* If the PDC has switched buffers, RPR won't contain
@@ -1460,8 +1529,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
                 */
                if (head >= pdc->dma_size) {
                        pdc->ofs = 0;
-                       UART_PUT_RNPR(port, pdc->dma_addr);
-                       UART_PUT_RNCR(port, pdc->dma_size);
+                       atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
+                       atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
 
                        rx_idx = !rx_idx;
                        atmel_port->pdc_rx_idx = rx_idx;
@@ -1476,7 +1545,8 @@ static void atmel_rx_from_pdc(struct uart_port *port)
        tty_flip_buffer_push(tport);
        spin_lock(&port->lock);
 
-       UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+       atmel_uart_writel(port, ATMEL_US_IER,
+                         ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
 }
 
 static int atmel_prepare_rx_pdc(struct uart_port *port)
@@ -1509,11 +1579,12 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
 
        atmel_port->pdc_rx_idx = 0;
 
-       UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
-       UART_PUT_RCR(port, PDC_BUFFER_SIZE);
+       atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
+       atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
 
-       UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
-       UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+       atmel_uart_writel(port, ATMEL_PDC_RNPR,
+                         atmel_port->pdc_rx[1].dma_addr);
+       atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
 
        return 0;
 }
@@ -1667,7 +1738,7 @@ static void atmel_set_ops(struct uart_port *port)
 static void atmel_get_ip_name(struct uart_port *port)
 {
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-       int name = UART_GET_IP_NAME(port);
+       int name = atmel_uart_readl(port, ATMEL_US_NAME);
        u32 version;
        int usart, uart;
        /* usart and uart ascii */
@@ -1684,7 +1755,7 @@ static void atmel_get_ip_name(struct uart_port *port)
                atmel_port->is_usart = false;
        } else {
                /* fallback for older SoCs: use version field */
-               version = UART_GET_IP_VERSION(port);
+               version = atmel_uart_readl(port, ATMEL_US_VERSION);
                switch (version) {
                case 0x302:
                case 0x10213:
@@ -1756,7 +1827,7 @@ static int atmel_startup(struct uart_port *port)
         * request_irq() is called we could get stuck trying to
         * handle an unexpected interrupt
         */
-       UART_PUT_IDR(port, -1);
+       atmel_uart_writel(port, ATMEL_US_IDR, -1);
        atmel_port->ms_irq_enabled = false;
 
        /*
@@ -1797,6 +1868,32 @@ static int atmel_startup(struct uart_port *port)
                        atmel_set_ops(port);
        }
 
+       /*
+        * Enable FIFO when available
+        */
+       if (atmel_port->fifo_size) {
+               unsigned int txrdym = ATMEL_US_ONE_DATA;
+               unsigned int rxrdym = ATMEL_US_ONE_DATA;
+               unsigned int fmr;
+
+               atmel_uart_writel(port, ATMEL_US_CR,
+                                 ATMEL_US_FIFOEN |
+                                 ATMEL_US_RXFCLR |
+                                 ATMEL_US_TXFLCLR);
+
+               if (atmel_use_dma_tx(port))
+                       txrdym = ATMEL_US_FOUR_DATA;
+
+               fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
+               if (atmel_port->rts_high &&
+                   atmel_port->rts_low)
+                       fmr |=  ATMEL_US_FRTSC |
+                               ATMEL_US_RXFTHRES(atmel_port->rts_high) |
+                               ATMEL_US_RXFTHRES2(atmel_port->rts_low);
+
+               atmel_uart_writel(port, ATMEL_US_FMR, fmr);
+       }
+
        /* Save current CSR for comparison in atmel_tasklet_func() */
        atmel_port->irq_status_prev = atmel_get_lines_status(port);
        atmel_port->irq_status = atmel_port->irq_status_prev;
@@ -1804,9 +1901,9 @@ static int atmel_startup(struct uart_port *port)
        /*
         * Finally, enable the serial port
         */
-       UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
        /* enable xmit & rcvr */
-       UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
        setup_timer(&atmel_port->uart_timer,
                        atmel_uart_timer_callback,
@@ -1819,13 +1916,14 @@ static int atmel_startup(struct uart_port *port)
                                        jiffies + uart_poll_timeout(port));
                /* set USART timeout */
                } else {
-                       UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-                       UART_PUT_CR(port, ATMEL_US_STTTO);
+                       atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+                       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-                       UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+                       atmel_uart_writel(port, ATMEL_US_IER,
+                                         ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
                }
                /* enable PDC controller */
-               UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
        } else if (atmel_use_dma_rx(port)) {
                /* set UART timeout */
                if (!atmel_port->is_usart) {
@@ -1833,14 +1931,15 @@ static int atmel_startup(struct uart_port *port)
                                        jiffies + uart_poll_timeout(port));
                /* set USART timeout */
                } else {
-                       UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
-                       UART_PUT_CR(port, ATMEL_US_STTTO);
+                       atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+                       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
 
-                       UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+                       atmel_uart_writel(port, ATMEL_US_IER,
+                                         ATMEL_US_TIMEOUT);
                }
        } else {
                /* enable receive only */
-               UART_PUT_IER(port, ATMEL_US_RXRDY);
+               atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
        }
 
        return 0;
@@ -1860,7 +1959,7 @@ static void atmel_flush_buffer(struct uart_port *port)
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
        if (atmel_use_pdc_tx(port)) {
-               UART_PUT_TCR(port, 0);
+               atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
                atmel_port->pdc_tx.ofs = 0;
        }
 }
@@ -1892,8 +1991,8 @@ static void atmel_shutdown(struct uart_port *port)
        atmel_stop_rx(port);
        atmel_stop_tx(port);
 
-       UART_PUT_CR(port, ATMEL_US_RSTSTA);
-       UART_PUT_IDR(port, -1);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+       atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
 
        /*
@@ -1938,12 +2037,12 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state,
                clk_prepare_enable(atmel_port->clk);
 
                /* re-enable interrupts if we disabled some on suspend */
-               UART_PUT_IER(port, atmel_port->backup_imr);
+               atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
                break;
        case 3:
                /* Back up the interrupt mask and disable all interrupts */
-               atmel_port->backup_imr = UART_GET_IMR(port);
-               UART_PUT_IDR(port, -1);
+               atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
+               atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
                /*
                 * Disable the peripheral clock for this serial port.
@@ -1966,7 +2065,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned int old_mode, mode, imr, quot, baud;
 
        /* save the current mode register */
-       mode = old_mode = UART_GET_MR(port);
+       mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
 
        /* reset the mode, clock divisor, parity, stop bits and data size */
        mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
@@ -2025,7 +2124,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (atmel_use_pdc_rx(port))
                /* need to enable error interrupts */
-               UART_PUT_IER(port, port->read_status_mask);
+               atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
 
        /*
         * Characters to ignore
@@ -2052,15 +2151,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
         * transmitter is empty if requested by the caller, so there's
         * no need to wait for it here.
         */
-       imr = UART_GET_IMR(port);
-       UART_PUT_IDR(port, -1);
+       imr = atmel_uart_readl(port, ATMEL_US_IMR);
+       atmel_uart_writel(port, ATMEL_US_IDR, -1);
 
        /* disable receiver and transmitter */
-       UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
 
        /* mode */
        if (port->rs485.flags & SER_RS485_ENABLED) {
-               UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+               atmel_uart_writel(port, ATMEL_US_TTGR,
+                                 port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else if (termios->c_cflag & CRTSCTS) {
                /* RS232 with hardware handshake (RTS/CTS) */
@@ -2071,7 +2171,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /* set the mode, clock divisor, parity, stop bits and data size */
-       UART_PUT_MR(port, mode);
+       atmel_uart_writel(port, ATMEL_US_MR, mode);
 
        /*
         * when switching the mode, set the RTS line state according to the
@@ -2088,16 +2188,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
                        rts_state = ATMEL_US_RTSEN;
                }
 
-               UART_PUT_CR(port, rts_state);
+               atmel_uart_writel(port, ATMEL_US_CR, rts_state);
        }
 
        /* set the baud rate */
-       UART_PUT_BRGR(port, quot);
-       UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-       UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+       atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
        /* restore interrupts */
-       UART_PUT_IER(port, imr);
+       atmel_uart_writel(port, ATMEL_US_IER, imr);
 
        /* CTS flow-control and modem-status interrupts */
        if (UART_ENABLE_MS(port, termios->c_cflag))
@@ -2208,18 +2308,18 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
 #ifdef CONFIG_CONSOLE_POLL
 static int atmel_poll_get_char(struct uart_port *port)
 {
-       while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+       while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
                cpu_relax();
 
-       return UART_GET_CHAR(port);
+       return atmel_uart_read_char(port);
 }
 
 static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
 {
-       while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+       while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
                cpu_relax();
 
-       UART_PUT_CHAR(port, ch);
+       atmel_uart_write_char(port, ch);
 }
 #endif
 
@@ -2324,9 +2424,9 @@ struct platform_device *atmel_default_console_device;     /* the serial console devi
 #ifdef CONFIG_SERIAL_ATMEL_CONSOLE
 static void atmel_console_putchar(struct uart_port *port, int ch)
 {
-       while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+       while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
                cpu_relax();
-       UART_PUT_CHAR(port, ch);
+       atmel_uart_write_char(port, ch);
 }
 
 /*
@@ -2342,12 +2442,13 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
        /*
         * First, save IMR and then disable interrupts
         */
-       imr = UART_GET_IMR(port);
-       UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
+       imr = atmel_uart_readl(port, ATMEL_US_IMR);
+       atmel_uart_writel(port, ATMEL_US_IDR,
+                         ATMEL_US_RXRDY | atmel_port->tx_done_mask);
 
        /* Store PDC transmit status and disable it */
-       pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
-       UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+       pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
+       atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
 
        uart_console_write(port, s, count, atmel_console_putchar);
 
@@ -2356,15 +2457,15 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
         * and restore IMR
         */
        do {
-               status = UART_GET_CSR(port);
+               status = atmel_uart_readl(port, ATMEL_US_CSR);
        } while (!(status & ATMEL_US_TXRDY));
 
        /* Restore PDC transmit status */
        if (pdc_tx)
-               UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+               atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 
        /* set interrupts back the way they were */
-       UART_PUT_IER(port, imr);
+       atmel_uart_writel(port, ATMEL_US_IER, imr);
 }
 
 /*
@@ -2380,17 +2481,17 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
         * If the baud rate generator isn't running, the port wasn't
         * initialized by the boot loader.
         */
-       quot = UART_GET_BRGR(port) & ATMEL_US_CD;
+       quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
        if (!quot)
                return;
 
-       mr = UART_GET_MR(port) & ATMEL_US_CHRL;
+       mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
        if (mr == ATMEL_US_CHRL_8)
                *bits = 8;
        else
                *bits = 7;
 
-       mr = UART_GET_MR(port) & ATMEL_US_PAR;
+       mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
        if (mr == ATMEL_US_PAR_EVEN)
                *parity = 'e';
        else if (mr == ATMEL_US_PAR_ODD)
@@ -2423,9 +2524,9 @@ static int __init atmel_console_setup(struct console *co, char *options)
        if (ret)
                return ret;
 
-       UART_PUT_IDR(port, -1);
-       UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
-       UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+       atmel_uart_writel(port, ATMEL_US_IDR, -1);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -2532,7 +2633,8 @@ static int atmel_serial_suspend(struct platform_device *pdev,
 
        if (atmel_is_console_port(port) && console_suspend_enabled) {
                /* Drain the TX shifter */
-               while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
+               while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
+                        ATMEL_US_TXEMPTY))
                        cpu_relax();
        }
 
@@ -2599,6 +2701,48 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
        return 0;
 }
 
+static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
+                                    struct platform_device *pdev)
+{
+       port->fifo_size = 0;
+       port->rts_low = 0;
+       port->rts_high = 0;
+
+       if (of_property_read_u32(pdev->dev.of_node,
+                                "atmel,fifo-size",
+                                &port->fifo_size))
+               return;
+
+       if (!port->fifo_size)
+               return;
+
+       if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
+               port->fifo_size = 0;
+               dev_err(&pdev->dev, "Invalid FIFO size\n");
+               return;
+       }
+
+       /*
+        * 0 <= rts_low <= rts_high <= fifo_size
+        * Once their CTS line asserted by the remote peer, some x86 UARTs tend
+        * to flush their internal TX FIFO, commonly up to 16 data, before
+        * actually stopping to send new data. So we try to set the RTS High
+        * Threshold to a reasonably high value respecting this 16 data
+        * empirical rule when possible.
+        */
+       port->rts_high = max_t(int, port->fifo_size >> 1,
+                              port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
+       port->rts_low  = max_t(int, port->fifo_size >> 2,
+                              port->fifo_size - ATMEL_RTS_LOW_OFFSET);
+
+       dev_info(&pdev->dev, "Using FIFO (%u data)\n",
+                port->fifo_size);
+       dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
+               port->rts_high);
+       dev_dbg(&pdev->dev, "RTS Low Threshold  : %2u data\n",
+               port->rts_low);
+}
+
 static int atmel_serial_probe(struct platform_device *pdev)
 {
        struct atmel_uart_port *port;
@@ -2635,6 +2779,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
        port = &atmel_ports[ret];
        port->backup_imr = 0;
        port->uart.line = ret;
+       atmel_serial_probe_fifos(port, pdev);
 
        spin_lock_init(&port->lock_suspended);
 
@@ -2684,8 +2829,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
        clk_prepare_enable(port->clk);
 
        if (rs485_enabled) {
-               UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
-               UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
+               atmel_uart_writel(&port->uart, ATMEL_US_MR,
+                                 ATMEL_US_USMODE_NORMAL);
+               atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
        }
 
        /*
index 679709f51fd4cfe4739fc2edb433cc4badaf0227..6813e316e9ff3d3e58fb2c68d582a3a285295aa3 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/of_address.h>
 #include <hwregs/ser_defs.h>
 
+#include "serial_mctrl_gpio.h"
+
 #define DRV_NAME "etraxfs-uart"
 #define UART_NR CONFIG_ETRAX_SERIAL_PORTS
 
@@ -28,10 +30,7 @@ struct uart_cris_port {
 
        void __iomem *regi_ser;
 
-       struct gpio_desc *dtr_pin;
-       struct gpio_desc *dsr_pin;
-       struct gpio_desc *ri_pin;
-       struct gpio_desc *cd_pin;
+       struct mctrl_gpios *gpios;
 
        int write_ongoing;
 };
@@ -112,17 +111,10 @@ cris_console_setup(struct console *co, char *options)
        return 0;
 }
 
-static struct tty_driver *cris_console_device(struct console *co, int *index)
-{
-       struct uart_driver *p = co->data;
-       *index = co->index;
-       return p->tty_driver;
-}
-
 static struct console cris_console = {
        .name = "ttyS",
        .write = cris_console_write,
-       .device = cris_console_device,
+       .device = uart_console_device,
        .setup = cris_console_setup,
        .flags = CON_PRINTBUFFER,
        .index = -1,
@@ -373,14 +365,6 @@ static void etraxfs_uart_stop_rx(struct uart_port *port)
        REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
 }
 
-static void etraxfs_uart_enable_ms(struct uart_port *port)
-{
-}
-
-static void check_modem_status(struct uart_cris_port *up)
-{
-}
-
 static unsigned int etraxfs_uart_tx_empty(struct uart_port *port)
 {
        struct uart_cris_port *up = (struct uart_cris_port *)port;
@@ -404,21 +388,9 @@ static unsigned int etraxfs_uart_get_mctrl(struct uart_port *port)
        ret = 0;
        if (crisv32_serial_get_rts(up))
                ret |= TIOCM_RTS;
-       /* DTR is active low */
-       if (up->dtr_pin && !gpiod_get_raw_value(up->dtr_pin))
-               ret |= TIOCM_DTR;
-       /* CD is active low */
-       if (up->cd_pin && !gpiod_get_raw_value(up->cd_pin))
-               ret |= TIOCM_CD;
-       /* RI is active low */
-       if (up->ri_pin && !gpiod_get_raw_value(up->ri_pin))
-               ret |= TIOCM_RI;
-       /* DSR is active low */
-       if (up->dsr_pin && !gpiod_get_raw_value(up->dsr_pin))
-               ret |= TIOCM_DSR;
        if (crisv32_serial_get_cts(up))
                ret |= TIOCM_CTS;
-       return ret;
+       return mctrl_gpio_get(up->gpios, &ret);
 }
 
 static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -426,15 +398,7 @@ static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
        struct uart_cris_port *up = (struct uart_cris_port *)port;
 
        crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
-       /* DTR is active low */
-       if (up->dtr_pin)
-               gpiod_set_raw_value(up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1);
-       /* RI is active low */
-       if (up->ri_pin)
-               gpiod_set_raw_value(up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1);
-       /* CD is active low */
-       if (up->cd_pin)
-               gpiod_set_raw_value(up->cd_pin, mctrl & TIOCM_CD ? 0 : 1);
+       mctrl_gpio_set(up->gpios, mctrl);
 }
 
 static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state)
@@ -598,7 +562,6 @@ ser_interrupt(int irq, void *dev_id)
                        receive_chars_no_dma(up);
                        handled = 1;
                }
-               check_modem_status(up);
 
                if (masked_intr.tr_rdy) {
                        transmit_chars_no_dma(up);
@@ -862,7 +825,6 @@ static const struct uart_ops etraxfs_uart_pops = {
        .start_tx = etraxfs_uart_start_tx,
        .send_xchar = etraxfs_uart_send_xchar,
        .stop_rx = etraxfs_uart_stop_rx,
-       .enable_ms = etraxfs_uart_enable_ms,
        .break_ctl = etraxfs_uart_break_ctl,
        .startup = etraxfs_uart_startup,
        .shutdown = etraxfs_uart_shutdown,
@@ -930,11 +892,12 @@ static int etraxfs_uart_probe(struct platform_device *pdev)
 
        up->irq = irq_of_parse_and_map(np, 0);
        up->regi_ser = of_iomap(np, 0);
-       up->dtr_pin = devm_gpiod_get_optional(&pdev->dev, "dtr");
-       up->dsr_pin = devm_gpiod_get_optional(&pdev->dev, "dsr");
-       up->ri_pin = devm_gpiod_get_optional(&pdev->dev, "ri");
-       up->cd_pin = devm_gpiod_get_optional(&pdev->dev, "cd");
        up->port.dev = &pdev->dev;
+
+       up->gpios = mctrl_gpio_init(&pdev->dev, 0);
+       if (IS_ERR(up->gpios))
+               return PTR_ERR(up->gpios);
+
        cris_serial_port_init(&up->port, dev_id);
 
        etraxfs_uart_ports[dev_id] = up;
index 54fdc7866ea17423836827ee374c1ecfd0b5257d..fe3d41cc841632134fd907b1fb7af08f0e9d6e81 100644 (file)
@@ -216,6 +216,8 @@ struct imx_port {
        unsigned int            tx_bytes;
        unsigned int            dma_tx_nents;
        wait_queue_head_t       dma_wait;
+       unsigned int            saved_reg[10];
+       bool                    context_saved;
 };
 
 struct imx_port_ucrs {
@@ -700,7 +702,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
                if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
                        goto out;
 
-               tty_insert_flip_char(port, rx, flg);
+               if (tty_insert_flip_char(port, rx, flg) == 0)
+                       sport->port.icount.buf_overrun++;
        }
 
 out:
@@ -766,7 +769,6 @@ static irqreturn_t imx_int(int irq, void *dev_id)
                writel(USR1_AWAKE, sport->port.membase + USR1);
 
        if (sts2 & USR2_ORE) {
-               dev_err(sport->port.dev, "Rx FIFO overrun\n");
                sport->port.icount.overrun++;
                writel(USR2_ORE, sport->port.membase + USR2);
        }
@@ -921,8 +923,13 @@ static void dma_rx_callback(void *data)
        dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
 
        if (count) {
-               if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ))
-                       tty_insert_flip_string(port, sport->rx_buf, count);
+               if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
+                       int bytes = tty_insert_flip_string(port, sport->rx_buf,
+                                       count);
+
+                       if (bytes != count)
+                               sport->port.icount.buf_overrun++;
+               }
                tty_flip_buffer_push(port);
 
                start_rx_dma(sport);
@@ -1624,12 +1631,12 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        int locked = 1;
        int retval;
 
-       retval = clk_enable(sport->clk_per);
+       retval = clk_prepare_enable(sport->clk_per);
        if (retval)
                return;
-       retval = clk_enable(sport->clk_ipg);
+       retval = clk_prepare_enable(sport->clk_ipg);
        if (retval) {
-               clk_disable(sport->clk_per);
+               clk_disable_unprepare(sport->clk_per);
                return;
        }
 
@@ -1668,8 +1675,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        if (locked)
                spin_unlock_irqrestore(&sport->port.lock, flags);
 
-       clk_disable(sport->clk_ipg);
-       clk_disable(sport->clk_per);
+       clk_disable_unprepare(sport->clk_ipg);
+       clk_disable_unprepare(sport->clk_per);
 }
 
 /*
@@ -1770,15 +1777,7 @@ imx_console_setup(struct console *co, char *options)
 
        retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
-       clk_disable(sport->clk_ipg);
-       if (retval) {
-               clk_unprepare(sport->clk_ipg);
-               goto error_console;
-       }
-
-       retval = clk_prepare(sport->clk_per);
-       if (retval)
-               clk_disable_unprepare(sport->clk_ipg);
+       clk_disable_unprepare(sport->clk_ipg);
 
 error_console:
        return retval;
@@ -1810,36 +1809,6 @@ static struct uart_driver imx_reg = {
        .cons           = IMX_CONSOLE,
 };
 
-static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct imx_port *sport = platform_get_drvdata(dev);
-       unsigned int val;
-
-       /* enable wakeup from i.MX UART */
-       val = readl(sport->port.membase + UCR3);
-       val |= UCR3_AWAKEN;
-       writel(val, sport->port.membase + UCR3);
-
-       uart_suspend_port(&imx_reg, &sport->port);
-
-       return 0;
-}
-
-static int serial_imx_resume(struct platform_device *dev)
-{
-       struct imx_port *sport = platform_get_drvdata(dev);
-       unsigned int val;
-
-       /* disable wakeup from i.MX UART */
-       val = readl(sport->port.membase + UCR3);
-       val &= ~UCR3_AWAKEN;
-       writel(val, sport->port.membase + UCR3);
-
-       uart_resume_port(&imx_reg, &sport->port);
-
-       return 0;
-}
-
 #ifdef CONFIG_OF
 /*
  * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
@@ -1901,7 +1870,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 {
        struct imx_port *sport;
        void __iomem *base;
-       int ret = 0;
+       int ret = 0, reg;
        struct resource *res;
        int txirq, rxirq, rtsirq;
 
@@ -1956,6 +1925,19 @@ static int serial_imx_probe(struct platform_device *pdev)
 
        sport->port.uartclk = clk_get_rate(sport->clk_per);
 
+       /* For register access, we only need to enable the ipg clock. */
+       ret = clk_prepare_enable(sport->clk_ipg);
+       if (ret)
+               return ret;
+
+       /* Disable interrupts before requesting them */
+       reg = readl_relaxed(sport->port.membase + UCR1);
+       reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
+                UCR1_TXMPTYEN | UCR1_RTSDEN);
+       writel_relaxed(reg, sport->port.membase + UCR1);
+
+       clk_disable_unprepare(sport->clk_ipg);
+
        /*
         * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
         * chips only have one interrupt.
@@ -1991,16 +1973,135 @@ static int serial_imx_remove(struct platform_device *pdev)
        return uart_remove_one_port(&imx_reg, &sport->port);
 }
 
+static void serial_imx_restore_context(struct imx_port *sport)
+{
+       if (!sport->context_saved)
+               return;
+
+       writel(sport->saved_reg[4], sport->port.membase + UFCR);
+       writel(sport->saved_reg[5], sport->port.membase + UESC);
+       writel(sport->saved_reg[6], sport->port.membase + UTIM);
+       writel(sport->saved_reg[7], sport->port.membase + UBIR);
+       writel(sport->saved_reg[8], sport->port.membase + UBMR);
+       writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
+       writel(sport->saved_reg[0], sport->port.membase + UCR1);
+       writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
+       writel(sport->saved_reg[2], sport->port.membase + UCR3);
+       writel(sport->saved_reg[3], sport->port.membase + UCR4);
+       sport->context_saved = false;
+}
+
+static void serial_imx_save_context(struct imx_port *sport)
+{
+       /* Save necessary regs */
+       sport->saved_reg[0] = readl(sport->port.membase + UCR1);
+       sport->saved_reg[1] = readl(sport->port.membase + UCR2);
+       sport->saved_reg[2] = readl(sport->port.membase + UCR3);
+       sport->saved_reg[3] = readl(sport->port.membase + UCR4);
+       sport->saved_reg[4] = readl(sport->port.membase + UFCR);
+       sport->saved_reg[5] = readl(sport->port.membase + UESC);
+       sport->saved_reg[6] = readl(sport->port.membase + UTIM);
+       sport->saved_reg[7] = readl(sport->port.membase + UBIR);
+       sport->saved_reg[8] = readl(sport->port.membase + UBMR);
+       sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
+       sport->context_saved = true;
+}
+
+static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
+{
+       unsigned int val;
+
+       val = readl(sport->port.membase + UCR3);
+       if (on)
+               val |= UCR3_AWAKEN;
+       else
+               val &= ~UCR3_AWAKEN;
+       writel(val, sport->port.membase + UCR3);
+
+       val = readl(sport->port.membase + UCR1);
+       if (on)
+               val |= UCR1_RTSDEN;
+       else
+               val &= ~UCR1_RTSDEN;
+       writel(val, sport->port.membase + UCR1);
+}
+
+static int imx_serial_port_suspend_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = clk_enable(sport->clk_ipg);
+       if (ret)
+               return ret;
+
+       serial_imx_save_context(sport);
+
+       clk_disable(sport->clk_ipg);
+
+       return 0;
+}
+
+static int imx_serial_port_resume_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = clk_enable(sport->clk_ipg);
+       if (ret)
+               return ret;
+
+       serial_imx_restore_context(sport);
+
+       clk_disable(sport->clk_ipg);
+
+       return 0;
+}
+
+static int imx_serial_port_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+
+       /* enable wakeup from i.MX UART */
+       serial_imx_enable_wakeup(sport, true);
+
+       uart_suspend_port(&imx_reg, &sport->port);
+
+       return 0;
+}
+
+static int imx_serial_port_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct imx_port *sport = platform_get_drvdata(pdev);
+
+       /* disable wakeup from i.MX UART */
+       serial_imx_enable_wakeup(sport, false);
+
+       uart_resume_port(&imx_reg, &sport->port);
+
+       return 0;
+}
+
+static const struct dev_pm_ops imx_serial_port_pm_ops = {
+       .suspend_noirq = imx_serial_port_suspend_noirq,
+       .resume_noirq = imx_serial_port_resume_noirq,
+       .suspend = imx_serial_port_suspend,
+       .resume = imx_serial_port_resume,
+};
+
 static struct platform_driver serial_imx_driver = {
        .probe          = serial_imx_probe,
        .remove         = serial_imx_remove,
 
-       .suspend        = serial_imx_suspend,
-       .resume         = serial_imx_resume,
        .id_table       = imx_uart_devtype,
        .driver         = {
                .name   = "imx-uart",
                .of_match_table = imx_uart_dt_ids,
+               .pm     = &imx_serial_port_pm_ops,
        },
 };
 
index 4ccc0397664cad0a244d74195b2cc0950631b359..b88832e8ee82273f3a1062f272980d6586b99300 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -740,7 +739,6 @@ static const struct of_device_id ltq_asc_match[] = {
        { .compatible = DRVNAME },
        {},
 };
-MODULE_DEVICE_TABLE(of, ltq_asc_match);
 
 static struct platform_driver lqasc_driver = {
        .driver         = {
@@ -764,8 +762,4 @@ init_lqasc(void)
 
        return ret;
 }
-
-module_init(init_lqasc);
-
-MODULE_DESCRIPTION("Lantiq serial port driver");
-MODULE_LICENSE("GPL");
+device_initcall(init_lqasc);
index 35c55505b3eb32e38536c2abbce86cfe523b6288..b90e7b30468b3c885b84b379e1cfa98993993f73 100644 (file)
@@ -392,7 +392,6 @@ static irqreturn_t men_z135_intr(int irq, void *data)
        struct men_z135_port *uart = (struct men_z135_port *)data;
        struct uart_port *port = &uart->port;
        bool handled = false;
-       unsigned long flags;
        int irq_id;
 
        uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
@@ -401,7 +400,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
        if (!irq_id)
                goto out;
 
-       spin_lock_irqsave(&port->lock, flags);
+       spin_lock(&port->lock);
        /* It's save to write to IIR[7:6] RXC[9:8] */
        iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
 
@@ -427,7 +426,7 @@ static irqreturn_t men_z135_intr(int irq, void *data)
                handled = true;
        }
 
-       spin_unlock_irqrestore(&port->lock, flags);
+       spin_unlock(&port->lock);
 out:
        return IRQ_RETVAL(handled);
 }
@@ -717,7 +716,7 @@ static void men_z135_set_termios(struct uart_port *port,
 
        baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
 
-       spin_lock(&port->lock);
+       spin_lock_irq(&port->lock);
        if (tty_termios_baud_rate(termios))
                tty_termios_encode_baud_rate(termios, baud, baud);
 
@@ -725,7 +724,7 @@ static void men_z135_set_termios(struct uart_port *port,
        iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
 
        uart_update_timeout(port, termios->c_cflag, baud);
-       spin_unlock(&port->lock);
+       spin_unlock_irq(&port->lock);
 }
 
 static const char *men_z135_type(struct uart_port *port)
@@ -840,7 +839,6 @@ static int men_z135_probe(struct mcb_device *mdev,
        uart->port.membase = NULL;
        uart->mdev = mdev;
 
-       spin_lock_init(&uart->port.lock);
        spin_lock_init(&uart->lock);
 
        err = uart_add_one_port(&men_z135_driver, &uart->port);
index 6fc07eb9d74ef6b9b4c2d81ae98c91c822f61e47..41de374d9784384ece372732e972a3de7c52e84f 100644 (file)
@@ -239,8 +239,9 @@ static int mpc52xx_psc_tx_rdy(struct uart_port *port)
 
 static int mpc52xx_psc_tx_empty(struct uart_port *port)
 {
-       return in_be16(&PSC(port)->mpc52xx_psc_status)
-           & MPC52xx_PSC_SR_TXEMP;
+       u16 sts = in_be16(&PSC(port)->mpc52xx_psc_status);
+
+       return (sts & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
 }
 
 static void mpc52xx_psc_start_tx(struct uart_port *port)
index 13cf7738fbdc915d66333e2bccc3928f8d56db20..7c7f30809849d24d337f8f2eedf4a83ed23907f1 100644 (file)
 #define AUART_CTRL2_TXE                                (1 << 8)
 #define AUART_CTRL2_UARTEN                     (1 << 0)
 
+#define AUART_LINECTRL_BAUD_DIV_MAX            0x003fffc0
+#define AUART_LINECTRL_BAUD_DIV_MIN            0x000000ec
 #define AUART_LINECTRL_BAUD_DIVINT_SHIFT       16
 #define AUART_LINECTRL_BAUD_DIVINT_MASK                0xffff0000
 #define AUART_LINECTRL_BAUD_DIVINT(v)          (((v) & 0xffff) << 16)
@@ -659,7 +661,7 @@ static void mxs_auart_settermios(struct uart_port *u,
 {
        struct mxs_auart_port *s = to_auart_port(u);
        u32 bm, ctrl, ctrl2, div;
-       unsigned int cflag, baud;
+       unsigned int cflag, baud, baud_min, baud_max;
 
        cflag = termios->c_cflag;
 
@@ -752,7 +754,9 @@ static void mxs_auart_settermios(struct uart_port *u,
        }
 
        /* set baud rate */
-       baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
+       baud_min = DIV_ROUND_UP(u->uartclk * 32, AUART_LINECTRL_BAUD_DIV_MAX);
+       baud_max = u->uartclk * 32 / AUART_LINECTRL_BAUD_DIV_MIN;
+       baud = uart_get_baud_rate(u, termios, old, baud_min, baud_max);
        div = u->uartclk * 32 / baud;
        ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
        ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
@@ -842,7 +846,7 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
        return IRQ_HANDLED;
 }
 
-static void mxs_auart_reset(struct uart_port *u)
+static void mxs_auart_reset_deassert(struct uart_port *u)
 {
        int i;
        unsigned int reg;
@@ -858,6 +862,30 @@ static void mxs_auart_reset(struct uart_port *u)
        writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
 }
 
+static void mxs_auart_reset_assert(struct uart_port *u)
+{
+       int i;
+       u32 reg;
+
+       reg = readl(u->membase + AUART_CTRL0);
+       /* if already in reset state, keep it untouched */
+       if (reg & AUART_CTRL0_SFTRST)
+               return;
+
+       writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+       writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET);
+
+       for (i = 0; i < 1000; i++) {
+               reg = readl(u->membase + AUART_CTRL0);
+               /* reset is finished when the clock is gated */
+               if (reg & AUART_CTRL0_CLKGATE)
+                       return;
+               udelay(10);
+       }
+
+       dev_err(u->dev, "Failed to reset the unit.");
+}
+
 static int mxs_auart_startup(struct uart_port *u)
 {
        int ret;
@@ -867,7 +895,13 @@ static int mxs_auart_startup(struct uart_port *u)
        if (ret)
                return ret;
 
-       writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+       if (uart_console(u)) {
+               writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+       } else {
+               /* reset the unit to a well known state */
+               mxs_auart_reset_assert(u);
+               mxs_auart_reset_deassert(u);
+       }
 
        writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
 
@@ -899,12 +933,14 @@ static void mxs_auart_shutdown(struct uart_port *u)
        if (auart_dma_enabled(s))
                mxs_auart_dma_exit(s);
 
-       writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
-
-       writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
-                       u->membase + AUART_INTR_CLR);
-
-       writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+       if (uart_console(u)) {
+               writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
+               writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
+                               u->membase + AUART_INTR_CLR);
+               writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+       } else {
+               mxs_auart_reset_assert(u);
+       }
 
        clk_disable_unprepare(s->clk);
 }
@@ -1291,7 +1327,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
 
        auart_port[s->port.line] = s;
 
-       mxs_auart_reset(&s->port);
+       mxs_auart_reset_deassert(&s->port);
 
        ret = uart_add_one_port(&auart_driver, &s->port);
        if (ret)
index 67d0c213b1c72bad58272800091eb2f8a466e9cd..856686d6dcdbc61adbadc5ae6c0d86dbdf2c18d9 100644 (file)
@@ -53,7 +53,6 @@
 #include "samsung.h"
 
 #if    defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
-       defined(CONFIG_DEBUG_LL) &&             \
        !defined(MODULE)
 
 extern void printascii(const char *);
@@ -295,15 +294,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
        if (ourport->tx_mode != S3C24XX_TX_DMA)
                enable_tx_dma(ourport);
 
-       while (xmit->tail & (dma_get_cache_alignment() - 1)) {
-               if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
-                       return 0;
-               wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-               count--;
-       }
-
        dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
        dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
 
@@ -342,7 +332,9 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
                return;
        }
 
-       if (!ourport->dma || !ourport->dma->tx_chan || count < port->fifosize)
+       if (!ourport->dma || !ourport->dma->tx_chan ||
+           count < ourport->min_dma_size ||
+           xmit->tail & (dma_get_cache_alignment() - 1))
                s3c24xx_serial_start_tx_pio(ourport);
        else
                s3c24xx_serial_start_tx_dma(ourport, count);
@@ -736,15 +728,20 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
        struct uart_port *port = &ourport->port;
        struct circ_buf *xmit = &port->state->xmit;
        unsigned long flags;
-       int count;
+       int count, dma_count = 0;
 
        spin_lock_irqsave(&port->lock, flags);
 
        count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 
-       if (ourport->dma && ourport->dma->tx_chan && count >= port->fifosize) {
-               s3c24xx_serial_start_tx_dma(ourport, count);
-               goto out;
+       if (ourport->dma && ourport->dma->tx_chan &&
+           count >= ourport->min_dma_size) {
+               int align = dma_get_cache_alignment() -
+                       (xmit->tail & (dma_get_cache_alignment() - 1));
+               if (count-align >= ourport->min_dma_size) {
+                       dma_count = count-align;
+                       count = align;
+               }
        }
 
        if (port->x_char) {
@@ -765,14 +762,24 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
 
        /* try and drain the buffer... */
 
-       count = port->fifosize;
-       while (!uart_circ_empty(xmit) && count-- > 0) {
+       if (count > port->fifosize) {
+               count = port->fifosize;
+               dma_count = 0;
+       }
+
+       while (!uart_circ_empty(xmit) && count > 0) {
                if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
                        break;
 
                wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                port->icount.tx++;
+               count--;
+       }
+
+       if (!count && dma_count) {
+               s3c24xx_serial_start_tx_dma(ourport, dma_count);
+               goto out;
        }
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
@@ -1838,6 +1845,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
        else if (ourport->info->fifosize)
                ourport->port.fifosize = ourport->info->fifosize;
 
+       /*
+        * DMA transfers must be aligned at least to cache line size,
+        * so find minimal transfer size suitable for DMA mode
+        */
+       ourport->min_dma_size = max_t(int, ourport->port.fifosize,
+                                   dma_get_cache_alignment());
+
        probe_index++;
 
        dbg("%s: initialising port %p...\n", __func__, ourport);
index d275032aa68d47ee68c42a0370ff7eecc42fb192..fc5deaa4f382def3e5d1bfe69497302a6c3a4abb 100644 (file)
@@ -82,6 +82,7 @@ struct s3c24xx_uart_port {
        unsigned char                   tx_claimed;
        unsigned int                    pm_level;
        unsigned long                   baudclk_rate;
+       unsigned int                    min_dma_size;
 
        unsigned int                    rx_irq;
        unsigned int                    tx_irq;
index 5ccc698cbbfa1ad9bde91200ea5907753fbb4b78..72ffd0dcab78459106abd44dc8da667c180c01b1 100644 (file)
@@ -11,6 +11,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -29,6 +31,7 @@
 #include <linux/uaccess.h>
 
 #define SC16IS7XX_NAME                 "sc16is7xx"
+#define SC16IS7XX_MAX_DEVS             8
 
 /* SC16IS7XX register definitions */
 #define SC16IS7XX_RHR_REG              (0x00) /* RX FIFO */
@@ -312,14 +315,14 @@ struct sc16is7xx_one_config {
 
 struct sc16is7xx_one {
        struct uart_port                port;
+       u8                              line;
        struct kthread_work             tx_work;
        struct kthread_work             reg_work;
        struct sc16is7xx_one_config     config;
 };
 
 struct sc16is7xx_port {
-       struct uart_driver              uart;
-       struct sc16is7xx_devtype        *devtype;
+       const struct sc16is7xx_devtype  *devtype;
        struct regmap                   *regmap;
        struct clk                      *clk;
 #ifdef CONFIG_GPIOLIB
@@ -332,16 +335,31 @@ struct sc16is7xx_port {
        struct sc16is7xx_one            p[0];
 };
 
+static unsigned long sc16is7xx_lines;
+
+static struct uart_driver sc16is7xx_uart = {
+       .owner          = THIS_MODULE,
+       .dev_name       = "ttySC",
+       .nr             = SC16IS7XX_MAX_DEVS,
+};
+
 #define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
 #define to_sc16is7xx_one(p,e)  ((container_of((p), struct sc16is7xx_one, e)))
 
+static int sc16is7xx_line(struct uart_port *port)
+{
+       struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+
+       return one->line;
+}
+
 static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
 {
        struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
        unsigned int val = 0;
+       const u8 line = sc16is7xx_line(port);
 
-       regmap_read(s->regmap,
-                   (reg << SC16IS7XX_REG_SHIFT) | port->line, &val);
+       regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
 
        return val;
 }
@@ -349,15 +367,16 @@ static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
 static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
 {
        struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+       const u8 line = sc16is7xx_line(port);
 
-       regmap_write(s->regmap,
-                    (reg << SC16IS7XX_REG_SHIFT) | port->line, val);
+       regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
 }
 
 static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
 {
        struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-       u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | port->line;
+       const u8 line = sc16is7xx_line(port);
+       u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | line;
 
        regcache_cache_bypass(s->regmap, true);
        regmap_raw_read(s->regmap, addr, s->buf, rxlen);
@@ -367,7 +386,8 @@ static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
 static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
 {
        struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-       u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | port->line;
+       const u8 line = sc16is7xx_line(port);
+       u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
 
        regcache_cache_bypass(s->regmap, true);
        regmap_raw_write(s->regmap, addr, s->buf, to_send);
@@ -378,12 +398,24 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
                                  u8 mask, u8 val)
 {
        struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+       const u8 line = sc16is7xx_line(port);
 
-       regmap_update_bits(s->regmap,
-                          (reg << SC16IS7XX_REG_SHIFT) | port->line,
+       regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
                           mask, val);
 }
 
+static int sc16is7xx_alloc_line(void)
+{
+       int i;
+
+       BUILD_BUG_ON(SC16IS7XX_MAX_DEVS > BITS_PER_LONG);
+
+       for (i = 0; i < SC16IS7XX_MAX_DEVS; i++)
+               if (!test_and_set_bit(i, &sc16is7xx_lines))
+                       break;
+
+       return i;
+}
 
 static void sc16is7xx_power(struct uart_port *port, int on)
 {
@@ -508,7 +540,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
 
        if (unlikely(rxlen >= sizeof(s->buf))) {
                dev_warn_ratelimited(port->dev,
-                                    "Port %i: Possible RX FIFO overrun: %d\n",
+                                    "ttySC%i: Possible RX FIFO overrun: %d\n",
                                     port->line, rxlen);
                port->icount.buf_overrun++;
                /* Ensure sanity of RX level */
@@ -649,7 +681,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
                        break;
                default:
                        dev_err_ratelimited(port->dev,
-                                           "Port %i: Unexpected interrupt: %x",
+                                           "ttySC%i: Unexpected interrupt: %x",
                                            port->line, iir);
                        break;
                }
@@ -661,7 +693,7 @@ static void sc16is7xx_ist(struct kthread_work *ws)
        struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
        int i;
 
-       for (i = 0; i < s->uart.nr; ++i)
+       for (i = 0; i < s->devtype->nr_uart; ++i)
                sc16is7xx_port_irq(s, i);
 }
 
@@ -1099,7 +1131,7 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
 #endif
 
 static int sc16is7xx_probe(struct device *dev,
-                          struct sc16is7xx_devtype *devtype,
+                          const struct sc16is7xx_devtype *devtype,
                           struct regmap *regmap, int irq, unsigned long flags)
 {
        struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
@@ -1134,23 +1166,13 @@ static int sc16is7xx_probe(struct device *dev,
        s->devtype = devtype;
        dev_set_drvdata(dev, s);
 
-       /* Register UART driver */
-       s->uart.owner           = THIS_MODULE;
-       s->uart.dev_name        = "ttySC";
-       s->uart.nr              = devtype->nr_uart;
-       ret = uart_register_driver(&s->uart);
-       if (ret) {
-               dev_err(dev, "Registering UART driver failed\n");
-               goto out_clk;
-       }
-
        init_kthread_worker(&s->kworker);
        init_kthread_work(&s->irq_work, sc16is7xx_ist);
        s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
                                      "sc16is7xx");
        if (IS_ERR(s->kworker_task)) {
                ret = PTR_ERR(s->kworker_task);
-               goto out_uart;
+               goto out_clk;
        }
        sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param);
 
@@ -1174,8 +1196,8 @@ static int sc16is7xx_probe(struct device *dev,
 #endif
 
        for (i = 0; i < devtype->nr_uart; ++i) {
+               s->p[i].line            = i;
                /* Initialize port data */
-               s->p[i].port.line       = i;
                s->p[i].port.dev        = dev;
                s->p[i].port.irq        = irq;
                s->p[i].port.type       = PORT_SC16IS7XX;
@@ -1185,6 +1207,12 @@ static int sc16is7xx_probe(struct device *dev,
                s->p[i].port.uartclk    = freq;
                s->p[i].port.rs485_config = sc16is7xx_config_rs485;
                s->p[i].port.ops        = &sc16is7xx_ops;
+               s->p[i].port.line       = sc16is7xx_alloc_line();
+               if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
+                       ret = -ENOMEM;
+                       goto out_ports;
+               }
+
                /* Disable all interrupts */
                sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
                /* Disable TX/RX */
@@ -1195,7 +1223,7 @@ static int sc16is7xx_probe(struct device *dev,
                init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
                init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
                /* Register port */
-               uart_add_one_port(&s->uart, &s->p[i].port);
+               uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);
                /* Go to suspend mode */
                sc16is7xx_power(&s->p[i].port, 0);
        }
@@ -1206,8 +1234,11 @@ static int sc16is7xx_probe(struct device *dev,
        if (!ret)
                return 0;
 
-       for (i = 0; i < s->uart.nr; i++)
-               uart_remove_one_port(&s->uart, &s->p[i].port);
+out_ports:
+       for (i--; i >= 0; i--) {
+               uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
+               clear_bit(s->p[i].port.line, &sc16is7xx_lines);
+       }
 
 #ifdef CONFIG_GPIOLIB
        if (devtype->nr_gpio)
@@ -1217,9 +1248,6 @@ out_thread:
 #endif
        kthread_stop(s->kworker_task);
 
-out_uart:
-       uart_unregister_driver(&s->uart);
-
 out_clk:
        if (!IS_ERR(s->clk))
                clk_disable_unprepare(s->clk);
@@ -1237,15 +1265,15 @@ static int sc16is7xx_remove(struct device *dev)
                gpiochip_remove(&s->gpio);
 #endif
 
-       for (i = 0; i < s->uart.nr; i++) {
-               uart_remove_one_port(&s->uart, &s->p[i].port);
+       for (i = 0; i < s->devtype->nr_uart; i++) {
+               uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
+               clear_bit(s->p[i].port.line, &sc16is7xx_lines);
                sc16is7xx_power(&s->p[i].port, 0);
        }
 
        flush_kthread_worker(&s->kworker);
        kthread_stop(s->kworker_task);
 
-       uart_unregister_driver(&s->uart);
        if (!IS_ERR(s->clk))
                clk_disable_unprepare(s->clk);
 
@@ -1275,7 +1303,7 @@ static struct regmap_config regcfg = {
 #ifdef CONFIG_SERIAL_SC16IS7XX_SPI
 static int sc16is7xx_spi_probe(struct spi_device *spi)
 {
-       struct sc16is7xx_devtype *devtype;
+       const struct sc16is7xx_devtype *devtype;
        unsigned long flags = 0;
        struct regmap *regmap;
        int ret;
@@ -1344,7 +1372,7 @@ MODULE_ALIAS("spi:sc16is7xx");
 static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
                               const struct i2c_device_id *id)
 {
-       struct sc16is7xx_devtype *devtype;
+       const struct sc16is7xx_devtype *devtype;
        unsigned long flags = 0;
        struct regmap *regmap;
 
@@ -1385,7 +1413,6 @@ MODULE_DEVICE_TABLE(i2c, sc16is7xx_i2c_id_table);
 static struct i2c_driver sc16is7xx_i2c_uart_driver = {
        .driver = {
                .name           = SC16IS7XX_NAME,
-               .owner          = THIS_MODULE,
                .of_match_table = of_match_ptr(sc16is7xx_dt_ids),
        },
        .probe          = sc16is7xx_i2c_probe,
@@ -1398,7 +1425,14 @@ MODULE_ALIAS("i2c:sc16is7xx");
 
 static int __init sc16is7xx_init(void)
 {
-       int ret = 0;
+       int ret;
+
+       ret = uart_register_driver(&sc16is7xx_uart);
+       if (ret) {
+               pr_err("Registering UART driver failed\n");
+               return ret;
+       }
+
 #ifdef CONFIG_SERIAL_SC16IS7XX_I2C
        ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
        if (ret < 0) {
@@ -1427,6 +1461,7 @@ static void __exit sc16is7xx_exit(void)
 #ifdef CONFIG_SERIAL_SC16IS7XX_SPI
        spi_unregister_driver(&sc16is7xx_spi_uart_driver);
 #endif
+       uart_unregister_driver(&sc16is7xx_uart);
 }
 module_exit(sc16is7xx_exit);
 
index f36852067f20e61ebaf67269ec08c37ea342c06a..603d2cc3f424f691c53f2ccb7c91efd4cf8ae9a5 100644 (file)
@@ -1377,7 +1377,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
        struct uart_state *state = tty->driver_data;
        struct tty_port *port;
        struct uart_port *uport;
-       unsigned long flags;
 
        if (!state) {
                struct uart_driver *drv = tty->driver->driver_state;
@@ -1403,10 +1402,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
         * disable the receive line status interrupts.
         */
        if (port->flags & ASYNC_INITIALIZED) {
-               unsigned long flags;
-               spin_lock_irqsave(&uport->lock, flags);
+               spin_lock_irq(&uport->lock);
                uport->ops->stop_rx(uport);
-               spin_unlock_irqrestore(&uport->lock, flags);
+               spin_unlock_irq(&uport->lock);
                /*
                 * Before we drop DTR, make sure the UART transmitter
                 * has completely drained; this is especially
@@ -1419,17 +1417,17 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
        uart_shutdown(tty, state);
        tty_port_tty_set(port, NULL);
 
-       spin_lock_irqsave(&port->lock, flags);
+       spin_lock_irq(&port->lock);
 
        if (port->blocked_open) {
-               spin_unlock_irqrestore(&port->lock, flags);
+               spin_unlock_irq(&port->lock);
                if (port->close_delay)
                        msleep_interruptible(jiffies_to_msecs(port->close_delay));
-               spin_lock_irqsave(&port->lock, flags);
+               spin_lock_irq(&port->lock);
        } else if (!uart_console(uport)) {
-               spin_unlock_irqrestore(&port->lock, flags);
+               spin_unlock_irq(&port->lock);
                uart_change_pm(state, UART_PM_STATE_OFF);
-               spin_lock_irqsave(&port->lock, flags);
+               spin_lock_irq(&port->lock);
        }
 
        /*
@@ -1437,7 +1435,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
         */
        clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
        clear_bit(ASYNCB_CLOSING, &port->flags);
-       spin_unlock_irqrestore(&port->lock, flags);
+       spin_unlock_irq(&port->lock);
        wake_up_interruptible(&port->open_wait);
        wake_up_interruptible(&port->close_wait);
 
@@ -1532,11 +1530,6 @@ static void uart_hangup(struct tty_struct *tty)
        mutex_unlock(&port->mutex);
 }
 
-static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
-{
-       return 0;
-}
-
 static void uart_port_shutdown(struct tty_port *port)
 {
        struct uart_state *state = container_of(port, struct uart_state, port);
@@ -2379,8 +2372,6 @@ static const struct tty_operations uart_ops = {
 };
 
 static const struct tty_port_operations uart_port_ops = {
-       .activate       = uart_port_activate,
-       .shutdown       = uart_port_shutdown,
        .carrier_raised = uart_carrier_raised,
        .dtr_rts        = uart_dtr_rts,
 };
index 653cdd5fb5088281049faa58c71566cd3a7aac5b..c6657de789977c9015899a2a2d581d68c81c349b 100644 (file)
@@ -413,7 +413,6 @@ sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count)
                        break;
        }
 
-       sirfport->rx_io_count += rx_count;
        port->icount.rx += rx_count;
 
        return rx_count;
@@ -600,7 +599,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
        struct sirfsoc_uart_port *sirfport = to_sirfport(port);
        struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
        struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-       sirfport->rx_io_count = 0;
        wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
                rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
                ~SIRFUART_IO_MODE);
@@ -632,31 +630,6 @@ static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port)
                                sirfport->uart_reg->uart_type));
 }
 
-static void sirfsoc_uart_start_rx(struct uart_port *port)
-{
-       struct sirfsoc_uart_port *sirfport = to_sirfport(port);
-       struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
-       struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-
-       sirfport->rx_io_count = 0;
-       wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
-       wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
-       wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
-       if (sirfport->rx_dma_chan)
-               sirfsoc_uart_start_next_rx_dma(port);
-       else {
-               if (!sirfport->is_atlas7)
-                       wr_regl(port, ureg->sirfsoc_int_en_reg,
-                               rd_regl(port, ureg->sirfsoc_int_en_reg) |
-                               SIRFUART_RX_IO_INT_EN(uint_en,
-                                       sirfport->uart_reg->uart_type));
-               else
-                       wr_regl(port, ureg->sirfsoc_int_en_reg,
-                               SIRFUART_RX_IO_INT_EN(uint_en,
-                                       sirfport->uart_reg->uart_type));
-       }
-}
-
 static unsigned int
 sirfsoc_usp_calc_sample_div(unsigned long set_rate,
                unsigned long ioclk_rate, unsigned long *sample_reg)
@@ -850,7 +823,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
        rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000);
        rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
        txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op);
-       wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_STOP);
        wr_regl(port, ureg->sirfsoc_tx_fifo_op,
                        (txfifo_op_reg & ~SIRFUART_FIFO_START));
        if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
@@ -886,9 +858,13 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
        else
                wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
        if (sirfport->rx_dma_chan)
-               wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
+               wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+                       rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
+                       ~SIRFUART_IO_MODE);
        else
-               wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
+               wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+                       rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
+                       SIRFUART_IO_MODE);
        sirfport->rx_period_time = 20000000;
        /* Reset Rx/Tx FIFO Threshold level for proper baudrate */
        if (set_baud < 1000000)
@@ -902,7 +878,6 @@ static void sirfsoc_uart_set_termios(struct uart_port *port,
        txfifo_op_reg |= SIRFUART_FIFO_START;
        wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg);
        uart_update_timeout(port, termios->c_cflag, set_baud);
-       sirfsoc_uart_start_rx(port);
        wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN);
        spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -921,6 +896,7 @@ static int sirfsoc_uart_startup(struct uart_port *port)
 {
        struct sirfsoc_uart_port *sirfport      = to_sirfport(port);
        struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+       struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
        unsigned int index                      = port->line;
        int ret;
        irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
@@ -958,9 +934,9 @@ static int sirfsoc_uart_startup(struct uart_port *port)
        wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
        if (sirfport->rx_dma_chan)
                wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
-                       SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
-                       SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
-                       SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
+                       SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) |
+                       SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) |
+                       SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4));
        if (sirfport->tx_dma_chan) {
                sirfport->tx_dma_state = TX_DMA_IDLE;
                wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
@@ -981,16 +957,41 @@ static int sirfsoc_uart_startup(struct uart_port *port)
                        goto init_rx_err;
                }
        }
-       enable_irq(port->irq);
+       if (sirfport->uart_reg->uart_type == SIRF_REAL_UART &&
+               sirfport->rx_dma_chan)
+               wr_regl(port, ureg->sirfsoc_swh_dma_io,
+                       SIRFUART_CLEAR_RX_ADDR_EN);
+       if (sirfport->uart_reg->uart_type == SIRF_USP_UART &&
+                       sirfport->rx_dma_chan)
+               wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+                       rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
+                       SIRFSOC_USP_FRADDR_CLR_EN);
        if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) {
                sirfport->is_hrt_enabled = true;
                sirfport->rx_period_time = 20000000;
+               sirfport->rx_last_pos = -1;
+               sirfport->pio_fetch_cnt = 0;
                sirfport->rx_dma_items.xmit.tail =
                        sirfport->rx_dma_items.xmit.head = 0;
                hrtimer_start(&sirfport->hrt,
                        ns_to_ktime(sirfport->rx_period_time),
                        HRTIMER_MODE_REL);
        }
+       wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
+       if (sirfport->rx_dma_chan)
+               sirfsoc_uart_start_next_rx_dma(port);
+       else {
+               if (!sirfport->is_atlas7)
+                       wr_regl(port, ureg->sirfsoc_int_en_reg,
+                               rd_regl(port, ureg->sirfsoc_int_en_reg) |
+                               SIRFUART_RX_IO_INT_EN(uint_en,
+                                       sirfport->uart_reg->uart_type));
+               else
+                       wr_regl(port, ureg->sirfsoc_int_en_reg,
+                               SIRFUART_RX_IO_INT_EN(uint_en,
+                                       sirfport->uart_reg->uart_type));
+       }
+       enable_irq(port->irq);
 
        return 0;
 init_rx_err:
@@ -1003,6 +1004,9 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
 {
        struct sirfsoc_uart_port *sirfport = to_sirfport(port);
        struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+       struct circ_buf *xmit;
+
+       xmit = &sirfport->rx_dma_items.xmit;
        if (!sirfport->is_atlas7)
                wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
        else
@@ -1019,8 +1023,10 @@ static void sirfsoc_uart_shutdown(struct uart_port *port)
        if (sirfport->tx_dma_chan)
                sirfport->tx_dma_state = TX_DMA_IDLE;
        if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
-               while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
-                       SIRFUART_RX_FIFO_MASK) > 0)
+               while (((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+                       SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt) &&
+                       !CIRC_CNT(xmit->head, xmit->tail,
+                       SIRFSOC_RX_DMA_BUF_SIZE))
                        ;
                sirfport->is_hrt_enabled = false;
                hrtimer_cancel(&sirfport->hrt);
@@ -1169,6 +1175,8 @@ static enum hrtimer_restart
        struct tty_struct *tty;
        struct sirfsoc_register *ureg;
        struct circ_buf *xmit;
+       struct sirfsoc_fifo_status *ufifo_st;
+       int max_pio_cnt;
 
        sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
        port = &sirfport->port;
@@ -1176,9 +1184,16 @@ static enum hrtimer_restart
        tty = port->state->port.tty;
        ureg = &sirfport->uart_reg->uart_reg;
        xmit = &sirfport->rx_dma_items.xmit;
+       ufifo_st = &sirfport->uart_reg->fifo_status;
+
        dmaengine_tx_status(sirfport->rx_dma_chan,
-               sirfport->rx_dma_items.cookie, &tx_state);
-       xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
+                       sirfport->rx_dma_items.cookie, &tx_state);
+       if (SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue !=
+               sirfport->rx_last_pos) {
+               xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
+               sirfport->rx_last_pos = xmit->head;
+               sirfport->pio_fetch_cnt = 0;
+       }
        count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
                        SIRFSOC_RX_DMA_BUF_SIZE);
        while (count > 0) {
@@ -1200,23 +1215,38 @@ static enum hrtimer_restart
         */
        if (!inserted && !count &&
                ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
-               SIRFUART_RX_FIFO_MASK) > 0)) {
+               SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt)) {
+               dmaengine_pause(sirfport->rx_dma_chan);
                /* switch to pio mode */
                wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
                        rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
                        SIRFUART_IO_MODE);
-               while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
-                       SIRFUART_RX_FIFO_MASK) > 0) {
-                       if (sirfsoc_uart_pio_rx_chars(port, 16) > 0)
-                               tty_flip_buffer_push(tty->port);
+               /*
+                * UART controller SWH_DMA_IO register have CLEAR_RX_ADDR_EN
+                * When found changing I/O to DMA mode, it clears
+                * two low bits of read point;
+                * USP have similar FRADDR_CLR_EN bit in USP_RX_DMA_IO_CTRL.
+                * Fetch data out from rxfifo into DMA buffer in PIO mode,
+                * while switch back to DMA mode, the data fetched will override
+                * by DMA, as hardware have a strange behaviour:
+                * after switch back to DMA mode, check rxfifo status it will
+                * be the number PIO fetched, so record the fetched data count
+                * to avoid the repeated fetch
+                */
+               max_pio_cnt = 3;
+               while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+                       ufifo_st->ff_empty(port)) && max_pio_cnt--) {
+                       xmit->buf[xmit->head] =
+                               rd_regl(port, ureg->sirfsoc_rx_fifo_data);
+                       xmit->head = (xmit->head + 1) &
+                                       (SIRFSOC_RX_DMA_BUF_SIZE - 1);
+                       sirfport->pio_fetch_cnt++;
                }
-               wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
-               wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
-               wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
                /* switch back to dma mode */
                wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
                        rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
                        ~SIRFUART_IO_MODE);
+               dmaengine_resume(sirfport->rx_dma_chan);
        }
 next_hrt:
        hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
@@ -1239,7 +1269,7 @@ static int sirfsoc_uart_probe(struct platform_device *pdev)
        struct resource *res;
        int ret;
        struct dma_slave_config slv_cfg = {
-               .src_maxburst = 2,
+               .src_maxburst = 1,
        };
        struct dma_slave_config tx_slv_cfg = {
                .dst_maxburst = 2,
index eb162b012eec31bdcff3ec95c167f240c47b262b..c3a885b4d76a73b41a3ed94c0abf920c012b88af 100644 (file)
@@ -296,6 +296,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 #define SIRFUART_DMA_MODE                      0x0
 #define SIRFUART_RX_DMA_FLUSH                  0x4
 
+#define SIRFUART_CLEAR_RX_ADDR_EN              0x2
 /* Baud Rate Calculation */
 #define SIRF_USP_MIN_SAMPLE_DIV                        0x1
 #define SIRF_MIN_SAMPLE_DIV                    0xf
@@ -325,6 +326,7 @@ struct sirfsoc_uart_register sirfsoc_uart = {
 #define SIRFSOC_USP_ASYNC_DIV2_MASK            0x3f
 #define SIRFSOC_USP_ASYNC_DIV2_OFFSET          16
 #define SIRFSOC_USP_LOOP_BACK_CTRL             BIT(2)
+#define SIRFSOC_USP_FRADDR_CLR_EN              BIT(1)
 /* USP-UART Common */
 #define SIRFSOC_UART_RX_TIMEOUT(br, to)        (((br) * (((to) + 999) / 1000)) / 1000)
 #define SIRFUART_RECV_TIMEOUT_VALUE(x) \
@@ -421,7 +423,6 @@ struct sirfsoc_uart_port {
        struct dma_chan                 *tx_dma_chan;
        dma_addr_t                      tx_dma_addr;
        struct dma_async_tx_descriptor  *tx_dma_desc;
-       unsigned int                    rx_io_count;
        unsigned long                   transfer_size;
        enum sirfsoc_tx_state           tx_dma_state;
        unsigned int                    cts_gpio;
@@ -431,6 +432,8 @@ struct sirfsoc_uart_port {
        struct hrtimer                  hrt;
        bool                            is_hrt_enabled;
        unsigned long                   rx_period_time;
+       unsigned long                   rx_last_pos;
+       unsigned long                   pio_fetch_cnt;
 };
 
 /* Register Access Control */
index 33e94e56dcdb085aef32e290222ac9d0f200c689..d4692d888e9da84dd730721dcb949403ccc957e5 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/console.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/circ_buf.h>
 #include <linux/serial_reg.h>
@@ -659,7 +659,7 @@ static void sn_sal_timer_poll(unsigned long data)
  * @port: Our sn_cons_port (which contains the uart port)
  *
  * So this is used by sn_sal_serial_console_init (early on, before we're
- * registered with serial core).  It's also used by sn_sal_module_init
+ * registered with serial core).  It's also used by sn_sal_init
  * right after we've registered with serial core.  The later only happens
  * if we didn't already come through here via sn_sal_serial_console_init.
  *
@@ -709,7 +709,7 @@ static void __init sn_sal_switch_to_asynch(struct sn_cons_port *port)
  * sn_sal_switch_to_interrupts - Switch to interrupt driven mode
  * @port: Our sn_cons_port (which contains the uart port)
  *
- * In sn_sal_module_init, after we're registered with serial core and
+ * In sn_sal_init, after we're registered with serial core and
  * the port is added, this function is called to switch us to interrupt
  * mode.  We were previously in asynch/polling mode (using init_timer).
  *
@@ -773,7 +773,7 @@ static struct uart_driver sal_console_uart = {
 };
 
 /**
- * sn_sal_module_init - When the kernel loads us, get us rolling w/ serial core
+ * sn_sal_init - When the kernel loads us, get us rolling w/ serial core
  *
  * Before this is called, we've been printing kernel messages in a special
  * early mode not making use of the serial core infrastructure.  When our
@@ -781,7 +781,7 @@ static struct uart_driver sal_console_uart = {
  * core and try to enable interrupt driven mode.
  *
  */
-static int __init sn_sal_module_init(void)
+static int __init sn_sal_init(void)
 {
        int retval;
 
@@ -811,7 +811,7 @@ static int __init sn_sal_module_init(void)
 
        if (uart_register_driver(&sal_console_uart) < 0) {
                printk
-                   ("ERROR sn_sal_module_init failed uart_register_driver, line %d\n",
+                   ("ERROR sn_sal_init failed uart_register_driver, line %d\n",
                     __LINE__);
                return -ENODEV;
        }
@@ -832,33 +832,19 @@ static int __init sn_sal_module_init(void)
 
        /* when this driver is compiled in, the console initialization
         * will have already switched us into asynchronous operation
-        * before we get here through the module initcalls */
+        * before we get here through the initcalls */
        if (!sal_console_port.sc_is_asynch) {
                sn_sal_switch_to_asynch(&sal_console_port);
        }
 
-       /* at this point (module_init) we can try to turn on interrupts */
+       /* at this point (device_init) we can try to turn on interrupts */
        if (!IS_RUNNING_ON_SIMULATOR()) {
                sn_sal_switch_to_interrupts(&sal_console_port);
        }
        sn_process_input = 1;
        return 0;
 }
-
-/**
- * sn_sal_module_exit - When we're unloaded, remove the driver/port
- *
- */
-static void __exit sn_sal_module_exit(void)
-{
-       del_timer_sync(&sal_console_port.sc_timer);
-       uart_remove_one_port(&sal_console_uart, &sal_console_port.sc_port);
-       uart_unregister_driver(&sal_console_uart);
-       misc_deregister(&misc);
-}
-
-module_init(sn_sal_module_init);
-module_exit(sn_sal_module_exit);
+device_initcall(sn_sal_init);
 
 /**
  * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
index 4a6eab6da63eb4ed0351764ba467f0bcd247b7e2..e3de9c6d22265746ea1b34ffa822b0a381898b19 100644 (file)
@@ -6,7 +6,7 @@
  * Inspired by st-asc.c from STMicroelectronics (c)
  */
 
-#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#if defined(CONFIG_SERIAL_STM32_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
 
index 6e4ac8db2d79169da320cc028a47423628b51f0f..127472bd6a7cfbbc9416bcb6e1720af59c5149e0 100644 (file)
@@ -10,7 +10,6 @@
  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/tty.h>
@@ -234,14 +233,10 @@ static int __init suncore_init(void)
 {
        return 0;
 }
+device_initcall(suncore_init);
 
-static void __exit suncore_exit(void)
-{
-}
-
-module_init(suncore_init);
-module_exit(suncore_exit);
-
+#if 0 /* ..def MODULE ; never supported as such */
 MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
 MODULE_DESCRIPTION("Sun serial common layer");
 MODULE_LICENSE("GPL");
+#endif
index 534754440fa8e90ada032a2f4246c0ffe00a403c..064031870ba0d1b0bf09fd3bcb299d17dcaf76d5 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
@@ -621,7 +620,6 @@ static const struct of_device_id hv_match[] = {
        },
        {},
 };
-MODULE_DEVICE_TABLE(of, hv_match);
 
 static struct platform_driver hv_driver = {
        .driver = {
@@ -639,16 +637,11 @@ static int __init sunhv_init(void)
 
        return platform_driver_register(&hv_driver);
 }
+device_initcall(sunhv_init);
 
-static void __exit sunhv_exit(void)
-{
-       platform_driver_unregister(&hv_driver);
-}
-
-module_init(sunhv_init);
-module_exit(sunhv_exit);
-
+#if 0 /* ...def MODULE ; never supported as such */
 MODULE_AUTHOR("David S. Miller");
 MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
 MODULE_VERSION("2.0");
 MODULE_LICENSE("GPL");
+#endif
index 7d2532b23969e738cc63f9c952ff737a18b2abea..73190f5d28327ad5a039132726f656258603cd26 100644 (file)
@@ -950,7 +950,7 @@ static void qe_uart_set_termios(struct uart_port *port,
        if ((termios->c_cflag & CREAD) == 0)
                port->read_status_mask &= ~BD_SC_EMPTY;
 
-       baud = uart_get_baud_rate(port, termios, old, 0, 115200);
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
 
        /* Do we really need a spinlock here? */
        spin_lock_irqsave(&port->lock, flags);
index 4cf263d7dffc0bd021924a1bf3f7a363c24e7bbd..5a3fa89138801ea63907ec102fbb589b36d7201c 100644 (file)
@@ -291,12 +291,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
                        n->flags = flags;
                        buf->tail = n;
                        b->commit = b->used;
-                       /* paired w/ barrier in flush_to_ldisc(); ensures the
+                       /* paired w/ acquire in flush_to_ldisc(); ensures the
                         * latest commit value can be read before the head is
                         * advanced to the next buffer
                         */
-                       smp_wmb();
-                       b->next = n;
+                       smp_store_release(&b->next, n);
                } else if (change)
                        size = 0;
                else
@@ -445,7 +444,6 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
                if (count)
                        disc->ops->receive_buf(tty, p, f, count);
        }
-       head->read += count;
        return count;
 }
 
@@ -488,12 +486,11 @@ static void flush_to_ldisc(struct work_struct *work)
                if (atomic_read(&buf->priority))
                        break;
 
-               next = head->next;
-               /* paired w/ barrier in __tty_buffer_request_room();
+               /* paired w/ release in __tty_buffer_request_room();
                 * ensures commit value read is not stale if the head
                 * is advancing to the next buffer
                 */
-               smp_rmb();
+               next = smp_load_acquire(&head->next);
                count = head->commit - head->read;
                if (!count) {
                        if (next == NULL) {
@@ -508,6 +505,7 @@ static void flush_to_ldisc(struct work_struct *work)
                count = receive_buf(tty, head, count);
                if (!count)
                        break;
+               head->read += count;
        }
 
        mutex_unlock(&buf->lock);
index 57fc6ee12332e6932472ac1cc1796d607f114e4f..02785d844354be01b9774ad10e70ab398297c6da 100644 (file)
 #include <linux/nsproxy.h>
 
 #undef TTY_DEBUG_HANGUP
+#ifdef TTY_DEBUG_HANGUP
+# define tty_debug_hangup(tty, f, args...)     tty_debug(tty, f, ##args)
+#else
+# define tty_debug_hangup(tty, f, args...)     do { } while (0)
+#endif
 
 #define TTY_PARANOIA_CHECK 1
 #define CHECK_TTY_COUNT 1
@@ -388,33 +393,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
 int tty_check_change(struct tty_struct *tty)
 {
        unsigned long flags;
+       struct pid *pgrp;
        int ret = 0;
 
        if (current->signal->tty != tty)
                return 0;
 
+       rcu_read_lock();
+       pgrp = task_pgrp(current);
+
        spin_lock_irqsave(&tty->ctrl_lock, flags);
 
        if (!tty->pgrp) {
                printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
                goto out_unlock;
        }
-       if (task_pgrp(current) == tty->pgrp)
+       if (pgrp == tty->pgrp)
                goto out_unlock;
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
        if (is_ignored(SIGTTOU))
-               goto out;
+               goto out_rcuunlock;
        if (is_current_pgrp_orphaned()) {
                ret = -EIO;
-               goto out;
+               goto out_rcuunlock;
        }
-       kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+       kill_pgrp(pgrp, SIGTTOU, 1);
+       rcu_read_unlock();
        set_thread_flag(TIF_SIGPENDING);
        ret = -ERESTARTSYS;
-out:
        return ret;
 out_unlock:
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+out_rcuunlock:
+       rcu_read_unlock();
        return ret;
 }
 
@@ -524,7 +536,8 @@ static void __proc_set_tty(struct tty_struct *tty)
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        tty->session = get_pid(task_session(current));
        if (current->signal->tty) {
-               printk(KERN_DEBUG "tty not NULL!!\n");
+               tty_debug(tty, "current tty %s not NULL!!\n",
+                         current->signal->tty->name);
                tty_kref_put(current->signal->tty);
        }
        put_pid(current->signal->tty_old_pgrp);
@@ -766,9 +779,7 @@ static void do_tty_hangup(struct work_struct *work)
 
 void tty_hangup(struct tty_struct *tty)
 {
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s hangup...\n", tty_name(tty));
-#endif
+       tty_debug_hangup(tty, "\n");
        schedule_work(&tty->hangup_work);
 }
 
@@ -785,9 +796,7 @@ EXPORT_SYMBOL(tty_hangup);
 
 void tty_vhangup(struct tty_struct *tty)
 {
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty));
-#endif
+       tty_debug_hangup(tty, "\n");
        __tty_hangup(tty, 0);
 }
 
@@ -824,9 +833,7 @@ void tty_vhangup_self(void)
 
 static void tty_vhangup_session(struct tty_struct *tty)
 {
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty));
-#endif
+       tty_debug_hangup(tty, "\n");
        __tty_hangup(tty, 1);
 }
 
@@ -920,12 +927,8 @@ void disassociate_ctty(int on_exit)
                tty->pgrp = NULL;
                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                tty_kref_put(tty);
-       } else {
-#ifdef TTY_DEBUG_HANGUP
-               printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
-                      " = NULL", tty);
-#endif
-       }
+       } else
+               tty_debug_hangup(tty, "no current tty\n");
 
        spin_unlock_irq(&current->sighand->siglock);
        /* Now clear signal->tty under the lock */
@@ -1705,8 +1708,7 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
 {
 #ifdef TTY_PARANOIA_CHECK
        if (idx < 0 || idx >= tty->driver->num) {
-               printk(KERN_DEBUG "%s: bad idx when trying to free (%s)\n",
-                               __func__, tty->name);
+               tty_debug(tty, "bad idx %d\n", idx);
                return -1;
        }
 
@@ -1715,20 +1717,20 @@ static int tty_release_checks(struct tty_struct *tty, int idx)
                return 0;
 
        if (tty != tty->driver->ttys[idx]) {
-               printk(KERN_DEBUG "%s: driver.table[%d] not tty for (%s)\n",
-                               __func__, idx, tty->name);
+               tty_debug(tty, "bad driver table[%d] = %p\n",
+                         idx, tty->driver->ttys[idx]);
                return -1;
        }
        if (tty->driver->other) {
                struct tty_struct *o_tty = tty->link;
 
                if (o_tty != tty->driver->other->ttys[idx]) {
-                       printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n",
-                                       __func__, idx, tty->name);
+                       tty_debug(tty, "bad other table[%d] = %p\n",
+                                 idx, tty->driver->other->ttys[idx]);
                        return -1;
                }
                if (o_tty->link != tty) {
-                       printk(KERN_DEBUG "%s: bad pty pointers\n", __func__);
+                       tty_debug(tty, "bad link = %p\n", o_tty->link);
                        return -1;
                }
        }
@@ -1782,10 +1784,7 @@ int tty_release(struct inode *inode, struct file *filp)
                return 0;
        }
 
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
-                       tty_name(tty), tty->count);
-#endif
+       tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count);
 
        if (tty->ops->close)
                tty->ops->close(tty, filp);
@@ -1895,9 +1894,7 @@ int tty_release(struct inode *inode, struct file *filp)
        if (!final)
                return 0;
 
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty));
-#endif
+       tty_debug_hangup(tty, "final close\n");
        /*
         * Ask the line discipline code to release its structures
         */
@@ -1906,10 +1903,7 @@ int tty_release(struct inode *inode, struct file *filp)
        /* Wait for pending work before tty destruction commmences */
        tty_flush_works(tty);
 
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__,
-              tty_name(tty));
-#endif
+       tty_debug_hangup(tty, "freeing structure...\n");
        /*
         * The release_tty function takes care of the details of clearing
         * the slots and preserving the termios structure. The tty_unlock_pair
@@ -2098,9 +2092,9 @@ retry_open:
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
            tty->driver->subtype == PTY_TYPE_MASTER)
                noctty = 1;
-#ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "%s: opening %s...\n", __func__, tty->name);
-#endif
+
+       tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
+
        if (tty->ops->open)
                retval = tty->ops->open(tty, filp);
        else
@@ -2108,10 +2102,8 @@ retry_open:
        filp->f_flags = saved_flags;
 
        if (retval) {
-#ifdef TTY_DEBUG_HANGUP
-               printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
-                               retval, tty->name);
-#endif
+               tty_debug_hangup(tty, "error %d, releasing...\n", retval);
+
                tty_unlock(tty); /* need to call tty_release without BTM */
                tty_release(inode, filp);
                if (retval != -ERESTARTSYS)
@@ -3160,9 +3152,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
                unsigned int index, unsigned int count)
 {
        /* init here, since reused cdevs cause crashes */
-       cdev_init(&driver->cdevs[index], &tty_fops);
-       driver->cdevs[index].owner = driver->owner;
-       return cdev_add(&driver->cdevs[index], dev, count);
+       driver->cdevs[index] = cdev_alloc();
+       if (!driver->cdevs[index])
+               return -ENOMEM;
+       cdev_init(driver->cdevs[index], &tty_fops);
+       driver->cdevs[index]->owner = driver->owner;
+       return cdev_add(driver->cdevs[index], dev, count);
 }
 
 /**
@@ -3268,8 +3263,10 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 
 error:
        put_device(dev);
-       if (cdev)
-               cdev_del(&driver->cdevs[index]);
+       if (cdev) {
+               cdev_del(driver->cdevs[index]);
+               driver->cdevs[index] = NULL;
+       }
        return ERR_PTR(retval);
 }
 EXPORT_SYMBOL_GPL(tty_register_device_attr);
@@ -3289,8 +3286,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
 {
        device_destroy(tty_class,
                MKDEV(driver->major, driver->minor_start) + index);
-       if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC))
-               cdev_del(&driver->cdevs[index]);
+       if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+               cdev_del(driver->cdevs[index]);
+               driver->cdevs[index] = NULL;
+       }
 }
 EXPORT_SYMBOL(tty_unregister_device);
 
@@ -3355,6 +3354,7 @@ err_free_all:
        kfree(driver->ports);
        kfree(driver->ttys);
        kfree(driver->termios);
+       kfree(driver->cdevs);
        kfree(driver);
        return ERR_PTR(err);
 }
@@ -3383,7 +3383,7 @@ static void destruct_tty_driver(struct kref *kref)
                }
                proc_tty_unregister_driver(driver);
                if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
-                       cdev_del(&driver->cdevs[0]);
+                       cdev_del(driver->cdevs[0]);
        }
        kfree(driver->cdevs);
        kfree(driver->ports);
index 5232fb60b0b16b9a235ee6cc090104380899b173..9c5aebfe7053cbcae1fd65a95f3312509525e8e6 100644 (file)
 
 #undef TTY_DEBUG_WAIT_UNTIL_SENT
 
+#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
+# define tty_debug_wait_until_sent(tty, f, args...)    tty_debug(tty, f, ##args)
+#else
+# define tty_debug_wait_until_sent(tty, f, args...)    do {} while (0)
+#endif
+
 #undef DEBUG
 
 /*
@@ -210,9 +216,8 @@ int tty_unthrottle_safe(struct tty_struct *tty)
 
 void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 {
-#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
-       printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty));
-#endif
+       tty_debug_wait_until_sent(tty, "\n");
+
        if (!timeout)
                timeout = MAX_SCHEDULE_TIMEOUT;
 
index c07fb5d9bcf9b5429689a908417021fb5716e8f9..71750cbac31f745a6a899bc598cf0af1b84556b2 100644 (file)
@@ -22,9 +22,7 @@
 #undef LDISC_DEBUG_HANGUP
 
 #ifdef LDISC_DEBUG_HANGUP
-#define tty_ldisc_debug(tty, f, args...) ({                              \
-       printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty), ##args); \
-})
+#define tty_ldisc_debug(tty, f, args...)       tty_debug(tty, f, ##args)
 #else
 #define tty_ldisc_debug(tty, f, args...)
 #endif
@@ -449,6 +447,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
                ret = ld->ops->open(tty);
                if (ret)
                        clear_bit(TTY_LDISC_OPEN, &tty->flags);
+
+               tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc);
                return ret;
        }
        return 0;
@@ -469,6 +469,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
        clear_bit(TTY_LDISC_OPEN, &tty->flags);
        if (ld->ops->close)
                ld->ops->close(tty);
+       tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc);
 }
 
 /**
@@ -662,7 +663,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
        int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
        int err = 0;
 
-       tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
+       tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc);
 
        ld = tty_ldisc_ref(tty);
        if (ld != NULL) {
@@ -712,7 +713,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
        if (reset)
                tty_reset_termios(tty);
 
-       tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
+       tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc);
 }
 
 /**
@@ -776,8 +777,6 @@ void tty_ldisc_release(struct tty_struct *tty)
         * it does not race with the set_ldisc code path.
         */
 
-       tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
-
        tty_ldisc_lock_pair(tty, o_tty);
        tty_ldisc_kill(tty);
        if (o_tty)
@@ -787,7 +786,7 @@ void tty_ldisc_release(struct tty_struct *tty)
        /* And the memory resources remaining (buffers, termios) will be
           disposed of when the kref hits zero */
 
-       tty_ldisc_debug(tty, "ldisc closed\n");
+       tty_ldisc_debug(tty, "released\n");
 }
 
 /**
index 48fb1d983f6c6adb00480bc4f6abb3cb229f4d65..52c98ce1b6febf02df27ae4be8c031db8d14acc3 100644 (file)
@@ -127,7 +127,7 @@ config UIO_FSL_ELBC_GPCM_NETX5152
 config UIO_PRUSS
        tristate "Texas Instruments PRUSS driver"
        select GENERIC_ALLOCATOR
-       depends on HAS_IOMEM
+       depends on HAS_IOMEM && HAS_DMA
        help
          PRUSS driver for OMAPL138/DA850/AM18XX devices
          PRUSS driver requires user space components, examples and user space
index 3257d4220d0102e876b8aa7888865797a616123e..8196581f54c2b95ed65619824573e4d9c3c4000a 100644 (file)
@@ -896,6 +896,7 @@ static int __init uio_init(void)
 static void __exit uio_exit(void)
 {
        release_uio_class();
+       idr_destroy(&uio_idr);
 }
 
 module_init(uio_init)
index b6cac91c2ced038ff36fce598b6c648294464564..2bcf80c159c18ff39f7fddc05f86c363296471e6 100644 (file)
@@ -480,19 +480,7 @@ static struct platform_driver uio_fsl_elbc_gpcm_driver = {
        .probe = uio_fsl_elbc_gpcm_probe,
        .remove = uio_fsl_elbc_gpcm_remove,
 };
-
-static int __init uio_fsl_elbc_gpcm_init(void)
-{
-       return platform_driver_register(&uio_fsl_elbc_gpcm_driver);
-}
-
-static void __exit uio_fsl_elbc_gpcm_exit(void)
-{
-       platform_driver_unregister(&uio_fsl_elbc_gpcm_driver);
-}
-
-module_init(uio_fsl_elbc_gpcm_init);
-module_exit(uio_fsl_elbc_gpcm_exit);
+module_platform_driver(uio_fsl_elbc_gpcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>");
index 813d4d3a51c699a8987c8f95fac0beed20248024..1173f9cbc137ef1b175a84de7d2c8c81219323f5 100644 (file)
@@ -270,6 +270,7 @@ static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
 static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
 {
        static char *str[] = { "no", "yes" };
+
        if (unlikely(value >= ARRAY_SIZE(str)))
                return snprintf(buf, PAGE_SIZE, "%u\n", value);
        return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
@@ -278,6 +279,7 @@ static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
 static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
 {
        static char *str[] = { NULL, "not connected", "connected", "lost" };
+
        if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
                return snprintf(buf, PAGE_SIZE, "%u\n", value);
        return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
@@ -702,6 +704,7 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ
        len = ret / 4;
        for (offb = 0; offb < len; ) {
                int l = le32_to_cpu(buf[offb++]);
+
                if (l < 0 || l > stride || l > (len - offb) / 2) {
                        if (printk_ratelimit())
                                usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n",
@@ -732,6 +735,7 @@ cleanup:
 static int cxacru_card_status(struct cxacru_data *instance)
 {
        int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
+
        if (ret < 0) {          /* firmware not loaded */
                usb_dbg(instance->usbatm, "cxacru_adsl_start: CARD_GET_STATUS returned %d\n", ret);
                return ret;
@@ -945,6 +949,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw,
        offb = offd = 0;
        do {
                int l = min_t(int, stride, size - offd);
+
                buf[offb++] = fw;
                buf[offb++] = l;
                buf[offb++] = code1;
@@ -1091,8 +1096,8 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
 {
        const struct firmware *fw, *bp;
        struct cxacru_data *instance = usbatm_instance->driver_data;
-
        int ret = cxacru_find_firmware(instance, "fw", &fw);
+
        if (ret) {
                usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
                return ret;
index 3cb9bda51ddfde76f991581736af7fb6e111a4e3..e462f55c8b996a3c15af54160c80060d8db2c7b5 100644 (file)
@@ -25,6 +25,9 @@
 #define VERSION                      (0xF << 25)
 #define CIVERSION            (0x7 << 29)
 
+/* SBUSCFG */
+#define AHBBRST_MASK           0x7
+
 /* HCCPARAMS */
 #define HCCPARAMS_LEN         BIT(17)
 
 #define DEVICEADDR_USBADRA    BIT(24)
 #define DEVICEADDR_USBADR     (0x7FUL << 25)
 
+/* TTCTRL */
+#define TTCTRL_TTHA_MASK       (0x7fUL << 24)
+/* Set non-zero value for internal TT Hub address representation */
+#define TTCTRL_TTHA            (0x7fUL << 24)
+
+/* BURSTSIZE */
+#define RX_BURST_MASK          0xff
+#define TX_BURST_MASK          0xff00
+
 /* PORTSC */
 #define PORTSC_CCS            BIT(0)
 #define PORTSC_CSC            BIT(1)
index 6d6200e37b71e02b0e0d4a67cdd35f160f61de3b..41d7cf6d63ba32a240add0eaa7c01f63fa8b1f28 100644 (file)
@@ -50,6 +50,8 @@ enum ci_hw_regs {
        OP_USBINTR,
        OP_DEVICEADDR,
        OP_ENDPTLISTADDR,
+       OP_TTCTRL,
+       OP_BURSTSIZE,
        OP_PORTSC,
        OP_DEVLC,
        OP_OTGSC,
@@ -406,8 +408,11 @@ static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
 static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
 {
 #ifdef CONFIG_USB_OTG_FSM
+       struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps;
+
        return ci->is_otg && ci->roles[CI_ROLE_HOST] &&
-                                       ci->roles[CI_ROLE_GADGET];
+               ci->roles[CI_ROLE_GADGET] && (otg_caps->srp_support ||
+               otg_caps->hnp_support || otg_caps->adp_support);
 #else
        return false;
 #endif
@@ -426,4 +431,6 @@ u8 hw_port_test_get(struct ci_hdrc *ci);
 int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
                                u32 value, unsigned int timeout_ms);
 
+void ci_platform_configure(struct ci_hdrc *ci);
+
 #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
index 389f0e0342596410c89b6c61b52b8907d90f9c0d..867e9f3f385959b5add2aad6b9c831f82949c809 100644 (file)
@@ -29,26 +29,31 @@ struct ci_hdrc_imx_platform_flag {
 };
 
 static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
+               CI_HDRC_DISABLE_STREAMING,
 };
 
 static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
        .flags = CI_HDRC_IMX28_WRITE_FIX |
-               CI_HDRC_TURN_VBUS_EARLY_ON,
+               CI_HDRC_TURN_VBUS_EARLY_ON |
+               CI_HDRC_DISABLE_STREAMING,
 };
 
 static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
-               CI_HDRC_TURN_VBUS_EARLY_ON,
+               CI_HDRC_TURN_VBUS_EARLY_ON |
+               CI_HDRC_DISABLE_STREAMING,
 };
 
 static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
-               CI_HDRC_TURN_VBUS_EARLY_ON,
+               CI_HDRC_TURN_VBUS_EARLY_ON |
+               CI_HDRC_DISABLE_HOST_STREAMING,
 };
 
 static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
-               CI_HDRC_TURN_VBUS_EARLY_ON,
+               CI_HDRC_TURN_VBUS_EARLY_ON |
+               CI_HDRC_DISABLE_HOST_STREAMING,
 };
 
 static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
@@ -104,7 +109,7 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
        misc_pdev = of_find_device_by_node(args.np);
        of_node_put(args.np);
 
-       if (!misc_pdev)
+       if (!misc_pdev || !platform_get_drvdata(misc_pdev))
                return ERR_PTR(-EPROBE_DEFER);
 
        data->dev = &misc_pdev->dev;
@@ -126,7 +131,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
        struct ci_hdrc_platform_data pdata = {
                .name           = dev_name(&pdev->dev),
                .capoffset      = DEF_CAPOFFSET,
-               .flags          = CI_HDRC_DISABLE_STREAMING,
+               .flags          = CI_HDRC_SET_NON_ZERO_TTHA,
        };
        int ret;
        const struct of_device_id *of_id =
index 3ad48e1c0c57e1722311c8393ad3bd21712fa1e7..3feebf7f31f09259249c76fa121f747a2380ff9e 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/regulator/consumer.h>
+#include <linux/usb/ehci_def.h>
 
 #include "ci.h"
 #include "udc.h"
@@ -84,6 +85,8 @@ static const u8 ci_regs_nolpm[] = {
        [OP_USBINTR]            = 0x08U,
        [OP_DEVICEADDR]         = 0x14U,
        [OP_ENDPTLISTADDR]      = 0x18U,
+       [OP_TTCTRL]             = 0x1CU,
+       [OP_BURSTSIZE]          = 0x20U,
        [OP_PORTSC]             = 0x44U,
        [OP_DEVLC]              = 0x84U,
        [OP_OTGSC]              = 0x64U,
@@ -106,6 +109,8 @@ static const u8 ci_regs_lpm[] = {
        [OP_USBINTR]            = 0x08U,
        [OP_DEVICEADDR]         = 0x14U,
        [OP_ENDPTLISTADDR]      = 0x18U,
+       [OP_TTCTRL]             = 0x1CU,
+       [OP_BURSTSIZE]          = 0x20U,
        [OP_PORTSC]             = 0x44U,
        [OP_DEVLC]              = 0x84U,
        [OP_OTGSC]              = 0xC4U,
@@ -118,7 +123,7 @@ static const u8 ci_regs_lpm[] = {
        [OP_ENDPTCTRL]          = 0xECU,
 };
 
-static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
+static void hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
 {
        int i;
 
@@ -134,7 +139,6 @@ static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
                         ? ci_regs_lpm[OP_ENDPTCTRL]
                         : ci_regs_nolpm[OP_ENDPTCTRL]);
 
-       return 0;
 }
 
 static enum ci_revision ci_get_revision(struct ci_hdrc *ci)
@@ -403,6 +407,55 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
        return ret;
 }
 
+
+/**
+ * ci_platform_configure: do controller configure
+ * @ci: the controller
+ *
+ */
+void ci_platform_configure(struct ci_hdrc *ci)
+{
+       bool is_device_mode, is_host_mode;
+
+       is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC;
+       is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC;
+
+       if (is_device_mode &&
+               (ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING))
+               hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
+       if (is_host_mode &&
+               (ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING))
+               hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
+       if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
+               if (ci->hw_bank.lpm)
+                       hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
+               else
+                       hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
+       }
+
+       if (ci->platdata->flags & CI_HDRC_SET_NON_ZERO_TTHA)
+               hw_write(ci, OP_TTCTRL, TTCTRL_TTHA_MASK, TTCTRL_TTHA);
+
+       hw_write(ci, OP_USBCMD, 0xff0000, ci->platdata->itc_setting << 16);
+
+       if (ci->platdata->flags & CI_HDRC_OVERRIDE_AHB_BURST)
+               hw_write_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK,
+                       ci->platdata->ahb_burst_config);
+
+       /* override burst size, take effect only when ahb_burst_config is 0 */
+       if (!hw_read_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK)) {
+               if (ci->platdata->flags & CI_HDRC_OVERRIDE_TX_BURST)
+                       hw_write(ci, OP_BURSTSIZE, TX_BURST_MASK,
+                       ci->platdata->tx_burst_size << __ffs(TX_BURST_MASK));
+
+               if (ci->platdata->flags & CI_HDRC_OVERRIDE_RX_BURST)
+                       hw_write(ci, OP_BURSTSIZE, RX_BURST_MASK,
+                               ci->platdata->rx_burst_size);
+       }
+}
+
 /**
  * hw_controller_reset: do controller reset
  * @ci: the controller
@@ -447,16 +500,6 @@ int hw_device_reset(struct ci_hdrc *ci)
                ci->platdata->notify_event(ci,
                        CI_HDRC_CONTROLLER_RESET_EVENT);
 
-       if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
-               hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
-
-       if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
-               if (ci->hw_bank.lpm)
-                       hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
-               else
-                       hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
-       }
-
        /* USBMODE should be configured step by step */
        hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
        hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_DC);
@@ -469,6 +512,8 @@ int hw_device_reset(struct ci_hdrc *ci)
                return -ENODEV;
        }
 
+       ci_platform_configure(ci);
+
        return 0;
 }
 
@@ -560,6 +605,8 @@ static irqreturn_t ci_irq(int irq, void *data)
 static int ci_get_platdata(struct device *dev,
                struct ci_hdrc_platform_data *platdata)
 {
+       int ret;
+
        if (!platdata->phy_mode)
                platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
 
@@ -588,9 +635,66 @@ static int ci_get_platdata(struct device *dev,
                                of_usb_host_tpl_support(dev->of_node);
        }
 
+       if (platdata->dr_mode == USB_DR_MODE_OTG) {
+               /* We can support HNP and SRP of OTG 2.0 */
+               platdata->ci_otg_caps.otg_rev = 0x0200;
+               platdata->ci_otg_caps.hnp_support = true;
+               platdata->ci_otg_caps.srp_support = true;
+
+               /* Update otg capabilities by DT properties */
+               ret = of_usb_update_otg_caps(dev->of_node,
+                                       &platdata->ci_otg_caps);
+               if (ret)
+                       return ret;
+       }
+
        if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
                platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
 
+       platdata->itc_setting = 1;
+       if (of_find_property(dev->of_node, "itc-setting", NULL)) {
+               ret = of_property_read_u32(dev->of_node, "itc-setting",
+                       &platdata->itc_setting);
+               if (ret) {
+                       dev_err(dev,
+                               "failed to get itc-setting\n");
+                       return ret;
+               }
+       }
+
+       if (of_find_property(dev->of_node, "ahb-burst-config", NULL)) {
+               ret = of_property_read_u32(dev->of_node, "ahb-burst-config",
+                       &platdata->ahb_burst_config);
+               if (ret) {
+                       dev_err(dev,
+                               "failed to get ahb-burst-config\n");
+                       return ret;
+               }
+               platdata->flags |= CI_HDRC_OVERRIDE_AHB_BURST;
+       }
+
+       if (of_find_property(dev->of_node, "tx-burst-size-dword", NULL)) {
+               ret = of_property_read_u32(dev->of_node, "tx-burst-size-dword",
+                       &platdata->tx_burst_size);
+               if (ret) {
+                       dev_err(dev,
+                               "failed to get tx-burst-size-dword\n");
+                       return ret;
+               }
+               platdata->flags |= CI_HDRC_OVERRIDE_TX_BURST;
+       }
+
+       if (of_find_property(dev->of_node, "rx-burst-size-dword", NULL)) {
+               ret = of_property_read_u32(dev->of_node, "rx-burst-size-dword",
+                       &platdata->rx_burst_size);
+               if (ret) {
+                       dev_err(dev,
+                               "failed to get rx-burst-size-dword\n");
+                       return ret;
+               }
+               platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST;
+       }
+
        return 0;
 }
 
index 5b7061a331038d36ad20b7ec3c05b2ab1f8b3efc..080b7be3daf034939bd12c509353c041b6027f49 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/usb/phy.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/otg-fsm.h>
+#include <linux/usb/chipidea.h>
 
 #include "ci.h"
 #include "udc.h"
@@ -66,9 +67,11 @@ static int ci_port_test_show(struct seq_file *s, void *data)
        unsigned long flags;
        unsigned mode;
 
+       pm_runtime_get_sync(ci->dev);
        spin_lock_irqsave(&ci->lock, flags);
        mode = hw_port_test_get(ci);
        spin_unlock_irqrestore(&ci->lock, flags);
+       pm_runtime_put_sync(ci->dev);
 
        seq_printf(s, "mode = %u\n", mode);
 
@@ -98,9 +101,11 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
        if (sscanf(buf, "%u", &mode) != 1)
                return -EINVAL;
 
+       pm_runtime_get_sync(ci->dev);
        spin_lock_irqsave(&ci->lock, flags);
        ret = hw_port_test_set(ci, mode);
        spin_unlock_irqrestore(&ci->lock, flags);
+       pm_runtime_put_sync(ci->dev);
 
        return ret ? ret : count;
 }
@@ -316,8 +321,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
        if (role == CI_ROLE_END || role == ci->role)
                return -EINVAL;
 
+       pm_runtime_get_sync(ci->dev);
        ci_role_stop(ci);
        ret = ci_role_start(ci, role);
+       pm_runtime_put_sync(ci->dev);
 
        return ret ? ret : count;
 }
index 7161439def19aa265c9f36530d3d97d63ecc51a7..3d24304405b36f358a56d7a8dc6a881804b62df9 100644 (file)
@@ -37,15 +37,14 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
 
 struct ehci_ci_priv {
        struct regulator *reg_vbus;
-       struct ci_hdrc *ci;
 };
 
 static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
-       struct ci_hdrc *ci = priv->ci;
        struct device *dev = hcd->self.controller;
+       struct ci_hdrc *ci = dev_get_drvdata(dev);
        int ret = 0;
        int port = HCS_N_PORTS(ehci->hcs_params);
 
@@ -78,9 +77,25 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
        return 0;
 };
 
+static int ehci_ci_reset(struct usb_hcd *hcd)
+{
+       struct device *dev = hcd->self.controller;
+       struct ci_hdrc *ci = dev_get_drvdata(dev);
+       int ret;
+
+       ret = ehci_setup(hcd);
+       if (ret)
+               return ret;
+
+       ci_platform_configure(ci);
+
+       return ret;
+}
+
 static const struct ehci_driver_overrides ehci_ci_overrides = {
        .extra_priv_size = sizeof(struct ehci_ci_priv),
        .port_power      = ehci_ci_portpower,
+       .reset           = ehci_ci_reset,
 };
 
 static irqreturn_t host_irq(struct ci_hdrc *ci)
@@ -123,7 +138,6 @@ static int host_start(struct ci_hdrc *ci)
 
        priv = (struct ehci_ci_priv *)ehci->priv;
        priv->reg_vbus = NULL;
-       priv->ci = ci;
 
        if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
                if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
@@ -153,12 +167,6 @@ static int host_start(struct ci_hdrc *ci)
                }
        }
 
-       if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
-               hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
-
-       if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED)
-               hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
-
        return ret;
 
 disable_reg:
index 19d655a743b55eb8e17f4308bc722a40bfe4e505..00ab59d45da1bf6708b3d77e3cfcfe31ac4e2304 100644 (file)
@@ -525,7 +525,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
                ci_role_start(ci, CI_ROLE_HOST);
        } else {
                ci_role_stop(ci);
-               hw_device_reset(ci);
                ci_role_start(ci, CI_ROLE_GADGET);
        }
        return 0;
index 764f668d45a9bb6ad4cde8ea0f4a8b0661dead86..a637da25dda0204d4b5d991903412fbf8fe0497b 100644 (file)
@@ -445,7 +445,7 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
                rest -= count;
        }
 
-       if (hwreq->req.zero && hwreq->req.length
+       if (hwreq->req.zero && hwreq->req.length && hwep->dir == TX
            && (hwreq->req.length % hwep->ep.maxpacket == 0))
                add_td_to_list(hwep, hwreq, 0);
 
@@ -1090,6 +1090,13 @@ __acquires(ci->lock)
                                if (ci_otg_is_fsm_mode(ci))
                                        err = otg_a_alt_hnp_support(ci);
                                break;
+                       case USB_DEVICE_A_HNP_SUPPORT:
+                               if (ci_otg_is_fsm_mode(ci)) {
+                                       ci->gadget.a_hnp_support = 1;
+                                       err = isr_setup_status_phase(
+                                                       ci);
+                               }
+                               break;
                        default:
                                goto delegate;
                        }
@@ -1624,6 +1631,20 @@ static int init_eps(struct ci_hdrc *ci)
 
                        hwep->ep.name      = hwep->name;
                        hwep->ep.ops       = &usb_ep_ops;
+
+                       if (i == 0) {
+                               hwep->ep.caps.type_control = true;
+                       } else {
+                               hwep->ep.caps.type_iso = true;
+                               hwep->ep.caps.type_bulk = true;
+                               hwep->ep.caps.type_int = true;
+                       }
+
+                       if (j == TX)
+                               hwep->ep.caps.dir_in = true;
+                       else
+                               hwep->ep.caps.dir_out = true;
+
                        /*
                         * for ep0: maxP defined in desc, for other
                         * eps, maxP is set by epautoconfig() called
@@ -1827,6 +1848,7 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
 static int udc_start(struct ci_hdrc *ci)
 {
        struct device *dev = ci->dev;
+       struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps;
        int retval = 0;
 
        spin_lock_init(&ci->lock);
@@ -1834,8 +1856,12 @@ static int udc_start(struct ci_hdrc *ci)
        ci->gadget.ops          = &usb_gadget_ops;
        ci->gadget.speed        = USB_SPEED_UNKNOWN;
        ci->gadget.max_speed    = USB_SPEED_HIGH;
-       ci->gadget.is_otg       = ci->is_otg ? 1 : 0;
        ci->gadget.name         = ci->platdata->name;
+       ci->gadget.otg_caps     = otg_caps;
+
+       if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support ||
+                                               otg_caps->adp_support))
+               ci->gadget.is_otg = 1;
 
        INIT_LIST_HEAD(&ci->gadget.ep_list);
 
index 3cefd49ddb00facd9e70cc83336e922d3e596eec..5ddab30ee240937d15d54cda0ad6642ea02247b5 100644 (file)
@@ -54,6 +54,7 @@
 #define MX53_USB_PHYCTRL1_PLLDIV_MASK  0x3
 #define MX53_USB_PLL_DIV_24_MHZ                0x01
 
+#define MX6_BM_NON_BURST_SETTING       BIT(1)
 #define MX6_BM_OVER_CUR_DIS            BIT(7)
 #define MX6_BM_WAKEUP_ENABLE           BIT(10)
 #define MX6_BM_ID_WAKEUP               BIT(16)
@@ -255,14 +256,21 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
        if (data->index > 3)
                return -EINVAL;
 
+       spin_lock_irqsave(&usbmisc->lock, flags);
+
        if (data->disable_oc) {
-               spin_lock_irqsave(&usbmisc->lock, flags);
                reg = readl(usbmisc->base + data->index * 4);
                writel(reg | MX6_BM_OVER_CUR_DIS,
                        usbmisc->base + data->index * 4);
-               spin_unlock_irqrestore(&usbmisc->lock, flags);
        }
 
+       /* SoC non-burst setting */
+       reg = readl(usbmisc->base + data->index * 4);
+       writel(reg | MX6_BM_NON_BURST_SETTING,
+                       usbmisc->base + data->index * 4);
+
+       spin_unlock_irqrestore(&usbmisc->lock, flags);
+
        usbmisc_imx6q_set_wakeup(data, false);
 
        return 0;
index f38e875a3fb19d10e00773607c3d37fb7dd28b8d..433bbc34a8a481ff15c8070e9917ecf1ec1455e8 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/mutex.h>
 #undef DEBUG
 #include <linux/usb.h>
+#include <linux/usb/ch9.h>
 #include <linux/ratelimit.h>
 
 /*
 #define IOCNR_SOFT_RESET               7
 /* Get device_id string: */
 #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
-/* The following ioctls were added for http://hpoj.sourceforge.net: */
-/* Get two-int array:
- * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
- * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
+/* The following ioctls were added for http://hpoj.sourceforge.net:
+ * Get two-int array:
+ * [0]=current protocol
+ *     (1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2,
+ *         3=USB_CLASS_PRINTER/1/3),
+ * [1]=supported protocol mask (mask&(1<<n)!=0 means
+ *     USB_CLASS_PRINTER/1/n supported):
+ */
 #define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
-/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
+/*
+ * Set protocol
+ *     (arg: 1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2,
+ *         3=USB_CLASS_PRINTER/1/3):
+ */
 #define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
 /* Set channel number (HP Vendor-specific command): */
 #define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
@@ -146,8 +155,10 @@ struct usblp {
        int                     readcount;              /* Counter for reads */
        int                     ifnum;                  /* Interface number */
        struct usb_interface    *intf;                  /* The interface */
-       /* Alternate-setting numbers and endpoints for each protocol
-        * (7/1/{index=1,2,3}) that the device supports: */
+       /*
+        * Alternate-setting numbers and endpoints for each protocol
+        * (USB_CLASS_PRINTER/1/{index=1,2,3}) that the device supports:
+        */
        struct {
                int                             alt_setting;
                struct usb_endpoint_descriptor  *epwrite;
@@ -1206,19 +1217,23 @@ abort_ret:
  * but our requirements are too intricate for simple match to handle.
  *
  * The "proto_bias" option may be used to specify the preferred protocol
- * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3).  If the device
- * supports the preferred protocol, then we bind to it.
+ * for all USB printers (1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2,
+ * 3=USB_CLASS_PRINTER/1/3).  If the device supports the preferred protocol,
+ * then we bind to it.
  *
- * The best interface for us is 7/1/2, because it is compatible
- * with a stream of characters. If we find it, we bind to it.
+ * The best interface for us is USB_CLASS_PRINTER/1/2, because it
+ * is compatible with a stream of characters. If we find it, we bind to it.
  *
  * Note that the people from hpoj.sourceforge.net need to be able to
- * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
+ * bind to USB_CLASS_PRINTER/1/3 (MLC/1284.4), so we provide them ioctls
+ * for this purpose.
  *
- * Failing 7/1/2, we look for 7/1/3, even though it's probably not
- * stream-compatible, because this matches the behaviour of the old code.
+ * Failing USB_CLASS_PRINTER/1/2, we look for USB_CLASS_PRINTER/1/3,
+ * even though it's probably not stream-compatible, because this matches
+ * the behaviour of the old code.
  *
- * If nothing else, we bind to 7/1/1 - the unidirectional interface.
+ * If nothing else, we bind to USB_CLASS_PRINTER/1/1
+ * - the unidirectional interface.
  */
 static int usblp_select_alts(struct usblp *usblp)
 {
@@ -1236,7 +1251,8 @@ static int usblp_select_alts(struct usblp *usblp)
        for (i = 0; i < if_alt->num_altsetting; i++) {
                ifd = &if_alt->altsetting[i];
 
-               if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1)
+               if (ifd->desc.bInterfaceClass != USB_CLASS_PRINTER ||
+                   ifd->desc.bInterfaceSubClass != 1)
                        if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS))
                                continue;
 
@@ -1262,8 +1278,10 @@ static int usblp_select_alts(struct usblp *usblp)
                if (!epwrite || (ifd->desc.bInterfaceProtocol > 1 && !epread))
                        continue;
 
-               /* Turn off reads for 7/1/1 (unidirectional) interfaces
-                * and buggy bidirectional printers. */
+               /*
+                * Turn off reads for USB_CLASS_PRINTER/1/1 (unidirectional)
+                * interfaces and buggy bidirectional printers.
+                */
                if (ifd->desc.bInterfaceProtocol == 1) {
                        epread = NULL;
                } else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
@@ -1406,12 +1424,12 @@ static int usblp_resume(struct usb_interface *intf)
 }
 
 static const struct usb_device_id usblp_ids[] = {
-       { USB_DEVICE_INFO(7, 1, 1) },
-       { USB_DEVICE_INFO(7, 1, 2) },
-       { USB_DEVICE_INFO(7, 1, 3) },
-       { USB_INTERFACE_INFO(7, 1, 1) },
-       { USB_INTERFACE_INFO(7, 1, 2) },
-       { USB_INTERFACE_INFO(7, 1, 3) },
+       { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 1) },
+       { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 2) },
+       { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 3) },
+       { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 1) },
+       { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 2) },
+       { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 3) },
        { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */
        { }                                             /* Terminating entry */
 };
index b530fd403ffb2538fd2077515127414323f7012e..9e39286a4e5a1df458339cfbfd3076a3d08125ad 100644 (file)
@@ -154,6 +154,62 @@ bool of_usb_host_tpl_support(struct device_node *np)
        return false;
 }
 EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
+
+/**
+ * of_usb_update_otg_caps - to update usb otg capabilities according to
+ * the passed properties in DT.
+ * @np: Pointer to the given device_node
+ * @otg_caps: Pointer to the target usb_otg_caps to be set
+ *
+ * The function updates the otg capabilities
+ */
+int of_usb_update_otg_caps(struct device_node *np,
+                       struct usb_otg_caps *otg_caps)
+{
+       u32 otg_rev;
+
+       if (!otg_caps)
+               return -EINVAL;
+
+       if (!of_property_read_u32(np, "otg-rev", &otg_rev)) {
+               switch (otg_rev) {
+               case 0x0100:
+               case 0x0120:
+               case 0x0130:
+               case 0x0200:
+                       /* Choose the lesser one if it's already been set */
+                       if (otg_caps->otg_rev)
+                               otg_caps->otg_rev = min_t(u16, otg_rev,
+                                                       otg_caps->otg_rev);
+                       else
+                               otg_caps->otg_rev = otg_rev;
+                       break;
+               default:
+                       pr_err("%s: unsupported otg-rev: 0x%x\n",
+                                               np->full_name, otg_rev);
+                       return -EINVAL;
+               }
+       } else {
+               /*
+                * otg-rev is mandatory for otg properties, if not passed
+                * we set it to be 0 and assume it's a legacy otg device.
+                * Non-dt platform can set it afterwards.
+                */
+               otg_caps->otg_rev = 0;
+       }
+
+       if (of_find_property(np, "hnp-disable", NULL))
+               otg_caps->hnp_support = false;
+       if (of_find_property(np, "srp-disable", NULL))
+               otg_caps->srp_support = false;
+       if (of_find_property(np, "adp-disable", NULL) ||
+                               (otg_caps->otg_rev < 0x0200))
+               otg_caps->adp_support = false;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_usb_update_otg_caps);
+
 #endif
 
 MODULE_LICENSE("GPL");
index 986abde076831921bf33f075a54fa8500630dd58..38ae877c46e3124eb07c2a46ddd33bc66ac54d93 100644 (file)
@@ -103,7 +103,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
 #define snoop(dev, format, arg...)                             \
        do {                                                    \
                if (usbfs_snoop)                                \
-                       dev_info(dev , format , ## arg);        \
+                       dev_info(dev, format, ## arg);          \
        } while (0)
 
 enum snoop_when {
@@ -1082,7 +1082,8 @@ static int proc_bulk(struct usb_dev_state *ps, void __user *arg)
        ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
        if (ret)
                return ret;
-       if (!(tbuf = kmalloc(len1, GFP_KERNEL))) {
+       tbuf = kmalloc(len1, GFP_KERNEL);
+       if (!tbuf) {
                ret = -ENOMEM;
                goto done;
        }
@@ -1224,7 +1225,8 @@ static int proc_setintf(struct usb_dev_state *ps, void __user *arg)
 
        if (copy_from_user(&setintf, arg, sizeof(setintf)))
                return -EFAULT;
-       if ((ret = checkintf(ps, setintf.interface)))
+       ret = checkintf(ps, setintf.interface);
+       if (ret)
                return ret;
 
        destroy_async_on_interface(ps, setintf.interface);
@@ -1319,7 +1321,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
        is_in = (uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0;
 
        u = 0;
-       switch(uurb->type) {
+       switch (uurb->type) {
        case USBDEVFS_URB_TYPE_CONTROL:
                if (!usb_endpoint_xfer_control(&ep->desc))
                        return -EINVAL;
@@ -1393,7 +1395,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
                number_of_packets = uurb->number_of_packets;
                isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) *
                                   number_of_packets;
-               if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+               isopkt = kmalloc(isofrmlen, GFP_KERNEL);
+               if (!isopkt)
                        return -ENOMEM;
                if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
                        ret = -EFAULT;
@@ -1904,7 +1907,8 @@ static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg)
 
        if (get_user(ifnum, (unsigned int __user *)arg))
                return -EFAULT;
-       if ((ret = releaseintf(ps, ifnum)) < 0)
+       ret = releaseintf(ps, ifnum);
+       if (ret < 0)
                return ret;
        destroy_async_on_interface (ps, ifnum);
        return 0;
@@ -1919,7 +1923,8 @@ static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl)
        struct usb_driver       *driver = NULL;
 
        /* alloc buffer */
-       if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) {
+       size = _IOC_SIZE(ctl->ioctl_code);
+       if (size > 0) {
                buf = kmalloc(size, GFP_KERNEL);
                if (buf == NULL)
                        return -ENOMEM;
index 818369afff63f3a6bc53059fc107937f0d6c0b42..6b5063e7943fac720a266478d79b04a352d51e41 100644 (file)
@@ -160,6 +160,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
        spin_lock(&usb_driver->dynids.lock);
        list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {
                struct usb_device_id *id = &dynid->id;
+
                if ((id->idVendor == idVendor) &&
                    (id->idProduct == idProduct)) {
                        list_del(&dynid->node);
index 39a24021fe4d95f3c68017bda07dec443aaf8f4a..101983b7e8d271f7aaedf1b594b4579dfefb489d 100644 (file)
@@ -51,7 +51,7 @@ static ssize_t wMaxPacketSize_show(struct device *dev,
 {
        struct ep_device *ep = to_ep_device(dev);
        return sprintf(buf, "%04x\n",
-                       usb_endpoint_maxp(ep->desc) & 0x07ff);
+                       usb_endpoint_maxp(ep->desc) & 0x07ff);
 }
 static DEVICE_ATTR_RO(wMaxPacketSize);
 
index cbcd0920fb5121ba44bd7c87de9a3b3fdd9f51d6..4d64e5c499e194d3c364543fca9f9e76442684b2 100644 (file)
@@ -2686,12 +2686,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
         * bottom up so that hcds can customize the root hubs before hub_wq
         * starts talking to them.  (Note, bus id is assigned early too.)
         */
-       if ((retval = hcd_buffer_create(hcd)) != 0) {
+       retval = hcd_buffer_create(hcd);
+       if (retval != 0) {
                dev_dbg(hcd->self.controller, "pool alloc failed\n");
                goto err_create_buf;
        }
 
-       if ((retval = usb_register_bus(&hcd->self)) < 0)
+       retval = usb_register_bus(&hcd->self);
+       if (retval < 0)
                goto err_register_bus;
 
        rhdev = usb_alloc_dev(NULL, &hcd->self, 0);
@@ -2737,9 +2739,13 @@ int usb_add_hcd(struct usb_hcd *hcd,
        /* "reset" is misnamed; its role is now one-time init. the controller
         * should already have been reset (and boot firmware kicked off etc).
         */
-       if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
-               dev_err(hcd->self.controller, "can't setup: %d\n", retval);
-               goto err_hcd_driver_setup;
+       if (hcd->driver->reset) {
+               retval = hcd->driver->reset(hcd);
+               if (retval < 0) {
+                       dev_err(hcd->self.controller, "can't setup: %d\n",
+                                       retval);
+                       goto err_hcd_driver_setup;
+               }
        }
        hcd->rh_pollable = 1;
 
@@ -2769,7 +2775,8 @@ int usb_add_hcd(struct usb_hcd *hcd,
        }
 
        /* starting here, usbcore will pay attention to this root hub */
-       if ((retval = register_root_hub(hcd)) != 0)
+       retval = register_root_hub(hcd);
+       if (retval != 0)
                goto err_register_root_hub;
 
        retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
index 73dfa194160b78fba6bec233b667b00bceac6cb1..431839bd291f0b2ab2d66b0019c16f04421efc3e 100644 (file)
@@ -50,8 +50,8 @@ DEFINE_MUTEX(usb_port_peer_mutex);
 
 /* cycle leds on hubs that aren't blinking for attention */
 static bool blinkenlights = 0;
-module_param (blinkenlights, bool, S_IRUGO);
-MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs");
+module_param(blinkenlights, bool, S_IRUGO);
+MODULE_PARM_DESC(blinkenlights, "true to cycle leds on hubs");
 
 /*
  * Device SATA8000 FW1.0 from DATAST0R Technology Corp requires about
@@ -439,7 +439,7 @@ static void set_port_led(struct usb_hub *hub, int port1, int selector)
 
 #define        LED_CYCLE_PERIOD        ((2*HZ)/3)
 
-static void led_work (struct work_struct *work)
+static void led_work(struct work_struct *work)
 {
        struct usb_hub          *hub =
                container_of(work, struct usb_hub, leds.work);
@@ -646,7 +646,7 @@ static void hub_irq(struct urb *urb)
 
        default:                /* presumably an error */
                /* Cause a hub reset after 10 consecutive errors */
-               dev_dbg (hub->intfdev, "transfer --> %d\n", status);
+               dev_dbg(hub->intfdev, "transfer --> %d\n", status);
                if ((++hub->nerrors < 10) || hub->error)
                        goto resubmit;
                hub->error = status;
@@ -671,14 +671,14 @@ resubmit:
        if (hub->quiescing)
                return;
 
-       if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
-                       && status != -ENODEV && status != -EPERM)
-               dev_err (hub->intfdev, "resubmit --> %d\n", status);
+       status = usb_submit_urb(hub->urb, GFP_ATOMIC);
+       if (status != 0 && status != -ENODEV && status != -EPERM)
+               dev_err(hub->intfdev, "resubmit --> %d\n", status);
 }
 
 /* USB 2.0 spec Section 11.24.2.3 */
 static inline int
-hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
+hub_clear_tt_buffer(struct usb_device *hdev, u16 devinfo, u16 tt)
 {
        /* Need to clear both directions for control ep */
        if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) ==
@@ -706,7 +706,7 @@ static void hub_tt_work(struct work_struct *work)
                container_of(work, struct usb_hub, tt.clear_work);
        unsigned long           flags;
 
-       spin_lock_irqsave (&hub->tt.lock, flags);
+       spin_lock_irqsave(&hub->tt.lock, flags);
        while (!list_empty(&hub->tt.clear_list)) {
                struct list_head        *next;
                struct usb_tt_clear     *clear;
@@ -715,14 +715,14 @@ static void hub_tt_work(struct work_struct *work)
                int                     status;
 
                next = hub->tt.clear_list.next;
-               clear = list_entry (next, struct usb_tt_clear, clear_list);
-               list_del (&clear->clear_list);
+               clear = list_entry(next, struct usb_tt_clear, clear_list);
+               list_del(&clear->clear_list);
 
                /* drop lock so HCD can concurrently report other TT errors */
-               spin_unlock_irqrestore (&hub->tt.lock, flags);
-               status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
+               spin_unlock_irqrestore(&hub->tt.lock, flags);
+               status = hub_clear_tt_buffer(hdev, clear->devinfo, clear->tt);
                if (status && status != -ENODEV)
-                       dev_err (&hdev->dev,
+                       dev_err(&hdev->dev,
                                "clear tt %d (%04x) error %d\n",
                                clear->tt, clear->devinfo, status);
 
@@ -734,7 +734,7 @@ static void hub_tt_work(struct work_struct *work)
                kfree(clear);
                spin_lock_irqsave(&hub->tt.lock, flags);
        }
-       spin_unlock_irqrestore (&hub->tt.lock, flags);
+       spin_unlock_irqrestore(&hub->tt.lock, flags);
 }
 
 /**
@@ -797,7 +797,7 @@ int usb_hub_clear_tt_buffer(struct urb *urb)
         */
        clear = kmalloc(sizeof *clear, GFP_ATOMIC);
        if (clear == NULL) {
-               dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
+               dev_err(&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
                /* FIXME recover somehow ... RESET_TT? */
                return -ENOMEM;
        }
@@ -806,10 +806,10 @@ int usb_hub_clear_tt_buffer(struct urb *urb)
        clear->tt = tt->multi ? udev->ttport : 1;
        clear->devinfo = usb_pipeendpoint (pipe);
        clear->devinfo |= udev->devnum << 4;
-       clear->devinfo |= usb_pipecontrol (pipe)
+       clear->devinfo |= usb_pipecontrol(pipe)
                        ? (USB_ENDPOINT_XFER_CONTROL << 11)
                        : (USB_ENDPOINT_XFER_BULK << 11);
-       if (usb_pipein (pipe))
+       if (usb_pipein(pipe))
                clear->devinfo |= 1 << 15;
 
        /* info for completion callback */
@@ -817,10 +817,10 @@ int usb_hub_clear_tt_buffer(struct urb *urb)
        clear->ep = urb->ep;
 
        /* tell keventd to clear state for this TT */
-       spin_lock_irqsave (&tt->lock, flags);
-       list_add_tail (&clear->clear_list, &tt->clear_list);
+       spin_lock_irqsave(&tt->lock, flags);
+       list_add_tail(&clear->clear_list, &tt->clear_list);
        schedule_work(&tt->clear_work);
-       spin_unlock_irqrestore (&tt->lock, flags);
+       spin_unlock_irqrestore(&tt->lock, flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
@@ -1442,8 +1442,8 @@ static int hub_configure(struct usb_hub *hub,
                break;
        }
 
-       spin_lock_init (&hub->tt.lock);
-       INIT_LIST_HEAD (&hub->tt.clear_list);
+       spin_lock_init(&hub->tt.lock);
+       INIT_LIST_HEAD(&hub->tt.clear_list);
        INIT_WORK(&hub->tt.clear_work, hub_tt_work);
        switch (hdev->descriptor.bDeviceProtocol) {
        case USB_HUB_PR_FS:
@@ -1632,7 +1632,7 @@ static int hub_configure(struct usb_hub *hub,
        return 0;
 
 fail:
-       dev_err (hub_dev, "config failed, %s (err %d)\n",
+       dev_err(hub_dev, "config failed, %s (err %d)\n",
                        message, ret);
        /* hub_disconnect() frees urb and descriptor */
        return ret;
@@ -1775,7 +1775,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if ((desc->desc.bInterfaceSubClass != 0) &&
            (desc->desc.bInterfaceSubClass != 1)) {
 descriptor_error:
-               dev_err (&intf->dev, "bad descriptor, ignoring hub\n");
+               dev_err(&intf->dev, "bad descriptor, ignoring hub\n");
                return -EIO;
        }
 
@@ -1790,11 +1790,11 @@ descriptor_error:
                goto descriptor_error;
 
        /* We found a hub */
-       dev_info (&intf->dev, "USB hub found\n");
+       dev_info(&intf->dev, "USB hub found\n");
 
        hub = kzalloc(sizeof(*hub), GFP_KERNEL);
        if (!hub) {
-               dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
+               dev_dbg(&intf->dev, "couldn't kmalloc hub struct\n");
                return -ENOMEM;
        }
 
@@ -1807,7 +1807,7 @@ descriptor_error:
        usb_get_intf(intf);
        usb_get_dev(hdev);
 
-       usb_set_intfdata (intf, hub);
+       usb_set_intfdata(intf, hub);
        intf->needs_remote_wakeup = 1;
        pm_suspend_ignore_children(&intf->dev, true);
 
@@ -1820,14 +1820,14 @@ descriptor_error:
        if (hub_configure(hub, endpoint) >= 0)
                return 0;
 
-       hub_disconnect (intf);
+       hub_disconnect(intf);
        return -ENODEV;
 }
 
 static int
 hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
 {
-       struct usb_device *hdev = interface_to_usbdev (intf);
+       struct usb_device *hdev = interface_to_usbdev(intf);
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
 
        /* assert ifno == 0 (part of hub spec) */
@@ -2143,7 +2143,7 @@ void usb_disconnect(struct usb_device **pdev)
         * cleaning up all state associated with the current configuration
         * so that the hardware is now fully quiesced.
         */
-       dev_dbg (&udev->dev, "unregistering device\n");
+       dev_dbg(&udev->dev, "unregistering device\n");
        usb_disable_device(udev, 0);
        usb_hcd_synchronize_unlinks(udev);
 
@@ -2242,7 +2242,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
                struct usb_bus                  *bus = udev->bus;
 
                /* descriptor may appear anywhere in config */
-               if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
+               if (__usb_get_extra_descriptor(udev->rawdescriptors[0],
                                        le16_to_cpu(udev->config[0].desc.wTotalLength),
                                        USB_DT_OTG, (void **) &desc) == 0) {
                        if (desc->bmAttributes & USB_OTG_HNP) {
@@ -3526,7 +3526,7 @@ static int check_ports_changed(struct usb_hub *hub)
 
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
-       struct usb_hub          *hub = usb_get_intfdata (intf);
+       struct usb_hub          *hub = usb_get_intfdata(intf);
        struct usb_device       *hdev = hub->hdev;
        unsigned                port1;
        int                     status;
@@ -3950,6 +3950,8 @@ int usb_disable_lpm(struct usb_device *udev)
        if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
                goto enable_lpm;
 
+       udev->usb3_lpm_enabled = 0;
+
        return 0;
 
 enable_lpm:
@@ -4007,6 +4009,8 @@ void usb_enable_lpm(struct usb_device *udev)
 
        usb_enable_link_state(hcd, udev, USB3_LPM_U1);
        usb_enable_link_state(hcd, udev, USB3_LPM_U2);
+
+       udev->usb3_lpm_enabled = 1;
 }
 EXPORT_SYMBOL_GPL(usb_enable_lpm);
 
index a6315abe7b7cec272f28265157f1e65a24f71ddb..a95b0c989c216eca774abd0709451096fda19792 100644 (file)
@@ -16,7 +16,7 @@
  * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
  */
 
-static struct usb_device_id whitelist_table [] = {
+static struct usb_device_id whitelist_table[] = {
 
 /* hubs are optional in OTG, but very handy ... */
 { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
index d26973844a4dea0186f759de848c3baf2442088f..cfc68c11c3f565d27bfb9898a9e0d18e7a5d58e6 100644 (file)
@@ -531,6 +531,25 @@ static ssize_t usb2_lpm_besl_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(usb2_lpm_besl);
 
+static ssize_t usb3_hardware_lpm_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev = to_usb_device(dev);
+       const char *p;
+
+       usb_lock_device(udev);
+
+       if (udev->usb3_lpm_enabled)
+               p = "enabled";
+       else
+               p = "disabled";
+
+       usb_unlock_device(udev);
+
+       return sprintf(buf, "%s\n", p);
+}
+static DEVICE_ATTR_RO(usb3_hardware_lpm);
+
 static struct attribute *usb2_hardware_lpm_attr[] = {
        &dev_attr_usb2_hardware_lpm.attr,
        &dev_attr_usb2_lpm_l1_timeout.attr,
@@ -542,6 +561,15 @@ static struct attribute_group usb2_hardware_lpm_attr_group = {
        .attrs  = usb2_hardware_lpm_attr,
 };
 
+static struct attribute *usb3_hardware_lpm_attr[] = {
+       &dev_attr_usb3_hardware_lpm.attr,
+       NULL,
+};
+static struct attribute_group usb3_hardware_lpm_attr_group = {
+       .name   = power_group_name,
+       .attrs  = usb3_hardware_lpm_attr,
+};
+
 static struct attribute *power_attrs[] = {
        &dev_attr_autosuspend.attr,
        &dev_attr_level.attr,
@@ -564,6 +592,9 @@ static int add_power_attributes(struct device *dev)
                if (udev->usb2_hw_lpm_capable == 1)
                        rc = sysfs_merge_group(&dev->kobj,
                                        &usb2_hardware_lpm_attr_group);
+               if (udev->lpm_capable == 1)
+                       rc = sysfs_merge_group(&dev->kobj,
+                                       &usb3_hardware_lpm_attr_group);
        }
 
        return rc;
index 4d47b7c092387fbbf672d9fb5b536ad94633a57c..3ee5b4c77a1f42eeecf1f222ab63e822b1530c9a 100644 (file)
@@ -2880,7 +2880,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
                epctl = readl(hs->regs + epreg);
 
                if (value) {
-                       epctl |= DXEPCTL_STALL + DXEPCTL_SNAK;
+                       epctl |= DXEPCTL_STALL | DXEPCTL_SNAK;
                        if (epctl & DXEPCTL_EPENA)
                                epctl |= DXEPCTL_EPDIS;
                } else {
@@ -3289,6 +3289,19 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
        usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT);
        hs_ep->ep.ops = &s3c_hsotg_ep_ops;
 
+       if (epnum == 0) {
+               hs_ep->ep.caps.type_control = true;
+       } else {
+               hs_ep->ep.caps.type_iso = true;
+               hs_ep->ep.caps.type_bulk = true;
+               hs_ep->ep.caps.type_int = true;
+       }
+
+       if (dir_in)
+               hs_ep->ep.caps.dir_in = true;
+       else
+               hs_ep->ep.caps.dir_out = true;
+
        /*
         * if we're using dma, we need to set the next-endpoint pointer
         * to be something valid.
index dede32e809b624e9d477adb8b465f7149832d9ca..5a42c459040295a98c286ca993f9468a054682ca 100644 (file)
@@ -104,11 +104,4 @@ config USB_DWC3_QCOM
          Recent Qualcomm SoCs ship with one DesignWare Core USB3 IP inside,
          say 'Y' or 'M' if you have one such device.
 
-comment "Debugging features"
-
-config USB_DWC3_DEBUG
-       bool "Enable Debugging Messages"
-       help
-         Say Y here to enable debugging messages on DWC3 Driver.
-
 endif
index c7076e37c4ed79a965eb502ebb6eaf31a1578824..acc951d46c278e2ccfb045ee1b09e438d2209229 100644 (file)
@@ -1,8 +1,6 @@
 # define_trace.h needs to know how to find our header
 CFLAGS_trace.o                         := -I$(src)
 
-ccflags-$(CONFIG_USB_DWC3_DEBUG)       := -DDEBUG
-
 obj-$(CONFIG_USB_DWC3)                 += dwc3.o
 
 dwc3-y                                 := core.o debug.o trace.o
index ff5773c66b84f22b8ffabe986546d2810d0a9864..064123e445664a5e23bb28ba48cfb1755ec7fb88 100644 (file)
@@ -455,8 +455,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
                        reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
                        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
                } else {
-                       dev_warn(dwc->dev, "HSPHY Interface not defined\n");
-
                        /* Relying on default value. */
                        if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
                                break;
index 7bd0a95b2815425d8e088dc39b83e7106177131f..dd5cb5577dcaf62d411fb9776e47a23d4a4dacf7 100644 (file)
@@ -145,7 +145,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 
        exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
        if (IS_ERR(exynos->susp_clk)) {
-               dev_dbg(dev, "no suspend clk specified\n");
+               dev_info(dev, "no suspend clk specified\n");
                exynos->susp_clk = NULL;
        }
        clk_prepare_enable(exynos->susp_clk);
index fe3b9335a74e1d279da69b73e80897ca2a70d5f0..2be268d2423d9339679d38dc0a01982912424b96 100644 (file)
@@ -115,7 +115,7 @@ static int kdwc3_probe(struct platform_device *pdev)
 
        error = clk_prepare_enable(kdwc->clk);
        if (error < 0) {
-               dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
+               dev_err(kdwc->dev, "unable to enable usb clock, error %d\n",
                        error);
                return error;
        }
index 6b486a36863c08dd908df48375d819602672762b..a5a1b7c45743302b5ce9ae78bee9fead19b45de9 100644 (file)
@@ -128,8 +128,7 @@ struct dwc3_omap {
 
        u32                     dma_status:1;
 
-       struct extcon_specific_cable_nb extcon_vbus_dev;
-       struct extcon_specific_cable_nb extcon_id_dev;
+       struct extcon_dev       *edev;
        struct notifier_block   vbus_nb;
        struct notifier_block   id_nb;
 
@@ -225,12 +224,10 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
 
        switch (status) {
        case OMAP_DWC3_ID_GROUND:
-               dev_dbg(omap->dev, "ID GND\n");
-
                if (omap->vbus_reg) {
                        ret = regulator_enable(omap->vbus_reg);
                        if (ret) {
-                               dev_dbg(omap->dev, "regulator enable failed\n");
+                               dev_err(omap->dev, "regulator enable failed\n");
                                return;
                        }
                }
@@ -245,8 +242,6 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
                break;
 
        case OMAP_DWC3_VBUS_VALID:
-               dev_dbg(omap->dev, "VBUS Connect\n");
-
                val = dwc3_omap_read_utmi_ctrl(omap);
                val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND;
                val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG
@@ -261,8 +256,6 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
                        regulator_disable(omap->vbus_reg);
 
        case OMAP_DWC3_VBUS_OFF:
-               dev_dbg(omap->dev, "VBUS Disconnect\n");
-
                val = dwc3_omap_read_utmi_ctrl(omap);
                val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID
                                | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
@@ -273,7 +266,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
                break;
 
        default:
-               dev_dbg(omap->dev, "invalid state\n");
+               dev_WARN(omap->dev, "invalid state\n");
        }
 }
 
@@ -284,37 +277,8 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 
        reg = dwc3_omap_read_irqmisc_status(omap);
 
-       if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
-               dev_dbg(omap->dev, "DMA Disable was Cleared\n");
+       if (reg & USBOTGSS_IRQMISC_DMADISABLECLR)
                omap->dma_status = false;
-       }
-
-       if (reg & USBOTGSS_IRQMISC_OEVT)
-               dev_dbg(omap->dev, "OTG Event\n");
-
-       if (reg & USBOTGSS_IRQMISC_DRVVBUS_RISE)
-               dev_dbg(omap->dev, "DRVVBUS Rise\n");
-
-       if (reg & USBOTGSS_IRQMISC_CHRGVBUS_RISE)
-               dev_dbg(omap->dev, "CHRGVBUS Rise\n");
-
-       if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_RISE)
-               dev_dbg(omap->dev, "DISCHRGVBUS Rise\n");
-
-       if (reg & USBOTGSS_IRQMISC_IDPULLUP_RISE)
-               dev_dbg(omap->dev, "IDPULLUP Rise\n");
-
-       if (reg & USBOTGSS_IRQMISC_DRVVBUS_FALL)
-               dev_dbg(omap->dev, "DRVVBUS Fall\n");
-
-       if (reg & USBOTGSS_IRQMISC_CHRGVBUS_FALL)
-               dev_dbg(omap->dev, "CHRGVBUS Fall\n");
-
-       if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_FALL)
-               dev_dbg(omap->dev, "DISCHRGVBUS Fall\n");
-
-       if (reg & USBOTGSS_IRQMISC_IDPULLUP_FALL)
-               dev_dbg(omap->dev, "IDPULLUP Fall\n");
 
        dwc3_omap_write_irqmisc_status(omap, reg);
 
@@ -434,7 +398,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
                reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
                break;
        default:
-               dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
+               dev_WARN(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
        }
 
        dwc3_omap_write_utmi_ctrl(omap, reg);
@@ -454,23 +418,23 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
                }
 
                omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
-               ret = extcon_register_interest(&omap->extcon_vbus_dev,
-                                              edev->name, "USB",
-                                              &omap->vbus_nb);
+               ret = extcon_register_notifier(edev, EXTCON_USB,
+                                               &omap->vbus_nb);
                if (ret < 0)
                        dev_vdbg(omap->dev, "failed to register notifier for USB\n");
 
                omap->id_nb.notifier_call = dwc3_omap_id_notifier;
-               ret = extcon_register_interest(&omap->extcon_id_dev,
-                                              edev->name, "USB-HOST",
-                                              &omap->id_nb);
+               ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
+                                               &omap->id_nb);
                if (ret < 0)
                        dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
 
-               if (extcon_get_cable_state(edev, "USB") == true)
+               if (extcon_get_cable_state_(edev, EXTCON_USB) == true)
                        dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
-               if (extcon_get_cable_state(edev, "USB-HOST") == true)
+               if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true)
                        dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+
+               omap->edev = edev;
        }
 
        return 0;
@@ -565,11 +529,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
        return 0;
 
 err3:
-       if (omap->extcon_vbus_dev.edev)
-               extcon_unregister_interest(&omap->extcon_vbus_dev);
-       if (omap->extcon_id_dev.edev)
-               extcon_unregister_interest(&omap->extcon_id_dev);
-
+       extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
+       extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
 err2:
        dwc3_omap_disable_irqs(omap);
 
@@ -586,10 +547,8 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 {
        struct dwc3_omap        *omap = platform_get_drvdata(pdev);
 
-       if (omap->extcon_vbus_dev.edev)
-               extcon_unregister_interest(&omap->extcon_vbus_dev);
-       if (omap->extcon_id_dev.edev)
-               extcon_unregister_interest(&omap->extcon_id_dev);
+       extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
+       extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
        dwc3_omap_disable_irqs(omap);
        of_platform_depopulate(omap->dev);
        pm_runtime_put_sync(&pdev->dev);
index 27e4fc896e9d93572c44acef20e25c6cea3a7d10..f62617999f3c7fb093ff09d18088560a6ecb003e 100644 (file)
@@ -83,17 +83,23 @@ static int dwc3_pci_quirks(struct pci_dev *pdev)
                acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
                                          acpi_dwc3_byt_gpios);
 
-               /* These GPIOs will turn on the USB2 PHY */
-               gpio = gpiod_get(&pdev->dev, "cs");
-               if (!IS_ERR(gpio)) {
-                       gpiod_direction_output(gpio, 0);
-                       gpiod_set_value_cansleep(gpio, 1);
-                       gpiod_put(gpio);
-               }
+               /*
+                * These GPIOs will turn on the USB2 PHY. Note that we have to
+                * put the gpio descriptors again here because the phy driver
+                * might want to grab them, too.
+                */
+               gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
+               if (IS_ERR(gpio))
+                       return PTR_ERR(gpio);
+
+               gpiod_set_value_cansleep(gpio, 1);
+               gpiod_put(gpio);
+
+               gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
+               if (IS_ERR(gpio))
+                       return PTR_ERR(gpio);
 
-               gpio = gpiod_get(&pdev->dev, "reset");
-               if (!IS_ERR(gpio)) {
-                       gpiod_direction_output(gpio, 0);
+               if (gpio) {
                        gpiod_set_value_cansleep(gpio, 1);
                        gpiod_put(gpio);
                        usleep_range(10000, 11000);
index 8c2e8eec80c21d24540ebc939be6123c88cc985b..088026048f49f827a8bf5d87d15705140cedf22c 100644 (file)
@@ -48,13 +48,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
 
        qdwc->iface_clk = devm_clk_get(qdwc->dev, "iface");
        if (IS_ERR(qdwc->iface_clk)) {
-               dev_dbg(qdwc->dev, "failed to get optional iface clock\n");
+               dev_info(qdwc->dev, "failed to get optional iface clock\n");
                qdwc->iface_clk = NULL;
        }
 
        qdwc->sleep_clk = devm_clk_get(qdwc->dev, "sleep");
        if (IS_ERR(qdwc->sleep_clk)) {
-               dev_dbg(qdwc->dev, "failed to get optional sleep clock\n");
+               dev_info(qdwc->dev, "failed to get optional sleep clock\n");
                qdwc->sleep_clk = NULL;
        }
 
index 4a1a543deeda7c61b0b8378fc9a1e36553f44372..de4d52f62517a8ec744c0897e97edc516bd8643f 100644 (file)
@@ -135,8 +135,6 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data)
                        | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
 
                val |= USB3_DEVICE_NOT_HOST;
-
-               dev_dbg(dwc3_data->dev, "Configuring as Device\n");
                break;
 
        case USB_DR_MODE_HOST:
@@ -154,8 +152,6 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data)
                 */
 
                val |= USB3_DELAY_VBUSVALID;
-
-               dev_dbg(dwc3_data->dev, "Configuring as Host\n");
                break;
 
        default:
index 69e769c35cf5dc798fb34a6924c19726690592a2..5320e939e0902647edb21a5e55d7e537c1b03b33 100644 (file)
@@ -56,7 +56,7 @@ static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
 }
 
 static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
-               u32 len, u32 type)
+               u32 len, u32 type, bool chain)
 {
        struct dwc3_gadget_ep_cmd_params params;
        struct dwc3_trb                 *trb;
@@ -70,7 +70,10 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
                return 0;
        }
 
-       trb = dwc->ep0_trb;
+       trb = &dwc->ep0_trb[dep->free_slot];
+
+       if (chain)
+               dep->free_slot++;
 
        trb->bpl = lower_32_bits(buf_dma);
        trb->bph = upper_32_bits(buf_dma);
@@ -78,10 +81,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
        trb->ctrl = type;
 
        trb->ctrl |= (DWC3_TRB_CTRL_HWO
-                       | DWC3_TRB_CTRL_LST
-                       | DWC3_TRB_CTRL_IOC
                        | DWC3_TRB_CTRL_ISP_IMI);
 
+       if (chain)
+               trb->ctrl |= DWC3_TRB_CTRL_CHN;
+       else
+               trb->ctrl |= (DWC3_TRB_CTRL_IOC
+                               | DWC3_TRB_CTRL_LST);
+
+       if (chain)
+               return 0;
+
        memset(&params, 0, sizeof(params));
        params.param0 = upper_32_bits(dwc->ep0_trb_addr);
        params.param1 = lower_32_bits(dwc->ep0_trb_addr);
@@ -302,7 +312,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
        int                             ret;
 
        ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
-                       DWC3_TRBCTL_CONTROL_SETUP);
+                       DWC3_TRBCTL_CONTROL_SETUP, false);
        WARN_ON(ret < 0);
 }
 
@@ -783,7 +793,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
        struct usb_request      *ur;
        struct dwc3_trb         *trb;
        struct dwc3_ep          *ep0;
-       u32                     transferred;
+       unsigned                transfer_size = 0;
+       unsigned                maxp;
+       unsigned                remaining_ur_length;
+       void                    *buf;
+       u32                     transferred = 0;
        u32                     status;
        u32                     length;
        u8                      epnum;
@@ -812,17 +826,37 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
        }
 
        ur = &r->request;
+       buf = ur->buf;
+       remaining_ur_length = ur->length;
 
        length = trb->size & DWC3_TRB_SIZE_MASK;
 
+       maxp = ep0->endpoint.maxpacket;
+
        if (dwc->ep0_bounced) {
-               unsigned transfer_size = ur->length;
-               unsigned maxp = ep0->endpoint.maxpacket;
+               /*
+                * Handle the first TRB before handling the bounce buffer if
+                * the request length is greater than the bounce buffer size
+                */
+               if (ur->length > DWC3_EP0_BOUNCE_SIZE) {
+                       transfer_size = ALIGN(ur->length - maxp, maxp);
+                       transferred = transfer_size - length;
+                       buf = (u8 *)buf + transferred;
+                       ur->actual += transferred;
+                       remaining_ur_length -= transferred;
+
+                       trb++;
+                       length = trb->size & DWC3_TRB_SIZE_MASK;
 
-               transfer_size += (maxp - (transfer_size % maxp));
-               transferred = min_t(u32, ur->length,
-                               transfer_size - length);
-               memcpy(ur->buf, dwc->ep0_bounce, transferred);
+                       ep0->free_slot = 0;
+               }
+
+               transfer_size = roundup((ur->length - transfer_size),
+                                       maxp);
+
+               transferred = min_t(u32, remaining_ur_length,
+                                   transfer_size - length);
+               memcpy(buf, dwc->ep0_bounce, transferred);
        } else {
                transferred = ur->length - length;
        }
@@ -844,7 +878,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 
                        ret = dwc3_ep0_start_trans(dwc, epnum,
                                        dwc->ctrl_req_addr, 0,
-                                       DWC3_TRBCTL_CONTROL_DATA);
+                                       DWC3_TRBCTL_CONTROL_DATA, false);
                        WARN_ON(ret < 0);
                }
        }
@@ -928,10 +962,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
        if (req->request.length == 0) {
                ret = dwc3_ep0_start_trans(dwc, dep->number,
                                dwc->ctrl_req_addr, 0,
-                               DWC3_TRBCTL_CONTROL_DATA);
+                               DWC3_TRBCTL_CONTROL_DATA, false);
        } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
                        && (dep->number == 0)) {
-               u32     transfer_size;
+               u32     transfer_size = 0;
                u32     maxpacket;
 
                ret = usb_gadget_map_request(&dwc->gadget, &req->request,
@@ -941,21 +975,26 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                        return;
                }
 
-               WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
-
                maxpacket = dep->endpoint.maxpacket;
-               transfer_size = roundup(req->request.length, maxpacket);
+
+               if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
+                       transfer_size = ALIGN(req->request.length - maxpacket,
+                                             maxpacket);
+                       ret = dwc3_ep0_start_trans(dwc, dep->number,
+                                                  req->request.dma,
+                                                  transfer_size,
+                                                  DWC3_TRBCTL_CONTROL_DATA,
+                                                  true);
+               }
+
+               transfer_size = roundup((req->request.length - transfer_size),
+                                       maxpacket);
 
                dwc->ep0_bounced = true;
 
-               /*
-                * REVISIT in case request length is bigger than
-                * DWC3_EP0_BOUNCE_SIZE we will need two chained
-                * TRBs to handle the transfer.
-                */
                ret = dwc3_ep0_start_trans(dwc, dep->number,
                                dwc->ep0_bounce_addr, transfer_size,
-                               DWC3_TRBCTL_CONTROL_DATA);
+                               DWC3_TRBCTL_CONTROL_DATA, false);
        } else {
                ret = usb_gadget_map_request(&dwc->gadget, &req->request,
                                dep->number);
@@ -965,7 +1004,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                }
 
                ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
-                               req->request.length, DWC3_TRBCTL_CONTROL_DATA);
+                               req->request.length, DWC3_TRBCTL_CONTROL_DATA,
+                               false);
        }
 
        WARN_ON(ret < 0);
@@ -980,7 +1020,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
                : DWC3_TRBCTL_CONTROL_STATUS2;
 
        return dwc3_ep0_start_trans(dwc, dep->number,
-                       dwc->ctrl_req_addr, 0, type);
+                       dwc->ctrl_req_addr, 0, type, false);
 }
 
 static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
index 333a7c0078fcf922b9effaae3deff795d8b0f63e..0c25704dcb6ba398a98012cf0d9480c9de4f44e2 100644 (file)
@@ -547,6 +547,23 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
                trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
        }
 
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               strlcat(dep->name, "-control", sizeof(dep->name));
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               strlcat(dep->name, "-isoc", sizeof(dep->name));
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               strlcat(dep->name, "-bulk", sizeof(dep->name));
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               strlcat(dep->name, "-int", sizeof(dep->name));
+               break;
+       default:
+               dev_err(dwc->dev, "invalid endpoint transfer type\n");
+       }
+
        return 0;
 }
 
@@ -586,6 +603,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
        struct dwc3             *dwc = dep->dwc;
        u32                     reg;
 
+       dwc3_trace(trace_dwc3_gadget, "Disabling %s", dep->name);
+
        dwc3_remove_requests(dwc, dep);
 
        /* make sure HW endpoint isn't stalled */
@@ -602,6 +621,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
        dep->type = 0;
        dep->flags = 0;
 
+       snprintf(dep->name, sizeof(dep->name), "ep%d%s",
+                       dep->number >> 1,
+                       (dep->number & 1) ? "in" : "out");
+
        return 0;
 }
 
@@ -647,23 +670,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
                return 0;
        }
 
-       switch (usb_endpoint_type(desc)) {
-       case USB_ENDPOINT_XFER_CONTROL:
-               strlcat(dep->name, "-control", sizeof(dep->name));
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               strlcat(dep->name, "-isoc", sizeof(dep->name));
-               break;
-       case USB_ENDPOINT_XFER_BULK:
-               strlcat(dep->name, "-bulk", sizeof(dep->name));
-               break;
-       case USB_ENDPOINT_XFER_INT:
-               strlcat(dep->name, "-int", sizeof(dep->name));
-               break;
-       default:
-               dev_err(dwc->dev, "invalid endpoint transfer type\n");
-       }
-
        spin_lock_irqsave(&dwc->lock, flags);
        ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false, false);
        spin_unlock_irqrestore(&dwc->lock, flags);
@@ -692,10 +698,6 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep)
                return 0;
        }
 
-       snprintf(dep->name, sizeof(dep->name), "ep%d%s",
-                       dep->number >> 1,
-                       (dep->number & 1) ? "in" : "out");
-
        spin_lock_irqsave(&dwc->lock, flags);
        ret = __dwc3_gadget_ep_disable(dep);
        spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1713,6 +1715,17 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
                                return ret;
                }
 
+               if (epnum == 0 || epnum == 1) {
+                       dep->endpoint.caps.type_control = true;
+               } else {
+                       dep->endpoint.caps.type_iso = true;
+                       dep->endpoint.caps.type_bulk = true;
+                       dep->endpoint.caps.type_int = true;
+               }
+
+               dep->endpoint.caps.dir_in = !!direction;
+               dep->endpoint.caps.dir_out = !direction;
+
                INIT_LIST_HEAD(&dep->request_list);
                INIT_LIST_HEAD(&dep->req_queued);
        }
@@ -2685,7 +2698,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                goto err0;
        }
 
-       dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+       dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
                        &dwc->ep0_trb_addr, GFP_KERNEL);
        if (!dwc->ep0_trb) {
                dev_err(dwc->dev, "failed to allocate ep0 trb\n");
index 58b4657fc721d3dabda76b2138ea6c30d539992c..b474499839d395289803501fdbb57d5c6c59b785 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/utsname.h>
 
 #include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
 #include <asm/unaligned.h>
 
 #include "u_os_desc.h"
@@ -209,6 +210,12 @@ int usb_add_function(struct usb_configuration *config,
        function->config = config;
        list_add_tail(&function->list, &config->functions);
 
+       if (function->bind_deactivated) {
+               value = usb_function_deactivate(function);
+               if (value)
+                       goto done;
+       }
+
        /* REVISIT *require* function->bind? */
        if (function->bind) {
                value = function->bind(config, function);
@@ -279,7 +286,7 @@ int usb_function_deactivate(struct usb_function *function)
        spin_lock_irqsave(&cdev->lock, flags);
 
        if (cdev->deactivations == 0)
-               status = usb_gadget_disconnect(cdev->gadget);
+               status = usb_gadget_deactivate(cdev->gadget);
        if (status == 0)
                cdev->deactivations++;
 
@@ -311,7 +318,7 @@ int usb_function_activate(struct usb_function *function)
        else {
                cdev->deactivations--;
                if (cdev->deactivations == 0)
-                       status = usb_gadget_connect(cdev->gadget);
+                       status = usb_gadget_activate(cdev->gadget);
        }
 
        spin_unlock_irqrestore(&cdev->lock, flags);
@@ -896,7 +903,7 @@ void usb_remove_config(struct usb_composite_dev *cdev,
 
 /* We support strings in multiple languages ... string descriptor zero
  * says which languages are supported.  The typical case will be that
- * only one language (probably English) is used, with I18N handled on
+ * only one language (probably English) is used, with i18n handled on
  * the host side.
  */
 
@@ -949,7 +956,7 @@ static int get_string(struct usb_composite_dev *cdev,
        struct usb_function             *f;
        int                             len;
 
-       /* Yes, not only is USB's I18N support probably more than most
+       /* Yes, not only is USB's i18n support probably more than most
         * folk will ever care about ... also, it's all supported here.
         * (Except for UTF8 support for Unicode's "Astral Planes".)
         */
@@ -1534,6 +1541,32 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                                value = min(w_length, (u16) value);
                        }
                        break;
+               case USB_DT_OTG:
+                       if (gadget_is_otg(gadget)) {
+                               struct usb_configuration *config;
+                               int otg_desc_len = 0;
+
+                               if (cdev->config)
+                                       config = cdev->config;
+                               else
+                                       config = list_first_entry(
+                                                       &cdev->configs,
+                                               struct usb_configuration, list);
+                               if (!config)
+                                       goto done;
+
+                               if (gadget->otg_caps &&
+                                       (gadget->otg_caps->otg_rev >= 0x0200))
+                                       otg_desc_len += sizeof(
+                                               struct usb_otg20_descriptor);
+                               else
+                                       otg_desc_len += sizeof(
+                                               struct usb_otg_descriptor);
+
+                               value = min_t(int, w_length, otg_desc_len);
+                               memcpy(req->buf, config->descriptors[0], value);
+                       }
+                       break;
                }
                break;
 
index 34e12fc52c23d45fa2148212938242bb05b777f3..0fafa7a1b6f6c38cf97e085a2cd295e450261aef 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
 
 /**
  * usb_descriptor_fillbuf - fill buffer with descriptors
@@ -195,3 +196,58 @@ void usb_free_all_descriptors(struct usb_function *f)
        usb_free_descriptors(f->ss_descriptors);
 }
 EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
+
+struct usb_descriptor_header *usb_otg_descriptor_alloc(
+                               struct usb_gadget *gadget)
+{
+       struct usb_descriptor_header *otg_desc;
+       unsigned length = 0;
+
+       if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200))
+               length = sizeof(struct usb_otg20_descriptor);
+       else
+               length = sizeof(struct usb_otg_descriptor);
+
+       otg_desc = kzalloc(length, GFP_KERNEL);
+       return otg_desc;
+}
+EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc);
+
+int usb_otg_descriptor_init(struct usb_gadget *gadget,
+               struct usb_descriptor_header *otg_desc)
+{
+       struct usb_otg_descriptor *otg1x_desc;
+       struct usb_otg20_descriptor *otg20_desc;
+       struct usb_otg_caps *otg_caps = gadget->otg_caps;
+       u8 otg_attributes = 0;
+
+       if (!otg_desc)
+               return -EINVAL;
+
+       if (otg_caps && otg_caps->otg_rev) {
+               if (otg_caps->hnp_support)
+                       otg_attributes |= USB_OTG_HNP;
+               if (otg_caps->srp_support)
+                       otg_attributes |= USB_OTG_SRP;
+               if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200))
+                       otg_attributes |= USB_OTG_ADP;
+       } else {
+               otg_attributes = USB_OTG_SRP | USB_OTG_HNP;
+       }
+
+       if (otg_caps && (otg_caps->otg_rev >= 0x0200)) {
+               otg20_desc = (struct usb_otg20_descriptor *)otg_desc;
+               otg20_desc->bLength = sizeof(struct usb_otg20_descriptor);
+               otg20_desc->bDescriptorType = USB_DT_OTG;
+               otg20_desc->bmAttributes = otg_attributes;
+               otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev);
+       } else {
+               otg1x_desc = (struct usb_otg_descriptor *)otg_desc;
+               otg1x_desc->bLength = sizeof(struct usb_otg_descriptor);
+               otg1x_desc->bDescriptorType = USB_DT_OTG;
+               otg1x_desc->bmAttributes = otg_attributes;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_descriptor_init);
index 289e20119fea25eb1d670c2abbef7ca3f671633e..294eb74fb078508f6889902e1a0c841f3b603ece 100644 (file)
@@ -41,6 +41,8 @@ int check_user_usb_string(const char *name,
 #define MAX_NAME_LEN   40
 #define MAX_USB_STRING_LANGS 2
 
+static const struct usb_descriptor_header *otg_desc[2];
+
 struct gadget_info {
        struct config_group group;
        struct config_group functions_group;
@@ -55,9 +57,6 @@ struct gadget_info {
        struct list_head available_func;
 
        const char *udc_name;
-#ifdef CONFIG_USB_OTG
-       struct usb_otg_descriptor otg;
-#endif
        struct usb_composite_driver composite;
        struct usb_composite_dev cdev;
        bool use_os_desc;
@@ -1376,6 +1375,19 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
                memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
        }
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc) {
+                       ret = -ENOMEM;
+                       goto err_comp_cleanup;
+               }
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* Go through all configs, attach all functions */
        list_for_each_entry(c, &gi->cdev.configs, list) {
                struct config_usb_cfg *cfg;
@@ -1383,6 +1395,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
                struct usb_function *tmp;
                struct gadget_config_name *cn;
 
+               if (gadget_is_otg(gadget))
+                       c->descriptors = otg_desc;
+
                cfg = container_of(c, struct config_usb_cfg, c);
                if (!list_empty(&cfg->string_list)) {
                        i = 0;
@@ -1437,6 +1452,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
        cdev = get_gadget_data(gadget);
        gi = container_of(cdev, struct gadget_info, cdev);
 
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
        purge_configs_funcs(gi);
        composite_dev_cleanup(cdev);
        usb_ep_autoconfig_reset(cdev->gadget);
@@ -1510,12 +1527,6 @@ static struct config_group *gadgets_make(
        if (!gi->composite.gadget_driver.function)
                goto err;
 
-#ifdef CONFIG_USB_OTG
-       gi->otg.bLength = sizeof(struct usb_otg_descriptor);
-       gi->otg.bDescriptorType = USB_DT_OTG;
-       gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
-#endif
-
        config_group_init_type_name(&gi->group, name,
                                &gadget_root_type);
        return &gi->group;
index 919cdfdda78b91c8a17c921a4c05ec5a6aaa600b..978435a5103875cf29890cbec24f5884ce3448a4 100644 (file)
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
-#include "gadget_chips.h"
-
-/*
- * This should work with endpoints from controller drivers sharing the
- * same endpoint naming convention.  By example:
- *
- *     - ep1, ep2, ... address is fixed, not direction or type
- *     - ep1in, ep2out, ... address and direction are fixed, not type
- *     - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
- *     - ep1in-bulk, ep2out-iso, ... all three are fixed
- *     - ep-* ... no functionality restrictions
- *
- * Type suffixes are "-bulk", "-iso", or "-int".  Numbers are decimal.
- * Less common restrictions are implied by gadget_is_*().
- *
- * NOTE:  each endpoint is unidirectional, as specified by its USB
- * descriptor; and isn't specific to a configuration or altsetting.
- */
-static int
-ep_matches (
-       struct usb_gadget               *gadget,
-       struct usb_ep                   *ep,
-       struct usb_endpoint_descriptor  *desc,
-       struct usb_ss_ep_comp_descriptor *ep_comp
-)
-{
-       u8              type;
-       const char      *tmp;
-       u16             max;
-
-       int             num_req_streams = 0;
-
-       /* endpoint already claimed? */
-       if (NULL != ep->driver_data)
-               return 0;
-
-       /* only support ep0 for portable CONTROL traffic */
-       type = usb_endpoint_type(desc);
-       if (USB_ENDPOINT_XFER_CONTROL == type)
-               return 0;
-
-       /* some other naming convention */
-       if ('e' != ep->name[0])
-               return 0;
-
-       /* type-restriction:  "-iso", "-bulk", or "-int".
-        * direction-restriction:  "in", "out".
-        */
-       if ('-' != ep->name[2]) {
-               tmp = strrchr (ep->name, '-');
-               if (tmp) {
-                       switch (type) {
-                       case USB_ENDPOINT_XFER_INT:
-                               /* bulk endpoints handle interrupt transfers,
-                                * except the toggle-quirky iso-synch kind
-                                */
-                               if ('s' == tmp[2])      // == "-iso"
-                                       return 0;
-                               /* for now, avoid PXA "interrupt-in";
-                                * it's documented as never using DATA1.
-                                */
-                               if (gadget_is_pxa (gadget)
-                                               && 'i' == tmp [1])
-                                       return 0;
-                               break;
-                       case USB_ENDPOINT_XFER_BULK:
-                               if ('b' != tmp[1])      // != "-bulk"
-                                       return 0;
-                               break;
-                       case USB_ENDPOINT_XFER_ISOC:
-                               if ('s' != tmp[2])      // != "-iso"
-                                       return 0;
-                       }
-               } else {
-                       tmp = ep->name + strlen (ep->name);
-               }
-
-               /* direction-restriction:  "..in-..", "out-.." */
-               tmp--;
-               if (!isdigit (*tmp)) {
-                       if (desc->bEndpointAddress & USB_DIR_IN) {
-                               if ('n' != *tmp)
-                                       return 0;
-                       } else {
-                               if ('t' != *tmp)
-                                       return 0;
-                       }
-               }
-       }
-
-       /*
-        * Get the number of required streams from the EP companion
-        * descriptor and see if the EP matches it
-        */
-       if (usb_endpoint_xfer_bulk(desc)) {
-               if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
-                       num_req_streams = ep_comp->bmAttributes & 0x1f;
-                       if (num_req_streams > ep->max_streams)
-                               return 0;
-               }
-
-       }
-
-       /*
-        * If the protocol driver hasn't yet decided on wMaxPacketSize
-        * and wants to know the maximum possible, provide the info.
-        */
-       if (desc->wMaxPacketSize == 0)
-               desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
-
-       /* endpoint maxpacket size is an input parameter, except for bulk
-        * where it's an output parameter representing the full speed limit.
-        * the usb spec fixes high speed bulk maxpacket at 512 bytes.
-        */
-       max = 0x7ff & usb_endpoint_maxp(desc);
-       switch (type) {
-       case USB_ENDPOINT_XFER_INT:
-               /* INT:  limit 64 bytes full speed, 1024 high/super speed */
-               if (!gadget_is_dualspeed(gadget) && max > 64)
-                       return 0;
-               /* FALLTHROUGH */
-
-       case USB_ENDPOINT_XFER_ISOC:
-               /* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
-               if (ep->maxpacket_limit < max)
-                       return 0;
-               if (!gadget_is_dualspeed(gadget) && max > 1023)
-                       return 0;
-
-               /* BOTH:  "high bandwidth" works only at high speed */
-               if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
-                       if (!gadget_is_dualspeed(gadget))
-                               return 0;
-                       /* configure your hardware with enough buffering!! */
-               }
-               break;
-       }
-
-       /* MATCH!! */
-
-       /* report address */
-       desc->bEndpointAddress &= USB_DIR_IN;
-       if (isdigit (ep->name [2])) {
-               u8      num = simple_strtoul (&ep->name [2], NULL, 10);
-               desc->bEndpointAddress |= num;
-       } else if (desc->bEndpointAddress & USB_DIR_IN) {
-               if (++gadget->in_epnum > 15)
-                       return 0;
-               desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
-       } else {
-               if (++gadget->out_epnum > 15)
-                       return 0;
-               desc->bEndpointAddress |= gadget->out_epnum;
-       }
-
-       /* report (variable) full speed bulk maxpacket */
-       if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
-               int size = ep->maxpacket_limit;
-
-               /* min() doesn't work on bitfields with gcc-3.5 */
-               if (size > 64)
-                       size = 64;
-               desc->wMaxPacketSize = cpu_to_le16(size);
-       }
-       ep->address = desc->bEndpointAddress;
-       return 1;
-}
-
-static struct usb_ep *
-find_ep (struct usb_gadget *gadget, const char *name)
-{
-       struct usb_ep   *ep;
-
-       list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-               if (0 == strcmp (ep->name, name))
-                       return ep;
-       }
-       return NULL;
-}
-
 /**
  * usb_ep_autoconfig_ss() - choose an endpoint matching the ep
  * descriptor and ep companion descriptor
@@ -240,7 +60,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
  * updated with the assigned number of streams if it is
  * different from the original value. To prevent the endpoint
  * from being returned by a later autoconfig call, claim it by
- * assigning ep->driver_data to some non-null value.
+ * assigning ep->claimed to true.
  *
  * On failure, this returns a null endpoint descriptor.
  */
@@ -255,74 +75,58 @@ struct usb_ep *usb_ep_autoconfig_ss(
 
        type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 
-       /* First, apply chip-specific "best usage" knowledge.
-        * This might make a good usb_gadget_ops hook ...
-        */
-       if (gadget_is_net2280(gadget)) {
-               char name[8];
-
-               if (type == USB_ENDPOINT_XFER_INT) {
-                       /* ep-e, ep-f are PIO with only 64 byte fifos */
-                       ep = find_ep(gadget, "ep-e");
-                       if (ep && ep_matches(gadget, ep, desc, ep_comp))
-                               goto found_ep;
-                       ep = find_ep(gadget, "ep-f");
-                       if (ep && ep_matches(gadget, ep, desc, ep_comp))
-                               goto found_ep;
-               }
-
-               /* USB3380: use same address for usb and hardware endpoints */
-               snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
-                               usb_endpoint_dir_in(desc) ? "in" : "out");
-               ep = find_ep(gadget, name);
-               if (ep && ep_matches(gadget, ep, desc, ep_comp))
+       if (gadget->ops->match_ep) {
+               ep = gadget->ops->match_ep(gadget, desc, ep_comp);
+               if (ep)
                        goto found_ep;
-       } else if (gadget_is_goku (gadget)) {
-               if (USB_ENDPOINT_XFER_INT == type) {
-                       /* single buffering is enough */
-                       ep = find_ep(gadget, "ep3-bulk");
-                       if (ep && ep_matches(gadget, ep, desc, ep_comp))
-                               goto found_ep;
-               } else if (USB_ENDPOINT_XFER_BULK == type
-                               && (USB_DIR_IN & desc->bEndpointAddress)) {
-                       /* DMA may be available */
-                       ep = find_ep(gadget, "ep2-bulk");
-                       if (ep && ep_matches(gadget, ep, desc,
-                                             ep_comp))
-                               goto found_ep;
-               }
-
-#ifdef CONFIG_BLACKFIN
-       } else if (gadget_is_musbhdrc(gadget)) {
-               if ((USB_ENDPOINT_XFER_BULK == type) ||
-                   (USB_ENDPOINT_XFER_ISOC == type)) {
-                       if (USB_DIR_IN & desc->bEndpointAddress)
-                               ep = find_ep (gadget, "ep5in");
-                       else
-                               ep = find_ep (gadget, "ep6out");
-               } else if (USB_ENDPOINT_XFER_INT == type) {
-                       if (USB_DIR_IN & desc->bEndpointAddress)
-                               ep = find_ep(gadget, "ep1in");
-                       else
-                               ep = find_ep(gadget, "ep2out");
-               } else
-                       ep = NULL;
-               if (ep && ep_matches(gadget, ep, desc, ep_comp))
-                       goto found_ep;
-#endif
        }
 
        /* Second, look at endpoints until an unclaimed one looks usable */
        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-               if (ep_matches(gadget, ep, desc, ep_comp))
+               if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
                        goto found_ep;
        }
 
        /* Fail */
        return NULL;
 found_ep:
+
+       /*
+        * If the protocol driver hasn't yet decided on wMaxPacketSize
+        * and wants to know the maximum possible, provide the info.
+        */
+       if (desc->wMaxPacketSize == 0)
+               desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
+
+       /* report address */
+       desc->bEndpointAddress &= USB_DIR_IN;
+       if (isdigit(ep->name[2])) {
+               u8 num = simple_strtoul(&ep->name[2], NULL, 10);
+               desc->bEndpointAddress |= num;
+       } else if (desc->bEndpointAddress & USB_DIR_IN) {
+               if (++gadget->in_epnum > 15)
+                       return NULL;
+               desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
+       } else {
+               if (++gadget->out_epnum > 15)
+                       return NULL;
+               desc->bEndpointAddress |= gadget->out_epnum;
+       }
+
+       /* report (variable) full speed bulk maxpacket */
+       if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) {
+               int size = ep->maxpacket_limit;
+
+               /* min() doesn't work on bitfields with gcc-3.5 */
+               if (size > 64)
+                       size = 64;
+               desc->wMaxPacketSize = cpu_to_le16(size);
+       }
+
+       ep->address = desc->bEndpointAddress;
        ep->desc = NULL;
        ep->comp_desc = NULL;
+       ep->claimed = true;
        return ep;
 }
 EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
@@ -354,7 +158,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
  * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
  * is initialized as if the endpoint were used at full speed.  To prevent
  * the endpoint from being returned by a later autoconfig call, claim it
- * by assigning ep->driver_data to some non-null value.
+ * by assigning ep->claimed to true.
  *
  * On failure, this returns a null endpoint descriptor.
  */
@@ -373,7 +177,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
  *
  * Use this for devices where one configuration may need to assign
  * endpoint resources very differently from the next one.  It clears
- * state such as ep->driver_data and the record of assigned endpoints
+ * state such as ep->claimed and the record of assigned endpoints
  * used by usb_ep_autoconfig().
  */
 void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
@@ -381,7 +185,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
        struct usb_ep   *ep;
 
        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
-               ep->driver_data = NULL;
+               ep->claimed = false;
        }
        gadget->in_epnum = 0;
        gadget->out_epnum = 0;
index aad8165e98ef84d314f74826e97d1bd0641a5b95..be9df09fde26508c6b658cd0686681fb43e1d4bb 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/err.h>
 
 #include "u_serial.h"
-#include "gadget_chips.h"
 
 
 /*
index 798760fa7e702b73285d21d6a2d69c55c351a44a..7b7424f10dddce479fca8945cd238293a2f02cc6 100644 (file)
@@ -585,8 +585,8 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                        /* Enable zlps by default for ECM conformance;
                         * override for musb_hdrc (avoids txdma ovhead).
                         */
-                       ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget)
-                               );
+                       ecm->port.is_zlp_ok =
+                               gadget_is_zlp_supported(cdev->gadget);
                        ecm->port.cdc_filter = DEFAULT_FILTER;
                        DBG(cdev, "activate ecm\n");
                        net = gether_connect(&ecm->port);
index 6e7be91e6097cf0cfb4d6106decc141aeb8a5eb3..adc6d52efa4639387c30bcde2ae7cee95331b1bc 100644 (file)
@@ -2897,11 +2897,17 @@ static int ffs_func_bind(struct usb_configuration *c,
                         struct usb_function *f)
 {
        struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
+       struct ffs_function *func = ffs_func_from_usb(f);
+       int ret;
 
        if (IS_ERR(ffs_opts))
                return PTR_ERR(ffs_opts);
 
-       return _ffs_func_bind(c, f);
+       ret = _ffs_func_bind(c, f);
+       if (ret && !--ffs_opts->refcnt)
+               functionfs_unbind(func->ffs);
+
+       return ret;
 }
 
 
index 39f49f1ad22f287e58df631077a9a1506381707b..6e2fe63b926741abf184f2ee54a0fe740a372e42 100644 (file)
  * This takes messages of various sizes written OUT to a device, and loops
  * them back so they can be read IN from it.  It has been used by certain
  * test applications.  It supports limited testing of data queueing logic.
- *
- *
- * This is currently packaged as a configuration driver, which can't be
- * combined with other functions to make composite devices.  However, it
- * can be combined with other independent configurations.
  */
 struct f_loopback {
        struct usb_function     function;
index f936268d26c6aaa9a5601614adf2e90319e0d364..a6eb537d77689f53e7b0e31cff14c2f523c52fe4 100644 (file)
@@ -54,7 +54,7 @@
  * following fields:
  *
  *     nluns           Number of LUNs function have (anywhere from 1
- *                             to FSG_MAX_LUNS which is 8).
+ *                             to FSG_MAX_LUNS).
  *     luns            An array of LUN configuration values.  This
  *                             should be filled for each LUN that
  *                             function will include (ie. for "nluns"
 #include <linux/string.h>
 #include <linux/freezer.h>
 #include <linux/module.h>
+#include <linux/uaccess.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
 
-#include "gadget_chips.h"
 #include "configfs.h"
 
 
@@ -279,9 +279,8 @@ struct fsg_common {
        int                     cmnd_size;
        u8                      cmnd[MAX_COMMAND_SIZE];
 
-       unsigned int            nluns;
        unsigned int            lun;
-       struct fsg_lun          **luns;
+       struct fsg_lun          *luns[FSG_MAX_LUNS];
        struct fsg_lun          *curlun;
 
        unsigned int            bulk_out_maxpacket;
@@ -490,6 +489,16 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
        spin_unlock(&common->lock);
 }
 
+static int _fsg_common_get_max_lun(struct fsg_common *common)
+{
+       int i = ARRAY_SIZE(common->luns) - 1;
+
+       while (i >= 0 && !common->luns[i])
+               --i;
+
+       return i;
+}
+
 static int fsg_setup(struct usb_function *f,
                     const struct usb_ctrlrequest *ctrl)
 {
@@ -533,7 +542,7 @@ static int fsg_setup(struct usb_function *f,
                                w_length != 1)
                        return -EDOM;
                VDBG(fsg, "get max LUN\n");
-               *(u8 *)req->buf = fsg->common->nluns - 1;
+               *(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
 
                /* Respond with data/status */
                req->length = min((u16)1, w_length);
@@ -2131,8 +2140,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
        }
 
        /* Is the CBW meaningful? */
-       if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
-                       cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
+       if (cbw->Lun >= ARRAY_SIZE(common->luns) ||
+           cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 ||
+           cbw->Length > MAX_COMMAND_SIZE) {
                DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
                                "cmdlen %u\n",
                                cbw->Lun, cbw->Flags, cbw->Length);
@@ -2159,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
        if (common->data_size == 0)
                common->data_dir = DATA_DIR_NONE;
        common->lun = cbw->Lun;
-       if (common->lun < common->nluns)
+       if (common->lun < ARRAY_SIZE(common->luns))
                common->curlun = common->luns[common->lun];
        else
                common->curlun = NULL;
@@ -2307,7 +2317,7 @@ reset:
        }
 
        common->running = 1;
-       for (i = 0; i < common->nluns; ++i)
+       for (i = 0; i < ARRAY_SIZE(common->luns); ++i)
                if (common->luns[i])
                        common->luns[i]->unit_attention_data =
                                SS_RESET_OCCURRED;
@@ -2409,7 +2419,7 @@ static void handle_exception(struct fsg_common *common)
        if (old_state == FSG_STATE_ABORT_BULK_OUT)
                common->state = FSG_STATE_STATUS_PHASE;
        else {
-               for (i = 0; i < common->nluns; ++i) {
+               for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
                        curlun = common->luns[i];
                        if (!curlun)
                                continue;
@@ -2453,7 +2463,7 @@ static void handle_exception(struct fsg_common *common)
                 * a waste of time.  Ditto for the INTERFACE_CHANGE and
                 * CONFIG_CHANGE cases.
                 */
-               /* for (i = 0; i < common->nluns; ++i) */
+               /* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */
                /*      if (common->luns[i]) */
                /*              common->luns[i]->unit_attention_data = */
                /*                      SS_RESET_OCCURRED;  */
@@ -2552,12 +2562,11 @@ static int fsg_main_thread(void *common_)
 
        if (!common->ops || !common->ops->thread_exits
         || common->ops->thread_exits(common) < 0) {
-               struct fsg_lun **curlun_it = common->luns;
-               unsigned i = common->nluns;
+               int i;
 
                down_write(&common->filesem);
-               for (; i--; ++curlun_it) {
-                       struct fsg_lun *curlun = *curlun_it;
+               for (i = 0; i < ARRAY_SIZE(common->luns); --i) {
+                       struct fsg_lun *curlun = common->luns[i];
                        if (!curlun || !fsg_lun_is_open(curlun))
                                continue;
 
@@ -2676,6 +2685,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
        init_completion(&common->thread_notifier);
        init_waitqueue_head(&common->fsg_wait);
        common->state = FSG_STATE_TERMINATED;
+       memset(common->luns, 0, sizeof(common->luns));
 
        return common;
 }
@@ -2742,9 +2752,9 @@ error_release:
 }
 EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers);
 
-void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
+void fsg_common_remove_lun(struct fsg_lun *lun)
 {
-       if (sysfs)
+       if (device_is_registered(&lun->dev))
                device_unregister(&lun->dev);
        fsg_lun_close(lun);
        kfree(lun);
@@ -2757,48 +2767,16 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n)
 
        for (i = 0; i < n; ++i)
                if (common->luns[i]) {
-                       fsg_common_remove_lun(common->luns[i], common->sysfs);
+                       fsg_common_remove_lun(common->luns[i]);
                        common->luns[i] = NULL;
                }
 }
-EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
 
 void fsg_common_remove_luns(struct fsg_common *common)
 {
-       _fsg_common_remove_luns(common, common->nluns);
-}
-
-void fsg_common_free_luns(struct fsg_common *common)
-{
-       fsg_common_remove_luns(common);
-       kfree(common->luns);
-       common->luns = NULL;
-}
-EXPORT_SYMBOL_GPL(fsg_common_free_luns);
-
-int fsg_common_set_nluns(struct fsg_common *common, int nluns)
-{
-       struct fsg_lun **curlun;
-
-       /* Find out how many LUNs there should be */
-       if (nluns < 1 || nluns > FSG_MAX_LUNS) {
-               pr_err("invalid number of LUNs: %u\n", nluns);
-               return -EINVAL;
-       }
-
-       curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL);
-       if (unlikely(!curlun))
-               return -ENOMEM;
-
-       if (common->luns)
-               fsg_common_free_luns(common);
-
-       common->luns = curlun;
-       common->nluns = nluns;
-
-       return 0;
+       _fsg_common_remove_luns(common, ARRAY_SIZE(common->luns));
 }
-EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
+EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
 
 void fsg_common_set_ops(struct fsg_common *common,
                        const struct fsg_operations *ops)
@@ -2836,7 +2814,8 @@ int fsg_common_set_cdev(struct fsg_common *common,
         * halt bulk endpoints correctly.  If one of them is present,
         * disable stalls.
         */
-       common->can_stall = can_stall && !(gadget_is_at91(common->gadget));
+       common->can_stall = can_stall &&
+                       gadget_is_stall_supported(common->gadget);
 
        return 0;
 }
@@ -2880,7 +2859,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
        char *pathbuf, *p;
        int rc = -ENOMEM;
 
-       if (!common->nluns || !common->luns)
+       if (id >= ARRAY_SIZE(common->luns))
                return -ENODEV;
 
        if (common->luns[id])
@@ -2949,7 +2928,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
        return 0;
 
 error_lun:
-       if (common->sysfs)
+       if (device_is_registered(&lun->dev))
                device_unregister(&lun->dev);
        fsg_lun_close(lun);
        common->luns[id] = NULL;
@@ -2964,14 +2943,16 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
        char buf[8]; /* enough for 100000000 different numbers, decimal */
        int i, rc;
 
-       for (i = 0; i < common->nluns; ++i) {
+       fsg_common_remove_luns(common);
+
+       for (i = 0; i < cfg->nluns; ++i) {
                snprintf(buf, sizeof(buf), "lun%d", i);
                rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL);
                if (rc)
                        goto fail;
        }
 
-       pr_info("Number of LUNs=%d\n", common->nluns);
+       pr_info("Number of LUNs=%d\n", cfg->nluns);
 
        return 0;
 
@@ -3020,6 +3001,7 @@ EXPORT_SYMBOL_GPL(fsg_common_run_thread);
 static void fsg_common_release(struct kref *ref)
 {
        struct fsg_common *common = container_of(ref, struct fsg_common, ref);
+       int i;
 
        /* If the thread isn't already dead, tell it to exit now */
        if (common->state != FSG_STATE_TERMINATED) {
@@ -3027,22 +3009,14 @@ static void fsg_common_release(struct kref *ref)
                wait_for_completion(&common->thread_notifier);
        }
 
-       if (likely(common->luns)) {
-               struct fsg_lun **lun_it = common->luns;
-               unsigned i = common->nluns;
-
-               /* In error recovery common->nluns may be zero. */
-               for (; i; --i, ++lun_it) {
-                       struct fsg_lun *lun = *lun_it;
-                       if (!lun)
-                               continue;
-                       fsg_lun_close(lun);
-                       if (common->sysfs)
-                               device_unregister(&lun->dev);
-                       kfree(lun);
-               }
-
-               kfree(common->luns);
+       for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
+               struct fsg_lun *lun = common->luns[i];
+               if (!lun)
+                       continue;
+               fsg_lun_close(lun);
+               if (device_is_registered(&lun->dev))
+                       device_unregister(&lun->dev);
+               kfree(lun);
        }
 
        _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
@@ -3056,6 +3030,7 @@ static void fsg_common_release(struct kref *ref)
 static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct fsg_dev          *fsg = fsg_from_func(f);
+       struct fsg_common       *common = fsg->common;
        struct usb_gadget       *gadget = c->cdev->gadget;
        int                     i;
        struct usb_ep           *ep;
@@ -3063,6 +3038,13 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        int                     ret;
        struct fsg_opts         *opts;
 
+       /* Don't allow to bind if we don't have at least one LUN */
+       ret = _fsg_common_get_max_lun(common);
+       if (ret < 0) {
+               pr_err("There should be at least one LUN.\n");
+               return -EINVAL;
+       }
+
        opts = fsg_opts_from_func_inst(f->fi);
        if (!opts->no_configfs) {
                ret = fsg_common_set_cdev(fsg->common, c->cdev,
@@ -3080,7 +3062,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        /* New interface */
        i = usb_interface_id(c, f);
        if (i < 0)
-               return i;
+               goto fail;
        fsg_intf_desc.bInterfaceNumber = i;
        fsg->interface_number = i;
 
@@ -3123,7 +3105,14 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 
 autoconf_fail:
        ERROR(fsg, "unable to autoconfigure all endpoints\n");
-       return -ENOTSUPP;
+       i = -ENOTSUPP;
+fail:
+       /* terminate the thread */
+       if (fsg->common->state != FSG_STATE_TERMINATED) {
+               raise_exception(fsg->common, FSG_STATE_EXIT);
+               wait_for_completion(&fsg->common->thread_notifier);
+       }
+       return i;
 }
 
 /****************************** ALLOCATE FUNCTION *************************/
@@ -3355,7 +3344,7 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item)
                unregister_gadget_item(gadget);
        }
 
-       fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs);
+       fsg_common_remove_lun(lun_opts->lun);
        fsg_opts->common->luns[lun_opts->lun_id] = NULL;
        lun_opts->lun_id = 0;
        mutex_unlock(&fsg_opts->lock);
@@ -3509,14 +3498,11 @@ static struct usb_function_instance *fsg_alloc_inst(void)
                rc = PTR_ERR(opts->common);
                goto release_opts;
        }
-       rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
-       if (rc)
-               goto release_opts;
 
        rc = fsg_common_set_num_buffers(opts->common,
                                        CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
        if (rc)
-               goto release_luns;
+               goto release_opts;
 
        pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
 
@@ -3524,6 +3510,9 @@ static struct usb_function_instance *fsg_alloc_inst(void)
        config.removable = true;
        rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0",
                        (const char **)&opts->func_inst.group.cg_item.ci_name);
+       if (rc)
+               goto release_buffers;
+
        opts->lun0.lun = opts->common->luns[0];
        opts->lun0.lun_id = 0;
        config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
@@ -3534,8 +3523,8 @@ static struct usb_function_instance *fsg_alloc_inst(void)
 
        return &opts->func_inst;
 
-release_luns:
-       kfree(opts->common->luns);
+release_buffers:
+       fsg_common_free_buffers(opts->common);
 release_opts:
        kfree(opts);
        return ERR_PTR(rc);
@@ -3561,23 +3550,12 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
        struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
        struct fsg_common *common = opts->common;
        struct fsg_dev *fsg;
-       unsigned nluns, i;
 
        fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
        if (unlikely(!fsg))
                return ERR_PTR(-ENOMEM);
 
        mutex_lock(&opts->lock);
-       if (!opts->refcnt) {
-               for (nluns = i = 0; i < FSG_MAX_LUNS; ++i)
-                       if (common->luns[i])
-                               nluns = i + 1;
-               if (!nluns)
-                       pr_warn("No LUNS defined, continuing anyway\n");
-               else
-                       common->nluns = nluns;
-               pr_info("Number of LUNs=%u\n", common->nluns);
-       }
        opts->refcnt++;
        mutex_unlock(&opts->lock);
 
index b4866fcef30bdb94a2b8d98ccbe033cd1f1c8951..445df67756091678336dd3e9490de1c6ec595096 100644 (file)
@@ -137,14 +137,10 @@ void fsg_common_free_buffers(struct fsg_common *common);
 int fsg_common_set_cdev(struct fsg_common *common,
                        struct usb_composite_dev *cdev, bool can_stall);
 
-void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs);
+void fsg_common_remove_lun(struct fsg_lun *lun);
 
 void fsg_common_remove_luns(struct fsg_common *common);
 
-void fsg_common_free_luns(struct fsg_common *common);
-
-int fsg_common_set_nluns(struct fsg_common *common, int nluns);
-
 void fsg_common_set_ops(struct fsg_common *common,
                        const struct fsg_operations *ops);
 
index ad50a67c14656aa70f6804572486954f0e389887..a287a48292731b2b9eda7a0294eed98dfd6b0987 100644 (file)
@@ -329,6 +329,10 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        unsigned i;
        int err;
 
+       /* For Control Device interface we do nothing */
+       if (intf == 0)
+               return 0;
+
        err = f_midi_start_ep(midi, f, midi->in_ep);
        if (err)
                return err;
index bdcda9f5148e5c42d2217fcae87be5f266c263f2..3f05c6bd57f0c3353b5a2973a3e344593834b5b5 100644 (file)
@@ -853,9 +853,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                        /* Enable zlps by default for NCM conformance;
                         * override for musb_hdrc (avoids txdma ovhead)
                         */
-                       ncm->port.is_zlp_ok = !(
-                               gadget_is_musbhdrc(cdev->gadget)
-                               );
+                       ncm->port.is_zlp_ok =
+                               gadget_is_zlp_supported(cdev->gadget);
                        ncm->port.cdc_filter = DEFAULT_FILTER;
                        DBG(cdev, "activate ncm\n");
                        net = gether_connect(&ncm->port);
index a1b79c53499c2f4e852b1599347df3a400337745..5460426057eb232d13e6a071a47f114fb8cd4e14 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 
 #include "u_serial.h"
-#include "gadget_chips.h"
 
 
 /*
@@ -37,7 +36,6 @@ struct f_obex {
        u8                              data_id;
        u8                              cur_alt;
        u8                              port_num;
-       u8                              can_activate;
 };
 
 static inline struct f_obex *func_to_obex(struct usb_function *f)
@@ -268,9 +266,6 @@ static void obex_connect(struct gserial *g)
        struct usb_composite_dev *cdev = g->func.config->cdev;
        int                     status;
 
-       if (!obex->can_activate)
-               return;
-
        status = usb_function_activate(&g->func);
        if (status)
                dev_dbg(&cdev->gadget->dev,
@@ -284,9 +279,6 @@ static void obex_disconnect(struct gserial *g)
        struct usb_composite_dev *cdev = g->func.config->cdev;
        int                     status;
 
-       if (!obex->can_activate)
-               return;
-
        status = usb_function_deactivate(&g->func);
        if (status)
                dev_dbg(&cdev->gadget->dev,
@@ -304,7 +296,7 @@ static inline bool can_support_obex(struct usb_configuration *c)
         *
         * Altsettings are mandatory, however...
         */
-       if (!gadget_supports_altsettings(c->cdev->gadget))
+       if (!gadget_is_altset_supported(c->cdev->gadget))
                return false;
 
        /* everything else is *probably* fine ... */
@@ -378,17 +370,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
        if (status)
                goto fail;
 
-       /* Avoid letting this gadget enumerate until the userspace
-        * OBEX server is active.
-        */
-       status = usb_function_deactivate(f);
-       if (status < 0)
-               WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
-                       obex->port_num, status);
-       else
-               obex->can_activate = true;
-
-
        dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
                obex->port_num,
                gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -529,6 +510,7 @@ static struct usb_function *obex_alloc(struct usb_function_instance *fi)
        obex->port.func.get_alt = obex_get_alt;
        obex->port.func.disable = obex_disable;
        obex->port.func.free_func = obex_free;
+       obex->port.func.bind_deactivated = true;
 
        return &obex->port.func;
 }
index 357f63f47b42aba69d92e24346963645227d39e2..8e2b6bea07bc0e6a6fa1758aa38841a52afdcf3c 100644 (file)
@@ -804,6 +804,8 @@ done:
 
 static void printer_reset_interface(struct printer_dev *dev)
 {
+       unsigned long   flags;
+
        if (dev->interface < 0)
                return;
 
@@ -815,9 +817,11 @@ static void printer_reset_interface(struct printer_dev *dev)
        if (dev->out_ep->desc)
                usb_ep_disable(dev->out_ep);
 
+       spin_lock_irqsave(&dev->lock, flags);
        dev->in_ep->desc = NULL;
        dev->out_ep->desc = NULL;
        dev->interface = -1;
+       spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 /* Change our operational Interface. */
@@ -1131,13 +1135,10 @@ static int printer_func_set_alt(struct usb_function *f,
 static void printer_func_disable(struct usb_function *f)
 {
        struct printer_dev *dev = func_to_printer(f);
-       unsigned long           flags;
 
        DBG(dev, "%s\n", __func__);
 
-       spin_lock_irqsave(&dev->lock, flags);
        printer_reset_interface(dev);
-       spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 static inline struct f_printer_opts
index 2e02dfabc7ae18394315de1f692d6abfc9f0f996..1d162e200e831ce1320a8e3d3f36f3bbd82b5a92 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/device.h>
 
 #include "u_serial.h"
-#include "gadget_chips.h"
 
 
 /*
index 3a5ae9900b1ee585881aa8233065ef9772de8da7..cbfaf86fe45652911744055d6549a88c88b056d3 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/err.h>
 
 #include "g_zero.h"
-#include "gadget_chips.h"
 #include "u_f.h"
 
 /*
  * queues are relatively independent, will receive a range of packet sizes,
  * and can often be made to run out completely.  Those issues are important
  * when stress testing peripheral controller drivers.
- *
- *
- * This is currently packaged as a configuration driver, which can't be
- * combined with other functions to make composite devices.  However, it
- * can be combined with other independent configurations.
  */
 struct f_sourcesink {
        struct usb_function     function;
index 53186154725330d4c1f710e4829d4a8b25b614cd..f8de7ea2a0c1e9585782e2fe60af23a41c072e37 100644 (file)
@@ -975,6 +975,29 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
                        "%s:%d Error!\n", __func__, __LINE__);
 }
 
+static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
+       struct usb_endpoint_descriptor *ep_desc,
+       unsigned int factor, bool is_playback)
+{
+       int chmask, srate, ssize;
+       u16 max_packet_size;
+
+       if (is_playback) {
+               chmask = uac2_opts->p_chmask;
+               srate = uac2_opts->p_srate;
+               ssize = uac2_opts->p_ssize;
+       } else {
+               chmask = uac2_opts->c_chmask;
+               srate = uac2_opts->c_srate;
+               ssize = uac2_opts->c_ssize;
+       }
+
+       max_packet_size = num_channels(chmask) * ssize *
+               DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
+       ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size,
+                               le16_to_cpu(ep_desc->wMaxPacketSize)));
+}
+
 static int
 afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 {
@@ -1070,10 +1093,14 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        uac2->p_prm.uac2 = uac2;
        uac2->c_prm.uac2 = uac2;
 
+       /* Calculate wMaxPacketSize according to audio bandwidth */
+       set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
+       set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
+       set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
+       set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
+
        hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
-       hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize;
        hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
-       hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
 
        ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
        if (ret)
index cf0df8fbba890130f427e748a98736a4eee3a6aa..743be34605dcbff26eaf066c80578fb5112e41cf 100644 (file)
@@ -733,12 +733,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        uvc->control_req->complete = uvc_function_ep0_complete;
        uvc->control_req->context = uvc;
 
-       /* Avoid letting this gadget enumerate until the userspace server is
-        * active.
-        */
-       if ((ret = usb_function_deactivate(f)) < 0)
-               goto error;
-
        if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) {
                printk(KERN_INFO "v4l2_device_register failed\n");
                goto error;
@@ -949,6 +943,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
        uvc->func.disable = uvc_function_disable;
        uvc->func.setup = uvc_function_setup;
        uvc->func.free_func = uvc_free;
+       uvc->func.bind_deactivated = true;
 
        return &uvc->func;
 }
index 70c891469f574ebd1d7719fc05bcf838d1d6e3cb..c3544e61da6690f2b377e0a8e2cc8e7f835389ea 100644 (file)
@@ -123,7 +123,7 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
 #define FSG_BUFLEN     ((u32)16384)
 
 /* Maximal number of LUNs supported in mass storage function */
-#define FSG_MAX_LUNS   8
+#define FSG_MAX_LUNS   16
 
 enum fsg_buffer_state {
        BUF_STATE_EMPTY = 0,
index 334b389479165b4bf3391ee39e086f18a777ca9e..c77145bd6b5b94f65b8531f2ab061c2770edbae5 100644 (file)
@@ -20,8 +20,6 @@
 #include <linux/usb/cdc.h>
 #include <linux/netdevice.h>
 
-#include "gadget_chips.h"
-
 #define QMULT_DEFAULT 5
 
 /*
@@ -259,7 +257,7 @@ void gether_disconnect(struct gether *);
 /* Some controllers can't support CDC Ethernet (ECM) ... */
 static inline bool can_support_ecm(struct usb_gadget *gadget)
 {
-       if (!gadget_supports_altsettings(gadget))
+       if (!gadget_is_altset_supported(gadget))
                return false;
 
        /* Everything else is *presumably* fine ... but this is a bit
index fe386df6dd3e67843c597ee0301298a01c490ee7..5c2ac8e8456d83cf4c7c462cb45eb5475932c8ad 100644 (file)
@@ -21,8 +21,6 @@
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 
-#include "gadget_chips.h"
-
 #define FILE_PCM_PLAYBACK      "/dev/snd/pcmC0D0p"
 #define FILE_PCM_CAPTURE       "/dev/snd/pcmC0D0c"
 #define FILE_CONTROL           "/dev/snd/controlC0"
index d5a7102de696611ea45124796610a20f9fb033cd..4d682ad7bf23de10b714ce46a28a312130f37f9c 100644 (file)
@@ -339,6 +339,7 @@ config USB_CDC_COMPOSITE
 config USB_G_NOKIA
        tristate "Nokia composite gadget"
        depends on PHONET
+       depends on BLOCK
        select USB_LIBCOMPOSITE
        select USB_U_SERIAL
        select USB_U_ETHER
@@ -346,6 +347,7 @@ config USB_G_NOKIA
        select USB_F_OBEX
        select USB_F_PHONET
        select USB_F_ECM
+       select USB_F_MASS_STORAGE
        help
          The Nokia composite gadget provides support for acm, obex
          and phonet in only one composite gadget driver.
index 1194b09ae7462638d689eb99af6a15bd209c9e9e..4b158e2d1e57b829b19c8eb30c3cf8cadb6d32c4 100644 (file)
@@ -58,21 +58,7 @@ static struct usb_device_descriptor device_desc = {
        /*.bNumConfigurations = DYNAMIC*/
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /*
-        * REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 /* string IDs are assigned dynamically */
 static struct usb_string strings_dev[] = {
@@ -200,10 +186,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
        if (status)
                goto fail;
 
-       status = fsg_common_set_nluns(opts->common, config.nluns);
-       if (status)
-               goto fail_set_nluns;
-
        status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
        if (status)
                goto fail_set_cdev;
@@ -225,10 +207,21 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc)
+                       goto fail_string_ids;
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* register our configuration */
        status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
        if (status < 0)
-               goto fail_string_ids;
+               goto fail_otg_desc;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -236,11 +229,12 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
        return 0;
 
        /* error recovery */
+fail_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail_string_ids:
        fsg_common_remove_luns(opts->common);
 fail_set_cdev:
-       fsg_common_free_luns(opts->common);
-fail_set_nluns:
        fsg_common_free_buffers(opts->common);
 fail:
        usb_put_function_instance(fi_msg);
@@ -255,6 +249,9 @@ static int acm_ms_unbind(struct usb_composite_dev *cdev)
        usb_put_function_instance(fi_msg);
        usb_put_function(f_acm);
        usb_put_function_instance(f_acm_inst);
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index f289caf18a45341dc613a676345bfe8eeb51ee8e..685cf3b4b78f8b47c3ea110bafc7637ec043c8d0 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/usb/composite.h>
 
-#include "gadget_chips.h"
 #define DRIVER_DESC            "Linux USB Audio Gadget"
 #define DRIVER_VERSION         "Feb 2, 2012"
 
@@ -124,7 +123,7 @@ static struct usb_device_descriptor device_desc = {
        .bLength =              sizeof device_desc,
        .bDescriptorType =      USB_DT_DEVICE,
 
-       .bcdUSB =               __constant_cpu_to_le16(0x200),
+       .bcdUSB =               cpu_to_le16(0x200),
 
 #ifdef CONFIG_GADGET_UAC1
        .bDeviceClass =         USB_CLASS_PER_INTERFACE,
@@ -141,8 +140,8 @@ static struct usb_device_descriptor device_desc = {
         * we support.  (As does bNumConfigurations.)  These values can
         * also be overridden by module parameters.
         */
-       .idVendor =             __constant_cpu_to_le16(AUDIO_VENDOR_NUM),
-       .idProduct =            __constant_cpu_to_le16(AUDIO_PRODUCT_NUM),
+       .idVendor =             cpu_to_le16(AUDIO_VENDOR_NUM),
+       .idProduct =            cpu_to_le16(AUDIO_PRODUCT_NUM),
        /* .bcdDevice = f(hardware) */
        /* .iManufacturer = DYNAMIC */
        /* .iProduct = DYNAMIC */
@@ -150,20 +149,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 /*-------------------------------------------------------------------------*/
 
@@ -259,14 +245,28 @@ static int audio_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+               if (!usb_desc)
+                       goto fail;
+               usb_otg_descriptor_init(cdev->gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
        if (status < 0)
-               goto fail;
+               goto fail_otg_desc;
        usb_composite_overwrite_options(cdev, &coverwrite);
 
        INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION);
        return 0;
 
+fail_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail:
 #ifndef CONFIG_GADGET_UAC1
        usb_put_function_instance(fi_uac2);
@@ -289,6 +289,9 @@ static int audio_unbind(struct usb_composite_dev *cdev)
        if (!IS_ERR_OR_NULL(fi_uac2))
                usb_put_function_instance(fi_uac2);
 #endif
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index afd3e37921a7d9f1cc879cda5fe64ac5f940b6fa..ecd8c8d62f2e9334062f68dce67a071765cdab7d 100644 (file)
@@ -60,21 +60,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
 
 /* string IDs are assigned dynamically */
 static struct usb_string strings_dev[] = {
@@ -193,10 +179,21 @@ static int cdc_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc)
+                       goto fail1;
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* register our configuration */
        status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
        if (status < 0)
-               goto fail1;
+               goto fail2;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -204,6 +201,9 @@ static int cdc_bind(struct usb_composite_dev *cdev)
 
        return 0;
 
+fail2:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail1:
        usb_put_function_instance(fi_serial);
 fail:
@@ -219,6 +219,9 @@ static int cdc_unbind(struct usb_composite_dev *cdev)
                usb_put_function(f_ecm);
        if (!IS_ERR_OR_NULL(fi_ecm))
                usb_put_function_instance(fi_ecm);
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index 204b10b1a7e7dd08c36bc00d44205e0c6753b1c2..5231a32aef55a4c6640a772038a260b76d7bf2b6 100644 (file)
@@ -35,10 +35,10 @@ static struct dbgp {
 static struct usb_device_descriptor device_desc = {
        .bLength = sizeof device_desc,
        .bDescriptorType = USB_DT_DEVICE,
-       .bcdUSB = __constant_cpu_to_le16(0x0200),
+       .bcdUSB = cpu_to_le16(0x0200),
        .bDeviceClass = USB_CLASS_VENDOR_SPEC,
-       .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
-       .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
+       .idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
+       .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
        .bNumConfigurations = 1,
 };
 
@@ -251,7 +251,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
 
        dbgp.i_ep->driver_data = gadget;
        i_desc.wMaxPacketSize =
-               __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+               cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
 
        dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
        if (!dbgp.o_ep) {
@@ -262,7 +262,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
 
        dbgp.o_ep->driver_data = gadget;
        o_desc.wMaxPacketSize =
-               __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+               cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
 
        dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
        dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
index a3323dca218f9514b4c2a5e4319d9866c950d8e5..31e9160223e9aa772669ad4128f27729e6decef5 100644 (file)
@@ -171,20 +171,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 static struct usb_string strings_dev[] = {
        [USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -416,17 +403,28 @@ static int eth_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc)
+                       goto fail1;
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* register our configuration(s); RNDIS first, if it's used */
        if (has_rndis()) {
                status = usb_add_config(cdev, &rndis_config_driver,
                                rndis_do_config);
                if (status < 0)
-                       goto fail1;
+                       goto fail2;
        }
 
        status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
        if (status < 0)
-               goto fail1;
+               goto fail2;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -434,6 +432,9 @@ static int eth_bind(struct usb_composite_dev *cdev)
 
        return 0;
 
+fail2:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail1:
        if (has_rndis())
                usb_put_function_instance(fi_rndis);
@@ -463,6 +464,9 @@ static int eth_unbind(struct usb_composite_dev *cdev)
                usb_put_function(f_geth);
                usb_put_function_instance(fi_geth);
        }
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index e821931c965cd9203a8011358ffeb16844dc7eed..320a81b2baa688cb4bc9db1eaad1ca7435bfca23 100644 (file)
@@ -88,21 +88,7 @@ MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
 module_param_array_named(functions, func_names, charp, &func_num, 0);
 MODULE_PARM_DESC(functions, "USB Functions list");
 
-static const struct usb_descriptor_header *gfs_otg_desc[] = {
-       (const struct usb_descriptor_header *)
-       &(const struct usb_otg_descriptor) {
-               .bLength                = sizeof(struct usb_otg_descriptor),
-               .bDescriptorType        = USB_DT_OTG,
-
-               /*
-                * REVISIT SRP-only hardware is possible, although
-                * it would not be called "OTG" ...
-                */
-               .bmAttributes           = USB_OTG_SRP | USB_OTG_HNP,
-       },
-
-       NULL
-};
+static const struct usb_descriptor_header *gfs_otg_desc[2];
 
 /* String IDs are assigned dynamically */
 static struct usb_string gfs_strings[] = {
@@ -412,6 +398,17 @@ static int gfs_bind(struct usb_composite_dev *cdev)
                goto error_rndis;
        gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+               if (!usb_desc)
+                       goto error_rndis;
+               usb_otg_descriptor_init(cdev->gadget, usb_desc);
+               gfs_otg_desc[0] = usb_desc;
+               gfs_otg_desc[1] = NULL;
+       }
+
        for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
                struct gfs_configuration *c = gfs_configurations + i;
                int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
@@ -432,6 +429,8 @@ static int gfs_bind(struct usb_composite_dev *cdev)
 
 /* TODO */
 error_unbind:
+       kfree(gfs_otg_desc[0]);
+       gfs_otg_desc[0] = NULL;
 error_rndis:
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
        usb_put_function_instance(fi_rndis);
@@ -473,6 +472,9 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
        for (i = 0; i < N_CONF * func_num; ++i)
                usb_put_function(*(f_ffs[0] + i));
 
+       kfree(gfs_otg_desc[0]);
+       gfs_otg_desc[0] = NULL;
+
        return 0;
 }
 
index da19c486b61e33a5b3214830f1c5db42ed979a75..8a18348ae86eef3807fabc066c12c143a1ac8da2 100644 (file)
@@ -35,8 +35,6 @@
 #include <linux/usb/audio.h>
 #include <linux/usb/midi.h>
 
-#include "gadget_chips.h"
-
 #include "u_midi.h"
 
 /*-------------------------------------------------------------------------*/
@@ -88,10 +86,10 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
 static struct usb_device_descriptor device_desc = {
        .bLength =              USB_DT_DEVICE_SIZE,
        .bDescriptorType =      USB_DT_DEVICE,
-       .bcdUSB =               __constant_cpu_to_le16(0x0200),
+       .bcdUSB =               cpu_to_le16(0x0200),
        .bDeviceClass =         USB_CLASS_PER_INTERFACE,
-       .idVendor =             __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
-       .idProduct =            __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+       .idVendor =             cpu_to_le16(DRIVER_VENDOR_NUM),
+       .idProduct =            cpu_to_le16(DRIVER_PRODUCT_NUM),
        /* .iManufacturer =     DYNAMIC */
        /* .iProduct =          DYNAMIC */
        .bNumConfigurations =   1,
index 2baa572686c6acbd5e1350ab167b65a367482302..7e5d2c48476e568021fa5c550040c999c3cfa7b0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/usb/composite.h>
 #include <linux/usb/g_hid.h>
 
-#include "gadget_chips.h"
 #define DRIVER_DESC            "HID Gadget"
 #define DRIVER_VERSION         "2010/03/16"
 
@@ -68,21 +67,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
 
 /* string IDs are assigned dynamically */
 static struct usb_string strings_dev[] = {
@@ -186,16 +171,30 @@ static int hid_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc)
+                       goto put;
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* register our configuration */
        status = usb_add_config(cdev, &config_driver, do_config);
        if (status < 0)
-               goto put;
+               goto free_otg_desc;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 
        return 0;
 
+free_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 put:
        list_for_each_entry(m, &hidg_func_list, node) {
                if (m == n)
@@ -213,6 +212,10 @@ static int hid_unbind(struct usb_composite_dev *cdev)
                usb_put_function(n->f);
                usb_put_function_instance(n->fi);
        }
+
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index e7bfb081f111e4b60e55bce9ae5cd5f0743dad20..bda3c519110fe266dec569c4e85159499fa062d1 100644 (file)
@@ -64,21 +64,7 @@ static struct usb_device_descriptor msg_device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /*
-        * REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 static struct usb_string strings_dev[] = {
        [USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -191,10 +177,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
        if (status)
                goto fail;
 
-       status = fsg_common_set_nluns(opts->common, config.nluns);
-       if (status)
-               goto fail_set_nluns;
-
        fsg_common_set_ops(opts->common, &ops);
 
        status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
@@ -214,9 +196,20 @@ static int msg_bind(struct usb_composite_dev *cdev)
                goto fail_string_ids;
        msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+               if (!usb_desc)
+                       goto fail_string_ids;
+               usb_otg_descriptor_init(cdev->gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
        if (status < 0)
-               goto fail_string_ids;
+               goto fail_otg_desc;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&cdev->gadget->dev,
@@ -224,11 +217,12 @@ static int msg_bind(struct usb_composite_dev *cdev)
        set_bit(0, &msg_registered);
        return 0;
 
+fail_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail_string_ids:
        fsg_common_remove_luns(opts->common);
 fail_set_cdev:
-       fsg_common_free_luns(opts->common);
-fail_set_nluns:
        fsg_common_free_buffers(opts->common);
 fail:
        usb_put_function_instance(fi_msg);
@@ -243,6 +237,9 @@ static int msg_unbind(struct usb_composite_dev *cdev)
        if (!IS_ERR(fi_msg))
                usb_put_function_instance(fi_msg);
 
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index b21b51f0c9fadb27bbe319791ad970502eb88aa3..4fe794ddcd49ced2c4206c730b251be8a008352f 100644 (file)
@@ -78,21 +78,7 @@ static struct usb_device_descriptor device_desc = {
        .idProduct =            cpu_to_le16(MULTI_PRODUCT_NUM),
 };
 
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &(struct usb_otg_descriptor){
-               .bLength =              sizeof(struct usb_otg_descriptor),
-               .bDescriptorType =      USB_DT_OTG,
-
-               /*
-                * REVISIT SRP-only hardware is possible, although
-                * it would not be called "OTG" ...
-                */
-               .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-       },
-       NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
 
 enum {
        MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
@@ -407,10 +393,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
        if (status)
                goto fail2;
 
-       status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
-       if (status)
-               goto fail_set_nluns;
-
        status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
        if (status)
                goto fail_set_cdev;
@@ -429,14 +411,25 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
                goto fail_string_ids;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc)
+                       goto fail_string_ids;
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* register configurations */
        status = rndis_config_register(cdev);
        if (unlikely(status < 0))
-               goto fail_string_ids;
+               goto fail_otg_desc;
 
        status = cdc_config_register(cdev);
        if (unlikely(status < 0))
-               goto fail_string_ids;
+               goto fail_otg_desc;
        usb_composite_overwrite_options(cdev, &coverwrite);
 
        /* we're done */
@@ -445,11 +438,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
 
 
        /* error recovery */
+fail_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail_string_ids:
        fsg_common_remove_luns(fsg_opts->common);
 fail_set_cdev:
-       fsg_common_free_luns(fsg_opts->common);
-fail_set_nluns:
        fsg_common_free_buffers(fsg_opts->common);
 fail2:
        usb_put_function_instance(fi_msg);
@@ -490,6 +484,9 @@ static int multi_unbind(struct usb_composite_dev *cdev)
        usb_put_function(f_ecm);
        usb_put_function_instance(fi_ecm);
 #endif
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index 6ce7421412e9c14d7766210ab3442d06ca8f49d6..2bae4381332d57203f95713f03e8a1f7aba9c35d 100644 (file)
@@ -69,20 +69,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 /* string IDs are assigned dynamically */
 static struct usb_string strings_dev[] = {
@@ -171,16 +158,30 @@ static int gncm_bind(struct usb_composite_dev *cdev)
        device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc)
+                       goto fail;
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        status = usb_add_config(cdev, &ncm_config_driver,
                                ncm_do_config);
        if (status < 0)
-               goto fail;
+               goto fail1;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
 
        return 0;
 
+fail1:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail:
        usb_put_function_instance(f_ncm_inst);
        return status;
@@ -192,6 +193,9 @@ static int gncm_unbind(struct usb_composite_dev *cdev)
                usb_put_function(f_ncm);
        if (!IS_ERR_OR_NULL(f_ncm_inst))
                usb_put_function_instance(f_ncm_inst);
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index 4bb498a38a1c01eb17077844bc163028c3e22b93..8b3f6fb1825d56a7266eeb5c09ce115e60f26be8 100644 (file)
@@ -23,7 +23,7 @@
 #include "u_ether.h"
 #include "u_phonet.h"
 #include "u_ecm.h"
-#include "gadget_chips.h"
+#include "f_mass_storage.h"
 
 /* Defines */
 
@@ -34,6 +34,29 @@ USB_GADGET_COMPOSITE_OPTIONS();
 
 USB_ETHERNET_MODULE_PARAMETERS();
 
+static struct fsg_module_parameters fsg_mod_data = {
+       .stall = 0,
+       .luns = 2,
+       .removable_count = 2,
+       .removable = { 1, 1, },
+};
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers        CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
+FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
+
 #define NOKIA_VENDOR_ID                        0x0421  /* Nokia */
 #define NOKIA_PRODUCT_ID               0x01c8  /* Nokia Gadget */
 
@@ -66,10 +89,10 @@ static struct usb_gadget_strings *dev_strings[] = {
 static struct usb_device_descriptor device_desc = {
        .bLength                = USB_DT_DEVICE_SIZE,
        .bDescriptorType        = USB_DT_DEVICE,
-       .bcdUSB                 = __constant_cpu_to_le16(0x0200),
+       .bcdUSB                 = cpu_to_le16(0x0200),
        .bDeviceClass           = USB_CLASS_COMM,
-       .idVendor               = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
-       .idProduct              = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
+       .idVendor               = cpu_to_le16(NOKIA_VENDOR_ID),
+       .idProduct              = cpu_to_le16(NOKIA_PRODUCT_ID),
        .bcdDevice              = cpu_to_le16(NOKIA_VERSION_NUM),
        /* .iManufacturer = DYNAMIC */
        /* .iProduct = DYNAMIC */
@@ -94,6 +117,8 @@ static struct usb_function *f_obex1_cfg2;
 static struct usb_function *f_obex2_cfg2;
 static struct usb_function *f_phonet_cfg1;
 static struct usb_function *f_phonet_cfg2;
+static struct usb_function *f_msg_cfg1;
+static struct usb_function *f_msg_cfg2;
 
 
 static struct usb_configuration nokia_config_500ma_driver = {
@@ -117,6 +142,7 @@ static struct usb_function_instance *fi_ecm;
 static struct usb_function_instance *fi_obex1;
 static struct usb_function_instance *fi_obex2;
 static struct usb_function_instance *fi_phonet;
+static struct usb_function_instance *fi_msg;
 
 static int nokia_bind_config(struct usb_configuration *c)
 {
@@ -125,6 +151,8 @@ static int nokia_bind_config(struct usb_configuration *c)
        struct usb_function *f_obex1 = NULL;
        struct usb_function *f_ecm;
        struct usb_function *f_obex2 = NULL;
+       struct usb_function *f_msg;
+       struct fsg_opts *fsg_opts;
        int status = 0;
        int obex1_stat = -1;
        int obex2_stat = -1;
@@ -160,6 +188,12 @@ static int nokia_bind_config(struct usb_configuration *c)
                goto err_get_ecm;
        }
 
+       f_msg = usb_get_function(fi_msg);
+       if (IS_ERR(f_msg)) {
+               status = PTR_ERR(f_msg);
+               goto err_get_msg;
+       }
+
        if (!IS_ERR_OR_NULL(f_phonet)) {
                phonet_stat = usb_add_function(c, f_phonet);
                if (phonet_stat)
@@ -187,21 +221,36 @@ static int nokia_bind_config(struct usb_configuration *c)
                pr_debug("could not bind ecm config %d\n", status);
                goto err_ecm;
        }
+
+       fsg_opts = fsg_opts_from_func_inst(fi_msg);
+
+       status = fsg_common_run_thread(fsg_opts->common);
+       if (status)
+               goto err_msg;
+
+       status = usb_add_function(c, f_msg);
+       if (status)
+               goto err_msg;
+
        if (c == &nokia_config_500ma_driver) {
                f_acm_cfg1 = f_acm;
                f_ecm_cfg1 = f_ecm;
                f_phonet_cfg1 = f_phonet;
                f_obex1_cfg1 = f_obex1;
                f_obex2_cfg1 = f_obex2;
+               f_msg_cfg1 = f_msg;
        } else {
                f_acm_cfg2 = f_acm;
                f_ecm_cfg2 = f_ecm;
                f_phonet_cfg2 = f_phonet;
                f_obex1_cfg2 = f_obex1;
                f_obex2_cfg2 = f_obex2;
+               f_msg_cfg2 = f_msg;
        }
 
        return status;
+err_msg:
+       usb_remove_function(c, f_ecm);
 err_ecm:
        usb_remove_function(c, f_acm);
 err_conf:
@@ -211,6 +260,8 @@ err_conf:
                usb_remove_function(c, f_obex1);
        if (!phonet_stat)
                usb_remove_function(c, f_phonet);
+       usb_put_function(f_msg);
+err_get_msg:
        usb_put_function(f_ecm);
 err_get_ecm:
        usb_put_function(f_acm);
@@ -227,6 +278,8 @@ err_get_acm:
 static int nokia_bind(struct usb_composite_dev *cdev)
 {
        struct usb_gadget       *gadget = cdev->gadget;
+       struct fsg_opts         *fsg_opts;
+       struct fsg_config       fsg_config;
        int                     status;
 
        status = usb_string_ids_tab(cdev, strings_dev);
@@ -238,7 +291,7 @@ static int nokia_bind(struct usb_composite_dev *cdev)
        nokia_config_500ma_driver.iConfiguration = status;
        nokia_config_100ma_driver.iConfiguration = status;
 
-       if (!gadget_supports_altsettings(gadget)) {
+       if (!gadget_is_altset_supported(gadget)) {
                status = -ENODEV;
                goto err_usb;
        }
@@ -267,11 +320,42 @@ static int nokia_bind(struct usb_composite_dev *cdev)
                goto err_acm_inst;
        }
 
+       fi_msg = usb_get_function_instance("mass_storage");
+       if (IS_ERR(fi_msg)) {
+               status = PTR_ERR(fi_msg);
+               goto err_ecm_inst;
+       }
+
+       /* set up mass storage function */
+       fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers);
+       fsg_config.vendor_name = "Nokia";
+       fsg_config.product_name = "N900";
+
+       fsg_opts = fsg_opts_from_func_inst(fi_msg);
+       fsg_opts->no_configfs = true;
+
+       status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
+       if (status)
+               goto err_msg_inst;
+
+       status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall);
+       if (status)
+               goto err_msg_buf;
+
+       fsg_common_set_sysfs(fsg_opts->common, true);
+
+       status = fsg_common_create_luns(fsg_opts->common, &fsg_config);
+       if (status)
+               goto err_msg_buf;
+
+       fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name,
+                                     fsg_config.product_name);
+
        /* finally register the configuration */
        status = usb_add_config(cdev, &nokia_config_500ma_driver,
                        nokia_bind_config);
        if (status < 0)
-               goto err_ecm_inst;
+               goto err_msg_luns;
 
        status = usb_add_config(cdev, &nokia_config_100ma_driver,
                        nokia_bind_config);
@@ -292,6 +376,12 @@ err_put_cfg1:
        if (!IS_ERR_OR_NULL(f_phonet_cfg1))
                usb_put_function(f_phonet_cfg1);
        usb_put_function(f_ecm_cfg1);
+err_msg_luns:
+       fsg_common_remove_luns(fsg_opts->common);
+err_msg_buf:
+       fsg_common_free_buffers(fsg_opts->common);
+err_msg_inst:
+       usb_put_function_instance(fi_msg);
 err_ecm_inst:
        usb_put_function_instance(fi_ecm);
 err_acm_inst:
@@ -325,7 +415,10 @@ static int nokia_unbind(struct usb_composite_dev *cdev)
        usb_put_function(f_acm_cfg2);
        usb_put_function(f_ecm_cfg1);
        usb_put_function(f_ecm_cfg2);
+       usb_put_function(f_msg_cfg1);
+       usb_put_function(f_msg_cfg2);
 
+       usb_put_function_instance(fi_msg);
        usb_put_function_instance(fi_ecm);
        if (!IS_ERR(fi_obex2))
                usb_put_function_instance(fi_obex2);
index 1ce7df1060a5b237ae2532f514d95e3edd63cf34..a22d30a4def1e0406512608d22aec7eaefd67561 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/g_printer.h>
 
-#include "gadget_chips.h"
-
 USB_GADGET_COMPOSITE_OPTIONS();
 
 #define DRIVER_DESC            "Printer Gadget"
@@ -82,16 +80,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-       .bmAttributes =         USB_OTG_SRP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 /*-------------------------------------------------------------------------*/
 
@@ -136,7 +125,6 @@ static int printer_do_config(struct usb_configuration *c)
        usb_gadget_set_selfpowered(gadget);
 
        if (gadget_is_otg(gadget)) {
-               otg_descriptor.bmAttributes |= USB_OTG_HNP;
                printer_cfg_driver.descriptors = otg_desc;
                printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
@@ -174,21 +162,39 @@ static int printer_bind(struct usb_composite_dev *cdev)
        opts->q_len = QLEN;
 
        ret = usb_string_ids_tab(cdev, strings);
-       if (ret < 0) {
-               usb_put_function_instance(fi_printer);
-               return ret;
-       }
+       if (ret < 0)
+               goto fail_put_func_inst;
+
        device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
        device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
        device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
 
-       ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
-       if (ret) {
-               usb_put_function_instance(fi_printer);
-               return ret;
+       if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+               if (!usb_desc) {
+                       ret = -ENOMEM;
+                       goto fail_put_func_inst;
+               }
+               usb_otg_descriptor_init(cdev->gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
        }
+
+       ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
+       if (ret)
+               goto fail_free_otg_desc;
+
        usb_composite_overwrite_options(cdev, &coverwrite);
        return ret;
+
+fail_free_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+fail_put_func_inst:
+       usb_put_function_instance(fi_printer);
+       return ret;
 }
 
 static int printer_unbind(struct usb_composite_dev *cdev)
@@ -196,6 +202,9 @@ static int printer_unbind(struct usb_composite_dev *cdev)
        usb_put_function(f_printer);
        usb_put_function_instance(fi_printer);
 
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index 8b7528f9b78eff02a7d20bca4122429d6294be6d..c5d42e0347a94cbd190c7162626ec9177f130662 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/tty_flip.h>
 
 #include "u_serial.h"
-#include "gadget_chips.h"
 
 
 /* Defines */
@@ -79,20 +78,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   1,
 };
 
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
 
 /*-------------------------------------------------------------------------*/
 
@@ -191,6 +177,18 @@ static int gs_bind(struct usb_composite_dev *cdev)
        serial_config_driver.iConfiguration = status;
 
        if (gadget_is_otg(cdev->gadget)) {
+               if (!otg_desc[0]) {
+                       struct usb_descriptor_header *usb_desc;
+
+                       usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+                       if (!usb_desc) {
+                               status = -ENOMEM;
+                               goto fail;
+                       }
+                       usb_otg_descriptor_init(cdev->gadget, usb_desc);
+                       otg_desc[0] = usb_desc;
+                       otg_desc[1] = NULL;
+               }
                serial_config_driver.descriptors = otg_desc;
                serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
@@ -208,13 +206,15 @@ static int gs_bind(struct usb_composite_dev *cdev)
                                "gser");
        }
        if (status < 0)
-               goto fail;
+               goto fail1;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        INFO(cdev, "%s\n", GS_VERSION_NAME);
 
        return 0;
-
+fail1:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 fail:
        return status;
 }
@@ -227,6 +227,10 @@ static int gs_unbind(struct usb_composite_dev *cdev)
                usb_put_function(f_serial[i]);
                usb_put_function_instance(fi_serial[i]);
        }
+
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index c986e8addb90ac809428f780e04cfb9242c22a90..37a410056fed2c8298211fe1491aef7765e283a5 100644 (file)
@@ -121,24 +121,7 @@ static struct usb_device_descriptor device_desc = {
        .bNumConfigurations =   2,
 };
 
-#ifdef CONFIG_USB_OTG
-static struct usb_otg_descriptor otg_descriptor = {
-       .bLength =              sizeof otg_descriptor,
-       .bDescriptorType =      USB_DT_OTG,
-
-       /* REVISIT SRP-only hardware is possible, although
-        * it would not be called "OTG" ...
-        */
-       .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
-       (struct usb_descriptor_header *) &otg_descriptor,
-       NULL,
-};
-#else
-#define otg_desc       NULL
-#endif
+static const struct usb_descriptor_header *otg_desc[2];
 
 /* string IDs are assigned dynamically */
 /* default serial number takes at least two packets */
@@ -341,6 +324,18 @@ static int zero_bind(struct usb_composite_dev *cdev)
 
        /* support OTG systems */
        if (gadget_is_otg(cdev->gadget)) {
+               if (!otg_desc[0]) {
+                       struct usb_descriptor_header *usb_desc;
+
+                       usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+                       if (!usb_desc) {
+                               status = -ENOMEM;
+                               goto err_conf_flb;
+                       }
+                       usb_otg_descriptor_init(cdev->gadget, usb_desc);
+                       otg_desc[0] = usb_desc;
+                       otg_desc[1] = NULL;
+               }
                sourcesink_driver.descriptors = otg_desc;
                sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
                loopback_driver.descriptors = otg_desc;
@@ -359,12 +354,12 @@ static int zero_bind(struct usb_composite_dev *cdev)
        }
        status = usb_add_function(&sourcesink_driver, func_ss);
        if (status)
-               goto err_conf_flb;
+               goto err_free_otg_desc;
 
        usb_ep_autoconfig_reset(cdev->gadget);
        status = usb_add_function(&loopback_driver, func_lb);
        if (status)
-               goto err_conf_flb;
+               goto err_free_otg_desc;
 
        usb_ep_autoconfig_reset(cdev->gadget);
        usb_composite_overwrite_options(cdev, &coverwrite);
@@ -373,6 +368,9 @@ static int zero_bind(struct usb_composite_dev *cdev)
 
        return 0;
 
+err_free_otg_desc:
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
 err_conf_flb:
        usb_put_function(func_lb);
        func_lb = NULL;
@@ -397,6 +395,9 @@ static int zero_unbind(struct usb_composite_dev *cdev)
        if (!IS_ERR_OR_NULL(func_lb))
                usb_put_function(func_lb);
        usb_put_function_instance(func_inst_lb);
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
+
        return 0;
 }
 
index de7e5e2ccf1c8956fcce928901e4a7cc1b4a4d09..fdacddb18c006c6d0cdaaf6b51ce3b962675275e 100644 (file)
@@ -138,15 +138,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
 
 /* endpoint names used for print */
 static const char ep0_string[] = "ep0in";
-static const char *const ep_string[] = {
-       ep0_string,
-       "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
-       "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
-       "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
-       "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
-       "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
-       "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
-       "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
+
+       EP_INFO(ep0_string,
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep1in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep2in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep3in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep4in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep5in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep6in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep7in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep8in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep9in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep10in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep11in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep12in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep13in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep14in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep15in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep0out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep1out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep2out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep3out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep4out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep5out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep6out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep7out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep8out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep9out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep10out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep11out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep12out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep13out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep14out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep15out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
 };
 
 /* DMA usage flag */
@@ -1517,7 +1584,8 @@ static void udc_setup_endpoints(struct udc *dev)
        for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
                ep = &dev->ep[tmp];
                ep->dev = dev;
-               ep->ep.name = ep_string[tmp];
+               ep->ep.name = ep_info[tmp].name;
+               ep->ep.caps = ep_info[tmp].caps;
                ep->num = tmp;
                /* txfifo size is calculated at enable time */
                ep->txfifo = dev->txfifo;
index fc4226462f8f5da2f71741a77093b7d69343afe3..d0d18947f58bfdf4147057107d0c36cd2ca20063 100644 (file)
 #define        DRIVER_VERSION  "3 May 2006"
 
 static const char driver_name [] = "at91_udc";
-static const char * const ep_names[] = {
-       "ep0",
-       "ep1",
-       "ep2",
-       "ep3-int",
-       "ep4",
-       "ep5",
+
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
+
+       EP_INFO("ep0",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep1",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep2",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep3-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep4",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep5",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+
+#undef EP_INFO
 };
-#define ep0name                ep_names[0]
+
+#define ep0name                ep_info[0].name
 
 #define VBUS_POLL_TIMEOUT      msecs_to_jiffies(1000)
 
@@ -825,6 +844,7 @@ static void udc_reinit(struct at91_udc *udc)
 
        INIT_LIST_HEAD(&udc->gadget.ep_list);
        INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+       udc->gadget.quirk_stall_not_supp = 1;
 
        for (i = 0; i < NUM_ENDPOINTS; i++) {
                struct at91_ep *ep = &udc->ep[i];
@@ -1830,7 +1850,8 @@ static int at91udc_probe(struct platform_device *pdev)
 
        for (i = 0; i < NUM_ENDPOINTS; i++) {
                ep = &udc->ep[i];
-               ep->ep.name = ep_names[i];
+               ep->ep.name = ep_info[i].name;
+               ep->ep.caps = ep_info[i].caps;
                ep->ep.ops = &at91_ep_ops;
                ep->udc = udc;
                ep->int_mask = BIT(i);
index 4095cce05e6a729ccf86ff5f6394e55f7cf0511f..3dfada8d60616fb89204ba2eee72d4bc6f2ef9c0 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/atmel_usba_udc.h>
 #include <linux/delay.h>
-#include <linux/platform_data/atmel.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
@@ -1989,6 +1988,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
                ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
 
                ret = of_property_read_string(pp, "name", &name);
+               if (ret) {
+                       dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
+                       goto err;
+               }
                ep->ep.name = name;
 
                ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
@@ -2063,6 +2066,17 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
                ep->can_dma = pdata->ep[i].can_dma;
                ep->can_isoc = pdata->ep[i].can_isoc;
 
+               if (i == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = ep->can_isoc;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
+
                if (i)
                        list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
        }
index 9db968ba39f54aec7f102a2948ec00cc326094c6..8cbb00325824a480b9c5558202cb74d55e9d81b8 100644 (file)
 #define DRV_MODULE_NAME                "bcm63xx_udc"
 
 static const char bcm63xx_ep0name[] = "ep0";
-static const char *const bcm63xx_ep_name[] = {
-       bcm63xx_ep0name,
-       "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
+
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} bcm63xx_ep_info[] = {
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
+
+       EP_INFO(bcm63xx_ep0name,
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep1in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep2out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep3in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep4out-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
 };
 
 static bool use_fullspeed;
@@ -943,7 +963,8 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
        for (i = 0; i < BCM63XX_NUM_EP; i++) {
                struct bcm63xx_ep *bep = &udc->bep[i];
 
-               bep->ep.name = bcm63xx_ep_name[i];
+               bep->ep.name = bcm63xx_ep_info[i].name;
+               bep->ep.caps = bcm63xx_ep_info[i].caps;
                bep->ep_num = i;
                bep->ep.ops = &bcm63xx_udc_ep_ops;
                list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
index 1efa61265d8d49c5116027c8e3555ae70b9cc12c..d1b81539d6320b3baed7c5bc9bc4cdde7440aee9 100644 (file)
@@ -1952,12 +1952,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
        ep->bdc = bdc;
        ep->dir = dir;
 
+       if (dir)
+               ep->usb_ep.caps.dir_in = true;
+       else
+               ep->usb_ep.caps.dir_out = true;
+
        /* ep->ep_num is the index inside bdc_ep */
        if (epnum == 1) {
                ep->ep_num = 1;
                bdc->bdc_ep_array[ep->ep_num] = ep;
                snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1);
                usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE);
+               ep->usb_ep.caps.type_control = true;
                ep->comp_desc = NULL;
                bdc->gadget.ep0 = &ep->usb_ep;
        } else {
@@ -1971,6 +1977,9 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
                         dir & 1 ? "in" : "out");
 
                usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024);
+               ep->usb_ep.caps.type_iso = true;
+               ep->usb_ep.caps.type_bulk = true;
+               ep->usb_ep.caps.type_int = true;
                ep->usb_ep.max_streams = 0;
                list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list);
        }
index 181112c88f430d39985c199312b2043337c02cf6..1379ad40d864bd42308f0c336fe931e8c757355e 100644 (file)
@@ -127,23 +127,87 @@ static inline struct dummy_request *usb_request_to_dummy_request
 
 static const char ep0name[] = "ep0";
 
-static const char *const ep_name[] = {
-       ep0name,                                /* everyone has ep0 */
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
 
+       /* everyone has ep0 */
+       EP_INFO(ep0name,
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
        /* act like a pxa250: fifteen fixed function endpoints */
-       "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
-       "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
-       "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
-               "ep15in-int",
-
+       EP_INFO("ep1in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep2out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep3in-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep4out-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep5in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep6in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep7out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep8in-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep9out-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep10in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep11in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep12out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep13in-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep14out-iso",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep15in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
        /* or like sa1100: two fixed function endpoints */
-       "ep1out-bulk", "ep2in-bulk",
-
+       EP_INFO("ep1out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep2in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
        /* and now some generic EPs so we have enough in multi config */
-       "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
-       "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
+       EP_INFO("ep3out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep4in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep5out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep6out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep7in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep8out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep9in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep10out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep11out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep12in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep13out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep14in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep15out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
 };
-#define DUMMY_ENDPOINTS        ARRAY_SIZE(ep_name)
+
+#define DUMMY_ENDPOINTS        ARRAY_SIZE(ep_info)
 
 /*-------------------------------------------------------------------------*/
 
@@ -938,9 +1002,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
        for (i = 0; i < DUMMY_ENDPOINTS; i++) {
                struct dummy_ep *ep = &dum->ep[i];
 
-               if (!ep_name[i])
+               if (!ep_info[i].name)
                        break;
-               ep->ep.name = ep_name[i];
+               ep->ep.name = ep_info[i].name;
+               ep->ep.caps = ep_info[i].caps;
                ep->ep.ops = &dummy_ep_ops;
                list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
                ep->halted = ep->wedged = ep->already_seen =
@@ -1684,7 +1749,7 @@ static void dummy_timer(unsigned long _dum_hcd)
        }
 
        for (i = 0; i < DUMMY_ENDPOINTS; i++) {
-               if (!ep_name[i])
+               if (!ep_info[i].name)
                        break;
                dum->ep[i].already_seen = 0;
        }
index 1137e3384218c11e738b88067f01fd8ee4105f25..6ba122cc7490b42acd0d9b004283e4d26f48c167 100644 (file)
@@ -384,25 +384,15 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep,
                return;
        }
        if (ep->dir_in) { /* if IN */
-               if (req->req.length) {
-                       fotg210_start_dma(ep, req);
-               } else {
-                       pr_err("%s : req->req.length = 0x%x\n",
-                              __func__, req->req.length);
-               }
+               fotg210_start_dma(ep, req);
                if ((req->req.length == req->req.actual) ||
                    (req->req.actual < ep->ep.maxpacket))
                        fotg210_done(ep, req, 0);
        } else { /* OUT */
-               if (!req->req.length) {
-                       fotg210_done(ep, req, 0);
-               } else {
-                       u32 value = ioread32(ep->fotg210->reg +
-                                               FOTG210_DMISGR0);
+               u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0);
 
-                       value &= ~DMISGR0_MCX_OUT_INT;
-                       iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
-               }
+               value &= ~DMISGR0_MCX_OUT_INT;
+               iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
        }
 }
 
@@ -1153,6 +1143,17 @@ static int fotg210_udc_probe(struct platform_device *pdev)
                ep->ep.name = fotg210_ep_name[i];
                ep->ep.ops = &fotg210_ep_ops;
                usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+
+               if (i == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
        }
        usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
        fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
index e0822f1b6639dfd699e212dccdf8d52ec7aa94bc..5fb6f8b4f0b4889f51d1686610ab07b40cc9bdc0 100644 (file)
@@ -2417,6 +2417,17 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
        strcpy(ep->name, ep_name[pipe_num]);
        ep->ep.name = ep_name[pipe_num];
 
+       if (pipe_num == 0) {
+               ep->ep.caps.type_control = true;
+       } else {
+               ep->ep.caps.type_iso = true;
+               ep->ep.caps.type_bulk = true;
+               ep->ep.caps.type_int = true;
+       }
+
+       ep->ep.caps.dir_in = true;
+       ep->ep.caps.dir_out = true;
+
        ep->ep.ops = &qe_ep_ops;
        ep->stopped = 1;
        usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
index c60022b46a4835b4cc2b151b7a46193fe0f5554b..aab5221d6c2e35050edccaaa170f960f90c40887 100644 (file)
@@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
        ep->ep.ops = &fsl_ep_ops;
        ep->stopped = 0;
 
+       if (index == 0) {
+               ep->ep.caps.type_control = true;
+       } else {
+               ep->ep.caps.type_iso = true;
+               ep->ep.caps.type_bulk = true;
+               ep->ep.caps.type_int = true;
+       }
+
+       if (index & 1)
+               ep->ep.caps.dir_in = true;
+       else
+               ep->ep.caps.dir_out = true;
+
        /* for ep0: maxP defined in desc
         * for other eps, maxP is set by epautoconfig() called by gadget layer
         */
index 3970f453de4903fb55c21831e4cb511b2a2afc11..948845c90e47d3cf3333511f74673b2d7cd62daf 100644 (file)
@@ -1450,6 +1450,17 @@ static int fusb300_probe(struct platform_device *pdev)
                ep->ep.name = fusb300_ep_name[i];
                ep->ep.ops = &fusb300_ep_ops;
                usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
+
+               if (i == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
        }
        usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
        fusb300->ep[0]->epnum = 0;
diff --git a/drivers/usb/gadget/udc/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h
deleted file mode 100644 (file)
index bcd04bc..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * USB device controllers have lots of quirks.  Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- * (And avoiding all runtime comparisons in typical one-choice configs!)
- *
- * NOTE:  some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
- */
-
-#ifndef __GADGET_CHIPS_H
-#define __GADGET_CHIPS_H
-
-#include <linux/usb/gadget.h>
-
-/*
- * NOTICE: the entries below are alphabetical and should be kept
- * that way.
- *
- * Always be sure to add new entries to the correct position or
- * accept the bashing later.
- *
- * If you have forgotten the alphabetical order let VIM/EMACS
- * do that for you.
- */
-#define gadget_is_at91(g)              (!strcmp("at91_udc", (g)->name))
-#define gadget_is_goku(g)              (!strcmp("goku_udc", (g)->name))
-#define gadget_is_musbhdrc(g)          (!strcmp("musb-hdrc", (g)->name))
-#define gadget_is_net2280(g)           (!strcmp("net2280", (g)->name))
-#define gadget_is_pxa(g)               (!strcmp("pxa25x_udc", (g)->name))
-#define gadget_is_pxa27x(g)            (!strcmp("pxa27x_udc", (g)->name))
-
-/**
- * gadget_supports_altsettings - return true if altsettings work
- * @gadget: the gadget in question
- */
-static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
-{
-       /* PXA 21x/25x/26x has no altsettings at all */
-       if (gadget_is_pxa(gadget))
-               return false;
-
-       /* PXA 27x and 3xx have *broken* altsetting support */
-       if (gadget_is_pxa27x(gadget))
-               return false;
-
-       /* Everything else is *presumably* fine ... */
-       return true;
-}
-
-#endif /* __GADGET_CHIPS_H */
index 9e8d842e8c08546ed1fe109a3586da6b3c4ee102..1fdfec14a3ba13eea57dfced8b170752e452fdb2 100644 (file)
@@ -990,6 +990,35 @@ static int goku_get_frame(struct usb_gadget *_gadget)
        return -EOPNOTSUPP;
 }
 
+static struct usb_ep *goku_match_ep(struct usb_gadget *g,
+               struct usb_endpoint_descriptor *desc,
+               struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+       struct goku_udc *dev = to_goku_udc(g);
+       struct usb_ep *ep;
+
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_INT:
+               /* single buffering is enough */
+               ep = &dev->ep[3].ep;
+               if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+                       return ep;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               if (usb_endpoint_dir_in(desc)) {
+                       /* DMA may be available */
+                       ep = &dev->ep[2].ep;
+                       if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+                               return ep;
+               }
+               break;
+       default:
+               /* nothing */ ;
+       }
+
+       return NULL;
+}
+
 static int goku_udc_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver);
 static int goku_udc_stop(struct usb_gadget *g);
@@ -998,6 +1027,7 @@ static const struct usb_gadget_ops goku_ops = {
        .get_frame      = goku_get_frame,
        .udc_start      = goku_udc_start,
        .udc_stop       = goku_udc_stop,
+       .match_ep       = goku_match_ep,
        // no remote wakeup
        // not selfpowered
 };
@@ -1257,6 +1287,14 @@ static void udc_reinit (struct goku_udc *dev)
                INIT_LIST_HEAD (&ep->queue);
 
                ep_reset(NULL, ep);
+
+               if (i == 0)
+                       ep->ep.caps.type_control = true;
+               else
+                       ep->ep.caps.type_bulk = true;
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
        }
 
        dev->ep[0].reg_mode = NULL;
index c8868870e21770782cf9049b4a8bdbcc80cf9a00..8aa2593c2c3633a7e9e81131f93a8c88f1ebb951 100644 (file)
@@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
 
                usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
                ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
+
+               ep->ep.caps.type_control = true;
        } else {
                usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
                list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+               ep->ep.caps.type_iso = true;
+               ep->ep.caps.type_bulk = true;
+               ep->ep.caps.type_int = true;
        }
        list_add_tail(&ep->ep_list, &dev->ep_list);
 
+       if (is_in)
+               ep->ep.caps.dir_in = true;
+       else
+               ep->ep.caps.dir_out = true;
+
        ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit,
                                         &ep->tailbuf_paddr, GFP_ATOMIC);
        if (!ep->tailbuf)
index 3b6a7852822d4aca3832876dabae212241268efd..00b5006baf154f82885428c333a31720c98edd6a 100644 (file)
@@ -2575,6 +2575,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep0",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 0,
@@ -2586,6 +2588,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep1-int",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 2,
@@ -2597,6 +2601,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep2-bulk",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 4,
@@ -2608,6 +2614,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep3-iso",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 1023,
                .hwep_num_base  = 6,
@@ -2619,6 +2627,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep4-int",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 8,
@@ -2630,6 +2640,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep5-bulk",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 10,
@@ -2641,6 +2653,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep6-iso",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 1023,
                .hwep_num_base  = 12,
@@ -2652,6 +2666,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep7-int",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 14,
@@ -2663,6 +2679,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep8-bulk",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 16,
@@ -2674,6 +2692,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep9-iso",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 1023,
                .hwep_num_base  = 18,
@@ -2685,6 +2705,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep10-int",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 20,
@@ -2696,6 +2718,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep11-bulk",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 22,
@@ -2707,6 +2731,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep12-iso",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 1023,
                .hwep_num_base  = 24,
@@ -2718,6 +2744,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep13-int",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 26,
@@ -2729,6 +2757,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep14-bulk",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 64,
                .hwep_num_base  = 28,
@@ -2740,6 +2770,8 @@ static const struct lpc32xx_udc controller_template = {
                .ep = {
                        .name   = "ep15-bulk",
                        .ops    = &lpc32xx_ep_ops,
+                       .caps   = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                       USB_EP_CAPS_DIR_ALL),
                },
                .maxpacket      = 1023,
                .hwep_num_base  = 30,
index 309706fe4bf0ab0fd61d37a492a2bef0d73deb2a..b1cfa96cc88f836b202f6d0ea8eb7dbcc5d09c36 100644 (file)
@@ -1052,7 +1052,7 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
                                tmp = m66592_read(m66592, M66592_INTSTS0) &
                                                                M66592_CTSQ;
                                udelay(1);
-                       } while (tmp != M66592_CS_IDST || timeout-- > 0);
+                       } while (tmp != M66592_CS_IDST && timeout-- > 0);
 
                        if (tmp == M66592_CS_IDST)
                                m66592_bset(m66592,
@@ -1644,6 +1644,17 @@ static int m66592_probe(struct platform_device *pdev)
                ep->ep.name = m66592_ep_name[i];
                ep->ep.ops = &m66592_ep_ops;
                usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+               if (i == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
        }
        usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
        m66592->ep[0].pipenum = 0;
index ea35a248c8985fbc8ecc8b65fb4a02c1ab070738..4c489692745e0d9ee77209846ec0f63fc08e3608 100644 (file)
@@ -1324,6 +1324,9 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
        ep->ep.ops = &mv_u3d_ep_ops;
        ep->wedge = 0;
        usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
+       ep->ep.caps.type_control = true;
+       ep->ep.caps.dir_in = true;
+       ep->ep.caps.dir_out = true;
        ep->ep_num = 0;
        ep->ep.desc = &mv_u3d_ep0_desc;
        INIT_LIST_HEAD(&ep->queue);
@@ -1339,14 +1342,20 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
                if (i & 1) {
                        snprintf(name, sizeof(name), "ep%din", i >> 1);
                        ep->direction = MV_U3D_EP_DIR_IN;
+                       ep->ep.caps.dir_in = true;
                } else {
                        snprintf(name, sizeof(name), "ep%dout", i >> 1);
                        ep->direction = MV_U3D_EP_DIR_OUT;
+                       ep->ep.caps.dir_out = true;
                }
                ep->u3d = u3d;
                strncpy(ep->name, name, sizeof(ep->name));
                ep->ep.name = ep->name;
 
+               ep->ep.caps.type_iso = true;
+               ep->ep.caps.type_bulk = true;
+               ep->ep.caps.type_int = true;
+
                ep->ep.ops = &mv_u3d_ep_ops;
                usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
                ep->ep_num = i / 2;
index 5da37c957b53ce34bd9820ebfd57b9f20a5815c4..339af51df57df9532749deff77efe1fc0a7c1d7f 100644 (file)
@@ -1257,6 +1257,9 @@ static int eps_init(struct mv_udc *udc)
        ep->wedge = 0;
        ep->stopped = 0;
        usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
+       ep->ep.caps.type_control = true;
+       ep->ep.caps.dir_in = true;
+       ep->ep.caps.dir_out = true;
        ep->ep_num = 0;
        ep->ep.desc = &mv_ep0_desc;
        INIT_LIST_HEAD(&ep->queue);
@@ -1269,14 +1272,20 @@ static int eps_init(struct mv_udc *udc)
                if (i % 2) {
                        snprintf(name, sizeof(name), "ep%din", i / 2);
                        ep->direction = EP_DIR_IN;
+                       ep->ep.caps.dir_in = true;
                } else {
                        snprintf(name, sizeof(name), "ep%dout", i / 2);
                        ep->direction = EP_DIR_OUT;
+                       ep->ep.caps.dir_out = true;
                }
                ep->udc = udc;
                strncpy(ep->name, name, sizeof(ep->name));
                ep->ep.name = ep->name;
 
+               ep->ep.caps.type_iso = true;
+               ep->ep.caps.type_bulk = true;
+               ep->ep.caps.type_int = true;
+
                ep->ep.ops = &mv_ep_ops;
                ep->stopped = 0;
                usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
index 195baf3e1fcd4722c80e47f0789de17cf2ad0a88..18f5ebd447b8239b88f73ab4cf6897a7f47ced7a 100644 (file)
@@ -1404,6 +1404,17 @@ net2272_usb_reinit(struct net2272 *dev)
                else
                        ep->fifo_size = 64;
                net2272_ep_reset(ep);
+
+               if (i == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
        }
        usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
 
@@ -1826,9 +1837,9 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
                                if (!e || u.r.wLength > 2)
                                        goto do_stall;
                                if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
-                                       status = __constant_cpu_to_le16(1);
+                                       status = cpu_to_le16(1);
                                else
-                                       status = __constant_cpu_to_le16(0);
+                                       status = cpu_to_le16(0);
 
                                /* don't bother with a request object! */
                                net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
index 2bee912ca65b1545ff32cd9933fe266f5103f779..cf0ed42f5591c93065d6d9c5741dea6967ad4829 100644 (file)
@@ -74,19 +74,58 @@ static const char driver_desc[] = DRIVER_DESC;
 
 static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
 static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
-       ep0name,
-       "ep-a", "ep-b", "ep-c", "ep-d",
-       "ep-e", "ep-f", "ep-g", "ep-h",
-};
 
-/* Endpoint names for usb3380 advance mode */
-static const char *const ep_name_adv[] = {
-       ep0name,
-       "ep1in", "ep2out", "ep3in", "ep4out",
-       "ep1out", "ep2in", "ep3out", "ep4in",
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
+
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} ep_info_dft[] = { /* Default endpoint configuration */
+       EP_INFO(ep0name,
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-a",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-b",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-c",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-d",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-e",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-f",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-g",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep-h",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */
+       EP_INFO(ep0name,
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+       EP_INFO("ep1in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep2out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep3in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep4out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep1out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep2in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep3out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep4in",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
 };
 
+#undef EP_INFO
+
 /* mode 0 == ep-{a,b,c,d} 1K fifo each
  * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
  * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
@@ -1511,6 +1550,33 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
        return 0;
 }
 
+static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
+               struct usb_endpoint_descriptor *desc,
+               struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+       char name[8];
+       struct usb_ep *ep;
+
+       if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) {
+               /* ep-e, ep-f are PIO with only 64 byte fifos */
+               ep = gadget_find_ep_by_name(_gadget, "ep-e");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+               ep = gadget_find_ep_by_name(_gadget, "ep-f");
+               if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+                       return ep;
+       }
+
+       /* USB3380: use same address for usb and hardware endpoints */
+       snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
+                       usb_endpoint_dir_in(desc) ? "in" : "out");
+       ep = gadget_find_ep_by_name(_gadget, name);
+       if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+               return ep;
+
+       return NULL;
+}
+
 static int net2280_start(struct usb_gadget *_gadget,
                struct usb_gadget_driver *driver);
 static int net2280_stop(struct usb_gadget *_gadget);
@@ -1522,6 +1588,7 @@ static const struct usb_gadget_ops net2280_ops = {
        .pullup         = net2280_pullup,
        .udc_start      = net2280_start,
        .udc_stop       = net2280_stop,
+       .match_ep       = net2280_match_ep,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -2055,7 +2122,8 @@ static void usb_reinit_228x(struct net2280 *dev)
        for (tmp = 0; tmp < 7; tmp++) {
                struct net2280_ep       *ep = &dev->ep[tmp];
 
-               ep->ep.name = ep_name[tmp];
+               ep->ep.name = ep_info_dft[tmp].name;
+               ep->ep.caps = ep_info_dft[tmp].caps;
                ep->dev = dev;
                ep->num = tmp;
 
@@ -2095,7 +2163,10 @@ static void usb_reinit_338x(struct net2280 *dev)
        for (i = 0; i < dev->n_ep; i++) {
                struct net2280_ep *ep = &dev->ep[i];
 
-               ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i];
+               ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name :
+                                                  ep_info_dft[i].name;
+               ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps :
+                                                  ep_info_dft[i].caps;
                ep->dev = dev;
                ep->num = i;
 
index e2fcdb8e55961fa3fee8093f55566e6271d41be1..9b7d39484ed3afa55c95a254379b995341bc7ad4 100644 (file)
@@ -2579,6 +2579,28 @@ omap_ep_setup(char *name, u8 addr, u8 type,
        ep->double_buf = dbuf;
        ep->udc = udc;
 
+       switch (type) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               ep->ep.caps.type_control = true;
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               ep->ep.caps.type_iso = true;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               ep->ep.caps.type_bulk = true;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               ep->ep.caps.type_int = true;
+               break;
+       };
+
+       if (addr & USB_DIR_IN)
+               ep->ep.caps.dir_in = true;
+       else
+               ep->ep.caps.dir_out = true;
+
        ep->ep.name = ep->name;
        ep->ep.ops = &omap_ep_ops;
        ep->maxpacket = maxp;
index 613547f078286f157bf8f1b499e3dfca55dc0953..e5f4c5274298684576ac33794da6d929249af797 100644 (file)
@@ -620,9 +620,9 @@ static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
                dev->vbus_session = 1;
        } else {
                if (dev->driver && dev->driver->disconnect) {
-                       spin_unlock(&dev->lock);
-                       dev->driver->disconnect(&dev->gadget);
                        spin_lock(&dev->lock);
+                       dev->driver->disconnect(&dev->gadget);
+                       spin_unlock(&dev->lock);
                }
                pch_udc_set_disconnect(dev);
                dev->vbus_session = 0;
@@ -1191,9 +1191,9 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
                pch_udc_reconnect(dev);
        } else {
                if (dev->driver && dev->driver->disconnect) {
-                       spin_unlock(&dev->lock);
-                       dev->driver->disconnect(&dev->gadget);
                        spin_lock(&dev->lock);
+                       dev->driver->disconnect(&dev->gadget);
+                       spin_unlock(&dev->lock);
                }
                pch_udc_set_disconnect(dev);
        }
@@ -1488,11 +1488,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
                req->dma_mapped = 0;
        }
        ep->halted = 1;
-       spin_unlock(&dev->lock);
+       spin_lock(&dev->lock);
        if (!ep->in)
                pch_udc_ep_clear_rrdy(ep);
        usb_gadget_giveback_request(&ep->ep, &req->req);
-       spin_lock(&dev->lock);
+       spin_unlock(&dev->lock);
        ep->halted = halted;
 }
 
@@ -1793,7 +1793,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
        }
        /* prevent from using desc. - set HOST BUSY */
        dma_desc->status |= PCH_UDC_BS_HST_BSY;
-       dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+       dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID);
        req->td_data = dma_desc;
        req->td_data_last = dma_desc;
        req->chain_len = 1;
@@ -2414,7 +2414,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
                        dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
                else /* OUT */
                        dev->gadget.ep0 = &ep->ep;
-               spin_unlock(&dev->lock);
+               spin_lock(&dev->lock);
                /* If Mass storage Reset */
                if ((dev->setup_data.bRequestType == 0x21) &&
                    (dev->setup_data.bRequest == 0xFF))
@@ -2422,7 +2422,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
                /* call gadget with setup data received */
                setup_supported = dev->driver->setup(&dev->gadget,
                                                     &dev->setup_data);
-               spin_lock(&dev->lock);
+               spin_unlock(&dev->lock);
 
                if (dev->setup_data.bRequestType & USB_DIR_IN) {
                        ep->td_data->status = (ep->td_data->status &
@@ -2594,9 +2594,9 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
                empty_req_queue(ep);
        }
        if (dev->driver) {
-               spin_unlock(&dev->lock);
-               usb_gadget_udc_reset(&dev->gadget, dev->driver);
                spin_lock(&dev->lock);
+               usb_gadget_udc_reset(&dev->gadget, dev->driver);
+               spin_unlock(&dev->lock);
        }
 }
 
@@ -2675,9 +2675,9 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
                dev->ep[i].halted = 0;
        }
        dev->stall = 0;
-       spin_unlock(&dev->lock);
-       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
        spin_lock(&dev->lock);
+       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+       spin_unlock(&dev->lock);
 }
 
 /**
@@ -2712,9 +2712,9 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
        dev->stall = 0;
 
        /* call gadget zero with setup data received */
-       spin_unlock(&dev->lock);
-       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
        spin_lock(&dev->lock);
+       ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+       spin_unlock(&dev->lock);
 }
 
 /**
@@ -2747,18 +2747,18 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
        if (dev_intr & UDC_DEVINT_US) {
                if (dev->driver
                        && dev->driver->suspend) {
-                       spin_unlock(&dev->lock);
-                       dev->driver->suspend(&dev->gadget);
                        spin_lock(&dev->lock);
+                       dev->driver->suspend(&dev->gadget);
+                       spin_unlock(&dev->lock);
                }
 
                vbus = pch_vbus_gpio_get_value(dev);
                if ((dev->vbus_session == 0)
                        && (vbus != 1)) {
                        if (dev->driver && dev->driver->disconnect) {
-                               spin_unlock(&dev->lock);
-                               dev->driver->disconnect(&dev->gadget);
                                spin_lock(&dev->lock);
+                               dev->driver->disconnect(&dev->gadget);
+                               spin_unlock(&dev->lock);
                        }
                        pch_udc_reconnect(dev);
                } else if ((dev->vbus_session == 0)
@@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
                ep->in = ~i & 1;
                ep->ep.name = ep_string[i];
                ep->ep.ops = &pch_udc_ep_ops;
-               if (ep->in)
+               if (ep->in) {
                        ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
-               else
+                       ep->ep.caps.dir_in = true;
+               } else {
                        ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
                                          UDC_EP_REG_SHIFT;
+                       ep->ep.caps.dir_out = true;
+               }
+               if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
                /* need to set ep->ep.maxpacket and set Default Configuration?*/
                usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
                list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
index f6cbe667ce398a88ed0e103e2c1b1240375a8ab9..b82cb14850b6cfd4b1836452451af67d1f9289b9 100644 (file)
@@ -1176,6 +1176,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
        INIT_LIST_HEAD (&dev->gadget.ep_list);
        INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
        dev->ep0state = EP0_IDLE;
+       dev->gadget.quirk_altset_not_supp = 1;
 
        /* basic endpoint records init */
        for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1821,6 +1822,8 @@ static struct pxa25x_udc memory = {
                        .name           = ep0name,
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = EP0_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+                                               USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
                .reg_udccs      = &UDCCS0,
@@ -1833,6 +1836,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep1in-bulk",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = BULK_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_IN),
                },
                .dev            = &memory,
                .fifo_size      = BULK_FIFO_SIZE,
@@ -1846,6 +1851,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep2out-bulk",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = BULK_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_OUT),
                },
                .dev            = &memory,
                .fifo_size      = BULK_FIFO_SIZE,
@@ -1861,6 +1868,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep3in-iso",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = ISO_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                               USB_EP_CAPS_DIR_IN),
                },
                .dev            = &memory,
                .fifo_size      = ISO_FIFO_SIZE,
@@ -1874,6 +1883,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep4out-iso",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = ISO_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                               USB_EP_CAPS_DIR_OUT),
                },
                .dev            = &memory,
                .fifo_size      = ISO_FIFO_SIZE,
@@ -1888,6 +1899,7 @@ static struct pxa25x_udc memory = {
                        .name           = "ep5in-int",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = INT_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(0, 0),
                },
                .dev            = &memory,
                .fifo_size      = INT_FIFO_SIZE,
@@ -1903,6 +1915,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep6in-bulk",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = BULK_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_IN),
                },
                .dev            = &memory,
                .fifo_size      = BULK_FIFO_SIZE,
@@ -1916,6 +1930,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep7out-bulk",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = BULK_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_OUT),
                },
                .dev            = &memory,
                .fifo_size      = BULK_FIFO_SIZE,
@@ -1930,6 +1946,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep8in-iso",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = ISO_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                               USB_EP_CAPS_DIR_IN),
                },
                .dev            = &memory,
                .fifo_size      = ISO_FIFO_SIZE,
@@ -1943,6 +1961,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep9out-iso",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = ISO_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                               USB_EP_CAPS_DIR_OUT),
                },
                .dev            = &memory,
                .fifo_size      = ISO_FIFO_SIZE,
@@ -1957,6 +1977,7 @@ static struct pxa25x_udc memory = {
                        .name           = "ep10in-int",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = INT_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(0, 0),
                },
                .dev            = &memory,
                .fifo_size      = INT_FIFO_SIZE,
@@ -1972,6 +1993,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep11in-bulk",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = BULK_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_IN),
                },
                .dev            = &memory,
                .fifo_size      = BULK_FIFO_SIZE,
@@ -1985,6 +2008,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep12out-bulk",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = BULK_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_OUT),
                },
                .dev            = &memory,
                .fifo_size      = BULK_FIFO_SIZE,
@@ -1999,6 +2024,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep13in-iso",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = ISO_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                               USB_EP_CAPS_DIR_IN),
                },
                .dev            = &memory,
                .fifo_size      = ISO_FIFO_SIZE,
@@ -2012,6 +2039,8 @@ static struct pxa25x_udc memory = {
                        .name           = "ep14out-iso",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = ISO_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+                                               USB_EP_CAPS_DIR_OUT),
                },
                .dev            = &memory,
                .fifo_size      = ISO_FIFO_SIZE,
@@ -2026,6 +2055,7 @@ static struct pxa25x_udc memory = {
                        .name           = "ep15in-int",
                        .ops            = &pxa25x_ep_ops,
                        .maxpacket      = INT_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(0, 0),
                },
                .dev            = &memory,
                .fifo_size      = INT_FIFO_SIZE,
index b51226abade625d2ac0f34de68a72842d9c6742b..670ac0b12f00842ad7a5b840c941f2e8a8a7f1cc 100644 (file)
@@ -1710,6 +1710,7 @@ static void udc_init_data(struct pxa_udc *dev)
        INIT_LIST_HEAD(&dev->gadget.ep_list);
        INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
        dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+       dev->gadget.quirk_altset_not_supp = 1;
        ep0_idle(dev);
 
        /* PXA endpoints init */
@@ -2422,7 +2423,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
                }
                udc->udc_command = mach->udc_command;
        } else {
-               udc->gpiod = devm_gpiod_get(&pdev->dev, NULL);
+               udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS);
        }
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 11e14232794b55a5fe2f75dc22b1f325578507e2..cea2cb79b30c011d60c93761cac10807366e78ee 100644 (file)
 /*
  * Endpoint definition helpers
  */
-#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
-{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \
+{ .usb_ep = {  .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \
+               .caps = USB_EP_CAPS(ctype, cdir), }, \
   .desc = {    .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
-               .bmAttributes = type, \
+               .bmAttributes = USB_ENDPOINT_XFER_ ## type, \
                .wMaxPacketSize = maxpkt, }, \
   .dev = &memory \
 }
-#define USB_EP_BULK(addr, bname, dir) \
-  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
-#define USB_EP_ISO(addr, bname, dir) \
-  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
-#define USB_EP_INT(addr, bname, dir) \
-  USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
-#define USB_EP_IN_BULK(n)      USB_EP_BULK(n, "ep" #n "in-bulk", 1)
-#define USB_EP_OUT_BULK(n)     USB_EP_BULK(n, "ep" #n "out-bulk", 0)
-#define USB_EP_IN_ISO(n)       USB_EP_ISO(n,  "ep" #n "in-iso", 1)
-#define USB_EP_OUT_ISO(n)      USB_EP_ISO(n,  "ep" #n "out-iso", 0)
-#define USB_EP_IN_INT(n)       USB_EP_INT(n,  "ep" #n "in-int", 1)
-#define USB_EP_CTRL            USB_EP_DEF(0,  "ep0", 0, 0, EP0_FIFO_SIZE)
+#define USB_EP_BULK(addr, bname, dir, cdir) \
+       USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \
+               USB_EP_CAPS_TYPE_BULK, cdir)
+#define USB_EP_ISO(addr, bname, dir, cdir) \
+       USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \
+               USB_EP_CAPS_TYPE_ISO, cdir)
+#define USB_EP_INT(addr, bname, dir, cdir) \
+       USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \
+               USB_EP_CAPS_TYPE_INT, cdir)
+#define USB_EP_IN_BULK(n)      USB_EP_BULK(n, "ep" #n "in-bulk", 1, \
+                                       USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_BULK(n)     USB_EP_BULK(n, "ep" #n "out-bulk", 0, \
+                                       USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_ISO(n)       USB_EP_ISO(n,  "ep" #n "in-iso", 1, \
+                                       USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_ISO(n)      USB_EP_ISO(n,  "ep" #n "out-iso", 0, \
+                                       USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_INT(n)       USB_EP_INT(n,  "ep" #n "in-int", 1, \
+                                       USB_EP_CAPS_DIR_IN)
+#define USB_EP_CTRL    USB_EP_DEF(0,  "ep0", 0, CONTROL, EP0_FIFO_SIZE, \
+                               USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)
 
 #define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
 { \
index 0293f7169deeace9688bab19316b2bd04fa8641c..baa0609a429d99d47711f9c33b5745dc9bd3888d 100644 (file)
@@ -1935,6 +1935,16 @@ static int r8a66597_probe(struct platform_device *pdev)
                ep->ep.name = r8a66597_ep_name[i];
                ep->ep.ops = &r8a66597_ep_ops;
                usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+               if (i == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
        }
        usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
        r8a66597->ep[0].pipenum = 0;
index 85a712a033439b5cb3ac1fa16646049051581304..e9def42ce50d735eaafb9a39abb0b8f497392402 100644 (file)
@@ -1005,6 +1005,21 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
        hsep->stopped = 0;
        hsep->wedge = 0;
 
+       if (epnum == 0) {
+               hsep->ep.caps.type_control = true;
+               hsep->ep.caps.dir_in = true;
+               hsep->ep.caps.dir_out = true;
+       } else {
+               hsep->ep.caps.type_iso = true;
+               hsep->ep.caps.type_bulk = true;
+               hsep->ep.caps.type_int = true;
+       }
+
+       if (epnum & 1)
+               hsep->ep.caps.dir_in = true;
+       else
+               hsep->ep.caps.dir_out = true;
+
        set_index(hsudc, epnum);
        writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
 }
index 5d9aa81969b442a708307304c23738ae79d410f3..eb3571ee59e3c4a454b87e2103a921ed88eea2f7 100644 (file)
@@ -1691,6 +1691,8 @@ static struct s3c2410_udc memory = {
                        .name           = ep0name,
                        .ops            = &s3c2410_ep_ops,
                        .maxpacket      = EP0_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+                                               USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
        },
@@ -1702,6 +1704,8 @@ static struct s3c2410_udc memory = {
                        .name           = "ep1-bulk",
                        .ops            = &s3c2410_ep_ops,
                        .maxpacket      = EP_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
                .fifo_size      = EP_FIFO_SIZE,
@@ -1714,6 +1718,8 @@ static struct s3c2410_udc memory = {
                        .name           = "ep2-bulk",
                        .ops            = &s3c2410_ep_ops,
                        .maxpacket      = EP_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
                .fifo_size      = EP_FIFO_SIZE,
@@ -1726,6 +1732,8 @@ static struct s3c2410_udc memory = {
                        .name           = "ep3-bulk",
                        .ops            = &s3c2410_ep_ops,
                        .maxpacket      = EP_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
                .fifo_size      = EP_FIFO_SIZE,
@@ -1738,6 +1746,8 @@ static struct s3c2410_udc memory = {
                        .name           = "ep4-bulk",
                        .ops            = &s3c2410_ep_ops,
                        .maxpacket      = EP_FIFO_SIZE,
+                       .caps           = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+                                               USB_EP_CAPS_DIR_ALL),
                },
                .dev            = &memory,
                .fifo_size      = EP_FIFO_SIZE,
index 89ed5e71a1991e0cd249c48b18bd04dd67bacf91..f660afba715da9babd033892e7b08c6096abfed9 100644 (file)
@@ -131,6 +131,96 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
 
 /* ------------------------------------------------------------------------- */
 
+/**
+ * gadget_find_ep_by_name - returns ep whose name is the same as sting passed
+ *     in second parameter or NULL if searched endpoint not found
+ * @g: controller to check for quirk
+ * @name: name of searched endpoint
+ */
+struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name)
+{
+       struct usb_ep *ep;
+
+       gadget_for_each_ep(ep, g) {
+               if (!strcmp(ep->name, name))
+                       return ep;
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(gadget_find_ep_by_name);
+
+/* ------------------------------------------------------------------------- */
+
+int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
+               struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
+               struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+       u8              type;
+       u16             max;
+       int             num_req_streams = 0;
+
+       /* endpoint already claimed? */
+       if (ep->claimed)
+               return 0;
+
+       type = usb_endpoint_type(desc);
+       max = 0x7ff & usb_endpoint_maxp(desc);
+
+       if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
+               return 0;
+       if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
+               return 0;
+
+       if (max > ep->maxpacket_limit)
+               return 0;
+
+       /* "high bandwidth" works only at high speed */
+       if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
+               return 0;
+
+       switch (type) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               /* only support ep0 for portable CONTROL traffic */
+               return 0;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (!ep->caps.type_iso)
+                       return 0;
+               /* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
+               if (!gadget_is_dualspeed(gadget) && max > 1023)
+                       return 0;
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               if (!ep->caps.type_bulk)
+                       return 0;
+               if (ep_comp && gadget_is_superspeed(gadget)) {
+                       /* Get the number of required streams from the
+                        * EP companion descriptor and see if the EP
+                        * matches it
+                        */
+                       num_req_streams = ep_comp->bmAttributes & 0x1f;
+                       if (num_req_streams > ep->max_streams)
+                               return 0;
+               }
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               /* Bulk endpoints handle interrupt transfers,
+                * except the toggle-quirky iso-synch kind
+                */
+               if (!ep->caps.type_int && !ep->caps.type_bulk)
+                       return 0;
+               /* INT:  limit 64 bytes full speed, 1024 high/super speed */
+               if (!gadget_is_dualspeed(gadget) && max > 64)
+                       return 0;
+               break;
+       }
+
+       return 1;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
+
+/* ------------------------------------------------------------------------- */
+
 static void usb_gadget_state_work(struct work_struct *work)
 {
        struct usb_gadget *gadget = work_to_gadget(work);
index 1f24274477ab9352ce582f96bfbfbdd61605d07e..1cbb0ac6b18233c36535a7bd42668e623119c4c5 100644 (file)
@@ -1317,12 +1317,21 @@ static void xudc_eps_init(struct xusb_udc *udc)
                        snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number);
                        ep->ep_usb.name = ep->name;
                        ep->ep_usb.ops = &xusb_ep_ops;
+
+                       ep->ep_usb.caps.type_iso = true;
+                       ep->ep_usb.caps.type_bulk = true;
+                       ep->ep_usb.caps.type_int = true;
                } else {
                        ep->ep_usb.name = ep0name;
                        usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET);
                        ep->ep_usb.ops = &xusb_ep0_ops;
+
+                       ep->ep_usb.caps.type_control = true;
                }
 
+               ep->ep_usb.caps.dir_in = true;
+               ep->ep_usb.caps.dir_out = true;
+
                ep->udc = udc;
                ep->epnumber = ep_number;
                ep->desc = NULL;
index 8afc3c1efdab10325ba7225483e6dd47d3abd5b6..079991e283e9e0a1dd1abcaf5794aa6dbf1aceb8 100644 (file)
@@ -32,7 +32,14 @@ config USB_XHCI_PCI
        default y
 
 config USB_XHCI_PLATFORM
-       tristate
+       tristate "Generic xHCI driver for a platform device"
+       ---help---
+         Adds an xHCI host driver for a generic platform device, which
+         provides a memory space and an irq.
+         It is also a prerequisite for platform specific drivers that
+         implement some extra quirks.
+
+         If unsure, say N.
 
 config USB_XHCI_MVEBU
        tristate "xHCI support for Marvell Armada 375/38x"
@@ -441,10 +448,10 @@ config USB_OHCI_HCD_PXA27X
          PXA27x/PXA3xx chips.
 
 config USB_OHCI_HCD_AT91
-        tristate "Support for Atmel on-chip OHCI USB controller"
-        depends on USB_OHCI_HCD && ARCH_AT91
-        default y
-        ---help---
+       tristate "Support for Atmel on-chip OHCI USB controller"
+       depends on USB_OHCI_HCD && ARCH_AT91 && OF
+       default y
+       ---help---
           Enables support for the on-chip OHCI controller on
           Atmel chips.
 
index 526cfab41d5f7022b4c62c3754a5eb69a30240f3..5398e3d42822cf41f566885a3ffa2ee2d757b98f 100644 (file)
@@ -2,7 +2,8 @@
  * Broadcom specific Advanced Microcontroller Bus
  * Broadcom USB-core driver (BCMA bus glue)
  *
- * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
  *
  * Based on ssb-ohci driver
  * Copyright 2007 Michael Buesch <m@bues.ch>
@@ -23,6 +24,8 @@
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/usb/ehci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
 
@@ -88,7 +91,7 @@ static void bcma_hcd_4716wa(struct bcma_device *dev)
 }
 
 /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-static void bcma_hcd_init_chip(struct bcma_device *dev)
+static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
 {
        u32 tmp;
 
@@ -159,6 +162,87 @@ static void bcma_hcd_init_chip(struct bcma_device *dev)
        }
 }
 
+static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
+{
+       struct bcma_device *arm_core;
+       void __iomem *dmu;
+
+       arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9);
+       if (!arm_core) {
+               dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n");
+               return;
+       }
+
+       dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000);
+       if (!dmu) {
+               dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n");
+               return;
+       }
+
+       /* Unlock DMU PLL settings */
+       iowrite32(0x0000ea68, dmu + 0x180);
+
+       /* Write USB 2.0 PLL control setting */
+       iowrite32(0x00dd10c3, dmu + 0x164);
+
+       /* Lock DMU PLL settings */
+       iowrite32(0x00000000, dmu + 0x180);
+
+       iounmap(dmu);
+}
+
+static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev)
+{
+       u32 val;
+
+       /*
+        * Delay after PHY initialized to ensure HC is ready to be configured
+        */
+       usleep_range(1000, 2000);
+
+       /* Set packet buffer OUT threshold */
+       val = bcma_read32(dev, 0x94);
+       val &= 0xffff;
+       val |= 0x80 << 16;
+       bcma_write32(dev, 0x94, val);
+
+       /* Enable break memory transfer */
+       val = bcma_read32(dev, 0x9c);
+       val |= 1;
+       bcma_write32(dev, 0x9c, val);
+}
+
+static void bcma_hcd_init_chip_arm(struct bcma_device *dev)
+{
+       bcma_core_enable(dev, 0);
+
+       if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 ||
+           dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) {
+               if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 ||
+                   dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708)
+                       bcma_hcd_init_chip_arm_phy(dev);
+
+               bcma_hcd_init_chip_arm_hc(dev);
+       }
+}
+
+static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
+{
+       int gpio;
+
+       gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0);
+       if (!gpio_is_valid(gpio))
+               return;
+
+       if (val) {
+               gpio_request(gpio, "bcma-hcd-gpio");
+               gpio_set_value(gpio, 1);
+       } else {
+               gpio_set_value(gpio, 0);
+               gpio_free(gpio);
+       }
+}
+
 static const struct usb_ehci_pdata ehci_pdata = {
 };
 
@@ -169,7 +253,7 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo
 {
        struct platform_device *hci_dev;
        struct resource hci_res[2];
-       int ret = -ENOMEM;
+       int ret;
 
        memset(hci_res, 0, sizeof(hci_res));
 
@@ -183,7 +267,7 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo
        hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
                                        "ehci-platform" , 0);
        if (!hci_dev)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        hci_dev->dev.parent = &dev->dev;
        hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
@@ -214,39 +298,45 @@ err_alloc:
 static int bcma_hcd_probe(struct bcma_device *dev)
 {
        int err;
-       u16 chipid_top;
        u32 ohci_addr;
        struct bcma_hcd_device *usb_dev;
        struct bcma_chipinfo *chipinfo;
 
        chipinfo = &dev->bus->chipinfo;
-       /* USBcores are only connected on embedded devices. */
-       chipid_top = (chipinfo->id & 0xFF00);
-       if (chipid_top != 0x4700 && chipid_top != 0x5300)
-               return -ENODEV;
 
        /* TODO: Probably need checks here; is the core connected? */
 
        if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
                return -EOPNOTSUPP;
 
-       usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
+       usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device),
+                              GFP_KERNEL);
        if (!usb_dev)
                return -ENOMEM;
 
-       bcma_hcd_init_chip(dev);
+       bcma_hci_platform_power_gpio(dev, true);
+
+       switch (dev->id.id) {
+       case BCMA_CORE_NS_USB20:
+               bcma_hcd_init_chip_arm(dev);
+               break;
+       case BCMA_CORE_USB20_HOST:
+               bcma_hcd_init_chip_mips(dev);
+               break;
+       default:
+               return -ENODEV;
+       }
 
        /* In AI chips EHCI is addrspace 0, OHCI is 1 */
        ohci_addr = dev->addr_s[0];
-       if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
+       if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
+            chipinfo->id == BCMA_CHIP_ID_BCM4749)
            && chipinfo->rev == 0)
                ohci_addr = 0x18009000;
 
        usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr);
-       if (IS_ERR(usb_dev->ohci_dev)) {
-               err = PTR_ERR(usb_dev->ohci_dev);
-               goto err_free_usb_dev;
-       }
+       if (IS_ERR(usb_dev->ohci_dev))
+               return PTR_ERR(usb_dev->ohci_dev);
 
        usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr);
        if (IS_ERR(usb_dev->ehci_dev)) {
@@ -259,8 +349,6 @@ static int bcma_hcd_probe(struct bcma_device *dev)
 
 err_unregister_ohci_dev:
        platform_device_unregister(usb_dev->ohci_dev);
-err_free_usb_dev:
-       kfree(usb_dev);
        return err;
 }
 
@@ -280,6 +368,7 @@ static void bcma_hcd_remove(struct bcma_device *dev)
 
 static void bcma_hcd_shutdown(struct bcma_device *dev)
 {
+       bcma_hci_platform_power_gpio(dev, false);
        bcma_core_disable(dev, 0);
 }
 
@@ -287,6 +376,7 @@ static void bcma_hcd_shutdown(struct bcma_device *dev)
 
 static int bcma_hcd_suspend(struct bcma_device *dev)
 {
+       bcma_hci_platform_power_gpio(dev, false);
        bcma_core_disable(dev, 0);
 
        return 0;
@@ -294,6 +384,7 @@ static int bcma_hcd_suspend(struct bcma_device *dev)
 
 static int bcma_hcd_resume(struct bcma_device *dev)
 {
+       bcma_hci_platform_power_gpio(dev, true);
        bcma_core_enable(dev, 0);
 
        return 0;
@@ -306,6 +397,7 @@ static int bcma_hcd_resume(struct bcma_device *dev)
 
 static const struct bcma_device_id bcma_hcd_table[] = {
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
        {},
 };
 MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
index 5352e74b92e2112c273c4e0a2c43387a8bd0a105..3b6eb219de1a714d31fc843718472efc6ab615f4 100644 (file)
@@ -127,7 +127,18 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
 
        /* Enable USB controller, 83xx or 8536 */
        if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
-               setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+               clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
+                               CONTROL_REGISTER_W1C_MASK, 0x4);
+
+       /*
+        * Enable UTMI phy and program PTS field in UTMI mode before asserting
+        * controller reset for USB Controller version 2.5
+        */
+       if (pdata->has_fsl_erratum_a007792) {
+               clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
+                               CONTROL_REGISTER_W1C_MASK, CTRL_UTMI_PHY_EN);
+               writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1);
+       }
 
        /* Don't need to set host mode here. It will be done by tdi_reset() */
 
@@ -191,9 +202,11 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
        case FSL_USB2_PHY_ULPI:
                if (pdata->have_sysif_regs && pdata->controller_ver) {
                        /* controller version 1.6 or above */
-                       clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
-                       setbits32(non_ehci + FSL_SOC_USB_CTRL,
-                               ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
+                       clrbits32(non_ehci + FSL_SOC_USB_CTRL,
+                                 CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN);
+                       clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+                                       CONTROL_REGISTER_W1C_MASK,
+                                       ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
                }
                portsc |= PORT_PTS_ULPI;
                break;
@@ -204,30 +217,33 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
                portsc |= PORT_PTS_PTW;
                /* fall through */
        case FSL_USB2_PHY_UTMI:
+       case FSL_USB2_PHY_UTMI_DUAL:
                if (pdata->have_sysif_regs && pdata->controller_ver) {
                        /* controller version 1.6 or above */
-                       setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
+                       clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+                                       CONTROL_REGISTER_W1C_MASK, UTMI_PHY_EN);
                        mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
                                                become stable - 10ms*/
                }
                /* enable UTMI PHY */
                if (pdata->have_sysif_regs)
-                       setbits32(non_ehci + FSL_SOC_USB_CTRL,
-                                 CTRL_UTMI_PHY_EN);
+                       clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+                                       CONTROL_REGISTER_W1C_MASK,
+                                       CTRL_UTMI_PHY_EN);
                portsc |= PORT_PTS_UTMI;
                break;
        case FSL_USB2_PHY_NONE:
                break;
        }
 
-       if (pdata->have_sysif_regs &&
-           pdata->controller_ver > FSL_USB_VER_1_6 &&
-           (phy_mode == FSL_USB2_PHY_ULPI)) {
-               /* check PHY_CLK_VALID to get phy clk valid */
-               if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
-                               PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
-                               in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
-                       dev_warn(hcd->self.controller, "USB PHY clock invalid\n");
+       /*
+        * check PHY_CLK_VALID to determine phy clock presence before writing
+        * to portsc
+        */
+       if (pdata->check_phy_clk_valid) {
+               if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) {
+                       dev_warn(hcd->self.controller,
+                                "USB PHY clock invalid\n");
                        return -EINVAL;
                }
        }
@@ -235,7 +251,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
        ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 
        if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
-               setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
+               clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+                               CONTROL_REGISTER_W1C_MASK, USB_CTRL_USB_EN);
 
        return 0;
 }
@@ -261,6 +278,10 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
                out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
        }
 
+       /* Deal with USB erratum A-005275 */
+       if (pdata->has_fsl_erratum_a005275 == 1)
+               ehci->has_fsl_hs_errata = 1;
+
        if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
                        (pdata->operating_mode == FSL_USB2_DR_OTG))
                if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
index dbd292e9f0a7d5a7a31b9a2dcb1bf968b2ed7fa4..1a8a60a57cf2719a032699179583ea3aaae07bac 100644 (file)
@@ -52,6 +52,7 @@
 #define SNOOP_SIZE_2GB         0x1e
 
 /* control Register Bit Masks */
+#define CONTROL_REGISTER_W1C_MASK       0x00020000  /* W1C: PHY_CLK_VALID */
 #define ULPI_INT_EN             (1<<0)
 #define WU_INT_EN               (1<<1)
 #define USB_CTRL_USB_EN         (1<<2)
index 22abb6830dfa9e33ca7e1a4cc56c28b2b4a3f662..086a7115d263c673ec4a4e10abe1a386546b8338 100644 (file)
@@ -1221,6 +1221,13 @@ int ehci_hub_control(
                                 */
                                ehci->reset_done [wIndex] = jiffies
                                                + msecs_to_jiffies (50);
+
+                               /*
+                                * Force full-speed connect for FSL high-speed
+                                * erratum; disable HS Chirp by setting PFSC bit
+                                */
+                               if (ehci_has_fsl_hs_errata(ehci))
+                                       temp |= (1 << PORTSC_FSL_PFSC);
                        }
                        ehci_writel(ehci, temp, status_reg);
                        break;
index 2593def13cea09c1a37210c6780c8752229b4f60..5c3c0859868251233c7672baf9f2ea01c5b82364 100644 (file)
@@ -45,6 +45,7 @@ struct ehci_platform_priv {
        struct reset_control *rst;
        struct phy **phys;
        int num_phys;
+       bool reset_on_resume;
 };
 
 static const char hcd_name[] = "ehci-platform";
@@ -56,7 +57,6 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
 
-       hcd->has_tt = pdata->has_tt;
        ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
 
        if (pdata->pre_setup) {
@@ -193,11 +193,11 @@ static int ehci_platform_probe(struct platform_device *dev)
 
                if (of_property_read_bool(dev->dev.of_node,
                                          "needs-reset-on-resume"))
-                       pdata->reset_on_resume = 1;
+                       priv->reset_on_resume = true;
 
                if (of_property_read_bool(dev->dev.of_node,
                                          "has-transaction-translator"))
-                       pdata->has_tt = 1;
+                       hcd->has_tt = 1;
 
                priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
                                "phys", "#phy-cells");
@@ -247,6 +247,10 @@ static int ehci_platform_probe(struct platform_device *dev)
                ehci->big_endian_desc = 1;
        if (pdata->big_endian_mmio)
                ehci->big_endian_mmio = 1;
+       if (pdata->has_tt)
+               hcd->has_tt = 1;
+       if (pdata->reset_on_resume)
+               priv->reset_on_resume = true;
 
 #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
        if (ehci->big_endian_mmio) {
@@ -359,6 +363,7 @@ static int ehci_platform_resume(struct device *dev)
        struct usb_ehci_pdata *pdata = dev_get_platdata(dev);
        struct platform_device *pdev =
                container_of(dev, struct platform_device, dev);
+       struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
 
        if (pdata->power_on) {
                int err = pdata->power_on(pdev);
@@ -366,7 +371,7 @@ static int ehci_platform_resume(struct device *dev)
                        return err;
        }
 
-       ehci_resume(hcd, pdata->reset_on_resume);
+       ehci_resume(hcd, priv->reset_on_resume);
        return 0;
 }
 #endif /* CONFIG_PM_SLEEP */
index 7e4bd39cf757eff2f07e68b4c7a5766fac57f89b..b7c5cfa37a83501f8430837cab16fdf19b370c13 100644 (file)
@@ -54,7 +54,6 @@ static int st_ehci_platform_reset(struct usb_hcd *hcd)
        struct platform_device *pdev = to_platform_device(hcd->self.controller);
        struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       int retval;
        u32 threshold;
 
        /* Set EHCI packet buffer IN/OUT threshold to 128 bytes */
@@ -62,11 +61,7 @@ static int st_ehci_platform_reset(struct usb_hcd *hcd)
        writel(threshold, hcd->regs + AHB2STBUS_INSREG01);
 
        ehci->caps = hcd->regs + pdata->caps_offset;
-       retval = ehci_setup(hcd);
-       if (retval)
-               return retval;
-
-       return 0;
+       return ehci_setup(hcd);
 }
 
 static int st_ehci_platform_power_on(struct platform_device *dev)
index 5e44407aa09972801bb759f729033ba21cc214d2..5216f2b09d633e0b29d3d0cdf361e1c76763db19 100644 (file)
@@ -29,7 +29,7 @@ static ssize_t show_companion(struct device *dev,
        int                     count = PAGE_SIZE;
        char                    *ptr = buf;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        nports = HCS_N_PORTS(ehci->hcs_params);
 
        for (index = 0; index < nports; ++index) {
@@ -54,7 +54,7 @@ static ssize_t store_companion(struct device *dev,
        struct ehci_hcd         *ehci;
        int                     portnum, new_owner;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        new_owner = PORT_OWNER;         /* Owned by companion */
        if (sscanf(buf, "%d", &portnum) != 1)
                return -EINVAL;
@@ -85,7 +85,7 @@ static ssize_t show_uframe_periodic_max(struct device *dev,
        struct ehci_hcd         *ehci;
        int                     n;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max);
        return n;
 }
@@ -101,7 +101,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
        unsigned long           flags;
        ssize_t                 ret;
 
-       ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+       ehci = hcd_to_ehci(dev_get_drvdata(dev));
        if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
                return -EINVAL;
 
index f700157cd084bfdc76eb8630cdea5b8e3796f338..46f62e41bcde984ad2cf7d91e1461bf3f60f7e3c 100644 (file)
@@ -215,6 +215,7 @@ struct ehci_hcd {                   /* one per controller */
        /* SILICON QUIRKS */
        unsigned                no_selective_suspend:1;
        unsigned                has_fsl_port_bug:1; /* FreeScale */
+       unsigned                has_fsl_hs_errata:1;    /* Freescale HS quirk */
        unsigned                big_endian_mmio:1;
        unsigned                big_endian_desc:1;
        unsigned                big_endian_capbase:1;
@@ -686,6 +687,17 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 #define        ehci_has_fsl_portno_bug(e)              (0)
 #endif
 
+#define PORTSC_FSL_PFSC        24      /* Port Force Full-Speed Connect */
+
+#if defined(CONFIG_PPC_85xx)
+/* Some Freescale processors have an erratum (USB A-005275) in which
+ * incoming packets get corrupted in HS mode
+ */
+#define ehci_has_fsl_hs_errata(e)      ((e)->has_fsl_hs_errata)
+#else
+#define ehci_has_fsl_hs_errata(e)      (0)
+#endif
+
 /*
  * While most USB host controllers implement their registers in
  * little-endian format, a minority (celleb companion chip) implement
index 5e0d600352163ae58e8351978de9e39ad61aa63f..534c4c5d278a31838f9afe7a7421a4397aa3d431 100644 (file)
@@ -69,6 +69,8 @@ static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
                return FSL_USB2_PHY_UTMI;
        if (!strcasecmp(phy_type, "utmi_wide"))
                return FSL_USB2_PHY_UTMI_WIDE;
+       if (!strcasecmp(phy_type, "utmi_dual"))
+               return FSL_USB2_PHY_UTMI_DUAL;
        if (!strcasecmp(phy_type, "serial"))
                return FSL_USB2_PHY_SERIAL;
 
@@ -119,9 +121,9 @@ error:
 
 static const struct of_device_id fsl_usb2_mph_dr_of_match[];
 
-static int usb_get_ver_info(struct device_node *np)
+static enum fsl_usb2_controller_ver usb_get_ver_info(struct device_node *np)
 {
-       int ver = -1;
+       enum fsl_usb2_controller_ver ver = FSL_USB_VER_NONE;
 
        /*
         * returns 1 for usb controller version 1.6
@@ -142,7 +144,7 @@ static int usb_get_ver_info(struct device_node *np)
                else /* for previous controller versions */
                        ver = FSL_USB_VER_OLD;
 
-               if (ver > -1)
+               if (ver > FSL_USB_VER_NONE)
                        return ver;
        }
 
@@ -214,8 +216,27 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
        pdata->phy_mode = determine_usb_phy(prop);
        pdata->controller_ver = usb_get_ver_info(np);
 
+       /* Activate Erratum by reading property in device tree */
+       if (of_get_property(np, "fsl,usb-erratum-a007792", NULL))
+               pdata->has_fsl_erratum_a007792 = 1;
+       else
+               pdata->has_fsl_erratum_a007792 = 0;
+       if (of_get_property(np, "fsl,usb-erratum-a005275", NULL))
+               pdata->has_fsl_erratum_a005275 = 1;
+       else
+               pdata->has_fsl_erratum_a005275 = 0;
+
+       /*
+        * Determine whether phy_clk_valid needs to be checked
+        * by reading property in device tree
+        */
+       if (of_get_property(np, "phy-clk-valid", NULL))
+               pdata->check_phy_clk_valid = 1;
+       else
+               pdata->check_phy_clk_valid = 0;
+
        if (pdata->have_sysif_regs) {
-               if (pdata->controller_ver < 0) {
+               if (pdata->controller_ver == FSL_USB_VER_NONE) {
                        dev_warn(&ofdev->dev, "Could not get controller version\n");
                        return -ENODEV;
                }
index 15df00cceed91efe1cffe340e60eefa87d092828..342ffd1401222179589906ccc1d09ec102a1f03b 100644 (file)
 #define hcd_to_ohci_at91_priv(h) \
        ((struct ohci_at91_priv *)hcd_to_ohci(h)->priv)
 
+#define AT91_MAX_USBH_PORTS    3
+struct at91_usbh_data {
+       int vbus_pin[AT91_MAX_USBH_PORTS];      /* port power-control pin */
+       int overcurrent_pin[AT91_MAX_USBH_PORTS];
+       u8 ports;                               /* number of ports on root hub */
+       u8 overcurrent_supported;
+       u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
+       u8 overcurrent_status[AT91_MAX_USBH_PORTS];
+       u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
+};
+
 struct ohci_at91_priv {
        struct clk *iclk;
        struct clk *fclk;
@@ -431,7 +442,6 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id at91_ohci_dt_ids[] = {
        { .compatible = "atmel,at91rm9200-ohci" },
        { /* sentinel */ }
@@ -439,16 +449,17 @@ static const struct of_device_id at91_ohci_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
 
-static int ohci_at91_of_init(struct platform_device *pdev)
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       int i, gpio, ret;
-       enum of_gpio_flags flags;
        struct at91_usbh_data   *pdata;
-       u32 ports;
-
-       if (!np)
-               return 0;
+       int                     i;
+       int                     gpio;
+       int                     ret;
+       enum of_gpio_flags      flags;
+       u32                     ports;
 
        /* Right now device-tree probed devices don't get dma_mask set.
         * Since shared usb code relies on it, set it here for now.
@@ -466,111 +477,83 @@ static int ohci_at91_of_init(struct platform_device *pdev)
                pdata->ports = ports;
 
        at91_for_each_port(i) {
-               gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
+               /*
+                * do not configure PIO if not in relation with
+                * real USB port on board
+                */
+               if (i >= pdata->ports) {
+                       pdata->vbus_pin[i] = -EINVAL;
+                       continue;
+               }
+
+               gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i,
+                                              &flags);
                pdata->vbus_pin[i] = gpio;
                if (!gpio_is_valid(gpio))
                        continue;
                pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
-       }
-
-       at91_for_each_port(i)
-               pdata->overcurrent_pin[i] =
-                       of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
-
-       pdev->dev.platform_data = pdata;
-
-       return 0;
-}
-#else
-static int ohci_at91_of_init(struct platform_device *pdev)
-{
-       return 0;
-}
-#endif
-
-/*-------------------------------------------------------------------------*/
 
-static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
-{
-       struct at91_usbh_data   *pdata;
-       int                     i;
-       int                     gpio;
-       int                     ret;
-
-       ret = ohci_at91_of_init(pdev);
-       if (ret)
-               return ret;
+               ret = gpio_request(gpio, "ohci_vbus");
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "can't request vbus gpio %d\n", gpio);
+                       continue;
+               }
+               ret = gpio_direction_output(gpio,
+                                       !pdata->vbus_pin_active_low[i]);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "can't put vbus gpio %d as output %d\n",
+                               gpio, !pdata->vbus_pin_active_low[i]);
+                       gpio_free(gpio);
+                       continue;
+               }
 
-       pdata = dev_get_platdata(&pdev->dev);
+               ohci_at91_usb_set_power(pdata, i, 1);
+       }
 
-       if (pdata) {
-               at91_for_each_port(i) {
-                       /*
-                        * do not configure PIO if not in relation with
-                        * real USB port on board
-                        */
-                       if (i >= pdata->ports) {
-                               pdata->vbus_pin[i] = -EINVAL;
-                               pdata->overcurrent_pin[i] = -EINVAL;
-                               break;
-                       }
+       at91_for_each_port(i) {
+               if (i >= pdata->ports) {
+                       pdata->overcurrent_pin[i] = -EINVAL;
+                       continue;
+               }
 
-                       if (!gpio_is_valid(pdata->vbus_pin[i]))
-                               continue;
-                       gpio = pdata->vbus_pin[i];
+               pdata->overcurrent_pin[i] =
+                       of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
 
-                       ret = gpio_request(gpio, "ohci_vbus");
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "can't request vbus gpio %d\n", gpio);
-                               continue;
-                       }
-                       ret = gpio_direction_output(gpio,
-                                               !pdata->vbus_pin_active_low[i]);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "can't put vbus gpio %d as output %d\n",
-                                       gpio, !pdata->vbus_pin_active_low[i]);
-                               gpio_free(gpio);
-                               continue;
-                       }
+               if (!gpio_is_valid(pdata->overcurrent_pin[i]))
+                       continue;
+               gpio = pdata->overcurrent_pin[i];
 
-                       ohci_at91_usb_set_power(pdata, i, 1);
+               ret = gpio_request(gpio, "ohci_overcurrent");
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "can't request overcurrent gpio %d\n",
+                               gpio);
+                       continue;
                }
 
-               at91_for_each_port(i) {
-                       if (!gpio_is_valid(pdata->overcurrent_pin[i]))
-                               continue;
-                       gpio = pdata->overcurrent_pin[i];
-
-                       ret = gpio_request(gpio, "ohci_overcurrent");
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "can't request overcurrent gpio %d\n",
-                                       gpio);
-                               continue;
-                       }
-
-                       ret = gpio_direction_input(gpio);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "can't configure overcurrent gpio %d as input\n",
-                                       gpio);
-                               gpio_free(gpio);
-                               continue;
-                       }
+               ret = gpio_direction_input(gpio);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "can't configure overcurrent gpio %d as input\n",
+                               gpio);
+                       gpio_free(gpio);
+                       continue;
+               }
 
-                       ret = request_irq(gpio_to_irq(gpio),
-                                         ohci_hcd_at91_overcurrent_irq,
-                                         IRQF_SHARED, "ohci_overcurrent", pdev);
-                       if (ret) {
-                               gpio_free(gpio);
-                               dev_err(&pdev->dev,
-                                       "can't get gpio IRQ for overcurrent\n");
-                       }
+               ret = request_irq(gpio_to_irq(gpio),
+                                 ohci_hcd_at91_overcurrent_irq,
+                                 IRQF_SHARED, "ohci_overcurrent", pdev);
+               if (ret) {
+                       gpio_free(gpio);
+                       dev_err(&pdev->dev,
+                               "can't get gpio IRQ for overcurrent\n");
                }
        }
 
+       pdev->dev.platform_data = pdata;
+
        device_init_wakeup(&pdev->dev, 1);
        return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
@@ -673,7 +656,7 @@ static struct platform_driver ohci_hcd_at91_driver = {
        .driver         = {
                .name   = "at91_ohci",
                .pm     = &ohci_hcd_at91_pm_ops,
-               .of_match_table = of_match_ptr(at91_ohci_dt_ids),
+               .of_match_table = at91_ohci_dt_ids,
        },
 };
 
index 6352f54e65a1d9359f999a26aa6f12cea08f877d..fe3bd1cb8b6bd9dcd82071fb9c98a0ae66fc1836 100644 (file)
@@ -2670,7 +2670,6 @@ static int oxu_hcd_init(struct usb_hcd *hcd)
 static int oxu_reset(struct usb_hcd *hcd)
 {
        struct oxu_hcd *oxu = hcd_to_oxu(hcd);
-       int ret;
 
        spin_lock_init(&oxu->mem_lock);
        INIT_LIST_HEAD(&oxu->urb_list);
@@ -2696,11 +2695,7 @@ static int oxu_reset(struct usb_hcd *hcd)
        oxu->hcs_params = readl(&oxu->caps->hcs_params);
        oxu->sbrn = 0x20;
 
-       ret = oxu_hcd_init(hcd);
-       if (ret)
-               return ret;
-
-       return 0;
+       return oxu_hcd_init(hcd);
 }
 
 static int oxu_run(struct usb_hcd *hcd)
index d51687780b61a5428c8cb2238931d63ac9690bdd..a67bd509033097cfc156f84605f43f3617b951d8 100644 (file)
@@ -1542,11 +1542,8 @@ static int u132_periodic_reinit(struct u132 *u132)
                (fit ^ FIT) | u132->hc_fminterval);
        if (retval)
                return retval;
-       retval = u132_write_pcimem(u132, periodicstart,
-               ((9 * fi) / 10) & 0x3fff);
-       if (retval)
-               return retval;
-       return 0;
+       return u132_write_pcimem(u132, periodicstart,
+              ((9 * fi) / 10) & 0x3fff);
 }
 
 static char *hcfs2string(int state)
@@ -2701,28 +2698,18 @@ static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
        if (wIndex == 0 || wIndex > u132->num_ports) {
                return -EINVAL;
        } else {
-               int retval;
                int port_index = wIndex - 1;
                struct u132_port *port = &u132->port[port_index];
                port->Status &= ~(1 << wValue);
                switch (wValue) {
                case USB_PORT_FEAT_SUSPEND:
-                       retval = u132_write_pcimem(u132,
-                               roothub.portstatus[port_index], RH_PS_PSS);
-                       if (retval)
-                               return retval;
-                       return 0;
+                       return u132_write_pcimem(u132,
+                              roothub.portstatus[port_index], RH_PS_PSS);
                case USB_PORT_FEAT_POWER:
-                       retval = u132_write_pcimem(u132,
-                               roothub.portstatus[port_index], RH_PS_PPS);
-                       if (retval)
-                               return retval;
-                       return 0;
+                       return u132_write_pcimem(u132,
+                              roothub.portstatus[port_index], RH_PS_PPS);
                case USB_PORT_FEAT_RESET:
-                       retval = u132_roothub_portreset(u132, port_index);
-                       if (retval)
-                               return retval;
-                       return 0;
+                       return u132_roothub_portreset(u132, port_index);
                default:
                        return -EPIPE;
                }
@@ -2737,7 +2724,6 @@ static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
        } else {
                int port_index = wIndex - 1;
                u32 temp;
-               int retval;
                struct u132_port *port = &u132->port[port_index];
                port->Status &= ~(1 << wValue);
                switch (wValue) {
@@ -2773,11 +2759,8 @@ static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
                default:
                        return -EPIPE;
                }
-               retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
-                        temp);
-               if (retval)
-                       return retval;
-               return 0;
+               return u132_write_pcimem(u132, roothub.portstatus[port_index],
+                      temp);
        }
 }
 
index 745717ec9c89a0fa9297cdbdec749ecd79e12527..2d16faefb429b03a529304136c1eaf19deb15572 100644 (file)
@@ -99,6 +99,10 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci)
        xhci_dbg(xhci, "HCC PARAMS 0x%x:\n", (unsigned int) temp);
        xhci_dbg(xhci, "  HC generates %s bit addresses\n",
                        HCC_64BIT_ADDR(temp) ? "64" : "32");
+       xhci_dbg(xhci, "  HC %s Contiguous Frame ID Capability\n",
+                       HCC_CFC(temp) ? "has" : "hasn't");
+       xhci_dbg(xhci, "  HC %s generate Stopped - Short Package event\n",
+                       HCC_SPC(temp) ? "can" : "can't");
        /* FIXME */
        xhci_dbg(xhci, "  FIXME: more HCCPARAMS debugging\n");
 
index 32f4d564494a9f48cfebd328e61d3c281387d252..a47a1e89708678e6d55dd6a13e4fbed229bedfe2 100644 (file)
@@ -1812,7 +1812,9 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
        if (skip)
                goto td_cleanup;
 
-       if (trb_comp_code == COMP_STOP_INVAL || trb_comp_code == COMP_STOP) {
+       if (trb_comp_code == COMP_STOP_INVAL ||
+                       trb_comp_code == COMP_STOP ||
+                       trb_comp_code == COMP_STOP_SHORT) {
                /* The Endpoint Stop Command completion will take care of any
                 * stopped TDs.  A stopped TD may be restarted, so don't update
                 * the ring dequeue pointer or take this TD off any lists yet.
@@ -1919,8 +1921,22 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                else
                        *status = 0;
                break;
-       case COMP_STOP_INVAL:
+       case COMP_STOP_SHORT:
+               if (event_trb == ep_ring->dequeue || event_trb == td->last_trb)
+                       xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n");
+               else
+                       td->urb->actual_length =
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+               return finish_td(xhci, td, event_trb, event, ep, status, false);
        case COMP_STOP:
+               /* Did we stop at data stage? */
+               if (event_trb != ep_ring->dequeue && event_trb != td->last_trb)
+                       td->urb->actual_length =
+                               td->urb->transfer_buffer_length -
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+               /* fall through */
+       case COMP_STOP_INVAL:
                return finish_td(xhci, td, event_trb, event, ep, status, false);
        default:
                if (!xhci_requires_manual_halt_cleanup(xhci,
@@ -2014,6 +2030,8 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
                }
                if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
                        trb_comp_code = COMP_SHORT_TX;
+       /* fallthrough */
+       case COMP_STOP_SHORT:
        case COMP_SHORT_TX:
                frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
                                -EREMOTEIO : 0;
@@ -2049,6 +2067,10 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
        if (trb_comp_code == COMP_SUCCESS || skip_td) {
                frame->actual_length = frame->length;
                td->urb->actual_length += frame->length;
+       } else if (trb_comp_code == COMP_STOP_SHORT) {
+               frame->actual_length =
+                       EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+               td->urb->actual_length += frame->actual_length;
        } else {
                for (cur_trb = ep_ring->dequeue,
                     cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
@@ -2129,6 +2151,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                        *status = 0;
                }
                break;
+       case COMP_STOP_SHORT:
        case COMP_SHORT_TX:
                if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
                        *status = -EREMOTEIO;
@@ -2145,8 +2168,20 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                                td->urb->ep->desc.bEndpointAddress,
                                td->urb->transfer_buffer_length,
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+       /* Stopped - short packet completion */
+       if (trb_comp_code == COMP_STOP_SHORT) {
+               td->urb->actual_length =
+                       EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+               if (td->urb->transfer_buffer_length <
+                               td->urb->actual_length) {
+                       xhci_warn(xhci, "HC gave bad length of %d bytes txed\n",
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+                       td->urb->actual_length = 0;
+                        /* status will be set by usb core for canceled urbs */
+               }
        /* Fast path - was this the last TRB in the TD for this URB? */
-       if (event_trb == td->last_trb) {
+       } else if (event_trb == td->last_trb) {
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
@@ -2300,6 +2335,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        case COMP_STOP_INVAL:
                xhci_dbg(xhci, "Stopped on No-op or Link TRB\n");
                break;
+       case COMP_STOP_SHORT:
+               xhci_dbg(xhci, "Stopped with short packet transfer detected\n");
+               break;
        case COMP_STALL:
                xhci_dbg(xhci, "Stalled endpoint\n");
                ep->ep_state |= EP_HALTED;
@@ -3041,9 +3079,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        struct xhci_td *td;
        struct scatterlist *sg;
        int num_sgs;
-       int trb_buff_len, this_sg_len, running_total;
+       int trb_buff_len, this_sg_len, running_total, ret;
        unsigned int total_packet_count;
+       bool zero_length_needed;
        bool first_trb;
+       int last_trb_num;
        u64 addr;
        bool more_trbs_coming;
 
@@ -3059,13 +3099,27 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
                        usb_endpoint_maxp(&urb->ep->desc));
 
-       trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
+       ret = prepare_transfer(xhci, xhci->devs[slot_id],
                        ep_index, urb->stream_id,
                        num_trbs, urb, 0, mem_flags);
-       if (trb_buff_len < 0)
-               return trb_buff_len;
+       if (ret < 0)
+               return ret;
 
        urb_priv = urb->hcpriv;
+
+       /* Deal with URB_ZERO_PACKET - need one more td/trb */
+       zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
+               urb_priv->length == 2;
+       if (zero_length_needed) {
+               num_trbs++;
+               xhci_dbg(xhci, "Creating zero length td.\n");
+               ret = prepare_transfer(xhci, xhci->devs[slot_id],
+                               ep_index, urb->stream_id,
+                               1, urb, 1, mem_flags);
+               if (ret < 0)
+                       return ret;
+       }
+
        td = urb_priv->td[0];
 
        /*
@@ -3095,6 +3149,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                trb_buff_len = urb->transfer_buffer_length;
 
        first_trb = true;
+       last_trb_num = zero_length_needed ? 2 : 1;
        /* Queue the first TRB, even if it's zero-length */
        do {
                u32 field = 0;
@@ -3112,12 +3167,15 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                /* Chain all the TRBs together; clear the chain bit in the last
                 * TRB to indicate it's the last TRB in the chain.
                 */
-               if (num_trbs > 1) {
+               if (num_trbs > last_trb_num) {
                        field |= TRB_CHAIN;
-               } else {
-                       /* FIXME - add check for ZERO_PACKET flag before this */
+               } else if (num_trbs == last_trb_num) {
                        td->last_trb = ep_ring->enqueue;
                        field |= TRB_IOC;
+               } else if (zero_length_needed && num_trbs == 1) {
+                       trb_buff_len = 0;
+                       urb_priv->td[1]->last_trb = ep_ring->enqueue;
+                       field |= TRB_IOC;
                }
 
                /* Only set interrupt on short packet for IN endpoints */
@@ -3179,7 +3237,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                if (running_total + trb_buff_len > urb->transfer_buffer_length)
                        trb_buff_len =
                                urb->transfer_buffer_length - running_total;
-       } while (running_total < urb->transfer_buffer_length);
+       } while (num_trbs > 0);
 
        check_trb_math(urb, num_trbs, running_total);
        giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
@@ -3197,7 +3255,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        int num_trbs;
        struct xhci_generic_trb *start_trb;
        bool first_trb;
+       int last_trb_num;
        bool more_trbs_coming;
+       bool zero_length_needed;
        int start_cycle;
        u32 field, length_field;
 
@@ -3228,7 +3288,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                num_trbs++;
                running_total += TRB_MAX_BUFF_SIZE;
        }
-       /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */
 
        ret = prepare_transfer(xhci, xhci->devs[slot_id],
                        ep_index, urb->stream_id,
@@ -3237,6 +3296,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                return ret;
 
        urb_priv = urb->hcpriv;
+
+       /* Deal with URB_ZERO_PACKET - need one more td/trb */
+       zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
+               urb_priv->length == 2;
+       if (zero_length_needed) {
+               num_trbs++;
+               xhci_dbg(xhci, "Creating zero length td.\n");
+               ret = prepare_transfer(xhci, xhci->devs[slot_id],
+                               ep_index, urb->stream_id,
+                               1, urb, 1, mem_flags);
+               if (ret < 0)
+                       return ret;
+       }
+
        td = urb_priv->td[0];
 
        /*
@@ -3258,7 +3331,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                trb_buff_len = urb->transfer_buffer_length;
 
        first_trb = true;
-
+       last_trb_num = zero_length_needed ? 2 : 1;
        /* Queue the first TRB, even if it's zero-length */
        do {
                u32 remainder = 0;
@@ -3275,12 +3348,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                /* Chain all the TRBs together; clear the chain bit in the last
                 * TRB to indicate it's the last TRB in the chain.
                 */
-               if (num_trbs > 1) {
+               if (num_trbs > last_trb_num) {
                        field |= TRB_CHAIN;
-               } else {
-                       /* FIXME - add check for ZERO_PACKET flag before this */
+               } else if (num_trbs == last_trb_num) {
                        td->last_trb = ep_ring->enqueue;
                        field |= TRB_IOC;
+               } else if (zero_length_needed && num_trbs == 1) {
+                       trb_buff_len = 0;
+                       urb_priv->td[1]->last_trb = ep_ring->enqueue;
+                       field |= TRB_IOC;
                }
 
                /* Only set interrupt on short packet for IN endpoints */
@@ -3318,7 +3394,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                trb_buff_len = urb->transfer_buffer_length - running_total;
                if (trb_buff_len > TRB_MAX_BUFF_SIZE)
                        trb_buff_len = TRB_MAX_BUFF_SIZE;
-       } while (running_total < urb->transfer_buffer_length);
+       } while (num_trbs > 0);
 
        check_trb_math(urb, num_trbs, running_total);
        giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
@@ -3517,6 +3593,97 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci,
        }
 }
 
+/*
+ * Calculates Frame ID field of the isochronous TRB identifies the
+ * target frame that the Interval associated with this Isochronous
+ * Transfer Descriptor will start on. Refer to 4.11.2.5 in 1.1 spec.
+ *
+ * Returns actual frame id on success, negative value on error.
+ */
+static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci,
+               struct urb *urb, int index)
+{
+       int start_frame, ist, ret = 0;
+       int start_frame_id, end_frame_id, current_frame_id;
+
+       if (urb->dev->speed == USB_SPEED_LOW ||
+                       urb->dev->speed == USB_SPEED_FULL)
+               start_frame = urb->start_frame + index * urb->interval;
+       else
+               start_frame = (urb->start_frame + index * urb->interval) >> 3;
+
+       /* Isochronous Scheduling Threshold (IST, bits 0~3 in HCSPARAMS2):
+        *
+        * If bit [3] of IST is cleared to '0', software can add a TRB no
+        * later than IST[2:0] Microframes before that TRB is scheduled to
+        * be executed.
+        * If bit [3] of IST is set to '1', software can add a TRB no later
+        * than IST[2:0] Frames before that TRB is scheduled to be executed.
+        */
+       ist = HCS_IST(xhci->hcs_params2) & 0x7;
+       if (HCS_IST(xhci->hcs_params2) & (1 << 3))
+               ist <<= 3;
+
+       /* Software shall not schedule an Isoch TD with a Frame ID value that
+        * is less than the Start Frame ID or greater than the End Frame ID,
+        * where:
+        *
+        * End Frame ID = (Current MFINDEX register value + 895 ms.) MOD 2048
+        * Start Frame ID = (Current MFINDEX register value + IST + 1) MOD 2048
+        *
+        * Both the End Frame ID and Start Frame ID values are calculated
+        * in microframes. When software determines the valid Frame ID value;
+        * The End Frame ID value should be rounded down to the nearest Frame
+        * boundary, and the Start Frame ID value should be rounded up to the
+        * nearest Frame boundary.
+        */
+       current_frame_id = readl(&xhci->run_regs->microframe_index);
+       start_frame_id = roundup(current_frame_id + ist + 1, 8);
+       end_frame_id = rounddown(current_frame_id + 895 * 8, 8);
+
+       start_frame &= 0x7ff;
+       start_frame_id = (start_frame_id >> 3) & 0x7ff;
+       end_frame_id = (end_frame_id >> 3) & 0x7ff;
+
+       xhci_dbg(xhci, "%s: index %d, reg 0x%x start_frame_id 0x%x, end_frame_id 0x%x, start_frame 0x%x\n",
+                __func__, index, readl(&xhci->run_regs->microframe_index),
+                start_frame_id, end_frame_id, start_frame);
+
+       if (start_frame_id < end_frame_id) {
+               if (start_frame > end_frame_id ||
+                               start_frame < start_frame_id)
+                       ret = -EINVAL;
+       } else if (start_frame_id > end_frame_id) {
+               if ((start_frame > end_frame_id &&
+                               start_frame < start_frame_id))
+                       ret = -EINVAL;
+       } else {
+                       ret = -EINVAL;
+       }
+
+       if (index == 0) {
+               if (ret == -EINVAL || start_frame == start_frame_id) {
+                       start_frame = start_frame_id + 1;
+                       if (urb->dev->speed == USB_SPEED_LOW ||
+                                       urb->dev->speed == USB_SPEED_FULL)
+                               urb->start_frame = start_frame;
+                       else
+                               urb->start_frame = start_frame << 3;
+                       ret = 0;
+               }
+       }
+
+       if (ret) {
+               xhci_warn(xhci, "Frame ID %d (reg %d, index %d) beyond range (%d, %d)\n",
+                               start_frame, current_frame_id, index,
+                               start_frame_id, end_frame_id);
+               xhci_warn(xhci, "Ignore frame ID field, use SIA bit instead\n");
+               return ret;
+       }
+
+       return start_frame;
+}
+
 /* This is for isoc transfer */
 static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3533,7 +3700,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        u64 start_addr, addr;
        int i, j;
        bool more_trbs_coming;
+       struct xhci_virt_ep *xep;
 
+       xep = &xhci->devs[slot_id]->eps[ep_index];
        ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
 
        num_tds = urb->number_of_packets;
@@ -3581,6 +3750,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
                td = urb_priv->td[i];
                for (j = 0; j < trbs_per_td; j++) {
+                       int frame_id = 0;
                        u32 remainder = 0;
                        field = 0;
 
@@ -3589,8 +3759,20 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                        TRB_TLBPC(residue);
                                /* Queue the isoc TRB */
                                field |= TRB_TYPE(TRB_ISOC);
-                               /* Assume URB_ISO_ASAP is set */
-                               field |= TRB_SIA;
+
+                               /* Calculate Frame ID and SIA fields */
+                               if (!(urb->transfer_flags & URB_ISO_ASAP) &&
+                                               HCC_CFC(xhci->hcc_params)) {
+                                       frame_id = xhci_get_isoc_frame_id(xhci,
+                                                                         urb,
+                                                                         i);
+                                       if (frame_id >= 0)
+                                               field |= TRB_FRAME_ID(frame_id);
+                                       else
+                                               field |= TRB_SIA;
+                               } else
+                                       field |= TRB_SIA;
+
                                if (i == 0) {
                                        if (start_cycle == 0)
                                                field |= 0x1;
@@ -3666,6 +3848,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                }
        }
 
+       /* store the next frame id */
+       if (HCC_CFC(xhci->hcc_params))
+               xep->next_frame_id = urb->start_frame + num_tds * urb->interval;
+
        if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) {
                if (xhci->quirks & XHCI_AMD_PLL_FIX)
                        usb_amd_quirk_pll_disable();
@@ -3699,12 +3885,34 @@ cleanup:
        return ret;
 }
 
+static int ep_ring_is_processing(struct xhci_hcd *xhci,
+               int slot_id, unsigned int ep_index)
+{
+       struct xhci_virt_device *xdev;
+       struct xhci_ring *ep_ring;
+       struct xhci_ep_ctx *ep_ctx;
+       struct xhci_virt_ep *xep;
+       dma_addr_t hw_deq;
+
+       xdev = xhci->devs[slot_id];
+       xep = &xhci->devs[slot_id]->eps[ep_index];
+       ep_ring = xep->ring;
+       ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+
+       if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING)
+               return 0;
+
+       hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
+       return (hw_deq !=
+               xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue));
+}
+
 /*
  * Check transfer ring to guarantee there is enough room for the urb.
  * Update ISO URB start_frame and interval.
- * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to
- * update the urb->start_frame by now.
- * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input.
+ * Update interval as xhci_queue_intr_tx does. Use xhci frame_index to
+ * update urb->start_frame if URB_ISO_ASAP is set in transfer_flags or
+ * Contiguous Frame ID is not supported by HC.
  */
 int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
                struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3717,8 +3925,11 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
        int ep_interval;
        int num_tds, num_trbs, i;
        int ret;
+       struct xhci_virt_ep *xep;
+       int ist;
 
        xdev = xhci->devs[slot_id];
+       xep = &xhci->devs[slot_id]->eps[ep_index];
        ep_ring = xdev->eps[ep_index].ring;
        ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
 
@@ -3735,14 +3946,10 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
        if (ret)
                return ret;
 
-       start_frame = readl(&xhci->run_regs->microframe_index);
-       start_frame &= 0x3fff;
-
-       urb->start_frame = start_frame;
-       if (urb->dev->speed == USB_SPEED_LOW ||
-                       urb->dev->speed == USB_SPEED_FULL)
-               urb->start_frame >>= 3;
-
+       /*
+        * Check interval value. This should be done before we start to
+        * calculate the start frame value.
+        */
        xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info));
        ep_interval = urb->interval;
        /* Convert to microframes */
@@ -3763,6 +3970,40 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
                                urb->dev->speed == USB_SPEED_FULL)
                        urb->interval /= 8;
        }
+
+       /* Calculate the start frame and put it in urb->start_frame. */
+       if (HCC_CFC(xhci->hcc_params) &&
+                       ep_ring_is_processing(xhci, slot_id, ep_index)) {
+               urb->start_frame = xep->next_frame_id;
+               goto skip_start_over;
+       }
+
+       start_frame = readl(&xhci->run_regs->microframe_index);
+       start_frame &= 0x3fff;
+       /*
+        * Round up to the next frame and consider the time before trb really
+        * gets scheduled by hardare.
+        */
+       ist = HCS_IST(xhci->hcs_params2) & 0x7;
+       if (HCS_IST(xhci->hcs_params2) & (1 << 3))
+               ist <<= 3;
+       start_frame += ist + XHCI_CFC_DELAY;
+       start_frame = roundup(start_frame, 8);
+
+       /*
+        * Round up to the next ESIT (Endpoint Service Interval Time) if ESIT
+        * is greate than 8 microframes.
+        */
+       if (urb->dev->speed == USB_SPEED_LOW ||
+                       urb->dev->speed == USB_SPEED_FULL) {
+               start_frame = roundup(start_frame, urb->interval << 3);
+               urb->start_frame = start_frame >> 3;
+       } else {
+               start_frame = roundup(start_frame, urb->interval);
+               urb->start_frame = start_frame;
+       }
+
+skip_start_over:
        ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
 
        return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
index 526ebc0c7e720b9d766bcf6abf1bc65672e584bb..6b0f4a47e4021d83e01fb76a0a1aa18d6b3ca793 100644 (file)
@@ -1340,6 +1340,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
 
        if (usb_endpoint_xfer_isoc(&urb->ep->desc))
                size = urb->number_of_packets;
+       else if (usb_endpoint_is_bulk_out(&urb->ep->desc) &&
+           urb->transfer_buffer_length > 0 &&
+           urb->transfer_flags & URB_ZERO_PACKET &&
+           !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc)))
+               size = 2;
        else
                size = 1;
 
@@ -3117,7 +3122,7 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci,
 }
 
 /*
- * The USB device drivers use this function (though the HCD interface in USB
+ * The USB device drivers use this function (through the HCD interface in USB
  * core) to prepare a set of bulk endpoints to use streams.  Streams are used to
  * coordinate mass storage command queueing across multiple endpoints (basically
  * a stream ID == a task ID).
@@ -4678,7 +4683,6 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
 {
        struct xhci_hcd *xhci;
        u16 mel;
-       int ret;
 
        xhci = hcd_to_xhci(hcd);
        if (!xhci || !(xhci->quirks & XHCI_LPM_SUPPORT) ||
@@ -4686,10 +4690,7 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
                return 0;
 
        mel = calculate_max_exit_latency(udev, state, USB3_LPM_DISABLED);
-       ret = xhci_change_max_exit_latency(xhci, udev, mel);
-       if (ret)
-               return ret;
-       return 0;
+       return xhci_change_max_exit_latency(xhci, udev, mel);
 }
 #else /* CONFIG_PM */
 
index ed2ebf647c380ebbdfe647544fb137283219cf87..dbda41e91c843f2e289c4a4aa0d4129f2641f2a9 100644 (file)
@@ -119,6 +119,10 @@ struct xhci_cap_regs {
 #define HCC_LTC(p)             ((p) & (1 << 6))
 /* true: no secondary Stream ID Support */
 #define HCC_NSS(p)             ((p) & (1 << 7))
+/* true: HC supports Stopped - Short Packet */
+#define HCC_SPC(p)             ((p) & (1 << 9))
+/* true: HC has Contiguous Frame ID Capability */
+#define HCC_CFC(p)             ((p) & (1 << 11))
 /* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
 #define HCC_MAX_PSA(p)         (1 << ((((p) >> 12) & 0xf) + 1))
 /* Extended Capabilities pointer from PCI base - section 5.3.6 */
@@ -891,6 +895,8 @@ struct xhci_virt_ep {
        /* Bandwidth checking storage */
        struct xhci_bw_info     bw_info;
        struct list_head        bw_endpoint_list;
+       /* Isoch Frame ID checking storage */
+       int                     next_frame_id;
 };
 
 enum xhci_overhead_type {
@@ -1059,8 +1065,8 @@ struct xhci_transfer_event {
 #define COMP_STOP      26
 /* Same as COMP_EP_STOPPED, but the transferred length in the event is invalid */
 #define COMP_STOP_INVAL        27
-/* Control Abort Error - Debug Capability - control pipe aborted */
-#define COMP_DBG_ABORT 28
+/* Same as COMP_EP_STOPPED, but a short packet detected */
+#define COMP_STOP_SHORT        28
 /* Max Exit Latency Too Large Error */
 #define COMP_MEL_ERR   29
 /* TRB type 30 reserved */
@@ -1165,6 +1171,7 @@ enum xhci_setup_dev {
 
 /* Isochronous TRB specific fields */
 #define TRB_SIA                        (1<<31)
+#define TRB_FRAME_ID(p)                (((p) & 0x7ff) << 20)
 
 struct xhci_generic_trb {
        __le32 field[4];
@@ -1601,6 +1608,8 @@ struct xhci_driver_overrides {
        int (*start)(struct usb_hcd *hcd);
 };
 
+#define        XHCI_CFC_DELAY          10
+
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
 static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd)
 {
index 18ebf5b1f2560d99f6722ce46877cc1b7b72ff9c..1c3d0fd658fa81bd31a60a7c59eec3c89bb0e5aa 100644 (file)
@@ -1382,14 +1382,25 @@ static void isp1760_udc_init_eps(struct isp1760_udc *udc)
                 * This fits in the 8kB FIFO without double-buffering.
                 */
                if (ep_num == 0) {
-                       ep->ep.maxpacket = 64;
+                       usb_ep_set_maxpacket_limit(&ep->ep, 64);
+                       ep->ep.caps.type_control = true;
+                       ep->ep.caps.dir_in = true;
+                       ep->ep.caps.dir_out = true;
                        ep->maxpacket = 64;
                        udc->gadget.ep0 = &ep->ep;
                } else {
-                       ep->ep.maxpacket = 512;
+                       usb_ep_set_maxpacket_limit(&ep->ep, 512);
+                       ep->ep.caps.type_iso = true;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
                        ep->maxpacket = 0;
                        list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
                }
+
+               if (is_in)
+                       ep->ep.caps.dir_in = true;
+               else
+                       ep->ep.caps.dir_out = true;
        }
 }
 
index 8ab1f8f3c26e6a2b7b3630b39356968ac98bf38d..52c27cab78c3e44d1927c7bcacebc7fbcf1f7c61 100644 (file)
@@ -2568,11 +2568,7 @@ static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn)
                                            0x00);
        if (UxxxStatus)
                return UxxxStatus;
-       UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
-                                          &pcidata);
-       if (UxxxStatus)
-               return UxxxStatus;
-       return 0;
+       return ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, &pcidata);
 }
 
 static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
@@ -2695,11 +2691,7 @@ static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
                }
        }
        if (ftdi->function > 0) {
-               UxxxStatus = ftdi_elan_setup_controller(ftdi,
-                                                       ftdi->function - 1);
-               if (UxxxStatus)
-                       return UxxxStatus;
-               return 0;
+               return ftdi_elan_setup_controller(ftdi, ftdi->function - 1);
        } else if (controllers > 0) {
                return -ENXIO;
        } else if (unrecognized > 0) {
index 0bbafe795a724bf2d7dfff846afe44e37aef242c..9517812a50e2982aa45db4102092c90e9732598f 100644 (file)
@@ -1925,10 +1925,11 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
        memset(urbs, 0, sizeof(urbs));
        udev = testdev_to_usbdev(dev);
        dev_info(&dev->intf->dev,
-               "... iso period %d %sframes, wMaxPacket %04x\n",
+               "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
                1 << (desc->bInterval - 1),
                (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
-               usb_endpoint_maxp(desc));
+               usb_endpoint_maxp(desc) & 0x7ff,
+               1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
 
        for (i = 0; i < param->sglen; i++) {
                urbs[i] = iso_alloc_urb(udev, pipe, desc,
@@ -1942,7 +1943,7 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
        }
        packets *= param->iterations;
        dev_info(&dev->intf->dev,
-               "... total %lu msec (%lu packets)\n",
+               "total %lu msec (%lu packets)\n",
                (packets * (1 << (desc->bInterval - 1)))
                        / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
                packets);
index 39db8b603627cae44b86bcbd2d9d028027cbe651..1f2037bbeb0d1619572a2912bda7fa6e2c168ac0 100644 (file)
@@ -5,7 +5,7 @@
 
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
-       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
+       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)'
        depends on (USB || USB_GADGET)
        help
          Say Y here if your system has a dual role high speed USB
@@ -20,6 +20,8 @@ config USB_MUSB_HDRC
          Analog Devices parts using this IP include Blackfin BF54x,
          BF525 and BF527.
 
+         Allwinner SoCs using this IP include A10, A13, A20, ...
+
          If you do not know what this is, please say N.
 
          To compile this driver as a module, choose M here; the
@@ -60,6 +62,15 @@ endchoice
 
 comment "Platform Glue Layer"
 
+config USB_MUSB_SUNXI
+       tristate "Allwinner (sunxi)"
+       depends on ARCH_SUNXI
+       depends on NOP_USB_XCEIV
+       depends on PHY_SUN4I_USB
+       depends on EXTCON
+       depends on GENERIC_PHY
+       select SUNXI_SRAM
+
 config USB_MUSB_DAVINCI
        tristate "DaVinci"
        depends on ARCH_DAVINCI_DMx
@@ -113,19 +124,20 @@ config USB_MUSB_JZ4740
 config USB_MUSB_AM335X_CHILD
        tristate
 
-choice
-       prompt 'MUSB DMA mode'
-       default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM || USB_MUSB_JZ4740
-       default USB_UX500_DMA if USB_MUSB_UX500
-       default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
-       default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
-       default USB_TUSB_OMAP_DMA if USB_MUSB_TUSB6010
-       default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X \
-                               || USB_MUSB_DSPS
+comment "MUSB DMA mode"
+
+config MUSB_PIO_ONLY
+       bool 'Disable DMA (always use PIO)'
        help
-         Unfortunately, only one option can be enabled here. Ideally one
-         should be able to build all these drivers into one kernel to
-         allow using DMA on multiplatform kernels.
+         All data is copied between memory and FIFO by the CPU.
+         DMA controllers are ignored.
+
+         Do not choose this unless DMA support for your SOC or board
+         is unavailable (or unstable).  When DMA is enabled at compile time,
+         you can still disable it at run time using the "use_dma=n" module
+         parameter.
+
+if !MUSB_PIO_ONLY
 
 config USB_UX500_DMA
        bool 'ST Ericsson Ux500'
@@ -157,17 +169,6 @@ config USB_TUSB_OMAP_DMA
        help
          Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
 
-config MUSB_PIO_ONLY
-       bool 'Disable DMA (always use PIO)'
-       help
-         All data is copied between memory and FIFO by the CPU.
-         DMA controllers are ignored.
-
-         Do not choose this unless DMA support for your SOC or board
-         is unavailable (or unstable).  When DMA is enabled at compile time,
-         you can still disable it at run time using the "use_dma=n" module
-         parameter.
-
-endchoice
+endif # !MUSB_PIO_ONLY
 
 endif # USB_MUSB_HDRC
index ba495018b4168d74b5a8271f1dbfa509dbcd2442..f95befe18cc1907f86aaf3e78fb366062bf4be7a 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX)                  += da8xx.o
 obj-$(CONFIG_USB_MUSB_BLACKFIN)                        += blackfin.o
 obj-$(CONFIG_USB_MUSB_UX500)                   += ux500.o
 obj-$(CONFIG_USB_MUSB_JZ4740)                  += jz4740.o
+obj-$(CONFIG_USB_MUSB_SUNXI)                   += sunxi.o
 
 
 obj-$(CONFIG_USB_MUSB_AM335X_CHILD)            += musb_am335x.o
index 4d1b44c232ee4e19e79b8ebd10f0626ad4be635a..d07cafb7d5f5a1d6c992d184dff22cd53b48b3de 100644 (file)
@@ -614,7 +614,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
 {
        struct musb *musb = controller->musb;
        struct device *dev = musb->controller;
-       struct device_node *np = dev->of_node;
+       struct device_node *np = dev->parent->of_node;
        struct cppi41_dma_channel *cppi41_channel;
        int count;
        int i;
@@ -664,7 +664,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
                musb_dma->status = MUSB_DMA_STATUS_FREE;
                musb_dma->max_len = SZ_4M;
 
-               dc = dma_request_slave_channel(dev, str);
+               dc = dma_request_slave_channel(dev->parent, str);
                if (!dc) {
                        dev_err(dev, "Failed to request %s.\n", str);
                        ret = -EPROBE_DEFER;
@@ -695,7 +695,7 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base)
        struct cppi41_dma_controller *controller;
        int ret = 0;
 
-       if (!musb->controller->of_node) {
+       if (!musb->controller->parent->of_node) {
                dev_err(musb->controller, "Need DT for the DMA engine.\n");
                return NULL;
        }
index 1334a3de31b8e937756d9546073d41f71ee513bd..a0cfead6150f13a58fc83d50fa0a0559b8bc8908 100644 (file)
@@ -482,11 +482,7 @@ static int dsps_musb_init(struct musb *musb)
                dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
        }
 
-       ret = dsps_musb_dbg_init(musb, glue);
-       if (ret)
-               return ret;
-
-       return 0;
+       return dsps_musb_dbg_init(musb, glue);
 }
 
 static int dsps_musb_exit(struct musb *musb)
index 625d482f1a97f30fea1135f5f03cd8155c36a206..67ad630c86c9c1179c7b7cdc5b42f13a26fc5a32 100644 (file)
@@ -313,8 +313,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
 
                /* MUSB_TXCSR_P_ISO is still set correctly */
 
-#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
-               {
+               if (musb_dma_inventra(musb) || musb_dma_ux500(musb)) {
                        if (request_size < musb_ep->packet_sz)
                                musb_ep->dma->desired_mode = 0;
                        else
@@ -365,7 +364,6 @@ static void txstate(struct musb *musb, struct musb_request *req)
                        }
                }
 
-#endif
                if (is_cppi_enabled(musb)) {
                        /* program endpoint CSR first, then setup DMA */
                        csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
@@ -641,8 +639,10 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                        use_mode_1 = 0;
 
                if (request->actual < request->length) {
-#ifdef CONFIG_USB_INVENTRA_DMA
-                       if (is_buffer_mapped(req)) {
+                       if (!is_buffer_mapped(req))
+                               goto buffer_aint_mapped;
+
+                       if (musb_dma_inventra(musb)) {
                                struct dma_controller   *c;
                                struct dma_channel      *channel;
                                int                     use_dma = 0;
@@ -716,8 +716,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                if (use_dma)
                                        return;
                        }
-#elif defined(CONFIG_USB_UX500_DMA)
-                       if ((is_buffer_mapped(req)) &&
+
+                       if ((musb_dma_ux500(musb)) &&
                                (request->actual < request->length)) {
 
                                struct dma_controller *c;
@@ -765,7 +765,6 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
                                        return;
                        }
-#endif /* Mentor's DMA */
 
                        len = request->length - request->actual;
                        dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
@@ -775,8 +774,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
                        fifo_count = min_t(unsigned, len, fifo_count);
 
-#ifdef CONFIG_USB_TUSB_OMAP_DMA
-                       if (tusb_dma_omap(musb) && is_buffer_mapped(req)) {
+                       if (tusb_dma_omap(musb)) {
                                struct dma_controller *c = musb->dma_controller;
                                struct dma_channel *channel = musb_ep->dma;
                                u32 dma_addr = request->dma + request->actual;
@@ -790,23 +788,22 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                if (ret)
                                        return;
                        }
-#endif
+
                        /*
                         * Unmap the dma buffer back to cpu if dma channel
                         * programming fails. This buffer is mapped if the
                         * channel allocation is successful
                         */
-                        if (is_buffer_mapped(req)) {
-                               unmap_dma_buffer(req, musb);
-
-                               /*
-                                * Clear DMAENAB and AUTOCLEAR for the
-                                * PIO mode transfer
-                                */
-                               csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
-                               musb_writew(epio, MUSB_RXCSR, csr);
-                       }
+                       unmap_dma_buffer(req, musb);
 
+                       /*
+                        * Clear DMAENAB and AUTOCLEAR for the
+                        * PIO mode transfer
+                        */
+                       csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
+                       musb_writew(epio, MUSB_RXCSR, csr);
+
+buffer_aint_mapped:
                        musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
                                        (request->buf + request->actual));
                        request->actual += fifo_count;
@@ -1684,6 +1681,40 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
        return 0;
 }
 
+#ifdef CONFIG_BLACKFIN
+static struct usb_ep *musb_match_ep(struct usb_gadget *g,
+               struct usb_endpoint_descriptor *desc,
+               struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+       struct usb_ep *ep = NULL;
+
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_ISOC:
+       case USB_ENDPOINT_XFER_BULK:
+               if (usb_endpoint_dir_in(desc))
+                       ep = gadget_find_ep_by_name(g, "ep5in");
+               else
+                       ep = gadget_find_ep_by_name(g, "ep6out");
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (usb_endpoint_dir_in(desc))
+                       ep = gadget_find_ep_by_name(g, "ep1in");
+               else
+                       ep = gadget_find_ep_by_name(g, "ep2out");
+               break;
+       default:
+               break;
+       }
+
+       if (ep && usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+               return ep;
+
+       return NULL;
+}
+#else
+#define musb_match_ep NULL
+#endif
+
 static int musb_gadget_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver);
 static int musb_gadget_stop(struct usb_gadget *g);
@@ -1697,6 +1728,7 @@ static const struct usb_gadget_ops musb_gadget_operations = {
        .pullup                 = musb_gadget_pullup,
        .udc_start              = musb_gadget_start,
        .udc_stop               = musb_gadget_stop,
+       .match_ep               = musb_match_ep,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -1729,6 +1761,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
        INIT_LIST_HEAD(&ep->end_point.ep_list);
        if (!epnum) {
                usb_ep_set_maxpacket_limit(&ep->end_point, 64);
+               ep->end_point.caps.type_control = true;
                ep->end_point.ops = &musb_g_ep0_ops;
                musb->g.ep0 = &ep->end_point;
        } else {
@@ -1736,9 +1769,20 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
                        usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_tx);
                else
                        usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_rx);
+               ep->end_point.caps.type_iso = true;
+               ep->end_point.caps.type_bulk = true;
+               ep->end_point.caps.type_int = true;
                ep->end_point.ops = &musb_ep_ops;
                list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
        }
+
+       if (!epnum || hw_ep->is_shared_fifo) {
+               ep->end_point.caps.dir_in = true;
+               ep->end_point.caps.dir_out = true;
+       } else if (is_in)
+               ep->end_point.caps.dir_in = true;
+       else
+               ep->end_point.caps.dir_out = true;
 }
 
 /*
@@ -2075,6 +2119,7 @@ __acquires(musb->lock)
        musb->g.b_hnp_enable = 0;
        musb->g.a_alt_hnp_support = 0;
        musb->g.a_hnp_support = 0;
+       musb->g.quirk_zlp_not_supp = 1;
 
        /* Normal reset, as B-Device;
         * or else after HNP, as A-Device
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
new file mode 100644 (file)
index 0000000..f9f6304
--- /dev/null
@@ -0,0 +1,756 @@
+/*
+ * Allwinner sun4i MUSB Glue Layer
+ *
+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy-sun4i-usb.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+#include <linux/usb/musb.h>
+#include <linux/usb/of.h>
+#include <linux/usb/usb_phy_generic.h>
+#include <linux/workqueue.h>
+#include "musb_core.h"
+
+/*
+ * Register offsets, note sunxi musb has a different layout then most
+ * musb implementations, we translate the layout in musb_readb & friends.
+ */
+#define SUNXI_MUSB_POWER                       0x0040
+#define SUNXI_MUSB_DEVCTL                      0x0041
+#define SUNXI_MUSB_INDEX                       0x0042
+#define SUNXI_MUSB_VEND0                       0x0043
+#define SUNXI_MUSB_INTRTX                      0x0044
+#define SUNXI_MUSB_INTRRX                      0x0046
+#define SUNXI_MUSB_INTRTXE                     0x0048
+#define SUNXI_MUSB_INTRRXE                     0x004a
+#define SUNXI_MUSB_INTRUSB                     0x004c
+#define SUNXI_MUSB_INTRUSBE                    0x0050
+#define SUNXI_MUSB_FRAME                       0x0054
+#define SUNXI_MUSB_TXFIFOSZ                    0x0090
+#define SUNXI_MUSB_TXFIFOADD                   0x0092
+#define SUNXI_MUSB_RXFIFOSZ                    0x0094
+#define SUNXI_MUSB_RXFIFOADD                   0x0096
+#define SUNXI_MUSB_FADDR                       0x0098
+#define SUNXI_MUSB_TXFUNCADDR                  0x0098
+#define SUNXI_MUSB_TXHUBADDR                   0x009a
+#define SUNXI_MUSB_TXHUBPORT                   0x009b
+#define SUNXI_MUSB_RXFUNCADDR                  0x009c
+#define SUNXI_MUSB_RXHUBADDR                   0x009e
+#define SUNXI_MUSB_RXHUBPORT                   0x009f
+#define SUNXI_MUSB_CONFIGDATA                  0x00c0
+
+/* VEND0 bits */
+#define SUNXI_MUSB_VEND0_PIO_MODE              0
+
+/* flags */
+#define SUNXI_MUSB_FL_ENABLED                  0
+#define SUNXI_MUSB_FL_HOSTMODE                 1
+#define SUNXI_MUSB_FL_HOSTMODE_PEND            2
+#define SUNXI_MUSB_FL_VBUS_ON                  3
+#define SUNXI_MUSB_FL_PHY_ON                   4
+#define SUNXI_MUSB_FL_HAS_SRAM                 5
+#define SUNXI_MUSB_FL_HAS_RESET                        6
+#define SUNXI_MUSB_FL_NO_CONFIGDATA            7
+
+/* Our read/write methods need access and do not get passed in a musb ref :| */
+static struct musb *sunxi_musb;
+
+struct sunxi_glue {
+       struct device           *dev;
+       struct platform_device  *musb;
+       struct clk              *clk;
+       struct reset_control    *rst;
+       struct phy              *phy;
+       struct platform_device  *usb_phy;
+       struct usb_phy          *xceiv;
+       unsigned long           flags;
+       struct work_struct      work;
+       struct extcon_dev       *extcon;
+       struct notifier_block   host_nb;
+};
+
+/* phy_power_on / off may sleep, so we use a workqueue  */
+static void sunxi_musb_work(struct work_struct *work)
+{
+       struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work);
+       bool vbus_on, phy_on;
+
+       if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
+               return;
+
+       if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
+               struct musb *musb = platform_get_drvdata(glue->musb);
+               unsigned long flags;
+               u8 devctl;
+
+               spin_lock_irqsave(&musb->lock, flags);
+
+               devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL);
+               if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
+                       set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+                       musb->xceiv->otg->default_a = 1;
+                       musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+                       MUSB_HST_MODE(musb);
+                       devctl |= MUSB_DEVCTL_SESSION;
+               } else {
+                       clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+                       musb->xceiv->otg->default_a = 0;
+                       musb->xceiv->otg->state = OTG_STATE_B_IDLE;
+                       MUSB_DEV_MODE(musb);
+                       devctl &= ~MUSB_DEVCTL_SESSION;
+               }
+               writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL);
+
+               spin_unlock_irqrestore(&musb->lock, flags);
+       }
+
+       vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+       phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+
+       if (phy_on != vbus_on) {
+               if (vbus_on) {
+                       phy_power_on(glue->phy);
+                       set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+               } else {
+                       phy_power_off(glue->phy);
+                       clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+               }
+       }
+}
+
+static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+       if (is_on)
+               set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+       else
+               clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+
+       schedule_work(&glue->work);
+}
+
+static void sunxi_musb_pre_root_reset_end(struct musb *musb)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+       sun4i_usb_phy_set_squelch_detect(glue->phy, false);
+}
+
+static void sunxi_musb_post_root_reset_end(struct musb *musb)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+       sun4i_usb_phy_set_squelch_detect(glue->phy, true);
+}
+
+static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
+{
+       struct musb *musb = __hci;
+       unsigned long flags;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB);
+       if (musb->int_usb)
+               writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
+
+       /*
+        * sunxi musb often signals babble on low / full speed device
+        * disconnect, without ever raising MUSB_INTR_DISCONNECT, since
+        * normally babble never happens treat it as disconnect.
+        */
+       if ((musb->int_usb & MUSB_INTR_BABBLE) && is_host_active(musb)) {
+               musb->int_usb &= ~MUSB_INTR_BABBLE;
+               musb->int_usb |= MUSB_INTR_DISCONNECT;
+       }
+
+       if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
+               /* ep0 FADDR must be 0 when (re)entering peripheral mode */
+               musb_ep_select(musb->mregs, 0);
+               musb_writeb(musb->mregs, MUSB_FADDR, 0);
+       }
+
+       musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX);
+       if (musb->int_tx)
+               writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX);
+
+       musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX);
+       if (musb->int_rx)
+               writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX);
+
+       musb_interrupt(musb);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static int sunxi_musb_host_notifier(struct notifier_block *nb,
+                                   unsigned long event, void *ptr)
+{
+       struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb);
+
+       if (event)
+               set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
+       else
+               clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
+
+       set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags);
+       schedule_work(&glue->work);
+
+       return NOTIFY_DONE;
+}
+
+static int sunxi_musb_init(struct musb *musb)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+       int ret;
+
+       sunxi_musb = musb;
+       musb->phy = glue->phy;
+       musb->xceiv = glue->xceiv;
+
+       if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
+               ret = sunxi_sram_claim(musb->controller->parent);
+               if (ret)
+                       return ret;
+       }
+
+       ret = clk_prepare_enable(glue->clk);
+       if (ret)
+               goto error_sram_release;
+
+       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
+               ret = reset_control_deassert(glue->rst);
+               if (ret)
+                       goto error_clk_disable;
+       }
+
+       writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
+
+       /* Register notifier before calling phy_init() */
+       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) {
+               ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
+                                              &glue->host_nb);
+               if (ret)
+                       goto error_reset_assert;
+       }
+
+       ret = phy_init(glue->phy);
+       if (ret)
+               goto error_unregister_notifier;
+
+       if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+               ret = phy_power_on(glue->phy);
+               if (ret)
+                       goto error_phy_exit;
+               set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+               /* Stop musb work from turning vbus off again */
+               set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+       }
+
+       musb->isr = sunxi_musb_interrupt;
+
+       /* Stop the musb-core from doing runtime pm (not supported on sunxi) */
+       pm_runtime_get(musb->controller);
+
+       return 0;
+
+error_phy_exit:
+       phy_exit(glue->phy);
+error_unregister_notifier:
+       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
+               extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+                                          &glue->host_nb);
+error_reset_assert:
+       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
+               reset_control_assert(glue->rst);
+error_clk_disable:
+       clk_disable_unprepare(glue->clk);
+error_sram_release:
+       if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
+               sunxi_sram_release(musb->controller->parent);
+       return ret;
+}
+
+static int sunxi_musb_exit(struct musb *musb)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+       pm_runtime_put(musb->controller);
+
+       cancel_work_sync(&glue->work);
+       if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags))
+               phy_power_off(glue->phy);
+
+       phy_exit(glue->phy);
+
+       if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
+               extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+                                          &glue->host_nb);
+
+       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
+               reset_control_assert(glue->rst);
+
+       clk_disable_unprepare(glue->clk);
+       if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
+               sunxi_sram_release(musb->controller->parent);
+
+       return 0;
+}
+
+static void sunxi_musb_enable(struct musb *musb)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+       /* musb_core does not call us in a balanced manner */
+       if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
+               return;
+
+       schedule_work(&glue->work);
+}
+
+static void sunxi_musb_disable(struct musb *musb)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+       clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
+}
+
+/*
+ * sunxi musb register layout
+ * 0x00 - 0x17 fifo regs, 1 long per fifo
+ * 0x40 - 0x57 generic control regs (power - frame)
+ * 0x80 - 0x8f ep control regs (addressed through hw_ep->regs, indexed)
+ * 0x90 - 0x97 fifo control regs (indexed)
+ * 0x98 - 0x9f multipoint / busctl regs (indexed)
+ * 0xc0                configdata reg
+ */
+
+static u32 sunxi_musb_fifo_offset(u8 epnum)
+{
+       return (epnum * 4);
+}
+
+static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset)
+{
+       WARN_ONCE(offset != 0,
+                 "sunxi_musb_ep_offset called with non 0 offset\n");
+
+       return 0x80; /* indexed, so ignore epnum */
+}
+
+static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
+{
+       return SUNXI_MUSB_TXFUNCADDR + offset;
+}
+
+static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset)
+{
+       struct sunxi_glue *glue;
+
+       if (addr == sunxi_musb->mregs) {
+               /* generic control or fifo control reg access */
+               switch (offset) {
+               case MUSB_FADDR:
+                       return readb(addr + SUNXI_MUSB_FADDR);
+               case MUSB_POWER:
+                       return readb(addr + SUNXI_MUSB_POWER);
+               case MUSB_INTRUSB:
+                       return readb(addr + SUNXI_MUSB_INTRUSB);
+               case MUSB_INTRUSBE:
+                       return readb(addr + SUNXI_MUSB_INTRUSBE);
+               case MUSB_INDEX:
+                       return readb(addr + SUNXI_MUSB_INDEX);
+               case MUSB_TESTMODE:
+                       return 0; /* No testmode on sunxi */
+               case MUSB_DEVCTL:
+                       return readb(addr + SUNXI_MUSB_DEVCTL);
+               case MUSB_TXFIFOSZ:
+                       return readb(addr + SUNXI_MUSB_TXFIFOSZ);
+               case MUSB_RXFIFOSZ:
+                       return readb(addr + SUNXI_MUSB_RXFIFOSZ);
+               case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */
+                       glue = dev_get_drvdata(sunxi_musb->controller->parent);
+                       /* A33 saves a reg, and we get to hardcode this */
+                       if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA,
+                                    &glue->flags))
+                               return 0xde;
+
+                       return readb(addr + SUNXI_MUSB_CONFIGDATA);
+               /* Offset for these is fixed by sunxi_musb_busctl_offset() */
+               case SUNXI_MUSB_TXFUNCADDR:
+               case SUNXI_MUSB_TXHUBADDR:
+               case SUNXI_MUSB_TXHUBPORT:
+               case SUNXI_MUSB_RXFUNCADDR:
+               case SUNXI_MUSB_RXHUBADDR:
+               case SUNXI_MUSB_RXHUBPORT:
+                       /* multipoint / busctl reg access */
+                       return readb(addr + offset);
+               default:
+                       dev_err(sunxi_musb->controller->parent,
+                               "Error unknown readb offset %u\n", offset);
+                       return 0;
+               }
+       } else if (addr == (sunxi_musb->mregs + 0x80)) {
+               /* ep control reg access */
+               /* sunxi has a 2 byte hole before the txtype register */
+               if (offset >= MUSB_TXTYPE)
+                       offset += 2;
+               return readb(addr + offset);
+       }
+
+       dev_err(sunxi_musb->controller->parent,
+               "Error unknown readb at 0x%x bytes offset\n",
+               (int)(addr - sunxi_musb->mregs));
+       return 0;
+}
+
+static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+{
+       if (addr == sunxi_musb->mregs) {
+               /* generic control or fifo control reg access */
+               switch (offset) {
+               case MUSB_FADDR:
+                       return writeb(data, addr + SUNXI_MUSB_FADDR);
+               case MUSB_POWER:
+                       return writeb(data, addr + SUNXI_MUSB_POWER);
+               case MUSB_INTRUSB:
+                       return writeb(data, addr + SUNXI_MUSB_INTRUSB);
+               case MUSB_INTRUSBE:
+                       return writeb(data, addr + SUNXI_MUSB_INTRUSBE);
+               case MUSB_INDEX:
+                       return writeb(data, addr + SUNXI_MUSB_INDEX);
+               case MUSB_TESTMODE:
+                       if (data)
+                               dev_warn(sunxi_musb->controller->parent,
+                                       "sunxi-musb does not have testmode\n");
+                       return;
+               case MUSB_DEVCTL:
+                       return writeb(data, addr + SUNXI_MUSB_DEVCTL);
+               case MUSB_TXFIFOSZ:
+                       return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ);
+               case MUSB_RXFIFOSZ:
+                       return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ);
+               /* Offset for these is fixed by sunxi_musb_busctl_offset() */
+               case SUNXI_MUSB_TXFUNCADDR:
+               case SUNXI_MUSB_TXHUBADDR:
+               case SUNXI_MUSB_TXHUBPORT:
+               case SUNXI_MUSB_RXFUNCADDR:
+               case SUNXI_MUSB_RXHUBADDR:
+               case SUNXI_MUSB_RXHUBPORT:
+                       /* multipoint / busctl reg access */
+                       return writeb(data, addr + offset);
+               default:
+                       dev_err(sunxi_musb->controller->parent,
+                               "Error unknown writeb offset %u\n", offset);
+                       return;
+               }
+       } else if (addr == (sunxi_musb->mregs + 0x80)) {
+               /* ep control reg access */
+               if (offset >= MUSB_TXTYPE)
+                       offset += 2;
+               return writeb(data, addr + offset);
+       }
+
+       dev_err(sunxi_musb->controller->parent,
+               "Error unknown writeb at 0x%x bytes offset\n",
+               (int)(addr - sunxi_musb->mregs));
+}
+
+static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset)
+{
+       if (addr == sunxi_musb->mregs) {
+               /* generic control or fifo control reg access */
+               switch (offset) {
+               case MUSB_INTRTX:
+                       return readw(addr + SUNXI_MUSB_INTRTX);
+               case MUSB_INTRRX:
+                       return readw(addr + SUNXI_MUSB_INTRRX);
+               case MUSB_INTRTXE:
+                       return readw(addr + SUNXI_MUSB_INTRTXE);
+               case MUSB_INTRRXE:
+                       return readw(addr + SUNXI_MUSB_INTRRXE);
+               case MUSB_FRAME:
+                       return readw(addr + SUNXI_MUSB_FRAME);
+               case MUSB_TXFIFOADD:
+                       return readw(addr + SUNXI_MUSB_TXFIFOADD);
+               case MUSB_RXFIFOADD:
+                       return readw(addr + SUNXI_MUSB_RXFIFOADD);
+               case MUSB_HWVERS:
+                       return 0; /* sunxi musb version is not known */
+               default:
+                       dev_err(sunxi_musb->controller->parent,
+                               "Error unknown readw offset %u\n", offset);
+                       return 0;
+               }
+       } else if (addr == (sunxi_musb->mregs + 0x80)) {
+               /* ep control reg access */
+               return readw(addr + offset);
+       }
+
+       dev_err(sunxi_musb->controller->parent,
+               "Error unknown readw at 0x%x bytes offset\n",
+               (int)(addr - sunxi_musb->mregs));
+       return 0;
+}
+
+static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data)
+{
+       if (addr == sunxi_musb->mregs) {
+               /* generic control or fifo control reg access */
+               switch (offset) {
+               case MUSB_INTRTX:
+                       return writew(data, addr + SUNXI_MUSB_INTRTX);
+               case MUSB_INTRRX:
+                       return writew(data, addr + SUNXI_MUSB_INTRRX);
+               case MUSB_INTRTXE:
+                       return writew(data, addr + SUNXI_MUSB_INTRTXE);
+               case MUSB_INTRRXE:
+                       return writew(data, addr + SUNXI_MUSB_INTRRXE);
+               case MUSB_FRAME:
+                       return writew(data, addr + SUNXI_MUSB_FRAME);
+               case MUSB_TXFIFOADD:
+                       return writew(data, addr + SUNXI_MUSB_TXFIFOADD);
+               case MUSB_RXFIFOADD:
+                       return writew(data, addr + SUNXI_MUSB_RXFIFOADD);
+               default:
+                       dev_err(sunxi_musb->controller->parent,
+                               "Error unknown writew offset %u\n", offset);
+                       return;
+               }
+       } else if (addr == (sunxi_musb->mregs + 0x80)) {
+               /* ep control reg access */
+               return writew(data, addr + offset);
+       }
+
+       dev_err(sunxi_musb->controller->parent,
+               "Error unknown writew at 0x%x bytes offset\n",
+               (int)(addr - sunxi_musb->mregs));
+}
+
+static const struct musb_platform_ops sunxi_musb_ops = {
+       .quirks         = MUSB_INDEXED_EP,
+       .init           = sunxi_musb_init,
+       .exit           = sunxi_musb_exit,
+       .enable         = sunxi_musb_enable,
+       .disable        = sunxi_musb_disable,
+       .fifo_offset    = sunxi_musb_fifo_offset,
+       .ep_offset      = sunxi_musb_ep_offset,
+       .busctl_offset  = sunxi_musb_busctl_offset,
+       .readb          = sunxi_musb_readb,
+       .writeb         = sunxi_musb_writeb,
+       .readw          = sunxi_musb_readw,
+       .writew         = sunxi_musb_writew,
+       .set_vbus       = sunxi_musb_set_vbus,
+       .pre_root_reset_end = sunxi_musb_pre_root_reset_end,
+       .post_root_reset_end = sunxi_musb_post_root_reset_end,
+};
+
+/* Allwinner OTG supports up to 5 endpoints */
+#define SUNXI_MUSB_MAX_EP_NUM  6
+#define SUNXI_MUSB_RAM_BITS    11
+
+static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
+       MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
+       MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
+       MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
+       MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
+       MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
+       MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
+       MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
+       MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
+       MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
+       MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
+};
+
+static struct musb_hdrc_config sunxi_musb_hdrc_config = {
+       .fifo_cfg       = sunxi_musb_mode_cfg,
+       .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg),
+       .multipoint     = true,
+       .dyn_fifo       = true,
+       .soft_con       = true,
+       .num_eps        = SUNXI_MUSB_MAX_EP_NUM,
+       .ram_bits       = SUNXI_MUSB_RAM_BITS,
+       .dma            = 0,
+};
+
+static int sunxi_musb_probe(struct platform_device *pdev)
+{
+       struct musb_hdrc_platform_data  pdata;
+       struct platform_device_info     pinfo;
+       struct sunxi_glue               *glue;
+       struct device_node              *np = pdev->dev.of_node;
+       int ret;
+
+       if (!np) {
+               dev_err(&pdev->dev, "Error no device tree node found\n");
+               return -EINVAL;
+       }
+
+       glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+       if (!glue)
+               return -ENOMEM;
+
+       memset(&pdata, 0, sizeof(pdata));
+       switch (of_usb_get_dr_mode(np)) {
+#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
+       case USB_DR_MODE_HOST:
+               pdata.mode = MUSB_PORT_MODE_HOST;
+               break;
+#endif
+#ifdef CONFIG_USB_MUSB_DUAL_ROLE
+       case USB_DR_MODE_OTG:
+               glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
+               if (IS_ERR(glue->extcon)) {
+                       if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+                       dev_err(&pdev->dev, "Invalid or missing extcon\n");
+                       return PTR_ERR(glue->extcon);
+               }
+               pdata.mode = MUSB_PORT_MODE_DUAL_ROLE;
+               break;
+#endif
+       default:
+               dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");
+               return -EINVAL;
+       }
+       pdata.platform_ops      = &sunxi_musb_ops;
+       pdata.config            = &sunxi_musb_hdrc_config;
+
+       glue->dev = &pdev->dev;
+       INIT_WORK(&glue->work, sunxi_musb_work);
+       glue->host_nb.notifier_call = sunxi_musb_host_notifier;
+
+       if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
+               set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
+
+       if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
+               set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
+
+       if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb")) {
+               set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
+               set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
+       }
+
+       glue->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(glue->clk)) {
+               dev_err(&pdev->dev, "Error getting clock: %ld\n",
+                       PTR_ERR(glue->clk));
+               return PTR_ERR(glue->clk);
+       }
+
+       if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
+               glue->rst = devm_reset_control_get(&pdev->dev, NULL);
+               if (IS_ERR(glue->rst)) {
+                       if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+                       dev_err(&pdev->dev, "Error getting reset %ld\n",
+                               PTR_ERR(glue->rst));
+                       return PTR_ERR(glue->rst);
+               }
+       }
+
+       glue->phy = devm_phy_get(&pdev->dev, "usb");
+       if (IS_ERR(glue->phy)) {
+               if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               dev_err(&pdev->dev, "Error getting phy %ld\n",
+                       PTR_ERR(glue->phy));
+               return PTR_ERR(glue->phy);
+       }
+
+       glue->usb_phy = usb_phy_generic_register();
+       if (IS_ERR(glue->usb_phy)) {
+               dev_err(&pdev->dev, "Error registering usb-phy %ld\n",
+                       PTR_ERR(glue->usb_phy));
+               return PTR_ERR(glue->usb_phy);
+       }
+
+       glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+       if (IS_ERR(glue->xceiv)) {
+               ret = PTR_ERR(glue->xceiv);
+               dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret);
+               goto err_unregister_usb_phy;
+       }
+
+       platform_set_drvdata(pdev, glue);
+
+       memset(&pinfo, 0, sizeof(pinfo));
+       pinfo.name       = "musb-hdrc";
+       pinfo.id        = PLATFORM_DEVID_AUTO;
+       pinfo.parent    = &pdev->dev;
+       pinfo.res       = pdev->resource;
+       pinfo.num_res   = pdev->num_resources;
+       pinfo.data      = &pdata;
+       pinfo.size_data = sizeof(pdata);
+
+       glue->musb = platform_device_register_full(&pinfo);
+       if (IS_ERR(glue->musb)) {
+               ret = PTR_ERR(glue->musb);
+               dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
+               goto err_unregister_usb_phy;
+       }
+
+       return 0;
+
+err_unregister_usb_phy:
+       usb_phy_generic_unregister(glue->usb_phy);
+       return ret;
+}
+
+static int sunxi_musb_remove(struct platform_device *pdev)
+{
+       struct sunxi_glue *glue = platform_get_drvdata(pdev);
+       struct platform_device *usb_phy = glue->usb_phy;
+
+       platform_device_unregister(glue->musb); /* Frees glue ! */
+       usb_phy_generic_unregister(usb_phy);
+
+       return 0;
+}
+
+static const struct of_device_id sunxi_musb_match[] = {
+       { .compatible = "allwinner,sun4i-a10-musb", },
+       { .compatible = "allwinner,sun6i-a31-musb", },
+       { .compatible = "allwinner,sun8i-a33-musb", },
+       {}
+};
+
+static struct platform_driver sunxi_musb_driver = {
+       .probe = sunxi_musb_probe,
+       .remove = sunxi_musb_remove,
+       .driver = {
+               .name = "musb-sunxi",
+               .of_match_table = sunxi_musb_match,
+       },
+};
+module_platform_driver(sunxi_musb_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
index 869c0cfcad98e28948c30ce68329fb34ab89d99a..7d3beee2a587d84e60ecffab4b4703dee4cd6976 100644 (file)
@@ -152,6 +152,20 @@ config USB_MSM_OTG
          This driver is not supported on boards like trout which
          has an external PHY.
 
+config USB_QCOM_8X16_PHY
+       tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
+       depends on ARCH_QCOM || COMPILE_TEST
+       depends on RESET_CONTROLLER
+       select USB_PHY
+       select USB_ULPI_VIEWPORT
+       help
+         Enable this to support the USB transceiver on Qualcomm 8x16 chipsets.
+         It handles PHY initialization, clock management, power management,
+         and workarounds required after resetting the hardware.
+
+         To compile this driver as a module, choose M here: the
+         module will be called phy-qcom-8x16-usb.
+
 config USB_MV_OTG
        tristate "Marvell USB OTG support"
        depends on USB_EHCI_MV && USB_MV_UDC && PM
index e36ab1d46d8b4fed21445e9c4adc2e7fe1e0974b..19c0dccbb1161b11ba001ee62181027a614be187 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_USB_EHCI_TEGRA)          += phy-tegra-usb.o
 obj-$(CONFIG_USB_GPIO_VBUS)            += phy-gpio-vbus-usb.o
 obj-$(CONFIG_USB_ISP1301)              += phy-isp1301.o
 obj-$(CONFIG_USB_MSM_OTG)              += phy-msm-usb.o
+obj-$(CONFIG_USB_QCOM_8X16_PHY)        += phy-qcom-8x16-usb.o
 obj-$(CONFIG_USB_MV_OTG)               += phy-mv-usb.o
 obj-$(CONFIG_USB_MXS_PHY)              += phy-mxs-usb.o
 obj-$(CONFIG_USB_RCAR_PHY)             += phy-rcar-usb.o
index deee68eafb72a70c8c504d659e8fc573cc270d09..ec6ecd03269cc90a3aa113e8070cfba14c8aa6c3 100644 (file)
@@ -218,11 +218,13 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
                        clk_rate = 0;
 
                needs_vcc = of_property_read_bool(node, "vcc-supply");
-               nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset");
+               nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
+                                                          GPIOD_ASIS);
                err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
                if (!err) {
                        nop->gpiod_vbus = devm_gpiod_get_optional(dev,
-                                                        "vbus-detect");
+                                                        "vbus-detect",
+                                                        GPIOD_ASIS);
                        err = PTR_ERR_OR_ZERO(nop->gpiod_vbus);
                }
        } else if (pdata) {
index e0556f7832b5534c29d593b165f473995e96e1da..01d4e4cdbc79ef3125482ccd0e94e8372315798e 100644 (file)
@@ -96,11 +96,7 @@ static int keystone_usbphy_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, k_phy);
 
-       ret = usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
-       if (ret)
-               return ret;
-
-       return 0;
+       return usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
 }
 
 static int keystone_usbphy_remove(struct platform_device *pdev)
index 00c49bb1bd29a8ac9a63d6f6a69aea6a71e837d8..c58c3c0dbe35edebec10a89ad7477484f4cab902 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/gpio/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
@@ -32,6 +33,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/reboot.h>
 #include <linux/reset.h>
 
 #include <linux/usb.h>
@@ -1471,6 +1473,14 @@ static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event,
        else
                clear_bit(B_SESS_VLD, &motg->inputs);
 
+       if (test_bit(B_SESS_VLD, &motg->inputs)) {
+               /* Switch D+/D- lines to Device connector */
+               gpiod_set_value_cansleep(motg->switch_gpio, 0);
+       } else {
+               /* Switch D+/D- lines to Hub */
+               gpiod_set_value_cansleep(motg->switch_gpio, 1);
+       }
+
        schedule_work(&motg->sm_work);
 
        return NOTIFY_DONE;
@@ -1546,6 +1556,11 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
 
        motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup");
 
+       motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch",
+                                                   GPIOD_OUT_LOW);
+       if (IS_ERR(motg->switch_gpio))
+               return PTR_ERR(motg->switch_gpio);
+
        ext_id = ERR_PTR(-ENODEV);
        ext_vbus = ERR_PTR(-ENODEV);
        if (of_property_read_bool(node, "extcon")) {
@@ -1561,15 +1576,16 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
        }
 
        if (!IS_ERR(ext_vbus)) {
+               motg->vbus.extcon = ext_vbus;
                motg->vbus.nb.notifier_call = msm_otg_vbus_notifier;
-               ret = extcon_register_interest(&motg->vbus.conn, ext_vbus->name,
-                                              "USB", &motg->vbus.nb);
+               ret = extcon_register_notifier(ext_vbus, EXTCON_USB,
+                                               &motg->vbus.nb);
                if (ret < 0) {
                        dev_err(&pdev->dev, "register VBUS notifier failed\n");
                        return ret;
                }
 
-               ret = extcon_get_cable_state(ext_vbus, "USB");
+               ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB);
                if (ret)
                        set_bit(B_SESS_VLD, &motg->inputs);
                else
@@ -1577,15 +1593,16 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
        }
 
        if (!IS_ERR(ext_id)) {
+               motg->id.extcon = ext_id;
                motg->id.nb.notifier_call = msm_otg_id_notifier;
-               ret = extcon_register_interest(&motg->id.conn, ext_id->name,
-                                              "USB-HOST", &motg->id.nb);
+               ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST,
+                                               &motg->id.nb);
                if (ret < 0) {
                        dev_err(&pdev->dev, "register ID notifier failed\n");
                        return ret;
                }
 
-               ret = extcon_get_cable_state(ext_id, "USB-HOST");
+               ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST);
                if (ret)
                        clear_bit(ID, &motg->inputs);
                else
@@ -1615,6 +1632,19 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
        return 0;
 }
 
+static int msm_otg_reboot_notify(struct notifier_block *this,
+                                unsigned long code, void *unused)
+{
+       struct msm_otg *motg = container_of(this, struct msm_otg, reboot);
+
+       /*
+        * Ensure that D+/D- lines are routed to uB connector, so
+        * we could load bootloader/kernel at next reboot
+        */
+       gpiod_set_value_cansleep(motg->switch_gpio, 0);
+       return NOTIFY_DONE;
+}
+
 static int msm_otg_probe(struct platform_device *pdev)
 {
        struct regulator_bulk_data regs[3];
@@ -1779,6 +1809,17 @@ static int msm_otg_probe(struct platform_device *pdev)
                        dev_dbg(&pdev->dev, "Can not create mode change file\n");
        }
 
+       if (test_bit(B_SESS_VLD, &motg->inputs)) {
+               /* Switch D+/D- lines to Device connector */
+               gpiod_set_value_cansleep(motg->switch_gpio, 0);
+       } else {
+               /* Switch D+/D- lines to Hub */
+               gpiod_set_value_cansleep(motg->switch_gpio, 1);
+       }
+
+       motg->reboot.notifier_call = msm_otg_reboot_notify;
+       register_reboot_notifier(&motg->reboot);
+
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
 
@@ -1805,10 +1846,16 @@ static int msm_otg_remove(struct platform_device *pdev)
        if (phy->otg->host || phy->otg->gadget)
                return -EBUSY;
 
-       if (motg->id.conn.edev)
-               extcon_unregister_interest(&motg->id.conn);
-       if (motg->vbus.conn.edev)
-               extcon_unregister_interest(&motg->vbus.conn);
+       unregister_reboot_notifier(&motg->reboot);
+
+       /*
+        * Ensure that D+/D- lines are routed to uB connector, so
+        * we could load bootloader/kernel at next reboot
+        */
+       gpiod_set_value_cansleep(motg->switch_gpio, 0);
+
+       extcon_unregister_notifier(motg->id.extcon, EXTCON_USB_HOST, &motg->id.nb);
+       extcon_unregister_notifier(motg->vbus.extcon, EXTCON_USB, &motg->vbus.nb);
 
        msm_otg_debugfs_cleanup();
        cancel_delayed_work_sync(&motg->chg_work);
index 3fcc0483a0811e8f7e2984aea1c4a11ce2da0951..4d863ebc117c0f59cce46f39fda4d191e93b9843 100644 (file)
@@ -506,11 +506,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 
        device_set_wakeup_capable(&pdev->dev, true);
 
-       ret = usb_add_phy_dev(&mxs_phy->phy);
-       if (ret)
-               return ret;
-
-       return 0;
+       return usb_add_phy_dev(&mxs_phy->phy);
 }
 
 static int mxs_phy_remove(struct platform_device *pdev)
index 56ee7603034b890fa49d7bf6574692d5c6383e41..1270906ccb95808714d174f0461a081c8d1d1cc6 100644 (file)
@@ -30,8 +30,7 @@ struct otg_device {
        void __iomem                    *base;
        bool                            id;
        bool                            vbus;
-       struct extcon_specific_cable_nb vbus_dev;
-       struct extcon_specific_cable_nb id_dev;
+       struct extcon_dev               *extcon;
        struct notifier_block           vbus_nb;
        struct notifier_block           id_nb;
 };
@@ -106,6 +105,7 @@ static int omap_otg_probe(struct platform_device *pdev)
        extcon = extcon_get_extcon_dev(config->extcon);
        if (!extcon)
                return -EPROBE_DEFER;
+       otg_dev->extcon = extcon;
 
        otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
        if (!otg_dev)
@@ -118,20 +118,19 @@ static int omap_otg_probe(struct platform_device *pdev)
        otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
        otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;
 
-       ret = extcon_register_interest(&otg_dev->id_dev, config->extcon,
-                                      "USB-HOST", &otg_dev->id_nb);
+       ret = extcon_register_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb);
        if (ret)
                return ret;
 
-       ret = extcon_register_interest(&otg_dev->vbus_dev, config->extcon,
-                                      "USB", &otg_dev->vbus_nb);
+       ret = extcon_register_notifier(extcon, EXTCON_USB, &otg_dev->vbus_nb);
        if (ret) {
-               extcon_unregister_interest(&otg_dev->id_dev);
+               extcon_unregister_notifier(extcon, EXTCON_USB_HOST,
+                                       &otg_dev->id_nb);
                return ret;
        }
 
-       otg_dev->id = extcon_get_cable_state(extcon, "USB-HOST");
-       otg_dev->vbus = extcon_get_cable_state(extcon, "USB");
+       otg_dev->id = extcon_get_cable_state_(extcon, EXTCON_USB_HOST);
+       otg_dev->vbus = extcon_get_cable_state_(extcon, EXTCON_USB);
        omap_otg_set_mode(otg_dev);
 
        rev = readl(otg_dev->base);
@@ -147,9 +146,10 @@ static int omap_otg_probe(struct platform_device *pdev)
 static int omap_otg_remove(struct platform_device *pdev)
 {
        struct otg_device *otg_dev = platform_get_drvdata(pdev);
+       struct extcon_dev *edev = otg_dev->extcon;
 
-       extcon_unregister_interest(&otg_dev->id_dev);
-       extcon_unregister_interest(&otg_dev->vbus_dev);
+       extcon_unregister_notifier(edev, EXTCON_USB_HOST,&otg_dev->id_nb);
+       extcon_unregister_notifier(edev, EXTCON_USB, &otg_dev->vbus_nb);
 
        return 0;
 }
diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c
new file mode 100644 (file)
index 0000000..5d357a9
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/ulpi.h>
+
+#define HSPHY_AHBBURST                 0x0090
+#define HSPHY_AHBMODE                  0x0098
+#define HSPHY_GENCONFIG                        0x009c
+#define HSPHY_GENCONFIG_2              0x00a0
+
+#define HSPHY_USBCMD                   0x0140
+#define HSPHY_ULPI_VIEWPORT            0x0170
+#define HSPHY_CTRL                     0x0240
+
+#define HSPHY_TXFIFO_IDLE_FORCE_DIS    BIT(4)
+#define HSPHY_SESS_VLD_CTRL_EN         BIT(7)
+#define HSPHY_POR_ASSERT               BIT(0)
+#define HSPHY_RETEN                    BIT(1)
+
+#define HSPHY_SESS_VLD_CTRL            BIT(25)
+
+#define ULPI_PWR_CLK_MNG_REG           0x88
+#define ULPI_PWR_OTG_COMP_DISABLE      BIT(0)
+
+#define ULPI_MISC_A                    0x96
+#define ULPI_MISC_A_VBUSVLDEXTSEL      BIT(1)
+#define ULPI_MISC_A_VBUSVLDEXT         BIT(0)
+
+#define HSPHY_3P3_MIN                  3050000 /* uV */
+#define HSPHY_3P3_MAX                  3300000 /* uV */
+
+#define HSPHY_1P8_MIN                  1800000 /* uV */
+#define HSPHY_1P8_MAX                  1800000 /* uV */
+
+#define HSPHY_VDD_MIN                  5
+#define HSPHY_VDD_MAX                  7
+
+struct phy_8x16 {
+       struct usb_phy                  phy;
+       void __iomem                    *regs;
+       struct clk                      *core_clk;
+       struct clk                      *iface_clk;
+       struct regulator                *v3p3;
+       struct regulator                *v1p8;
+       struct regulator                *vdd;
+
+       struct reset_control            *phy_reset;
+
+       struct extcon_specific_cable_nb vbus_cable;
+       struct notifier_block           vbus_notify;
+
+       struct gpio_desc                *switch_gpio;
+       struct notifier_block           reboot_notify;
+};
+
+static int phy_8x16_regulators_enable(struct phy_8x16 *qphy)
+{
+       int ret;
+
+       ret = regulator_set_voltage(qphy->vdd, HSPHY_VDD_MIN, HSPHY_VDD_MAX);
+       if (ret)
+               return ret;
+
+       ret = regulator_enable(qphy->vdd);
+       if (ret)
+               return ret;
+
+       ret = regulator_set_voltage(qphy->v3p3, HSPHY_3P3_MIN, HSPHY_3P3_MAX);
+       if (ret)
+               goto off_vdd;
+
+       ret = regulator_enable(qphy->v3p3);
+       if (ret)
+               goto off_vdd;
+
+       ret = regulator_set_voltage(qphy->v1p8, HSPHY_1P8_MIN, HSPHY_1P8_MAX);
+       if (ret)
+               goto off_3p3;
+
+       ret = regulator_enable(qphy->v1p8);
+       if (ret)
+               goto off_3p3;
+
+       return 0;
+
+off_3p3:
+       regulator_disable(qphy->v3p3);
+off_vdd:
+       regulator_disable(qphy->vdd);
+
+       return ret;
+}
+
+static void phy_8x16_regulators_disable(struct phy_8x16 *qphy)
+{
+       regulator_disable(qphy->v1p8);
+       regulator_disable(qphy->v3p3);
+       regulator_disable(qphy->vdd);
+}
+
+static int phy_8x16_notify_connect(struct usb_phy *phy,
+                                  enum usb_device_speed speed)
+{
+       struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy);
+       u32 val;
+
+       val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT;
+       usb_phy_io_write(&qphy->phy, val, ULPI_SET(ULPI_MISC_A));
+
+       val = readl(qphy->regs + HSPHY_USBCMD);
+       val |= HSPHY_SESS_VLD_CTRL;
+       writel(val, qphy->regs + HSPHY_USBCMD);
+
+       return 0;
+}
+
+static int phy_8x16_notify_disconnect(struct usb_phy *phy,
+                                     enum usb_device_speed speed)
+{
+       struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy);
+       u32 val;
+
+       val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL;
+       usb_phy_io_write(&qphy->phy, val, ULPI_CLR(ULPI_MISC_A));
+
+       val = readl(qphy->regs + HSPHY_USBCMD);
+       val &= ~HSPHY_SESS_VLD_CTRL;
+       writel(val, qphy->regs + HSPHY_USBCMD);
+
+       return 0;
+}
+
+static int phy_8x16_vbus_on(struct phy_8x16 *qphy)
+{
+       phy_8x16_notify_connect(&qphy->phy, USB_SPEED_UNKNOWN);
+
+       /* Switch D+/D- lines to Device connector */
+       gpiod_set_value_cansleep(qphy->switch_gpio, 0);
+
+       return 0;
+}
+
+static int phy_8x16_vbus_off(struct phy_8x16 *qphy)
+{
+       phy_8x16_notify_disconnect(&qphy->phy, USB_SPEED_UNKNOWN);
+
+       /* Switch D+/D- lines to USB HUB */
+       gpiod_set_value_cansleep(qphy->switch_gpio, 1);
+
+       return 0;
+}
+
+static int phy_8x16_vbus_notify(struct notifier_block *nb, unsigned long event,
+                               void *ptr)
+{
+       struct phy_8x16 *qphy = container_of(nb, struct phy_8x16, vbus_notify);
+
+       if (event)
+               phy_8x16_vbus_on(qphy);
+       else
+               phy_8x16_vbus_off(qphy);
+
+       return NOTIFY_DONE;
+}
+
+static int phy_8x16_init(struct usb_phy *phy)
+{
+       struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy);
+       u32 val, init[] = {0x44, 0x6B, 0x24, 0x13};
+       u32 addr = ULPI_EXT_VENDOR_SPECIFIC;
+       int idx, state;
+
+       for (idx = 0; idx < ARRAY_SIZE(init); idx++)
+               usb_phy_io_write(phy, init[idx], addr + idx);
+
+       reset_control_reset(qphy->phy_reset);
+
+       /* Assert USB HSPHY_POR */
+       val = readl(qphy->regs + HSPHY_CTRL);
+       val |= HSPHY_POR_ASSERT;
+       writel(val, qphy->regs + HSPHY_CTRL);
+
+       /*
+        * wait for minimum 10 microseconds as suggested in HPG.
+        * Use a slightly larger value since the exact value didn't
+        * work 100% of the time.
+        */
+       usleep_range(12, 15);
+
+       /* Deassert USB HSPHY_POR */
+       val = readl(qphy->regs + HSPHY_CTRL);
+       val &= ~HSPHY_POR_ASSERT;
+       writel(val, qphy->regs + HSPHY_CTRL);
+
+       usleep_range(10, 15);
+
+       writel(0x00, qphy->regs + HSPHY_AHBBURST);
+       writel(0x08, qphy->regs + HSPHY_AHBMODE);
+
+       /* workaround for rx buffer collision issue */
+       val = readl(qphy->regs + HSPHY_GENCONFIG);
+       val &= ~HSPHY_TXFIFO_IDLE_FORCE_DIS;
+       writel(val, qphy->regs + HSPHY_GENCONFIG);
+
+       val = readl(qphy->regs + HSPHY_GENCONFIG_2);
+       val |= HSPHY_SESS_VLD_CTRL_EN;
+       writel(val, qphy->regs + HSPHY_GENCONFIG_2);
+
+       val = ULPI_PWR_OTG_COMP_DISABLE;
+       usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG));
+
+       state = extcon_get_cable_state(qphy->vbus_cable.edev, "USB");
+       if (state)
+               phy_8x16_vbus_on(qphy);
+       else
+               phy_8x16_vbus_off(qphy);
+
+       val = usb_phy_io_read(&qphy->phy, ULPI_FUNC_CTRL);
+       val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+       val |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+       usb_phy_io_write(&qphy->phy, val, ULPI_FUNC_CTRL);
+
+       return 0;
+}
+
+static void phy_8x16_shutdown(struct usb_phy *phy)
+{
+       u32 val;
+
+       /* Put the controller in non-driving mode */
+       val = usb_phy_io_read(phy, ULPI_FUNC_CTRL);
+       val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+       val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+       usb_phy_io_write(phy, val, ULPI_FUNC_CTRL);
+}
+
+static int phy_8x16_read_devicetree(struct phy_8x16 *qphy)
+{
+       struct regulator_bulk_data regs[3];
+       struct device *dev = qphy->phy.dev;
+       int ret;
+
+       qphy->core_clk = devm_clk_get(dev, "core");
+       if (IS_ERR(qphy->core_clk))
+               return PTR_ERR(qphy->core_clk);
+
+       qphy->iface_clk = devm_clk_get(dev, "iface");
+       if (IS_ERR(qphy->iface_clk))
+               return PTR_ERR(qphy->iface_clk);
+
+       regs[0].supply = "v3p3";
+       regs[1].supply = "v1p8";
+       regs[2].supply = "vddcx";
+
+       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
+       if (ret)
+               return ret;
+
+       qphy->v3p3 = regs[0].consumer;
+       qphy->v1p8 = regs[1].consumer;
+       qphy->vdd  = regs[2].consumer;
+
+       qphy->phy_reset = devm_reset_control_get(dev, "phy");
+       if (IS_ERR(qphy->phy_reset))
+               return PTR_ERR(qphy->phy_reset);
+
+       qphy->switch_gpio = devm_gpiod_get_optional(dev, "switch",
+                                                  GPIOD_OUT_LOW);
+       if (IS_ERR(qphy->switch_gpio))
+               return PTR_ERR(qphy->switch_gpio);
+
+       return 0;
+}
+
+static int phy_8x16_reboot_notify(struct notifier_block *this,
+                                 unsigned long code, void *unused)
+{
+       struct phy_8x16 *qphy;
+
+       qphy = container_of(this, struct phy_8x16, reboot_notify);
+
+       /*
+        * Ensure that D+/D- lines are routed to uB connector, so
+        * we could load bootloader/kernel at next reboot_notify
+        */
+       gpiod_set_value_cansleep(qphy->switch_gpio, 0);
+       return NOTIFY_DONE;
+}
+
+static int phy_8x16_probe(struct platform_device *pdev)
+{
+       struct extcon_dev *edev;
+       struct phy_8x16 *qphy;
+       struct resource *res;
+       struct usb_phy *phy;
+       int ret;
+
+       qphy = devm_kzalloc(&pdev->dev, sizeof(*qphy), GFP_KERNEL);
+       if (!qphy)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, qphy);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
+
+       qphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+       if (!qphy->regs)
+               return -ENOMEM;
+
+       phy                     = &qphy->phy;
+       phy->dev                = &pdev->dev;
+       phy->label              = dev_name(&pdev->dev);
+       phy->init               = phy_8x16_init;
+       phy->shutdown           = phy_8x16_shutdown;
+       phy->notify_connect     = phy_8x16_notify_connect;
+       phy->notify_disconnect  = phy_8x16_notify_disconnect;
+       phy->io_priv            = qphy->regs + HSPHY_ULPI_VIEWPORT;
+       phy->io_ops             = &ulpi_viewport_access_ops;
+       phy->type               = USB_PHY_TYPE_USB2;
+
+       ret = phy_8x16_read_devicetree(qphy);
+       if (ret < 0)
+               return ret;
+
+       edev = extcon_get_edev_by_phandle(phy->dev, 0);
+       if (IS_ERR(edev))
+               return PTR_ERR(edev);
+
+       ret = clk_set_rate(qphy->core_clk, INT_MAX);
+       if (ret < 0)
+               dev_dbg(phy->dev, "Can't boost core clock\n");
+
+       ret = clk_prepare_enable(qphy->core_clk);
+       if (ret < 0)
+               return ret;
+
+       ret = clk_prepare_enable(qphy->iface_clk);
+       if (ret < 0)
+               goto off_core;
+
+       ret = phy_8x16_regulators_enable(qphy);
+       if (0 && ret)
+               goto off_clks;
+
+       qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
+       ret = extcon_register_interest(&qphy->vbus_cable, edev->name,
+                                      "USB", &qphy->vbus_notify);
+       if (ret < 0)
+               goto off_power;
+
+       ret = usb_add_phy_dev(&qphy->phy);
+       if (ret)
+               goto off_extcon;
+
+       qphy->reboot_notify.notifier_call = phy_8x16_reboot_notify;
+       register_reboot_notifier(&qphy->reboot_notify);
+
+       return 0;
+
+off_extcon:
+       extcon_unregister_interest(&qphy->vbus_cable);
+off_power:
+       phy_8x16_regulators_disable(qphy);
+off_clks:
+       clk_disable_unprepare(qphy->iface_clk);
+off_core:
+       clk_disable_unprepare(qphy->core_clk);
+       return ret;
+}
+
+static int phy_8x16_remove(struct platform_device *pdev)
+{
+       struct phy_8x16 *qphy = platform_get_drvdata(pdev);
+
+       unregister_reboot_notifier(&qphy->reboot_notify);
+       extcon_unregister_interest(&qphy->vbus_cable);
+
+       /*
+        * Ensure that D+/D- lines are routed to uB connector, so
+        * we could load bootloader/kernel at next reboot_notify
+        */
+       gpiod_set_value_cansleep(qphy->switch_gpio, 0);
+
+       usb_remove_phy(&qphy->phy);
+
+       clk_disable_unprepare(qphy->iface_clk);
+       clk_disable_unprepare(qphy->core_clk);
+       phy_8x16_regulators_disable(qphy);
+       return 0;
+}
+
+static const struct of_device_id phy_8x16_dt_match[] = {
+       { .compatible = "qcom,usb-8x16-phy" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, phy_8x16_dt_match);
+
+static struct platform_driver phy_8x16_driver = {
+       .probe  = phy_8x16_probe,
+       .remove = phy_8x16_remove,
+       .driver = {
+               .name = "phy-qcom-8x16-usb",
+               .of_match_table = phy_8x16_dt_match,
+       },
+};
+module_platform_driver(phy_8x16_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm APQ8016/MSM8916 chipsets USB transceiver driver");
index b40d6a87d69491b3a016c2a481026580a2d9a143..ab5d364f6e8c7964e004c01c78b50baf3f32832c 100644 (file)
@@ -57,7 +57,7 @@ struct tahvo_usb {
        struct clk              *ick;
        int                     irq;
        int                     tahvo_mode;
-       struct extcon_dev       extcon;
+       struct extcon_dev       *extcon;
 };
 
 static const unsigned int tahvo_cable[] = {
@@ -121,7 +121,7 @@ static void check_vbus_state(struct tahvo_usb *tu)
        prev_state = tu->vbus_state;
        tu->vbus_state = reg & TAHVO_STAT_VBUS;
        if (prev_state != tu->vbus_state) {
-               extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state);
+               extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state);
                sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state");
        }
 }
@@ -130,7 +130,7 @@ static void tahvo_usb_become_host(struct tahvo_usb *tu)
 {
        struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
 
-       extcon_set_cable_state(&tu->extcon, "USB-HOST", true);
+       extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, true);
 
        /* Power up the transceiver in USB host mode */
        retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
@@ -149,7 +149,7 @@ static void tahvo_usb_become_peripheral(struct tahvo_usb *tu)
 {
        struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
 
-       extcon_set_cable_state(&tu->extcon, "USB-HOST", false);
+       extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, false);
 
        /* Power up transceiver and set it in USB peripheral mode */
        retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT |
@@ -365,11 +365,13 @@ static int tahvo_usb_probe(struct platform_device *pdev)
         */
        tu->vbus_state = retu_read(rdev, TAHVO_REG_IDSR) & TAHVO_STAT_VBUS;
 
-       tu->extcon.name = DRIVER_NAME;
-       tu->extcon.supported_cable = tahvo_cable;
-       tu->extcon.dev.parent = &pdev->dev;
+       tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable);
+       if (IS_ERR(tu->extcon)) {
+               dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
+               return -ENOMEM;
+       }
 
-       ret = extcon_dev_register(&tu->extcon);
+       ret = devm_extcon_dev_register(&pdev->dev, tu->extcon);
        if (ret) {
                dev_err(&pdev->dev, "could not register extcon device: %d\n",
                        ret);
@@ -377,9 +379,9 @@ static int tahvo_usb_probe(struct platform_device *pdev)
        }
 
        /* Set the initial cable state. */
-       extcon_set_cable_state(&tu->extcon, "USB-HOST",
+       extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST,
                               tu->tahvo_mode == TAHVO_MODE_HOST);
-       extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state);
+       extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state);
 
        /* Create OTG interface */
        tahvo_usb_power_off(tu);
@@ -396,7 +398,7 @@ static int tahvo_usb_probe(struct platform_device *pdev)
        if (ret < 0) {
                dev_err(&pdev->dev, "cannot register USB transceiver: %d\n",
                        ret);
-               goto err_extcon_unreg;
+               goto err_disable_clk;
        }
 
        dev_set_drvdata(&pdev->dev, tu);
@@ -424,8 +426,6 @@ err_free_irq:
        free_irq(tu->irq, tu);
 err_remove_phy:
        usb_remove_phy(&tu->phy);
-err_extcon_unreg:
-       extcon_dev_unregister(&tu->extcon);
 err_disable_clk:
        if (!IS_ERR(tu->ick))
                clk_disable(tu->ick);
@@ -440,7 +440,6 @@ static int tahvo_usb_remove(struct platform_device *pdev)
        sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group);
        free_irq(tu->irq, tu);
        usb_remove_phy(&tu->phy);
-       extcon_dev_unregister(&tu->extcon);
        if (!IS_ERR(tu->ick))
                clk_disable(tu->ick);
 
index e8bf40808b3989c59bd4bb61a32986b3e57f77a2..7b98e1d9194cb3571452c7143603f4e9d9966244 100644 (file)
@@ -388,7 +388,7 @@ static void usbhsc_hotplug(struct usbhs_priv *priv)
 
        if (enable && !mod) {
                if (priv->edev) {
-                       cable = extcon_get_cable_state(priv->edev, "USB-HOST");
+                       cable = extcon_get_cable_state_(priv->edev, EXTCON_USB_HOST);
                        if ((cable > 0 && id != USBHS_HOST) ||
                            (!cable && id != USBHS_GADGET)) {
                                dev_info(&pdev->dev,
index dc2aa326120252bcb1ed3eb45c3f31459d4f6497..de4f97d84a822ffd746b5550dcb68da08b581438 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 #include "common.h"
 
 /*
@@ -50,6 +51,8 @@ struct usbhsg_gpriv {
        int                      uep_size;
 
        struct usb_gadget_driver        *driver;
+       struct usb_phy          *transceiver;
+       bool                     vbus_active;
 
        u32     status;
 #define USBHSG_STATUS_STARTED          (1 << 0)
@@ -872,6 +875,27 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
        return 0;
 }
 
+/*
+ * VBUS provided by the PHY
+ */
+static int usbhsm_phy_get_vbus(struct platform_device *pdev)
+{
+       struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+       struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
+
+       return  gpriv->vbus_active;
+}
+
+static void usbhs_mod_phy_mode(struct usbhs_priv *priv)
+{
+       struct usbhs_mod_info *info = &priv->mod_info;
+
+       info->irq_vbus          = NULL;
+       priv->pfunc.get_vbus    = usbhsm_phy_get_vbus;
+
+       usbhs_irq_callback_update(priv, NULL);
+}
+
 /*
  *
  *             linux usb function
@@ -882,12 +906,28 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,
 {
        struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
        struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+       struct device *dev = usbhs_priv_to_dev(priv);
+       int ret;
 
        if (!driver             ||
            !driver->setup      ||
            driver->max_speed < USB_SPEED_FULL)
                return -EINVAL;
 
+       /* connect to bus through transceiver */
+       if (!IS_ERR_OR_NULL(gpriv->transceiver)) {
+               ret = otg_set_peripheral(gpriv->transceiver->otg,
+                                       &gpriv->gadget);
+               if (ret) {
+                       dev_err(dev, "%s: can't bind to transceiver\n",
+                               gpriv->gadget.name);
+                       return ret;
+               }
+
+               /* get vbus using phy versions */
+               usbhs_mod_phy_mode(priv);
+       }
+
        /* first hook up the driver ... */
        gpriv->driver = driver;
 
@@ -900,6 +940,10 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget)
        struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 
        usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
+
+       if (!IS_ERR_OR_NULL(gpriv->transceiver))
+               otg_set_peripheral(gpriv->transceiver->otg, NULL);
+
        gpriv->driver = NULL;
 
        return 0;
@@ -947,12 +991,26 @@ static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
        return 0;
 }
 
+static int usbhsg_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+       struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+       struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+       struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+
+       gpriv->vbus_active = !!is_active;
+
+       renesas_usbhs_call_notify_hotplug(pdev);
+
+       return 0;
+}
+
 static const struct usb_gadget_ops usbhsg_gadget_ops = {
        .get_frame              = usbhsg_get_frame,
        .set_selfpowered        = usbhsg_set_selfpowered,
        .udc_start              = usbhsg_gadget_start,
        .udc_stop               = usbhsg_gadget_stop,
        .pullup                 = usbhsg_pullup,
+       .vbus_session           = usbhsg_vbus_session,
 };
 
 static int usbhsg_start(struct usbhs_priv *priv)
@@ -994,6 +1052,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
                goto usbhs_mod_gadget_probe_err_gpriv;
        }
 
+       gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
+       dev_info(dev, "%stransceiver found\n",
+                gpriv->transceiver ? "" : "no ");
+
        /*
         * CAUTION
         *
@@ -1041,12 +1103,18 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
                if (usbhsg_is_dcp(uep)) {
                        gpriv->gadget.ep0 = &uep->ep;
                        usb_ep_set_maxpacket_limit(&uep->ep, 64);
+                       uep->ep.caps.type_control = true;
                }
                /* init normal pipe */
                else {
                        usb_ep_set_maxpacket_limit(&uep->ep, 512);
+                       uep->ep.caps.type_iso = true;
+                       uep->ep.caps.type_bulk = true;
+                       uep->ep.caps.type_int = true;
                        list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list);
                }
+               uep->ep.caps.dir_in = true;
+               uep->ep.caps.dir_out = true;
        }
 
        ret = usb_add_gadget_udc(dev, &gpriv->gadget);
index 4c8b3b82103d6318ea1d46250ad708bb3f722260..a5a0376bbd48c2596b908aa0409befb1136bf128 100644 (file)
@@ -605,6 +605,10 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) },
        /*
         * ELV devices:
         */
index 792e054126de51402711814f5962945f7742e188..67c6d446973092ddf98dd703152b7cd0d8dec24c 100644 (file)
  */
 #define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */
 
+/*
+ * CustomWare / ShipModul NMEA multiplexers product ids (FTDI_VID)
+ */
+#define FTDI_CUSTOMWARE_MINIPLEX_PID   0xfd48  /* MiniPlex first generation NMEA Multiplexer */
+#define FTDI_CUSTOMWARE_MINIPLEX2_PID  0xfd49  /* MiniPlex-USB and MiniPlex-2 series */
+#define FTDI_CUSTOMWARE_MINIPLEX2WI_PID        0xfd4a  /* MiniPlex-2Wi */
+#define FTDI_CUSTOMWARE_MINIPLEX3_PID  0xfd4b  /* MiniPlex-3 series */
+
 
 /********************************/
 /** third-party VID/PID combos **/
 #define FTDI_CTI_NANO_PID      0xF60B
 
 /*
- * ZeitControl cardsystems GmbH rfid-readers http://zeitconrol.de
+ * ZeitControl cardsystems GmbH rfid-readers http://zeitcontrol.de
  */
 /* TagTracer MIFARE*/
 #define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID   0xF7C0
index ddbb8fe1046d6868476cb0613068cca0cae30a15..0ac1b10be1f73a6d28a825a85dd9e468c9f2a48c 100644 (file)
@@ -71,6 +71,25 @@ struct product_info {
        __u8    hardware_type;          /* Type of hardware */
 } __attribute__((packed));
 
+/*
+ * Edgeport firmware header
+ *
+ * "build_number" has been set to 0 in all three of the images I have
+ * seen, and Digi Tech Support suggests that it is safe to ignore it.
+ *
+ * "length" is the number of bytes of actual data following the header.
+ *
+ * "checksum" is the low order byte resulting from adding the values of
+ * all the data bytes.
+ */
+struct edgeport_fw_hdr {
+       u8 major_version;
+       u8 minor_version;
+       __le16 build_number;
+       __le16 length;
+       u8 checksum;
+} __packed;
+
 struct edgeport_port {
        __u16 uart_base;
        __u16 dma_address;
@@ -101,6 +120,9 @@ struct edgeport_serial {
        struct mutex es_lock;
        int num_ports_open;
        struct usb_serial *serial;
+       struct delayed_work heartbeat_work;
+       int fw_version;
+       bool use_heartbeat;
 };
 
 
@@ -187,10 +209,6 @@ static const struct usb_device_id id_table_combined[] = {
 
 MODULE_DEVICE_TABLE(usb, id_table_combined);
 
-static unsigned char OperationalMajorVersion;
-static unsigned char OperationalMinorVersion;
-static unsigned short OperationalBuildNumber;
-
 static int closing_wait = EDGE_CLOSING_WAIT;
 static bool ignore_cpu_rev;
 static int default_uart_mode;          /* RS232 */
@@ -209,6 +227,26 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
 static int edge_create_sysfs_attrs(struct usb_serial_port *port);
 static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
 
+/*
+ * Some release of Edgeport firmware "down3.bin" after version 4.80
+ * introduced code to automatically disconnect idle devices on some
+ * Edgeport models after periods of inactivity, typically ~60 seconds.
+ * This occurs without regard to whether ports on the device are open
+ * or not.  Digi International Tech Support suggested:
+ *
+ * 1.  Adding driver "heartbeat" code to reset the firmware timer by
+ *     requesting a descriptor record every 15 seconds, which should be
+ *     effective with newer firmware versions that require it, and benign
+ *     with older versions that do not. In practice 40 seconds seems often
+ *     enough.
+ * 2.  The heartbeat code is currently required only on Edgeport/416 models.
+ */
+#define FW_HEARTBEAT_VERSION_CUTOFF ((4 << 8) + 80)
+#define FW_HEARTBEAT_SECS 40
+
+/* Timeouts in msecs: firmware downloads take longer */
+#define TI_VSEND_TIMEOUT_DEFAULT 1000
+#define TI_VSEND_TIMEOUT_FW_DOWNLOAD 10000
 
 static int ti_vread_sync(struct usb_device *dev, __u8 request,
                                __u16 value, __u16 index, u8 *data, int size)
@@ -228,14 +266,14 @@ static int ti_vread_sync(struct usb_device *dev, __u8 request,
        return 0;
 }
 
-static int ti_vsend_sync(struct usb_device *dev, __u8 request,
-                               __u16 value, __u16 index, u8 *data, int size)
+static int ti_vsend_sync(struct usb_device *dev, u8 request, u16 value,
+               u16 index, u8 *data, int size, int timeout)
 {
        int status;
 
        status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
                        (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
-                       value, index, data, size, 1000);
+                       value, index, data, size, timeout);
        if (status < 0)
                return status;
        if (status != size) {
@@ -250,7 +288,8 @@ static int send_cmd(struct usb_device *dev, __u8 command,
                                __u8 moduleid, __u16 value, u8 *data,
                                int size)
 {
-       return ti_vsend_sync(dev, command, value, moduleid, data, size);
+       return ti_vsend_sync(dev, command, value, moduleid, data, size,
+                       TI_VSEND_TIMEOUT_DEFAULT);
 }
 
 /* clear tx/rx buffers and fifo in TI UMP */
@@ -378,9 +417,9 @@ static int write_boot_mem(struct edgeport_serial *serial,
        }
 
        for (i = 0; i < length; ++i) {
-               status = ti_vsend_sync(serial->serial->dev,
-                               UMPC_MEMORY_WRITE, buffer[i],
-                               (__u16)(i + start_address), NULL, 0);
+               status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
+                               buffer[i], (u16)(i + start_address), NULL,
+                               0, TI_VSEND_TIMEOUT_DEFAULT);
                if (status)
                        return status;
        }
@@ -421,10 +460,9 @@ static int write_i2c_mem(struct edgeport_serial *serial,
         *       regardless of host byte order.
         */
        be_start_address = swab16((u16)start_address);
-       status = ti_vsend_sync(serial->serial->dev,
-                               UMPC_MEMORY_WRITE, (__u16)address_type,
-                               be_start_address,
-                               buffer, write_length);
+       status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
+                               (u16)address_type, be_start_address,
+                               buffer, write_length, TI_VSEND_TIMEOUT_DEFAULT);
        if (status) {
                dev_dbg(dev, "%s - ERROR %d\n", __func__, status);
                return status;
@@ -454,9 +492,8 @@ static int write_i2c_mem(struct edgeport_serial *serial,
                 */
                be_start_address = swab16((u16)start_address);
                status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
-                               (__u16)address_type,
-                               be_start_address,
-                               buffer, write_length);
+                               (u16)address_type, be_start_address, buffer,
+                               write_length, TI_VSEND_TIMEOUT_DEFAULT);
                if (status) {
                        dev_err(dev, "%s - ERROR %d\n", __func__, status);
                        return status;
@@ -748,18 +785,17 @@ exit:
 }
 
 /* Build firmware header used for firmware update */
-static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
+static int build_i2c_fw_hdr(u8 *header, struct device *dev,
+               const struct firmware *fw)
 {
        __u8 *buffer;
        int buffer_size;
        int i;
-       int err;
        __u8 cs = 0;
        struct ti_i2c_desc *i2c_header;
        struct ti_i2c_image_header *img_header;
        struct ti_i2c_firmware_rec *firmware_rec;
-       const struct firmware *fw;
-       const char *fw_name = "edgeport/down3.bin";
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
 
        /* In order to update the I2C firmware we must change the type 2 record
         * to type 0xF2.  This will force the UMP to come up in Boot Mode.
@@ -782,24 +818,11 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
        // Set entire image of 0xffs
        memset(buffer, 0xff, buffer_size);
 
-       err = request_firmware(&fw, fw_name, dev);
-       if (err) {
-               dev_err(dev, "Failed to load image \"%s\" err %d\n",
-                       fw_name, err);
-               kfree(buffer);
-               return err;
-       }
-
-       /* Save Download Version Number */
-       OperationalMajorVersion = fw->data[0];
-       OperationalMinorVersion = fw->data[1];
-       OperationalBuildNumber = fw->data[2] | (fw->data[3] << 8);
-
        /* Copy version number into firmware record */
        firmware_rec = (struct ti_i2c_firmware_rec *)buffer;
 
-       firmware_rec->Ver_Major = OperationalMajorVersion;
-       firmware_rec->Ver_Minor = OperationalMinorVersion;
+       firmware_rec->Ver_Major = fw_hdr->major_version;
+       firmware_rec->Ver_Minor = fw_hdr->minor_version;
 
        /* Pointer to fw_down memory image */
        img_header = (struct ti_i2c_image_header *)&fw->data[4];
@@ -808,8 +831,6 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
                &fw->data[4 + sizeof(struct ti_i2c_image_header)],
                le16_to_cpu(img_header->Length));
 
-       release_firmware(fw);
-
        for (i=0; i < buffer_size; i++) {
                cs = (__u8)(cs + buffer[i]);
        }
@@ -823,8 +844,8 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
        i2c_header->Type        = I2C_DESC_TYPE_FIRMWARE_BLANK;
        i2c_header->Size        = cpu_to_le16(buffer_size);
        i2c_header->CheckSum    = cs;
-       firmware_rec->Ver_Major = OperationalMajorVersion;
-       firmware_rec->Ver_Minor = OperationalMinorVersion;
+       firmware_rec->Ver_Major = fw_hdr->major_version;
+       firmware_rec->Ver_Minor = fw_hdr->minor_version;
 
        return 0;
 }
@@ -925,13 +946,49 @@ static int ti_cpu_rev(struct edge_ti_manuf_descriptor *desc)
        return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev);
 }
 
+static int check_fw_sanity(struct edgeport_serial *serial,
+               const struct firmware *fw)
+{
+       u16 length_total;
+       u8 checksum = 0;
+       int pos;
+       struct device *dev = &serial->serial->interface->dev;
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+       if (fw->size < sizeof(struct edgeport_fw_hdr)) {
+               dev_err(dev, "incomplete fw header\n");
+               return -EINVAL;
+       }
+
+       length_total = le16_to_cpu(fw_hdr->length) +
+                       sizeof(struct edgeport_fw_hdr);
+
+       if (fw->size != length_total) {
+               dev_err(dev, "bad fw size (expected: %u, got: %zu)\n",
+                               length_total, fw->size);
+               return -EINVAL;
+       }
+
+       for (pos = sizeof(struct edgeport_fw_hdr); pos < fw->size; ++pos)
+               checksum += fw->data[pos];
+
+       if (checksum != fw_hdr->checksum) {
+               dev_err(dev, "bad fw checksum (expected: 0x%x, got: 0x%x)\n",
+                               fw_hdr->checksum, checksum);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * DownloadTIFirmware - Download run-time operating firmware to the TI5052
  *
  * This routine downloads the main operating code into the TI5052, using the
  * boot code already burned into E2PROM or ROM.
  */
-static int download_fw(struct edgeport_serial *serial)
+static int download_fw(struct edgeport_serial *serial,
+               const struct firmware *fw)
 {
        struct device *dev = &serial->serial->dev->dev;
        int status = 0;
@@ -940,6 +997,14 @@ static int download_fw(struct edgeport_serial *serial)
        struct usb_interface_descriptor *interface;
        int download_cur_ver;
        int download_new_ver;
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+       if (check_fw_sanity(serial, fw))
+               return -EINVAL;
+
+       /* If on-board version is newer, "fw_version" will be updated below. */
+       serial->fw_version = (fw_hdr->major_version << 8) +
+                       fw_hdr->minor_version;
 
        /* This routine is entered by both the BOOT mode and the Download mode
         * We can determine which code is running by the reading the config
@@ -1047,14 +1112,13 @@ static int download_fw(struct edgeport_serial *serial)
                           version in I2c */
                        download_cur_ver = (firmware_version->Ver_Major << 8) +
                                           (firmware_version->Ver_Minor);
-                       download_new_ver = (OperationalMajorVersion << 8) +
-                                          (OperationalMinorVersion);
+                       download_new_ver = (fw_hdr->major_version << 8) +
+                                          (fw_hdr->minor_version);
 
                        dev_dbg(dev, "%s - >> FW Versions Device %d.%d  Driver %d.%d\n",
                                __func__, firmware_version->Ver_Major,
                                firmware_version->Ver_Minor,
-                               OperationalMajorVersion,
-                               OperationalMinorVersion);
+                               fw_hdr->major_version, fw_hdr->minor_version);
 
                        /* Check if we have an old version in the I2C and
                           update if necessary */
@@ -1063,8 +1127,8 @@ static int download_fw(struct edgeport_serial *serial)
                                        __func__,
                                        firmware_version->Ver_Major,
                                        firmware_version->Ver_Minor,
-                                       OperationalMajorVersion,
-                                       OperationalMinorVersion);
+                                       fw_hdr->major_version,
+                                       fw_hdr->minor_version);
 
                                record = kmalloc(1, GFP_KERNEL);
                                if (!record) {
@@ -1129,7 +1193,8 @@ static int download_fw(struct edgeport_serial *serial)
                                /* Reset UMP -- Back to BOOT MODE */
                                status = ti_vsend_sync(serial->serial->dev,
                                                UMPC_HARDWARE_RESET,
-                                               0, 0, NULL, 0);
+                                               0, 0, NULL, 0,
+                                               TI_VSEND_TIMEOUT_DEFAULT);
 
                                dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
 
@@ -1139,6 +1204,9 @@ static int download_fw(struct edgeport_serial *serial)
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return -ENODEV;
+                       } else {
+                               /* Same or newer fw version is already loaded */
+                               serial->fw_version = download_cur_ver;
                        }
                        kfree(firmware_version);
                }
@@ -1177,7 +1245,7 @@ static int download_fw(struct edgeport_serial *serial)
                         * UMP Ram to I2C and the firmware will update the
                         * record type from 0xf2 to 0x02.
                         */
-                       status = build_i2c_fw_hdr(header, dev);
+                       status = build_i2c_fw_hdr(header, dev, fw);
                        if (status) {
                                kfree(vheader);
                                kfree(header);
@@ -1229,7 +1297,9 @@ static int download_fw(struct edgeport_serial *serial)
 
                        /* Tell firmware to copy download image into I2C */
                        status = ti_vsend_sync(serial->serial->dev,
-                                       UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0);
+                                       UMPC_COPY_DNLD_TO_I2C,
+                                       0, 0, NULL, 0,
+                                       TI_VSEND_TIMEOUT_FW_DOWNLOAD);
 
                        dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status);
                        if (status) {
@@ -1278,9 +1348,6 @@ static int download_fw(struct edgeport_serial *serial)
                __u8 cs = 0;
                __u8 *buffer;
                int buffer_size;
-               int err;
-               const struct firmware *fw;
-               const char *fw_name = "edgeport/down3.bin";
 
                /* Validate Hardware version number
                 * Read Manufacturing Descriptor from TI Based Edgeport
@@ -1328,16 +1395,7 @@ static int download_fw(struct edgeport_serial *serial)
 
                /* Initialize the buffer to 0xff (pad the buffer) */
                memset(buffer, 0xff, buffer_size);
-
-               err = request_firmware(&fw, fw_name, dev);
-               if (err) {
-                       dev_err(dev, "Failed to load image \"%s\" err %d\n",
-                               fw_name, err);
-                       kfree(buffer);
-                       return err;
-               }
                memcpy(buffer, &fw->data[4], fw->size - 4);
-               release_firmware(fw);
 
                for (i = sizeof(struct ti_i2c_image_header);
                                i < buffer_size; i++) {
@@ -1352,7 +1410,9 @@ static int download_fw(struct edgeport_serial *serial)
                header->CheckSum = cs;
 
                /* Download the operational code  */
-               dev_dbg(dev, "%s - Downloading operational code image (TI UMP)\n", __func__);
+               dev_dbg(dev, "%s - Downloading operational code image version %d.%d (TI UMP)\n",
+                               __func__,
+                               fw_hdr->major_version, fw_hdr->minor_version);
                status = download_code(serial, buffer, buffer_size);
 
                kfree(buffer);
@@ -2373,10 +2433,44 @@ static void edge_break(struct tty_struct *tty, int break_state)
                        __func__, status);
 }
 
+static void edge_heartbeat_schedule(struct edgeport_serial *edge_serial)
+{
+       if (!edge_serial->use_heartbeat)
+               return;
+
+       schedule_delayed_work(&edge_serial->heartbeat_work,
+                       FW_HEARTBEAT_SECS * HZ);
+}
+
+static void edge_heartbeat_work(struct work_struct *work)
+{
+       struct edgeport_serial *serial;
+       struct ti_i2c_desc *rom_desc;
+
+       serial = container_of(work, struct edgeport_serial,
+                       heartbeat_work.work);
+
+       rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
+
+       /* Descriptor address request is enough to reset the firmware timer */
+       if (!rom_desc || !get_descriptor_addr(serial, I2C_DESC_TYPE_ION,
+                       rom_desc)) {
+               dev_err(&serial->serial->interface->dev,
+                               "%s - Incomplete heartbeat\n", __func__);
+       }
+       kfree(rom_desc);
+
+       edge_heartbeat_schedule(serial);
+}
+
 static int edge_startup(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial;
        int status;
+       const struct firmware *fw;
+       const char *fw_name = "edgeport/down3.bin";
+       struct device *dev = &serial->interface->dev;
+       u16 product_id;
 
        /* create our private serial structure */
        edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
@@ -2387,12 +2481,35 @@ static int edge_startup(struct usb_serial *serial)
        edge_serial->serial = serial;
        usb_set_serial_data(serial, edge_serial);
 
-       status = download_fw(edge_serial);
+       status = request_firmware(&fw, fw_name, dev);
        if (status) {
+               dev_err(dev, "Failed to load image \"%s\" err %d\n",
+                               fw_name, status);
                kfree(edge_serial);
                return status;
        }
 
+       status = download_fw(edge_serial, fw);
+       release_firmware(fw);
+       if (status) {
+               kfree(edge_serial);
+               return status;
+       }
+
+       product_id = le16_to_cpu(
+                       edge_serial->serial->dev->descriptor.idProduct);
+
+       /* Currently only the EP/416 models require heartbeat support */
+       if (edge_serial->fw_version > FW_HEARTBEAT_VERSION_CUTOFF) {
+               if (product_id == ION_DEVICE_ID_TI_EDGEPORT_416 ||
+                       product_id == ION_DEVICE_ID_TI_EDGEPORT_416B) {
+                       edge_serial->use_heartbeat = true;
+               }
+       }
+
+       INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
+       edge_heartbeat_schedule(edge_serial);
+
        return 0;
 }
 
@@ -2402,7 +2519,10 @@ static void edge_disconnect(struct usb_serial *serial)
 
 static void edge_release(struct usb_serial *serial)
 {
-       kfree(usb_get_serial_data(serial));
+       struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+       cancel_delayed_work_sync(&edge_serial->heartbeat_work);
+       kfree(edge_serial);
 }
 
 static int edge_port_probe(struct usb_serial_port *port)
@@ -2506,6 +2626,25 @@ static int edge_remove_sysfs_attrs(struct usb_serial_port *port)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int edge_suspend(struct usb_serial *serial, pm_message_t message)
+{
+       struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+       cancel_delayed_work_sync(&edge_serial->heartbeat_work);
+
+       return 0;
+}
+
+static int edge_resume(struct usb_serial *serial)
+{
+       struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+       edge_heartbeat_schedule(edge_serial);
+
+       return 0;
+}
+#endif
 
 static struct usb_serial_driver edgeport_1port_device = {
        .driver = {
@@ -2538,6 +2677,10 @@ static struct usb_serial_driver edgeport_1port_device = {
        .read_int_callback      = edge_interrupt_callback,
        .read_bulk_callback     = edge_bulk_in_callback,
        .write_bulk_callback    = edge_bulk_out_callback,
+#ifdef CONFIG_PM
+       .suspend                = edge_suspend,
+       .resume                 = edge_resume,
+#endif
 };
 
 static struct usb_serial_driver edgeport_2port_device = {
@@ -2571,6 +2714,10 @@ static struct usb_serial_driver edgeport_2port_device = {
        .read_int_callback      = edge_interrupt_callback,
        .read_bulk_callback     = edge_bulk_in_callback,
        .write_bulk_callback    = edge_bulk_out_callback,
+#ifdef CONFIG_PM
+       .suspend                = edge_suspend,
+       .resume                 = edge_resume,
+#endif
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 460a40669967855cfeea7c6cc911064822c6882a..31a8b47f1ac65f325ce285aa80bce66bf74298d7 100644 (file)
@@ -1137,13 +1137,9 @@ static int mxuport_port_probe(struct usb_serial_port *port)
                return err;
 
        /* Set interface (RS-232) */
-       err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE,
-                                   MX_INT_RS232,
-                                   port->port_number);
-       if (err)
-               return err;
-
-       return 0;
+       return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE,
+                                    MX_INT_RS232,
+                                    port->port_number);
 }
 
 static int mxuport_alloc_write_urb(struct usb_serial *serial,
index 876423b8892c96f80930fa7a103f36370e519dfe..6d1941a2396a7c76dc8a9a4d905bb1850c63282d 100644 (file)
@@ -1941,7 +1941,7 @@ static void option_instat_callback(struct urb *urb)
        } else if (status == -ENOENT || status == -ESHUTDOWN) {
                dev_dbg(dev, "%s: urb stopped: %d\n", __func__, status);
        } else
-               dev_err(dev, "%s: error %d\n", __func__, status);
+               dev_dbg(dev, "%s: error %d\n", __func__, status);
 
        /* Resubmit urb so we continue receiving IRQ data */
        if (status != -ESHUTDOWN && status != -ENOENT) {
index f5257af33ecfbc30bb0989fe03fea09af215639e..ae682e4eeaef575a23c90a8dda15407e862d42e1 100644 (file)
@@ -362,21 +362,38 @@ static speed_t pl2303_encode_baud_rate_direct(unsigned char buf[4],
 static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4],
                                                                speed_t baud)
 {
-       unsigned int tmp;
+       unsigned int baseline, mantissa, exponent;
 
        /*
         * Apparently the formula is:
-        * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
+        *   baudrate = 12M * 32 / (mantissa * 4^exponent)
+        * where
+        *   mantissa = buf[8:0]
+        *   exponent = buf[11:9]
         */
-       tmp = 12000000 * 32 / baud;
+       baseline = 12000000 * 32;
+       mantissa = baseline / baud;
+       if (mantissa == 0)
+               mantissa = 1;   /* Avoid dividing by zero if baud > 32*12M. */
+       exponent = 0;
+       while (mantissa >= 512) {
+               if (exponent < 7) {
+                       mantissa >>= 2; /* divide by 4 */
+                       exponent++;
+               } else {
+                       /* Exponent is maxed. Trim mantissa and leave. */
+                       mantissa = 511;
+                       break;
+               }
+       }
+
        buf[3] = 0x80;
        buf[2] = 0;
-       buf[1] = (tmp >= 256);
-       while (tmp >= 256) {
-               tmp >>= 2;
-               buf[1] <<= 1;
-       }
-       buf[0] = tmp;
+       buf[1] = exponent << 1 | mantissa >> 8;
+       buf[0] = mantissa & 0xff;
+
+       /* Calculate and return the exact baud rate. */
+       baud = (baseline / mantissa) >> (exponent << 1);
 
        return baud;
 }
index d156545728c2ab5b8bb81cf7537aa8a60805c08a..ebcec8cda85840d4d336f92b2558747f6efb2843 100644 (file)
@@ -139,6 +139,7 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x0AF0, 0x8120)},   /* Option GTM681W */
 
        /* non-Gobi Sierra Wireless devices */
+       {DEVICE_SWI(0x03f0, 0x4e1d)},   /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
        {DEVICE_SWI(0x0f3d, 0x68a2)},   /* Sierra Wireless MC7700 */
        {DEVICE_SWI(0x114f, 0x68a2)},   /* Sierra Wireless MC7750 */
        {DEVICE_SWI(0x1199, 0x68a2)},   /* Sierra Wireless MC7710 */
index 8fceec7298e007919f8585a93e9298d2256e6bb7..37f3ad15ed06a5f6c1cf9db54ca0beef801d523f 100644 (file)
@@ -60,17 +60,15 @@ static void symbol_int_callback(struct urb *urb)
 
        usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
 
+       /*
+        * Data from the device comes with a 1 byte header:
+        *
+        * <size of data> <data>...
+        */
        if (urb->actual_length > 1) {
-               data_length = urb->actual_length - 1;
-
-               /*
-                * Data from the device comes with a 1 byte header:
-                *
-                * <size of data>data...
-                *      This is real data to be sent to the tty layer
-                * we pretty much just ignore the size and send everything
-                * else to the tty layer.
-                */
+               data_length = data[0];
+               if (data_length > (urb->actual_length - 1))
+                       data_length = urb->actual_length - 1;
                tty_insert_flip_string(&port->port, &data[1], data_length);
                tty_flip_buffer_push(&port->port);
        } else {
@@ -94,7 +92,7 @@ exit:
 
 static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-       struct symbol_private *priv = usb_get_serial_data(port->serial);
+       struct symbol_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        int result = 0;
 
@@ -120,7 +118,7 @@ static void symbol_close(struct usb_serial_port *port)
 static void symbol_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct symbol_private *priv = usb_get_serial_data(port->serial);
+       struct symbol_private *priv = usb_get_serial_port_data(port);
 
        spin_lock_irq(&priv->lock);
        priv->throttled = true;
@@ -130,7 +128,7 @@ static void symbol_throttle(struct tty_struct *tty)
 static void symbol_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct symbol_private *priv = usb_get_serial_data(port->serial);
+       struct symbol_private *priv = usb_get_serial_port_data(port);
        int result;
        bool was_throttled;
 
index 2f805cb386a5ae429ce9e0676a3311268ab273a6..825305cb71d9dda11ce5a429feaed075a959a508 100644 (file)
@@ -282,7 +282,7 @@ static void usb_wwan_indat_callback(struct urb *urb)
        /* Resubmit urb so we continue receiving */
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (err) {
-               if (err != -EPERM) {
+               if (err != -EPERM && err != -ENODEV) {
                        dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
                                __func__, err);
                        /* busy also in error unless we are killed */
index 540add24a12ffa428bda0e7a0db07650ecd29eab..5e67f63b2e462ffc68b5acc1a9f8557828e44489 100644 (file)
@@ -1111,7 +1111,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
         * command phase and the data phase.  Some devices need a little
         * more than that, probably because of clock rate inaccuracies. */
        if (unlikely(us->fflags & US_FL_GO_SLOW))
-               udelay(125);
+               usleep_range(125, 150);
 
        if (transfer_length) {
                unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
index dfcc02c936485199c44d1545bf95b73bfe23ff97..f114a9dbb48f0ea59718da7fe59a02180da07821 100644 (file)
@@ -1573,9 +1573,9 @@ static int __init vhost_scsi_register(void)
        return misc_register(&vhost_scsi_misc);
 }
 
-static int vhost_scsi_deregister(void)
+static void vhost_scsi_deregister(void)
 {
-       return misc_deregister(&vhost_scsi_misc);
+       misc_deregister(&vhost_scsi_misc);
 }
 
 static char *vhost_scsi_dump_proto_id(struct vhost_scsi_tport *tport)
index f888561568d91735a3a765a772630e8b2be0a54a..811acfc6048e7f3f99b9c28c9b70a2d9a6e2a936 100644 (file)
@@ -2475,3 +2475,17 @@ config FB_SSD1307
        help
          This driver implements support for the Solomon SSD1307
          OLED controller over I2C.
+
+config FB_SM712
+       tristate "Silicon Motion SM712 framebuffer support"
+       depends on FB && PCI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         Frame buffer driver for the Silicon Motion SM710, SM712, SM721
+         and SM722 chips.
+
+         This driver is also available as a module. The module will be
+         called sm712fb. If you want to compile it as a module, say M
+         here and read <file:Documentation/kbuild/modules.txt>.
index cecea5063a802afbf3d211dce5e831d3d31e8cd5..50ed1b4fc2bf33b3d82b10d211616765839bc818 100644 (file)
@@ -131,6 +131,7 @@ obj-$(CONFIG_FB_JZ4740)               += jz4740_fb.o
 obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
 obj-$(CONFIG_FB_HYPERV)                  += hyperv_fb.o
 obj-$(CONFIG_FB_OPENCORES)       += ocfb.o
+obj-$(CONFIG_FB_SM712)           += sm712fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
index 807ee22ef2292204eb85dc6e3bce75d0f9fbe74c..e2451bdb4525d50fbd3de1aab743c51f7b05cef5 100644 (file)
@@ -213,7 +213,7 @@ struct synthvid_msg {
 
 struct hvfb_par {
        struct fb_info *info;
-       struct resource mem;
+       struct resource *mem;
        bool fb_ready; /* fb device is ready */
        struct completion wait;
        u32 synthvid_version;
@@ -677,26 +677,18 @@ static void hvfb_get_option(struct fb_info *info)
 
 
 /* Get framebuffer memory from Hyper-V video pci space */
-static int hvfb_getmem(struct fb_info *info)
+static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
 {
        struct hvfb_par *par = info->par;
        struct pci_dev *pdev  = NULL;
        void __iomem *fb_virt;
        int gen2vm = efi_enabled(EFI_BOOT);
+       resource_size_t pot_start, pot_end;
        int ret;
 
-       par->mem.name = KBUILD_MODNAME;
-       par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
        if (gen2vm) {
-               ret = allocate_resource(&hyperv_mmio, &par->mem,
-                                       screen_fb_size,
-                                       0, -1,
-                                       screen_fb_size,
-                                       NULL, NULL);
-               if (ret != 0) {
-                       pr_err("Unable to allocate framebuffer memory\n");
-                       return -ENODEV;
-               }
+               pot_start = 0;
+               pot_end = -1;
        } else {
                pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
                              PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
@@ -709,16 +701,18 @@ static int hvfb_getmem(struct fb_info *info)
                    pci_resource_len(pdev, 0) < screen_fb_size)
                        goto err1;
 
-               par->mem.end = pci_resource_end(pdev, 0);
-               par->mem.start = par->mem.end - screen_fb_size + 1;
-               ret = request_resource(&pdev->resource[0], &par->mem);
-               if (ret != 0) {
-                       pr_err("Unable to request framebuffer memory\n");
-                       goto err1;
-               }
+               pot_end = pci_resource_end(pdev, 0);
+               pot_start = pot_end - screen_fb_size + 1;
+       }
+
+       ret = vmbus_allocate_mmio(&par->mem, hdev, pot_start, pot_end,
+                                 screen_fb_size, 0x100000, true);
+       if (ret != 0) {
+               pr_err("Unable to allocate framebuffer memory\n");
+               goto err1;
        }
 
-       fb_virt = ioremap(par->mem.start, screen_fb_size);
+       fb_virt = ioremap(par->mem->start, screen_fb_size);
        if (!fb_virt)
                goto err2;
 
@@ -736,7 +730,7 @@ static int hvfb_getmem(struct fb_info *info)
                info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
        }
 
-       info->fix.smem_start = par->mem.start;
+       info->fix.smem_start = par->mem->start;
        info->fix.smem_len = screen_fb_size;
        info->screen_base = fb_virt;
        info->screen_size = screen_fb_size;
@@ -749,7 +743,8 @@ static int hvfb_getmem(struct fb_info *info)
 err3:
        iounmap(fb_virt);
 err2:
-       release_resource(&par->mem);
+       release_mem_region(par->mem->start, screen_fb_size);
+       par->mem = NULL;
 err1:
        if (!gen2vm)
                pci_dev_put(pdev);
@@ -763,7 +758,8 @@ static void hvfb_putmem(struct fb_info *info)
        struct hvfb_par *par = info->par;
 
        iounmap(info->screen_base);
-       release_resource(&par->mem);
+       release_mem_region(par->mem->start, screen_fb_size);
+       par->mem = NULL;
 }
 
 
@@ -794,7 +790,7 @@ static int hvfb_probe(struct hv_device *hdev,
                goto error1;
        }
 
-       ret = hvfb_getmem(info);
+       ret = hvfb_getmem(hdev, info);
        if (ret) {
                pr_err("No memory for framebuffer\n");
                goto error2;
index 1085c0432158c02038aba6f961ea7e300f7f950b..52c5c7e63b525786754689ce0e2751d9790ae0ff 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/platform_data/simplefb.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_platform.h>
 
similarity index 81%
rename from drivers/staging/sm7xxfb/sm7xx.h
rename to drivers/video/fbdev/sm712.h
index 4bed0946c1b1fab453254b898cecc0f2aa5b5c73..aad1cc4be34a9069ca5312bc075d8440aa46b797 100644 (file)
@@ -13,8 +13,6 @@
  *  more details.
  */
 
-#define NR_PALETTE        256
-
 #define FB_ACCEL_SMI_LYNX 88
 
 #define SCREEN_X_RES      1024
 
 extern void __iomem *smtc_regbaseaddress;
 #define smtc_mmiowb(dat, reg)  writeb(dat, smtc_regbaseaddress + reg)
-#define smtc_mmioww(dat, reg)  writew(dat, smtc_regbaseaddress + reg)
-#define smtc_mmiowl(dat, reg)  writel(dat, smtc_regbaseaddress + reg)
 
 #define smtc_mmiorb(reg)       readb(smtc_regbaseaddress + reg)
-#define smtc_mmiorw(reg)       readw(smtc_regbaseaddress + reg)
-#define smtc_mmiorl(reg)       readl(smtc_regbaseaddress + reg)
 
 #define SIZE_SR00_SR04      (0x04 - 0x00 + 1)
 #define SIZE_SR10_SR24      (0x24 - 0x10 + 1)
@@ -48,8 +42,6 @@ extern void __iomem *smtc_regbaseaddress;
 #define SIZE_CR00_CR18      (0x18 - 0x00 + 1)
 #define SIZE_CR30_CR4D      (0x4D - 0x30 + 1)
 #define SIZE_CR90_CRA7      (0xA7 - 0x90 + 1)
-#define SIZE_VPR               (0x6C + 1)
-#define SIZE_DPR               (0x44 + 1)
 
 static inline void smtc_crtcw(int reg, int val)
 {
@@ -57,24 +49,12 @@ static inline void smtc_crtcw(int reg, int val)
        smtc_mmiowb(val, 0x3d5);
 }
 
-static inline unsigned int smtc_crtcr(int reg)
-{
-       smtc_mmiowb(reg, 0x3d4);
-       return smtc_mmiorb(0x3d5);
-}
-
 static inline void smtc_grphw(int reg, int val)
 {
        smtc_mmiowb(reg, 0x3ce);
        smtc_mmiowb(val, 0x3cf);
 }
 
-static inline unsigned int smtc_grphr(int reg)
-{
-       smtc_mmiowb(reg, 0x3ce);
-       return smtc_mmiorb(0x3cf);
-}
-
 static inline void smtc_attrw(int reg, int val)
 {
        smtc_mmiorb(0x3da);
@@ -115,3 +95,22 @@ struct modeinit {
        unsigned char init_cr30_cr4d[SIZE_CR30_CR4D];
        unsigned char init_cr90_cra7[SIZE_CR90_CRA7];
 };
+
+#ifdef __BIG_ENDIAN
+#define pal_rgb(r, g, b, val)  (((r & 0xf800) >> 8) | \
+                               ((g & 0xe000) >> 13) | \
+                               ((g & 0x1c00) << 3) | \
+                               ((b & 0xf800) >> 3))
+#define big_addr               0x800000
+#define mmio_addr              0x00800000
+#define seqw17()               smtc_seqw(0x17, 0x30)
+#define big_pixel_depth(p, d)  {if (p == 24) {p = 32; d = 32; } }
+#define big_swap(p)            ((p & 0xff00ff00 >> 8) | (p & 0x00ff00ff << 8))
+#else
+#define pal_rgb(r, g, b, val)  val
+#define big_addr               0
+#define mmio_addr              0x00c00000
+#define seqw17()               do { } while (0)
+#define big_pixel_depth(p, d)  do { } while (0)
+#define big_swap(p)            p
+#endif
similarity index 97%
rename from drivers/staging/sm7xxfb/sm7xxfb.c
rename to drivers/video/fbdev/sm712fb.c
index 2ff4fe73d148e194178cd47cbf74256cf6fd8eb5..629bfa2d2f516bcdf52670cbfe1bb525885ce730 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/pm.h>
 #endif
 
-#include "sm7xx.h"
+#include "sm712.h"
 
 /*
 * Private structure
@@ -923,25 +923,14 @@ static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
                        val = chan_to_field(red, &sfb->fb->var.red);
                        val |= chan_to_field(green, &sfb->fb->var.green);
                        val |= chan_to_field(blue, &sfb->fb->var.blue);
-#ifdef __BIG_ENDIAN
-                       pal[regno] = ((red & 0xf800) >> 8) |
-                                    ((green & 0xe000) >> 13) |
-                                    ((green & 0x1c00) << 3) |
-                                    ((blue & 0xf800) >> 3);
-#else
-                       pal[regno] = val;
-#endif
+                       pal[regno] = pal_rgb(red, green, blue, val);
                } else {
                        u32 *pal = sfb->fb->pseudo_palette;
 
                        val = chan_to_field(red, &sfb->fb->var.red);
                        val |= chan_to_field(green, &sfb->fb->var.green);
                        val |= chan_to_field(blue, &sfb->fb->var.blue);
-#ifdef __BIG_ENDIAN
-                       val = (val & 0xff00ff00 >> 8) |
-                             (val & 0x00ff00ff << 8);
-#endif
-                       pal[regno] = val;
+                       pal[regno] = big_swap(val);
                }
                break;
 
@@ -957,7 +946,6 @@ static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
        return 0;
 }
 
-#ifdef __BIG_ENDIAN
 static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
                           size_t count, loff_t *ppos)
 {
@@ -1002,8 +990,7 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
                dst = buffer;
                for (i = c >> 2; i--;) {
                        *dst = fb_readl(src++);
-                       *dst = (*dst & 0xff00ff00 >> 8) |
-                              (*dst & 0x00ff00ff << 8);
+                       *dst = big_swap(*dst);
                        dst++;
                }
                if (c & 3) {
@@ -1091,8 +1078,7 @@ static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
                }
 
                for (i = c >> 2; i--;) {
-                       fb_writel((*src & 0xff00ff00 >> 8) |
-                                 (*src & 0x00ff00ff << 8), dst++);
+                       fb_writel(big_swap(*src), dst++);
                        src++;
                }
                if (c & 3) {
@@ -1120,7 +1106,6 @@ static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
 
        return (cnt) ? cnt : err;
 }
-#endif /* ! __BIG_ENDIAN */
 
 static void sm7xx_set_timing(struct smtcfb_info *sfb)
 {
@@ -1316,10 +1301,8 @@ static struct fb_ops smtcfb_ops = {
        .fb_fillrect  = cfb_fillrect,
        .fb_imageblit = cfb_imageblit,
        .fb_copyarea  = cfb_copyarea,
-#ifdef __BIG_ENDIAN
        .fb_read      = smtcfb_read,
        .fb_write     = smtcfb_write,
-#endif
 };
 
 /*
@@ -1341,10 +1324,8 @@ static int smtc_map_smem(struct smtcfb_info *sfb,
 {
        sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
 
-#ifdef __BIG_ENDIAN
        if (sfb->fb->var.bits_per_pixel == 32)
-               sfb->fb->fix.smem_start += 0x800000;
-#endif
+               sfb->fb->fix.smem_start += big_addr;
 
        sfb->fb->fix.smem_len = smem_len;
 
@@ -1437,10 +1418,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
                sfb->fb->var.bits_per_pixel = SCREEN_BPP;
        }
 
-#ifdef __BIG_ENDIAN
-       if (sfb->fb->var.bits_per_pixel == 24)
-               sfb->fb->var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32);
-#endif
+       big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
        /* Map address and memory detection */
        mmio_base = pci_resource_start(pdev, 0);
        pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
@@ -1451,28 +1429,23 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
                sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
                sfb->fb->fix.mmio_len = 0x00400000;
                smem_size = SM712_VIDEOMEMORYSIZE;
-#ifdef __BIG_ENDIAN
-               sfb->lfb = ioremap(mmio_base, 0x00c00000);
-#else
-               sfb->lfb = ioremap(mmio_base, 0x00800000);
-#endif
+               sfb->lfb = ioremap(mmio_base, mmio_addr);
+               if (!sfb->lfb) {
+                       dev_err(&pdev->dev,
+                               "%s: unable to map memory mapped IO!\n",
+                               sfb->fb->fix.id);
+                       err = -ENOMEM;
+                       goto failed_fb;
+               }
+
                sfb->mmio = (smtc_regbaseaddress =
                    sfb->lfb + 0x00700000);
                sfb->dp_regs = sfb->lfb + 0x00408000;
                sfb->vp_regs = sfb->lfb + 0x0040c000;
-#ifdef __BIG_ENDIAN
                if (sfb->fb->var.bits_per_pixel == 32) {
-                       sfb->lfb += 0x800000;
+                       sfb->lfb += big_addr;
                        dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
                }
-#endif
-               if (!smtc_regbaseaddress) {
-                       dev_err(&pdev->dev,
-                               "%s: unable to map memory mapped IO!\n",
-                               sfb->fb->fix.id);
-                       err = -ENOMEM;
-                       goto failed_fb;
-               }
 
                /* set MCLK = 14.31818 * (0x16 / 0x2) */
                smtc_seqw(0x6a, 0x16);
@@ -1481,10 +1454,8 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
                /* enable PCI burst */
                smtc_seqw(0x17, 0x20);
                /* enable word swap */
-#ifdef __BIG_ENDIAN
                if (sfb->fb->var.bits_per_pixel == 32)
-                       smtc_seqw(0x17, 0x30);
-#endif
+                       seqw17();
                break;
        case 0x720:
                sfb->fb->fix.mmio_start = mmio_base;
@@ -1616,10 +1587,8 @@ static int smtcfb_pci_resume(struct device *device)
                smtc_seqw(0x62, 0x3e);
                /* enable PCI burst */
                smtc_seqw(0x17, 0x20);
-#ifdef __BIG_ENDIAN
                if (sfb->fb->var.bits_per_pixel == 32)
-                       smtc_seqw(0x17, 0x30);
-#endif
+                       seqw17();
                break;
        case 0x720:
                smtc_seqw(0x62, 0xff);
@@ -1659,14 +1628,12 @@ static struct pci_driver smtcfb_driver = {
 
 static int __init sm712fb_init(void)
 {
-#ifndef MODULE
        char *option = NULL;
 
        if (fb_get_options("sm712fb", &option))
                return -ENODEV;
        if (option && *option)
                mode_option = option;
-#endif
        sm7xx_vga_setup(mode_option);
 
        return pci_register_driver(&smtcfb_driver);
index a674409edfb39a2788e4e45691167cb59966ebda..b05e8fefbabd98d379797b6dfc05744ad248a584 100644 (file)
@@ -97,7 +97,6 @@ MODULE_DEVICE_TABLE(i2c, ds2482_id);
 
 static struct i2c_driver ds2482_driver = {
        .driver = {
-               .owner  = THIS_MODULE,
                .name   = "ds2482",
        },
        .probe          = ds2482_probe,
index d8667b0212d7c28121bcc2339a381c5d1ceb8cff..684bc9d861cb592a16456be71a0fbb1b211d051f 100644 (file)
@@ -232,16 +232,4 @@ static void matrox_w1_remove(struct pci_dev *pdev)
        }
        kfree(dev);
 }
-
-static int __init matrox_w1_init(void)
-{
-       return pci_register_driver(&matrox_w1_pci_driver);
-}
-
-static void __exit matrox_w1_fini(void)
-{
-       pci_unregister_driver(&matrox_w1_pci_driver);
-}
-
-module_init(matrox_w1_init);
-module_exit(matrox_w1_fini);
+module_pci_driver(matrox_w1_pci_driver);
index 41cecb55766c049b600834d6ee021ef45f15332e..9ba1153465ae8a1ef051dca258875940feb77b74 100644 (file)
@@ -269,9 +269,8 @@ static int at91wdt_remove(struct platform_device *pdev)
        if (res)
                dev_warn(dev, "failed to unregister restart handler\n");
 
-       res = misc_deregister(&at91wdt_miscdev);
-       if (!res)
-               at91wdt_miscdev.parent = NULL;
+       misc_deregister(&at91wdt_miscdev);
+       at91wdt_miscdev.parent = NULL;
 
        return res;
 }
index b7ea39b455c86c730f895e1a63ad8d1ee172068f..1e41818a44bc828f88c9fba9829bebcd31819dba 100644 (file)
@@ -254,13 +254,10 @@ static int ks8695wdt_probe(struct platform_device *pdev)
 
 static int ks8695wdt_remove(struct platform_device *pdev)
 {
-       int res;
-
-       res = misc_deregister(&ks8695wdt_miscdev);
-       if (!res)
-               ks8695wdt_miscdev.parent = NULL;
+       misc_deregister(&ks8695wdt_miscdev);
+       ks8695wdt_miscdev.parent = NULL;
 
-       return res;
+       return 0;
 }
 
 static void ks8695wdt_shutdown(struct platform_device *pdev)
index 119beb7f6017ca1cd6e2abd8c18ad701433b36e1..4b541934b6c59e6702345e14ea90360ff67a694e 100644 (file)
@@ -428,7 +428,8 @@ static int ts72xx_wdt_probe(struct platform_device *pdev)
 
 static int ts72xx_wdt_remove(struct platform_device *pdev)
 {
-       return misc_deregister(&ts72xx_wdt_miscdev);
+       misc_deregister(&ts72xx_wdt_miscdev);
+       return 0;
 }
 
 static struct platform_driver ts72xx_wdt_driver = {
index 1495eccb161762f482db77121f5102eb1caf5ff9..96093ae369a5613938962b4970decda66c19d342 100644 (file)
@@ -452,12 +452,10 @@ static void xen_free_irq(unsigned irq)
        irq_free_desc(irq);
 }
 
-static void xen_evtchn_close(unsigned int port, unsigned int cpu)
+static void xen_evtchn_close(unsigned int port)
 {
        struct evtchn_close close;
 
-       xen_evtchn_op_close(port, cpu);
-
        close.port = port;
        if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
                BUG();
@@ -546,7 +544,7 @@ out:
 
 err:
        pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc);
-       xen_evtchn_close(evtchn, NR_CPUS);
+       xen_evtchn_close(evtchn);
        return 0;
 }
 
@@ -567,7 +565,7 @@ static void shutdown_pirq(struct irq_data *data)
                return;
 
        mask_evtchn(evtchn);
-       xen_evtchn_close(evtchn, cpu_from_evtchn(evtchn));
+       xen_evtchn_close(evtchn);
        xen_irq_info_cleanup(info);
 }
 
@@ -611,7 +609,7 @@ static void __unbind_from_irq(unsigned int irq)
        if (VALID_EVTCHN(evtchn)) {
                unsigned int cpu = cpu_from_irq(irq);
 
-               xen_evtchn_close(evtchn, cpu);
+               xen_evtchn_close(evtchn);
 
                switch (type_from_irq(irq)) {
                case IRQT_VIRQ:
index 6df8aac966b909b2fd5db9d9e4950c448f1621c9..ed673e1acd6159a3ca34dc10238fef8936e43249 100644 (file)
@@ -255,12 +255,6 @@ static void evtchn_fifo_unmask(unsigned port)
        }
 }
 
-static bool evtchn_fifo_is_linked(unsigned port)
-{
-       event_word_t *word = event_word_from_port(port);
-       return sync_test_bit(EVTCHN_FIFO_BIT(LINKED, word), BM(word));
-}
-
 static uint32_t clear_linked(volatile event_word_t *word)
 {
        event_word_t new, old, w;
@@ -287,8 +281,7 @@ static void handle_irq_for_port(unsigned port)
 
 static void consume_one_event(unsigned cpu,
                              struct evtchn_fifo_control_block *control_block,
-                             unsigned priority, unsigned long *ready,
-                             bool drop)
+                             unsigned priority, unsigned long *ready)
 {
        struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
        uint32_t head;
@@ -320,15 +313,13 @@ static void consume_one_event(unsigned cpu,
        if (head == 0)
                clear_bit(priority, ready);
 
-       if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) {
-               if (likely(!drop))
-                       handle_irq_for_port(port);
-       }
+       if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
+               handle_irq_for_port(port);
 
        q->head[priority] = head;
 }
 
-static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
+static void evtchn_fifo_handle_events(unsigned cpu)
 {
        struct evtchn_fifo_control_block *control_block;
        unsigned long ready;
@@ -340,16 +331,11 @@ static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
 
        while (ready) {
                q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
-               consume_one_event(cpu, control_block, q, &ready, drop);
+               consume_one_event(cpu, control_block, q, &ready);
                ready |= xchg(&control_block->ready, 0);
        }
 }
 
-static void evtchn_fifo_handle_events(unsigned cpu)
-{
-       __evtchn_fifo_handle_events(cpu, false);
-}
-
 static void evtchn_fifo_resume(void)
 {
        unsigned cpu;
@@ -385,26 +371,6 @@ static void evtchn_fifo_resume(void)
        event_array_pages = 0;
 }
 
-static void evtchn_fifo_close(unsigned port, unsigned int cpu)
-{
-       if (cpu == NR_CPUS)
-               return;
-
-       get_online_cpus();
-       if (cpu_online(cpu)) {
-               if (WARN_ON(irqs_disabled()))
-                       goto out;
-
-               while (evtchn_fifo_is_linked(port))
-                       cpu_relax();
-       } else {
-               __evtchn_fifo_handle_events(cpu, true);
-       }
-
-out:
-       put_online_cpus();
-}
-
 static const struct evtchn_ops evtchn_ops_fifo = {
        .max_channels      = evtchn_fifo_max_channels,
        .nr_channels       = evtchn_fifo_nr_channels,
@@ -418,7 +384,6 @@ static const struct evtchn_ops evtchn_ops_fifo = {
        .unmask            = evtchn_fifo_unmask,
        .handle_events     = evtchn_fifo_handle_events,
        .resume            = evtchn_fifo_resume,
-       .close             = evtchn_fifo_close,
 };
 
 static int evtchn_fifo_alloc_control_block(unsigned cpu)
index d18e12315ec0832899fea654dee742298842356a..50c2050a1e32026901217a10029b4b344054e389 100644 (file)
@@ -68,7 +68,6 @@ struct evtchn_ops {
        bool (*test_and_set_mask)(unsigned port);
        void (*mask)(unsigned port);
        void (*unmask)(unsigned port);
-       void (*close)(unsigned port, unsigned cpu);
 
        void (*handle_events)(unsigned cpu);
        void (*resume)(void);
@@ -146,12 +145,6 @@ static inline void xen_evtchn_resume(void)
                evtchn_ops->resume();
 }
 
-static inline void xen_evtchn_op_close(unsigned port, unsigned cpu)
-{
-       if (evtchn_ops->close)
-               return evtchn_ops->close(port, cpu);
-}
-
 void xen_evtchn_2l_init(void);
 int xen_evtchn_fifo_init(void);
 
index 9ad327238ba931243967455b5790916dc6b184f1..e30353575d5da11f75e8c927ba53945a23b73d76 100644 (file)
@@ -814,8 +814,10 @@ static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr)
 
        rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
                               addrs);
-       if (!rv)
+       if (!rv) {
                vunmap(vaddr);
+               free_xenballooned_pages(node->nr_handles, node->hvm.pages);
+       }
        else
                WARN(1, "Leaking %p, size %u page(s)\n", vaddr,
                     node->nr_handles);
index cd7ef34d2dce99987fe87f3040ba20038bb3f041..6bad63379a4ce23dc730605035f098db1d03ef00 100644 (file)
@@ -2163,8 +2163,7 @@ static int btrfs_interface_init(void)
 
 static void btrfs_interface_exit(void)
 {
-       if (misc_deregister(&btrfs_misc) < 0)
-               printk(KERN_INFO "BTRFS: misc_deregister failed for control device\n");
+       misc_deregister(&btrfs_misc);
 }
 
 static void btrfs_print_info(void)
index ea06a3d0364cc218d5dad4885023d1829f28f214..24b142569ca9b5beea55b5cf6224b8ad81e6a16c 100644 (file)
@@ -274,7 +274,7 @@ out2:
 }
 
 /**
- * unregister_chrdev_region() - return a range of device numbers
+ * unregister_chrdev_region() - unregister a range of device numbers
  * @from: the first in the range of numbers to unregister
  * @count: the number of device numbers to unregister
  *
index e0ab3a93eeff01b42ec4ffaeb48160bcd0fc9ad6..5532f097f6dac5fddbfde8030ba981fe417b6877 100644 (file)
@@ -509,7 +509,6 @@ int dlm_plock_init(void)
 
 void dlm_plock_exit(void)
 {
-       if (misc_deregister(&plock_dev_misc) < 0)
-               log_print("dlm_plock_exit: misc_deregister failed");
+       misc_deregister(&plock_dev_misc);
 }
 
index fb85f32e9eca66f238d3cfb97a82781be626d0b2..75ecc0d3bc85ad1bfa7096bff0a498d5de56bb06 100644 (file)
@@ -362,18 +362,15 @@ fail:
 
 int dlm_device_deregister(struct dlm_ls *ls)
 {
-       int error;
-
        /* The device is not registered.  This happens when the lockspace
           was never used from userspace, or when device_create_lockspace()
           calls dlm_release_lockspace() after the register fails. */
        if (!ls->ls_device.name)
                return 0;
 
-       error = misc_deregister(&ls->ls_device);
-       if (!error)
-               kfree(ls->ls_device.name);
-       return error;
+       misc_deregister(&ls->ls_device);
+       kfree(ls->ls_device.name);
+       return 0;
 }
 
 static int device_user_purge(struct dlm_user_proc *proc,
index 518c6294bf6c0ef965e9f56baa4e11d2eccc0165..5fa588e933d5eaeb72f1ac1b4bd97e7dce785612 100644 (file)
@@ -844,14 +844,15 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
        struct wb_iter iter;
 
        might_sleep();
-
-       if (!bdi_has_dirty_io(bdi))
-               return;
 restart:
        rcu_read_lock();
        bdi_for_each_wb(wb, bdi, &iter, next_blkcg_id) {
-               if (!wb_has_dirty_io(wb) ||
-                   (skip_if_busy && writeback_in_progress(wb)))
+               /* SYNC_ALL writes out I_DIRTY_TIME too */
+               if (!wb_has_dirty_io(wb) &&
+                   (base_work->sync_mode == WB_SYNC_NONE ||
+                    list_empty(&wb->b_dirty_time)))
+                       continue;
+               if (skip_if_busy && writeback_in_progress(wb))
                        continue;
 
                base_work->nr_pages = wb_split_bdi_pages(wb, nr_pages);
@@ -899,8 +900,7 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
 {
        might_sleep();
 
-       if (bdi_has_dirty_io(bdi) &&
-           (!skip_if_busy || !writeback_in_progress(&bdi->wb))) {
+       if (!skip_if_busy || !writeback_in_progress(&bdi->wb)) {
                base_work->auto_free = 0;
                base_work->single_wait = 0;
                base_work->single_done = 0;
@@ -2275,8 +2275,12 @@ void sync_inodes_sb(struct super_block *sb)
        };
        struct backing_dev_info *bdi = sb->s_bdi;
 
-       /* Nothing to do? */
-       if (!bdi_has_dirty_io(bdi) || bdi == &noop_backing_dev_info)
+       /*
+        * Can't skip on !bdi_has_dirty() because we should wait for !dirty
+        * inodes under writeback and I_DIRTY_TIME inodes ignored by
+        * bdi_has_dirty() need to be written out too.
+        */
+       if (bdi == &noop_backing_dev_info)
                return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
index 80cc1b35d46043c16bc456e0cadf61e76c281d52..ebb5e37455a07acd86f5fbf1b76d474e99b937fb 100644 (file)
@@ -2246,7 +2246,15 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
 
                        err = -EINVAL;
                        if (old) {
-                               struct fuse_dev *fud = fuse_get_dev(old);
+                               struct fuse_dev *fud = NULL;
+
+                               /*
+                                * Check against file->f_op because CUSE
+                                * uses the same ioctl handler.
+                                */
+                               if (old->f_op == file->f_op &&
+                                   old->f_cred->user_ns == file->f_cred->user_ns)
+                                       fud = fuse_get_dev(old);
 
                                if (fud) {
                                        mutex_lock(&fuse_mutex);
index 2768eb1da2b865f4afba3c35087da7c477c87309..ced70c8139f7391346e7c7eaffc8c8a2fec6303b 100644 (file)
@@ -655,14 +655,7 @@ static int ocfs2_control_init(void)
 
 static void ocfs2_control_exit(void)
 {
-       int rc;
-
-       rc = misc_deregister(&ocfs2_control_device);
-       if (rc)
-               printk(KERN_ERR
-                      "ocfs2: Unable to deregister ocfs2_control device "
-                      "(errno %d)\n",
-                      -rc);
+       misc_deregister(&ocfs2_control_device);
 }
 
 static void fsdlm_lock_ast_wrapper(void *astarg)
index 7169ad04acc06602aa10ffaeeedcf26c061a2da2..077cae1e6b516779eb4bb7e4e35058838bd019d8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AEAD: Authenticated Encryption with Associated Data
  * 
- * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
  *
  * 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
  * a breach in the integrity of the message. In essence, that -EBADMSG error
  * code is the key bonus an AEAD cipher has over "standard" block chaining
  * modes.
+ *
+ * Memory Structure:
+ *
+ * To support the needs of the most prominent user of AEAD ciphers, namely
+ * IPSEC, the AEAD ciphers have a special memory layout the caller must adhere
+ * to.
+ *
+ * The scatter list pointing to the input data must contain:
+ *
+ * * for RFC4106 ciphers, the concatenation of
+ * associated authentication data || IV || plaintext or ciphertext. Note, the
+ * same IV (buffer) is also set with the aead_request_set_crypt call. Note,
+ * the API call of aead_request_set_ad must provide the length of the AAD and
+ * the IV. The API call of aead_request_set_crypt only points to the size of
+ * the input plaintext or ciphertext.
+ *
+ * * for "normal" AEAD ciphers, the concatenation of
+ * associated authentication data || plaintext or ciphertext.
+ *
+ * It is important to note that if multiple scatter gather list entries form
+ * the input data mentioned above, the first entry must not point to a NULL
+ * buffer. If there is any potential where the AAD buffer can be NULL, the
+ * calling code must contain a precaution to ensure that this does not result
+ * in the first scatter gather list entry pointing to a NULL buffer.
  */
 
+struct crypto_aead;
+
 /**
  *     struct aead_request - AEAD request
  *     @base: Common attributes for async crypto requests
- *     @old: Boolean whether the old or new AEAD API is used
  *     @assoclen: Length in bytes of associated data for authentication
  *     @cryptlen: Length of data to be encrypted or decrypted
  *     @iv: Initialisation vector
- *     @assoc: Associated data
  *     @src: Source data
  *     @dst: Destination data
  *     @__ctx: Start of private context data
 struct aead_request {
        struct crypto_async_request base;
 
-       bool old;
-
        unsigned int assoclen;
        unsigned int cryptlen;
 
        u8 *iv;
 
-       struct scatterlist *assoc;
        struct scatterlist *src;
        struct scatterlist *dst;
 
        void *__ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
-/**
- *     struct aead_givcrypt_request - AEAD request with IV generation
- *     @seq: Sequence number for IV generation
- *     @giv: Space for generated IV
- *     @areq: The AEAD request itself
- */
-struct aead_givcrypt_request {
-       u64 seq;
-       u8 *giv;
-
-       struct aead_request areq;
-};
-
 /**
  * struct aead_alg - AEAD cipher definition
  * @maxauthsize: Set the maximum authentication tag size supported by the
@@ -141,16 +149,6 @@ struct aead_alg {
 };
 
 struct crypto_aead {
-       int (*setkey)(struct crypto_aead *tfm, const u8 *key,
-                     unsigned int keylen);
-       int (*setauthsize)(struct crypto_aead *tfm, unsigned int authsize);
-       int (*encrypt)(struct aead_request *req);
-       int (*decrypt)(struct aead_request *req);
-       int (*givencrypt)(struct aead_givcrypt_request *req);
-       int (*givdecrypt)(struct aead_givcrypt_request *req);
-
-       struct crypto_aead *child;
-
        unsigned int authsize;
        unsigned int reqsize;
 
@@ -192,16 +190,6 @@ static inline void crypto_free_aead(struct crypto_aead *tfm)
        crypto_destroy_tfm(tfm, crypto_aead_tfm(tfm));
 }
 
-static inline struct crypto_aead *crypto_aead_crt(struct crypto_aead *tfm)
-{
-       return tfm;
-}
-
-static inline struct old_aead_alg *crypto_old_aead_alg(struct crypto_aead *tfm)
-{
-       return &crypto_aead_tfm(tfm)->__crt_alg->cra_aead;
-}
-
 static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm)
 {
        return container_of(crypto_aead_tfm(tfm)->__crt_alg,
@@ -210,8 +198,7 @@ static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm)
 
 static inline unsigned int crypto_aead_alg_ivsize(struct aead_alg *alg)
 {
-       return alg->base.cra_aead.encrypt ? alg->base.cra_aead.ivsize :
-                                           alg->ivsize;
+       return alg->ivsize;
 }
 
 /**
@@ -337,7 +324,7 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
  */
 static inline int crypto_aead_encrypt(struct aead_request *req)
 {
-       return crypto_aead_reqtfm(req)->encrypt(req);
+       return crypto_aead_alg(crypto_aead_reqtfm(req))->encrypt(req);
 }
 
 /**
@@ -364,10 +351,12 @@ static inline int crypto_aead_encrypt(struct aead_request *req)
  */
 static inline int crypto_aead_decrypt(struct aead_request *req)
 {
-       if (req->cryptlen < crypto_aead_authsize(crypto_aead_reqtfm(req)))
+       struct crypto_aead *aead = crypto_aead_reqtfm(req);
+
+       if (req->cryptlen < crypto_aead_authsize(aead))
                return -EINVAL;
 
-       return crypto_aead_reqtfm(req)->decrypt(req);
+       return crypto_aead_alg(aead)->decrypt(req);
 }
 
 /**
@@ -387,7 +376,10 @@ static inline int crypto_aead_decrypt(struct aead_request *req)
  *
  * Return: number of bytes
  */
-unsigned int crypto_aead_reqsize(struct crypto_aead *tfm);
+static inline unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
+{
+       return tfm->reqsize;
+}
 
 /**
  * aead_request_set_tfm() - update cipher handle reference in request
@@ -400,7 +392,7 @@ unsigned int crypto_aead_reqsize(struct crypto_aead *tfm);
 static inline void aead_request_set_tfm(struct aead_request *req,
                                        struct crypto_aead *tfm)
 {
-       req->base.tfm = crypto_aead_tfm(tfm->child);
+       req->base.tfm = crypto_aead_tfm(tfm);
 }
 
 /**
@@ -525,23 +517,6 @@ static inline void aead_request_set_crypt(struct aead_request *req,
        req->iv = iv;
 }
 
-/**
- * aead_request_set_assoc() - set the associated data scatter / gather list
- * @req: request handle
- * @assoc: associated data scatter / gather list
- * @assoclen: number of bytes to process from @assoc
- *
- * Obsolete, do not use.
- */
-static inline void aead_request_set_assoc(struct aead_request *req,
-                                         struct scatterlist *assoc,
-                                         unsigned int assoclen)
-{
-       req->assoc = assoc;
-       req->assoclen = assoclen;
-       req->old = true;
-}
-
 /**
  * aead_request_set_ad - set associated data information
  * @req: request handle
@@ -554,77 +529,6 @@ static inline void aead_request_set_ad(struct aead_request *req,
                                       unsigned int assoclen)
 {
        req->assoclen = assoclen;
-       req->old = false;
-}
-
-static inline struct crypto_aead *aead_givcrypt_reqtfm(
-       struct aead_givcrypt_request *req)
-{
-       return crypto_aead_reqtfm(&req->areq);
-}
-
-static inline int crypto_aead_givencrypt(struct aead_givcrypt_request *req)
-{
-       return aead_givcrypt_reqtfm(req)->givencrypt(req);
-};
-
-static inline int crypto_aead_givdecrypt(struct aead_givcrypt_request *req)
-{
-       return aead_givcrypt_reqtfm(req)->givdecrypt(req);
-};
-
-static inline void aead_givcrypt_set_tfm(struct aead_givcrypt_request *req,
-                                        struct crypto_aead *tfm)
-{
-       req->areq.base.tfm = crypto_aead_tfm(tfm);
-}
-
-static inline struct aead_givcrypt_request *aead_givcrypt_alloc(
-       struct crypto_aead *tfm, gfp_t gfp)
-{
-       struct aead_givcrypt_request *req;
-
-       req = kmalloc(sizeof(struct aead_givcrypt_request) +
-                     crypto_aead_reqsize(tfm), gfp);
-
-       if (likely(req))
-               aead_givcrypt_set_tfm(req, tfm);
-
-       return req;
-}
-
-static inline void aead_givcrypt_free(struct aead_givcrypt_request *req)
-{
-       kfree(req);
-}
-
-static inline void aead_givcrypt_set_callback(
-       struct aead_givcrypt_request *req, u32 flags,
-       crypto_completion_t compl, void *data)
-{
-       aead_request_set_callback(&req->areq, flags, compl, data);
-}
-
-static inline void aead_givcrypt_set_crypt(struct aead_givcrypt_request *req,
-                                          struct scatterlist *src,
-                                          struct scatterlist *dst,
-                                          unsigned int nbytes, void *iv)
-{
-       aead_request_set_crypt(&req->areq, src, dst, nbytes, iv);
-}
-
-static inline void aead_givcrypt_set_assoc(struct aead_givcrypt_request *req,
-                                          struct scatterlist *assoc,
-                                          unsigned int assoclen)
-{
-       aead_request_set_assoc(&req->areq, assoc, assoclen);
-}
-
-static inline void aead_givcrypt_set_giv(struct aead_givcrypt_request *req,
-                                        u8 *giv, u64 seq)
-{
-       req->giv = giv;
-       req->seq = seq;
 }
 
 #endif /* _CRYPTO_AEAD_H */
index d4ebf6e9af6a536c589d55c914e56f1c6000f910..c9fe145f7dd3bad3af8cd7902accefbc8c7b5366 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/skbuff.h>
 
 struct crypto_aead;
+struct crypto_instance;
 struct module;
 struct rtattr;
 struct seq_file;
@@ -30,6 +31,7 @@ struct crypto_type {
        void (*show)(struct seq_file *m, struct crypto_alg *alg);
        int (*report)(struct sk_buff *skb, struct crypto_alg *alg);
        struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask);
+       void (*free)(struct crypto_instance *inst);
 
        unsigned int type;
        unsigned int maskclear;
@@ -180,7 +182,6 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
 void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen);
 int crypto_enqueue_request(struct crypto_queue *queue,
                           struct crypto_async_request *request);
-void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset);
 struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
 int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm);
 
diff --git a/include/crypto/chacha20.h b/include/crypto/chacha20.h
new file mode 100644 (file)
index 0000000..274bbae
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Common values for the ChaCha20 algorithm
+ */
+
+#ifndef _CRYPTO_CHACHA20_H
+#define _CRYPTO_CHACHA20_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+
+#define CHACHA20_IV_SIZE       16
+#define CHACHA20_KEY_SIZE      32
+#define CHACHA20_BLOCK_SIZE    64
+
+struct chacha20_ctx {
+       u32 key[8];
+};
+
+void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv);
+int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
+                          unsigned int keysize);
+int crypto_chacha20_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+                         struct scatterlist *src, unsigned int nbytes);
+
+#endif
index 57c8a6ee33c27321d1a1e366559a858ae5cccdb3..8e920b44c0ac4b14238ef0877812fab4eaf7f8b8 100644 (file)
@@ -63,6 +63,11 @@ struct ahash_request {
        void *__ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
+#define AHASH_REQUEST_ON_STACK(name, ahash) \
+       char __##name##_desc[sizeof(struct ahash_request) + \
+               crypto_ahash_reqsize(ahash)] CRYPTO_MINALIGN_ATTR; \
+       struct ahash_request *name = (void *)__##name##_desc
+
 /**
  * struct ahash_alg - asynchronous message digest definition
  * @init: Initialize the transformation context. Intended only to initialize the
index 4b2547186519f80e00729144dd8edafab238b5ef..5554cdd8d6c17344f049f138e57027defc050dc1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AEAD: Authenticated Encryption with Associated Data
  * 
- * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
  *
  * 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
@@ -21,6 +21,7 @@
 struct rtattr;
 
 struct aead_instance {
+       void (*free)(struct aead_instance *inst);
        union {
                struct {
                        char head[offsetof(struct aead_alg, base)];
@@ -34,20 +35,15 @@ struct crypto_aead_spawn {
        struct crypto_spawn base;
 };
 
-extern const struct crypto_type crypto_aead_type;
-extern const struct crypto_type crypto_nivaead_type;
+struct aead_queue {
+       struct crypto_queue base;
+};
 
 static inline void *crypto_aead_ctx(struct crypto_aead *tfm)
 {
        return crypto_tfm_ctx(&tfm->base);
 }
 
-static inline struct crypto_instance *crypto_aead_alg_instance(
-       struct crypto_aead *aead)
-{
-       return crypto_tfm_alg_instance(&aead->base);
-}
-
 static inline struct crypto_instance *aead_crypto_instance(
        struct aead_instance *inst)
 {
@@ -61,7 +57,7 @@ static inline struct aead_instance *aead_instance(struct crypto_instance *inst)
 
 static inline struct aead_instance *aead_alg_instance(struct crypto_aead *aead)
 {
-       return aead_instance(crypto_aead_alg_instance(aead));
+       return aead_instance(crypto_tfm_alg_instance(&aead->base));
 }
 
 static inline void *aead_instance_ctx(struct aead_instance *inst)
@@ -90,8 +86,6 @@ static inline void crypto_set_aead_spawn(
        crypto_set_spawn(&spawn->base, inst);
 }
 
-struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask);
-
 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
                     u32 type, u32 mask);
 
@@ -100,12 +94,6 @@ static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn)
        crypto_drop_spawn(&spawn->base);
 }
 
-static inline struct crypto_alg *crypto_aead_spawn_alg(
-       struct crypto_aead_spawn *spawn)
-{
-       return spawn->base.alg;
-}
-
 static inline struct aead_alg *crypto_spawn_aead_alg(
        struct crypto_aead_spawn *spawn)
 {
@@ -118,43 +106,51 @@ static inline struct crypto_aead *crypto_spawn_aead(
        return crypto_spawn_tfm2(&spawn->base);
 }
 
-struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
-                                      struct rtattr **tb, u32 type, u32 mask);
-void aead_geniv_free(struct aead_instance *inst);
-int aead_geniv_init(struct crypto_tfm *tfm);
-void aead_geniv_exit(struct crypto_tfm *tfm);
+static inline void crypto_aead_set_reqsize(struct crypto_aead *aead,
+                                          unsigned int reqsize)
+{
+       aead->reqsize = reqsize;
+}
 
-static inline struct crypto_aead *aead_geniv_base(struct crypto_aead *geniv)
+static inline unsigned int crypto_aead_alg_maxauthsize(struct aead_alg *alg)
 {
-       return geniv->child;
+       return alg->maxauthsize;
 }
 
-static inline void *aead_givcrypt_reqctx(struct aead_givcrypt_request *req)
+static inline unsigned int crypto_aead_maxauthsize(struct crypto_aead *aead)
 {
-       return aead_request_ctx(&req->areq);
+       return crypto_aead_alg_maxauthsize(crypto_aead_alg(aead));
 }
 
-static inline void aead_givcrypt_complete(struct aead_givcrypt_request *req,
-                                         int err)
+static inline void aead_init_queue(struct aead_queue *queue,
+                                  unsigned int max_qlen)
 {
-       aead_request_complete(&req->areq, err);
+       crypto_init_queue(&queue->base, max_qlen);
 }
 
-static inline void crypto_aead_set_reqsize(struct crypto_aead *aead,
-                                          unsigned int reqsize)
+static inline int aead_enqueue_request(struct aead_queue *queue,
+                                      struct aead_request *request)
 {
-       crypto_aead_crt(aead)->reqsize = reqsize;
+       return crypto_enqueue_request(&queue->base, &request->base);
 }
 
-static inline unsigned int crypto_aead_alg_maxauthsize(struct aead_alg *alg)
+static inline struct aead_request *aead_dequeue_request(
+       struct aead_queue *queue)
 {
-       return alg->base.cra_aead.encrypt ? alg->base.cra_aead.maxauthsize :
-                                           alg->maxauthsize;
+       struct crypto_async_request *req;
+
+       req = crypto_dequeue_request(&queue->base);
+
+       return req ? container_of(req, struct aead_request, base) : NULL;
 }
 
-static inline unsigned int crypto_aead_maxauthsize(struct crypto_aead *aead)
+static inline struct aead_request *aead_get_backlog(struct aead_queue *queue)
 {
-       return crypto_aead_alg_maxauthsize(crypto_aead_alg(aead));
+       struct crypto_async_request *req;
+
+       req = crypto_get_backlog(&queue->base);
+
+       return req ? container_of(req, struct aead_request, base) : NULL;
 }
 
 int crypto_register_aead(struct aead_alg *alg);
index 9ca9b871aba56a1fe9fa81bfcd665bbfa0e39697..59333635e712d15a109919f03c70107183df473e 100644 (file)
 
 #include <crypto/internal/aead.h>
 #include <linux/spinlock.h>
+#include <linux/types.h>
 
 struct aead_geniv_ctx {
        spinlock_t lock;
        struct crypto_aead *child;
+       struct crypto_blkcipher *null;
+       u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
 };
 
+struct aead_instance *aead_geniv_alloc(struct crypto_template *tmpl,
+                                      struct rtattr **tb, u32 type, u32 mask);
+void aead_geniv_free(struct aead_instance *inst);
+int aead_init_geniv(struct crypto_aead *tfm);
+void aead_exit_geniv(struct crypto_aead *tfm);
+
 #endif /* _CRYPTO_INTERNAL_GENIV_H */
index b3a46c515d1b7ed2cedb5185898e9b6a685ea434..2cf7a61ece59e987893138a35c3c48336a630c19 100644 (file)
@@ -107,5 +107,20 @@ static inline u32 ablkcipher_request_flags(struct ablkcipher_request *req)
        return req->base.flags;
 }
 
+static inline void *crypto_skcipher_ctx(struct crypto_skcipher *tfm)
+{
+       return crypto_tfm_ctx(&tfm->base);
+}
+
+static inline void *skcipher_request_ctx(struct skcipher_request *req)
+{
+       return req->__ctx;
+}
+
+static inline u32 skcipher_request_flags(struct skcipher_request *req)
+{
+       return req->base.flags;
+}
+
 #endif /* _CRYPTO_INTERNAL_SKCIPHER_H */
 
diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h
new file mode 100644 (file)
index 0000000..894df59
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Common values for the Poly1305 algorithm
+ */
+
+#ifndef _CRYPTO_POLY1305_H
+#define _CRYPTO_POLY1305_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+
+#define POLY1305_BLOCK_SIZE    16
+#define POLY1305_KEY_SIZE      32
+#define POLY1305_DIGEST_SIZE   16
+
+struct poly1305_desc_ctx {
+       /* key */
+       u32 r[5];
+       /* finalize key */
+       u32 s[4];
+       /* accumulator */
+       u32 h[5];
+       /* partial buffer */
+       u8 buf[POLY1305_BLOCK_SIZE];
+       /* bytes used in partial buffer */
+       unsigned int buflen;
+       /* r key has been set */
+       bool rset;
+       /* s key has been set */
+       bool sset;
+};
+
+int crypto_poly1305_init(struct shash_desc *desc);
+int crypto_poly1305_setkey(struct crypto_shash *tfm,
+                          const u8 *key, unsigned int keylen);
+unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
+                                       const u8 *src, unsigned int srclen);
+int crypto_poly1305_update(struct shash_desc *desc,
+                          const u8 *src, unsigned int srclen);
+int crypto_poly1305_final(struct shash_desc *desc, u8 *dst);
+
+#endif
index 07d245f073d161a8e6f2380a910b2698e44919ae..d8dd41fb034fe5af52b68699096abb6ebc5559d5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Symmetric key ciphers.
  * 
- * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2007-2015 Herbert Xu <herbert@gondor.apana.org.au>
  *
  * 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
 #include <linux/kernel.h>
 #include <linux/slab.h>
 
+/**
+ *     struct skcipher_request - Symmetric key cipher request
+ *     @cryptlen: Number of bytes to encrypt or decrypt
+ *     @iv: Initialisation Vector
+ *     @src: Source SG list
+ *     @dst: Destination SG list
+ *     @base: Underlying async request request
+ *     @__ctx: Start of private context data
+ */
+struct skcipher_request {
+       unsigned int cryptlen;
+
+       u8 *iv;
+
+       struct scatterlist *src;
+       struct scatterlist *dst;
+
+       struct crypto_async_request base;
+
+       void *__ctx[] CRYPTO_MINALIGN_ATTR;
+};
+
 /**
  *     struct skcipher_givcrypt_request - Crypto request with IV generation
  *     @seq: Sequence number for IV generation
@@ -30,6 +52,23 @@ struct skcipher_givcrypt_request {
        struct ablkcipher_request creq;
 };
 
+struct crypto_skcipher {
+       int (*setkey)(struct crypto_skcipher *tfm, const u8 *key,
+                     unsigned int keylen);
+       int (*encrypt)(struct skcipher_request *req);
+       int (*decrypt)(struct skcipher_request *req);
+
+       unsigned int ivsize;
+       unsigned int reqsize;
+
+       struct crypto_tfm base;
+};
+
+#define SKCIPHER_REQUEST_ON_STACK(name, tfm) \
+       char __##name##_desc[sizeof(struct skcipher_request) + \
+               crypto_skcipher_reqsize(tfm)] CRYPTO_MINALIGN_ATTR; \
+       struct skcipher_request *name = (void *)__##name##_desc
+
 static inline struct crypto_ablkcipher *skcipher_givcrypt_reqtfm(
        struct skcipher_givcrypt_request *req)
 {
@@ -106,5 +145,355 @@ static inline void skcipher_givcrypt_set_giv(
        req->seq = seq;
 }
 
+/**
+ * DOC: Symmetric Key Cipher API
+ *
+ * Symmetric key cipher API is used with the ciphers of type
+ * CRYPTO_ALG_TYPE_SKCIPHER (listed as type "skcipher" in /proc/crypto).
+ *
+ * Asynchronous cipher operations imply that the function invocation for a
+ * cipher request returns immediately before the completion of the operation.
+ * The cipher request is scheduled as a separate kernel thread and therefore
+ * load-balanced on the different CPUs via the process scheduler. To allow
+ * the kernel crypto API to inform the caller about the completion of a cipher
+ * request, the caller must provide a callback function. That function is
+ * invoked with the cipher handle when the request completes.
+ *
+ * To support the asynchronous operation, additional information than just the
+ * cipher handle must be supplied to the kernel crypto API. That additional
+ * information is given by filling in the skcipher_request data structure.
+ *
+ * For the symmetric key cipher API, the state is maintained with the tfm
+ * cipher handle. A single tfm can be used across multiple calls and in
+ * parallel. For asynchronous block cipher calls, context data supplied and
+ * only used by the caller can be referenced the request data structure in
+ * addition to the IV used for the cipher request. The maintenance of such
+ * state information would be important for a crypto driver implementer to
+ * have, because when calling the callback function upon completion of the
+ * cipher operation, that callback function may need some information about
+ * which operation just finished if it invoked multiple in parallel. This
+ * state information is unused by the kernel crypto API.
+ */
+
+static inline struct crypto_skcipher *__crypto_skcipher_cast(
+       struct crypto_tfm *tfm)
+{
+       return container_of(tfm, struct crypto_skcipher, base);
+}
+
+/**
+ * crypto_alloc_skcipher() - allocate symmetric key cipher handle
+ * @alg_name: is the cra_name / name or cra_driver_name / driver name of the
+ *           skcipher cipher
+ * @type: specifies the type of the cipher
+ * @mask: specifies the mask for the cipher
+ *
+ * Allocate a cipher handle for an skcipher. The returned struct
+ * crypto_skcipher is the cipher handle that is required for any subsequent
+ * API invocation for that skcipher.
+ *
+ * Return: allocated cipher handle in case of success; IS_ERR() is true in case
+ *        of an error, PTR_ERR() returns the error code.
+ */
+struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name,
+                                             u32 type, u32 mask);
+
+static inline struct crypto_tfm *crypto_skcipher_tfm(
+       struct crypto_skcipher *tfm)
+{
+       return &tfm->base;
+}
+
+/**
+ * crypto_free_skcipher() - zeroize and free cipher handle
+ * @tfm: cipher handle to be freed
+ */
+static inline void crypto_free_skcipher(struct crypto_skcipher *tfm)
+{
+       crypto_destroy_tfm(tfm, crypto_skcipher_tfm(tfm));
+}
+
+/**
+ * crypto_has_skcipher() - Search for the availability of an skcipher.
+ * @alg_name: is the cra_name / name or cra_driver_name / driver name of the
+ *           skcipher
+ * @type: specifies the type of the cipher
+ * @mask: specifies the mask for the cipher
+ *
+ * Return: true when the skcipher is known to the kernel crypto API; false
+ *        otherwise
+ */
+static inline int crypto_has_skcipher(const char *alg_name, u32 type,
+                                       u32 mask)
+{
+       return crypto_has_alg(alg_name, crypto_skcipher_type(type),
+                             crypto_skcipher_mask(mask));
+}
+
+/**
+ * crypto_skcipher_ivsize() - obtain IV size
+ * @tfm: cipher handle
+ *
+ * The size of the IV for the skcipher referenced by the cipher handle is
+ * returned. This IV size may be zero if the cipher does not need an IV.
+ *
+ * Return: IV size in bytes
+ */
+static inline unsigned int crypto_skcipher_ivsize(struct crypto_skcipher *tfm)
+{
+       return tfm->ivsize;
+}
+
+/**
+ * crypto_skcipher_blocksize() - obtain block size of cipher
+ * @tfm: cipher handle
+ *
+ * The block size for the skcipher referenced with the cipher handle is
+ * returned. The caller may use that information to allocate appropriate
+ * memory for the data returned by the encryption or decryption operation
+ *
+ * Return: block size of cipher
+ */
+static inline unsigned int crypto_skcipher_blocksize(
+       struct crypto_skcipher *tfm)
+{
+       return crypto_tfm_alg_blocksize(crypto_skcipher_tfm(tfm));
+}
+
+static inline unsigned int crypto_skcipher_alignmask(
+       struct crypto_skcipher *tfm)
+{
+       return crypto_tfm_alg_alignmask(crypto_skcipher_tfm(tfm));
+}
+
+static inline u32 crypto_skcipher_get_flags(struct crypto_skcipher *tfm)
+{
+       return crypto_tfm_get_flags(crypto_skcipher_tfm(tfm));
+}
+
+static inline void crypto_skcipher_set_flags(struct crypto_skcipher *tfm,
+                                              u32 flags)
+{
+       crypto_tfm_set_flags(crypto_skcipher_tfm(tfm), flags);
+}
+
+static inline void crypto_skcipher_clear_flags(struct crypto_skcipher *tfm,
+                                                u32 flags)
+{
+       crypto_tfm_clear_flags(crypto_skcipher_tfm(tfm), flags);
+}
+
+/**
+ * crypto_skcipher_setkey() - set key for cipher
+ * @tfm: cipher handle
+ * @key: buffer holding the key
+ * @keylen: length of the key in bytes
+ *
+ * The caller provided key is set for the skcipher referenced by the cipher
+ * handle.
+ *
+ * Note, the key length determines the cipher type. Many block ciphers implement
+ * different cipher modes depending on the key size, such as AES-128 vs AES-192
+ * vs. AES-256. When providing a 16 byte key for an AES cipher handle, AES-128
+ * is performed.
+ *
+ * Return: 0 if the setting of the key was successful; < 0 if an error occurred
+ */
+static inline int crypto_skcipher_setkey(struct crypto_skcipher *tfm,
+                                        const u8 *key, unsigned int keylen)
+{
+       return tfm->setkey(tfm, key, keylen);
+}
+
+/**
+ * crypto_skcipher_reqtfm() - obtain cipher handle from request
+ * @req: skcipher_request out of which the cipher handle is to be obtained
+ *
+ * Return the crypto_skcipher handle when furnishing an skcipher_request
+ * data structure.
+ *
+ * Return: crypto_skcipher handle
+ */
+static inline struct crypto_skcipher *crypto_skcipher_reqtfm(
+       struct skcipher_request *req)
+{
+       return __crypto_skcipher_cast(req->base.tfm);
+}
+
+/**
+ * crypto_skcipher_encrypt() - encrypt plaintext
+ * @req: reference to the skcipher_request handle that holds all information
+ *      needed to perform the cipher operation
+ *
+ * Encrypt plaintext data using the skcipher_request handle. That data
+ * structure and how it is filled with data is discussed with the
+ * skcipher_request_* functions.
+ *
+ * Return: 0 if the cipher operation was successful; < 0 if an error occurred
+ */
+static inline int crypto_skcipher_encrypt(struct skcipher_request *req)
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+
+       return tfm->encrypt(req);
+}
+
+/**
+ * crypto_skcipher_decrypt() - decrypt ciphertext
+ * @req: reference to the skcipher_request handle that holds all information
+ *      needed to perform the cipher operation
+ *
+ * Decrypt ciphertext data using the skcipher_request handle. That data
+ * structure and how it is filled with data is discussed with the
+ * skcipher_request_* functions.
+ *
+ * Return: 0 if the cipher operation was successful; < 0 if an error occurred
+ */
+static inline int crypto_skcipher_decrypt(struct skcipher_request *req)
+{
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+
+       return tfm->decrypt(req);
+}
+
+/**
+ * DOC: Symmetric Key Cipher Request Handle
+ *
+ * The skcipher_request data structure contains all pointers to data
+ * required for the symmetric key cipher operation. This includes the cipher
+ * handle (which can be used by multiple skcipher_request instances), pointer
+ * to plaintext and ciphertext, asynchronous callback function, etc. It acts
+ * as a handle to the skcipher_request_* API calls in a similar way as
+ * skcipher handle to the crypto_skcipher_* API calls.
+ */
+
+/**
+ * crypto_skcipher_reqsize() - obtain size of the request data structure
+ * @tfm: cipher handle
+ *
+ * Return: number of bytes
+ */
+static inline unsigned int crypto_skcipher_reqsize(struct crypto_skcipher *tfm)
+{
+       return tfm->reqsize;
+}
+
+/**
+ * skcipher_request_set_tfm() - update cipher handle reference in request
+ * @req: request handle to be modified
+ * @tfm: cipher handle that shall be added to the request handle
+ *
+ * Allow the caller to replace the existing skcipher handle in the request
+ * data structure with a different one.
+ */
+static inline void skcipher_request_set_tfm(struct skcipher_request *req,
+                                           struct crypto_skcipher *tfm)
+{
+       req->base.tfm = crypto_skcipher_tfm(tfm);
+}
+
+static inline struct skcipher_request *skcipher_request_cast(
+       struct crypto_async_request *req)
+{
+       return container_of(req, struct skcipher_request, base);
+}
+
+/**
+ * skcipher_request_alloc() - allocate request data structure
+ * @tfm: cipher handle to be registered with the request
+ * @gfp: memory allocation flag that is handed to kmalloc by the API call.
+ *
+ * Allocate the request data structure that must be used with the skcipher
+ * encrypt and decrypt API calls. During the allocation, the provided skcipher
+ * handle is registered in the request data structure.
+ *
+ * Return: allocated request handle in case of success; IS_ERR() is true in case
+ *        of an error, PTR_ERR() returns the error code.
+ */
+static inline struct skcipher_request *skcipher_request_alloc(
+       struct crypto_skcipher *tfm, gfp_t gfp)
+{
+       struct skcipher_request *req;
+
+       req = kmalloc(sizeof(struct skcipher_request) +
+                     crypto_skcipher_reqsize(tfm), gfp);
+
+       if (likely(req))
+               skcipher_request_set_tfm(req, tfm);
+
+       return req;
+}
+
+/**
+ * skcipher_request_free() - zeroize and free request data structure
+ * @req: request data structure cipher handle to be freed
+ */
+static inline void skcipher_request_free(struct skcipher_request *req)
+{
+       kzfree(req);
+}
+
+/**
+ * skcipher_request_set_callback() - set asynchronous callback function
+ * @req: request handle
+ * @flags: specify zero or an ORing of the flags
+ *         CRYPTO_TFM_REQ_MAY_BACKLOG the request queue may back log and
+ *        increase the wait queue beyond the initial maximum size;
+ *        CRYPTO_TFM_REQ_MAY_SLEEP the request processing may sleep
+ * @compl: callback function pointer to be registered with the request handle
+ * @data: The data pointer refers to memory that is not used by the kernel
+ *       crypto API, but provided to the callback function for it to use. Here,
+ *       the caller can provide a reference to memory the callback function can
+ *       operate on. As the callback function is invoked asynchronously to the
+ *       related functionality, it may need to access data structures of the
+ *       related functionality which can be referenced using this pointer. The
+ *       callback function can access the memory via the "data" field in the
+ *       crypto_async_request data structure provided to the callback function.
+ *
+ * This function allows setting the callback function that is triggered once the
+ * cipher operation completes.
+ *
+ * The callback function is registered with the skcipher_request handle and
+ * must comply with the following template
+ *
+ *     void callback_function(struct crypto_async_request *req, int error)
+ */
+static inline void skcipher_request_set_callback(struct skcipher_request *req,
+                                                u32 flags,
+                                                crypto_completion_t compl,
+                                                void *data)
+{
+       req->base.complete = compl;
+       req->base.data = data;
+       req->base.flags = flags;
+}
+
+/**
+ * skcipher_request_set_crypt() - set data buffers
+ * @req: request handle
+ * @src: source scatter / gather list
+ * @dst: destination scatter / gather list
+ * @cryptlen: number of bytes to process from @src
+ * @iv: IV for the cipher operation which must comply with the IV size defined
+ *      by crypto_skcipher_ivsize
+ *
+ * This function allows setting of the source data and destination data
+ * scatter / gather lists.
+ *
+ * For encryption, the source is treated as the plaintext and the
+ * destination is the ciphertext. For a decryption operation, the use is
+ * reversed - the source is the ciphertext and the destination is the plaintext.
+ */
+static inline void skcipher_request_set_crypt(
+       struct skcipher_request *req,
+       struct scatterlist *src, struct scatterlist *dst,
+       unsigned int cryptlen, void *iv)
+{
+       req->src = src;
+       req->dst = dst;
+       req->cryptlen = cryptlen;
+       req->iv = iv;
+}
+
 #endif /* _CRYPTO_SKCIPHER_H */
 
index 57ca8cc383a615344498202384b1b814911bc766..3b4d8a4a23fb760867fc7d59ede2a3459eac2375 100644 (file)
@@ -743,8 +743,6 @@ struct drm_connector {
        uint8_t num_h_tile, num_v_tile;
        uint8_t tile_h_loc, tile_v_loc;
        uint16_t tile_h_size, tile_v_size;
-
-       struct list_head destroy_list;
 };
 
 /**
index 799050198323e852c7cbb45e3c1236cc67d386ac..53c53c459b15c8207997da61234d0ab9ea2805ae 100644 (file)
@@ -347,6 +347,25 @@ static inline int drm_eld_mnl(const uint8_t *eld)
        return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
 }
 
+/**
+ * drm_eld_sad - Get ELD SAD structures.
+ * @eld: pointer to an eld memory structure with sad_count set
+ */
+static inline const uint8_t *drm_eld_sad(const uint8_t *eld)
+{
+       unsigned int ver, mnl;
+
+       ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT;
+       if (ver != 2 && ver != 31)
+               return NULL;
+
+       mnl = drm_eld_mnl(eld);
+       if (mnl > 16)
+               return NULL;
+
+       return eld + DRM_ELD_CEA_SAD(mnl, 0);
+}
+
 /**
  * drm_eld_sad_count - Get ELD SAD count.
  * @eld: pointer to an eld memory structure with sad_count set
index 45c39a37f9249562761dc9615ffecf12ec194846..8bc073d297db2a233cf389d6c0656dec78c0445a 100644 (file)
        {0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6617, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
index aab088d301999278fa283a7f6d4a6e38ce6546d6..63d01c15d2b368f63114622c2fac1eb51977eee7 100644 (file)
@@ -31,6 +31,7 @@
 #define CLK_FOUT_VPLL                  4
 #define CLK_FOUT_UPLL                  5
 #define CLK_FOUT_MPLL                  6
+#define CLK_ARM_CLK                    7
 
 /* Muxes */
 #define CLK_MOUT_MPLL_USER_L           16
index 4273891dc78e41b998fcf17a203868a7237f3095..8183d1c237d9562fc899ea44571a756a7f1491c7 100644 (file)
@@ -21,6 +21,7 @@
 #define CLK_FOUT_CPLL          6
 #define CLK_FOUT_EPLL          7
 #define CLK_FOUT_VPLL          8
+#define CLK_ARM_CLK            9
 
 /* gate for special clocks (sclk) */
 #define CLK_SCLK_CAM_BAYER     128
index 8780868458a09e9b35d7fdee97f732663da0a61c..8de173ff19f310bbb8c0e9d7a7e26cb442079ff7 100644 (file)
 #define IMX6QDL_CLK_VIDEO_27M                  238
 #define IMX6QDL_CLK_MIPI_CORE_CFG              239
 #define IMX6QDL_CLK_MIPI_IPG                   240
-#define IMX6QDL_CLK_END                                241
+#define IMX6QDL_CLK_CAAM_MEM                   241
+#define IMX6QDL_CLK_CAAM_ACLK                  242
+#define IMX6QDL_CLK_CAAM_IPG                   243
+#define IMX6QDL_CLK_END                                244
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6QDL_H */
diff --git a/include/dt-bindings/clock/imx6ul-clock.h b/include/dt-bindings/clock/imx6ul-clock.h
new file mode 100644 (file)
index 0000000..c343894
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX6UL_H
+#define __DT_BINDINGS_CLOCK_IMX6UL_H
+
+#define IMX6UL_CLK_DUMMY               0
+#define IMX6UL_CLK_CKIL                        1
+#define IMX6UL_CLK_CKIH                        2
+#define IMX6UL_CLK_OSC                 3
+#define IMX6UL_PLL1_BYPASS_SRC         4
+#define IMX6UL_PLL2_BYPASS_SRC         5
+#define IMX6UL_PLL3_BYPASS_SRC         6
+#define IMX6UL_PLL4_BYPASS_SRC         7
+#define IMX6UL_PLL5_BYPASS_SRC         8
+#define IMX6UL_PLL6_BYPASS_SRC         9
+#define IMX6UL_PLL7_BYPASS_SRC         10
+#define IMX6UL_CLK_PLL1                11
+#define IMX6UL_CLK_PLL2                12
+#define IMX6UL_CLK_PLL3                13
+#define IMX6UL_CLK_PLL4                14
+#define IMX6UL_CLK_PLL5                15
+#define IMX6UL_CLK_PLL6                16
+#define IMX6UL_CLK_PLL7                17
+#define IMX6UL_PLL1_BYPASS             18
+#define IMX6UL_PLL2_BYPASS             19
+#define IMX6UL_PLL3_BYPASS             20
+#define IMX6UL_PLL4_BYPASS             21
+#define IMX6UL_PLL5_BYPASS             22
+#define IMX6UL_PLL6_BYPASS             23
+#define IMX6UL_PLL7_BYPASS             24
+#define IMX6UL_CLK_PLL1_SYS            25
+#define IMX6UL_CLK_PLL2_BUS            26
+#define IMX6UL_CLK_PLL3_USB_OTG        27
+#define IMX6UL_CLK_PLL4_AUDIO          28
+#define IMX6UL_CLK_PLL5_VIDEO          29
+#define IMX6UL_CLK_PLL6_ENET           30
+#define IMX6UL_CLK_PLL7_USB_HOST       31
+#define IMX6UL_CLK_USBPHY1             32
+#define IMX6UL_CLK_USBPHY2             33
+#define IMX6UL_CLK_USBPHY1_GATE                34
+#define IMX6UL_CLK_USBPHY2_GATE                35
+#define IMX6UL_CLK_PLL2_PFD0           36
+#define IMX6UL_CLK_PLL2_PFD1           37
+#define IMX6UL_CLK_PLL2_PFD2           38
+#define IMX6UL_CLK_PLL2_PFD3           39
+#define IMX6UL_CLK_PLL3_PFD0           40
+#define IMX6UL_CLK_PLL3_PFD1           41
+#define IMX6UL_CLK_PLL3_PFD2           42
+#define IMX6UL_CLK_PLL3_PFD3           43
+#define IMX6UL_CLK_ENET_REF            44
+#define IMX6UL_CLK_ENET2_REF           45
+#define IMX6UL_CLK_ENET2_REF_125M      46
+#define IMX6UL_CLK_ENET_PTP_REF                47
+#define IMX6UL_CLK_ENET_PTP            48
+#define IMX6UL_CLK_PLL4_POST_DIV       49
+#define IMX6UL_CLK_PLL4_AUDIO_DIV      50
+#define IMX6UL_CLK_PLL5_POST_DIV       51
+#define IMX6UL_CLK_PLL5_VIDEO_DIV      52
+#define IMX6UL_CLK_PLL2_198M           53
+#define IMX6UL_CLK_PLL3_80M            54
+#define IMX6UL_CLK_PLL3_60M            55
+#define IMX6UL_CLK_STEP                56
+#define IMX6UL_CLK_PLL1_SW             57
+#define IMX6UL_CLK_AXI_ALT_SEL         58
+#define IMX6UL_CLK_AXI_SEL             59
+#define IMX6UL_CLK_PERIPH_PRE          60
+#define IMX6UL_CLK_PERIPH2_PRE         61
+#define IMX6UL_CLK_PERIPH_CLK2_SEL     62
+#define IMX6UL_CLK_PERIPH2_CLK2_SEL    63
+#define IMX6UL_CLK_USDHC1_SEL          64
+#define IMX6UL_CLK_USDHC2_SEL          65
+#define IMX6UL_CLK_BCH_SEL             66
+#define IMX6UL_CLK_GPMI_SEL            67
+#define IMX6UL_CLK_EIM_SLOW_SEL        68
+#define IMX6UL_CLK_SPDIF_SEL           69
+#define IMX6UL_CLK_SAI1_SEL            70
+#define IMX6UL_CLK_SAI2_SEL            71
+#define IMX6UL_CLK_SAI3_SEL            72
+#define IMX6UL_CLK_LCDIF_PRE_SEL       73
+#define IMX6UL_CLK_SIM_PRE_SEL         74
+#define IMX6UL_CLK_LDB_DI0_SEL         75
+#define IMX6UL_CLK_LDB_DI1_SEL         76
+#define IMX6UL_CLK_ENFC_SEL            77
+#define IMX6UL_CLK_CAN_SEL             78
+#define IMX6UL_CLK_ECSPI_SEL           79
+#define IMX6UL_CLK_UART_SEL            80
+#define IMX6UL_CLK_QSPI1_SEL           81
+#define IMX6UL_CLK_PERCLK_SEL          82
+#define IMX6UL_CLK_LCDIF_SEL           83
+#define IMX6UL_CLK_SIM_SEL             84
+#define IMX6UL_CLK_PERIPH              85
+#define IMX6UL_CLK_PERIPH2             86
+#define IMX6UL_CLK_LDB_DI0_DIV_3_5     87
+#define IMX6UL_CLK_LDB_DI0_DIV_7       88
+#define IMX6UL_CLK_LDB_DI1_DIV_3_5     89
+#define IMX6UL_CLK_LDB_DI1_DIV_7       90
+#define IMX6UL_CLK_LDB_DI0_DIV_SEL     91
+#define IMX6UL_CLK_LDB_DI1_DIV_SEL     92
+#define IMX6UL_CLK_ARM                 93
+#define IMX6UL_CLK_PERIPH_CLK2         94
+#define IMX6UL_CLK_PERIPH2_CLK2        95
+#define IMX6UL_CLK_AHB                 96
+#define IMX6UL_CLK_MMDC_PODF           97
+#define IMX6UL_CLK_AXI_PODF            98
+#define IMX6UL_CLK_PERCLK              99
+#define IMX6UL_CLK_IPG                 100
+#define IMX6UL_CLK_USDHC1_PODF         101
+#define IMX6UL_CLK_USDHC2_PODF         102
+#define IMX6UL_CLK_BCH_PODF            103
+#define IMX6UL_CLK_GPMI_PODF           104
+#define IMX6UL_CLK_EIM_SLOW_PODF       105
+#define IMX6UL_CLK_SPDIF_PRED          106
+#define IMX6UL_CLK_SPDIF_PODF          107
+#define IMX6UL_CLK_SAI1_PRED           108
+#define IMX6UL_CLK_SAI1_PODF           109
+#define IMX6UL_CLK_SAI2_PRED           110
+#define IMX6UL_CLK_SAI2_PODF           111
+#define IMX6UL_CLK_SAI3_PRED           112
+#define IMX6UL_CLK_SAI3_PODF           113
+#define IMX6UL_CLK_LCDIF_PRED          114
+#define IMX6UL_CLK_LCDIF_PODF          115
+#define IMX6UL_CLK_SIM_PODF            116
+#define IMX6UL_CLK_QSPI1_PDOF          117
+#define IMX6UL_CLK_ENFC_PRED           118
+#define IMX6UL_CLK_ENFC_PODF           119
+#define IMX6UL_CLK_CAN_PODF            120
+#define IMX6UL_CLK_ECSPI_PODF          121
+#define IMX6UL_CLK_UART_PODF           122
+#define IMX6UL_CLK_ADC1                123
+#define IMX6UL_CLK_ADC2                124
+#define IMX6UL_CLK_AIPSTZ1             125
+#define IMX6UL_CLK_AIPSTZ2             126
+#define IMX6UL_CLK_AIPSTZ3             127
+#define IMX6UL_CLK_APBHDMA             128
+#define IMX6UL_CLK_ASRC_IPG            129
+#define IMX6UL_CLK_ASRC_MEM            130
+#define IMX6UL_CLK_GPMI_BCH_APB        131
+#define IMX6UL_CLK_GPMI_BCH            132
+#define IMX6UL_CLK_GPMI_IO             133
+#define IMX6UL_CLK_GPMI_APB            134
+#define IMX6UL_CLK_CAAM_MEM            135
+#define IMX6UL_CLK_CAAM_ACLK           136
+#define IMX6UL_CLK_CAAM_IPG            137
+#define IMX6UL_CLK_CSI                 138
+#define IMX6UL_CLK_ECSPI1              139
+#define IMX6UL_CLK_ECSPI2              140
+#define IMX6UL_CLK_ECSPI3              141
+#define IMX6UL_CLK_ECSPI4              142
+#define IMX6UL_CLK_EIM                 143
+#define IMX6UL_CLK_ENET                144
+#define IMX6UL_CLK_ENET_AHB            145
+#define IMX6UL_CLK_EPIT1               146
+#define IMX6UL_CLK_EPIT2               147
+#define IMX6UL_CLK_CAN1_IPG            148
+#define IMX6UL_CLK_CAN1_SERIAL         149
+#define IMX6UL_CLK_CAN2_IPG            150
+#define IMX6UL_CLK_CAN2_SERIAL         151
+#define IMX6UL_CLK_GPT1_BUS            152
+#define IMX6UL_CLK_GPT1_SERIAL         153
+#define IMX6UL_CLK_GPT2_BUS            154
+#define IMX6UL_CLK_GPT2_SERIAL         155
+#define IMX6UL_CLK_I2C1                156
+#define IMX6UL_CLK_I2C2                157
+#define IMX6UL_CLK_I2C3                158
+#define IMX6UL_CLK_I2C4                159
+#define IMX6UL_CLK_IOMUXC              160
+#define IMX6UL_CLK_LCDIF_APB           161
+#define IMX6UL_CLK_LCDIF_PIX           162
+#define IMX6UL_CLK_MMDC_P0_FAST        163
+#define IMX6UL_CLK_MMDC_P0_IPG         164
+#define IMX6UL_CLK_OCOTP               165
+#define IMX6UL_CLK_OCRAM               166
+#define IMX6UL_CLK_PWM1                167
+#define IMX6UL_CLK_PWM2                168
+#define IMX6UL_CLK_PWM3                169
+#define IMX6UL_CLK_PWM4                170
+#define IMX6UL_CLK_PWM5                171
+#define IMX6UL_CLK_PWM6                172
+#define IMX6UL_CLK_PWM7                173
+#define IMX6UL_CLK_PWM8                174
+#define IMX6UL_CLK_PXP                 175
+#define IMX6UL_CLK_QSPI                176
+#define IMX6UL_CLK_ROM                 177
+#define IMX6UL_CLK_SAI1                178
+#define IMX6UL_CLK_SAI1_IPG            179
+#define IMX6UL_CLK_SAI2                180
+#define IMX6UL_CLK_SAI2_IPG            181
+#define IMX6UL_CLK_SAI3                182
+#define IMX6UL_CLK_SAI3_IPG            183
+#define IMX6UL_CLK_SDMA                184
+#define IMX6UL_CLK_SIM                 185
+#define IMX6UL_CLK_SIM_S               186
+#define IMX6UL_CLK_SPBA                187
+#define IMX6UL_CLK_SPDIF               188
+#define IMX6UL_CLK_UART1_IPG           189
+#define IMX6UL_CLK_UART1_SERIAL        190
+#define IMX6UL_CLK_UART2_IPG           191
+#define IMX6UL_CLK_UART2_SERIAL        192
+#define IMX6UL_CLK_UART3_IPG           193
+#define IMX6UL_CLK_UART3_SERIAL        194
+#define IMX6UL_CLK_UART4_IPG           195
+#define IMX6UL_CLK_UART4_SERIAL        196
+#define IMX6UL_CLK_UART5_IPG           197
+#define IMX6UL_CLK_UART5_SERIAL        198
+#define IMX6UL_CLK_UART6_IPG           199
+#define IMX6UL_CLK_UART6_SERIAL        200
+#define IMX6UL_CLK_UART7_IPG           201
+#define IMX6UL_CLK_UART7_SERIAL        202
+#define IMX6UL_CLK_UART8_IPG           203
+#define IMX6UL_CLK_UART8_SERIAL        204
+#define IMX6UL_CLK_USBOH3              205
+#define IMX6UL_CLK_USDHC1              206
+#define IMX6UL_CLK_USDHC2              207
+#define IMX6UL_CLK_WDOG1               208
+#define IMX6UL_CLK_WDOG2               209
+#define IMX6UL_CLK_WDOG3               210
+#define IMX6UL_CLK_LDB_DI0             211
+#define IMX6UL_CLK_AXI                 212
+#define IMX6UL_CLK_SPDIF_GCLK          213
+#define IMX6UL_CLK_GPT_3M              214
+#define IMX6UL_CLK_SIM2                        215
+#define IMX6UL_CLK_SIM1                        216
+#define IMX6UL_CLK_IPP_DI0             217
+#define IMX6UL_CLK_IPP_DI1             218
+#define IMX6UL_CA7_SECONDARY_SEL       219
+#define IMX6UL_CLK_PER_BCH             220
+#define IMX6UL_CLK_CSI_SEL             221
+#define IMX6UL_CLK_CSI_PODF            222
+#define IMX6UL_CLK_PLL3_120M           223
+
+#define IMX6UL_CLK_END                 224
+
+#endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
index bc1ed1dbd855667a7b0d62704544af1e4b3ea34d..d3a9824ef6462d775405b38fa41f7b31740d7508 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3066A_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3066A_H
+
 #include <dt-bindings/clock/rk3188-cru-common.h>
 
 /* soft-reset indices */
@@ -33,3 +36,5 @@
 #define SRST_HDMI              96
 #define SRST_HDMI_APB          97
 #define SRST_CIF1              111
+
+#endif
index 6a370503c954e1466e124292fcac0d4584136c8d..8df77a7c030b0647abbf81e3a592c488f273638c 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3188_COMMON_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3188_COMMON_H
+
 /* core clocks from */
 #define PLL_APLL               1
 #define PLL_DPLL               2
 #define SRST_PTM1_ATB          141
 #define SRST_CTM               142
 #define SRST_TS                        143
+
+#endif
index 9fac8edd3f9df65523eaa42b6b02d5c19bdd984a..9f2e631f2651001327c7761d5c1fdc86cb4bf35b 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3188_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3188_H
+
 #include <dt-bindings/clock/rk3188-cru-common.h>
 
 /* soft-reset indices */
@@ -49,3 +52,5 @@
 #define SRST_GPU_BRIDGE                121
 #define SRST_CTI3              123
 #define SRST_CTI3_APB          124
+
+#endif
index dea419708d73ed112fd63a4c8bea747fd087e3ee..c719aacef14fb84f030603d5435a733f7dc2b1ba 100644 (file)
@@ -13,6 +13,9 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3288_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3288_H
+
 /* core clocks */
 #define PLL_APLL               1
 #define PLL_DPLL               2
 #define SRST_TSP_CLKIN0                189
 #define SRST_TSP_CLKIN1                190
 #define SRST_TSP_27M           191
+
+#endif
diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h
new file mode 100644 (file)
index 0000000..9c5dd9b
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3368_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RK3368_H
+
+/* core clocks */
+#define PLL_APLLB              1
+#define PLL_APLLL              2
+#define PLL_DPLL               3
+#define PLL_CPLL               4
+#define PLL_GPLL               5
+#define PLL_NPLL               6
+#define ARMCLKB                        7
+#define ARMCLKL                        8
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU_CORE          64
+#define SCLK_SPI0              65
+#define SCLK_SPI1              66
+#define SCLK_SPI2              67
+#define SCLK_SDMMC             68
+#define SCLK_SDIO0             69
+#define SCLK_EMMC              71
+#define SCLK_TSADC             72
+#define SCLK_SARADC            73
+#define SCLK_NANDC0            75
+#define SCLK_UART0             77
+#define SCLK_UART1             78
+#define SCLK_UART2             79
+#define SCLK_UART3             80
+#define SCLK_UART4             81
+#define SCLK_I2S_8CH           82
+#define SCLK_SPDIF_8CH         83
+#define SCLK_I2S_2CH           84
+#define SCLK_TIMER0            85
+#define SCLK_TIMER1            86
+#define SCLK_TIMER2            87
+#define SCLK_TIMER3            88
+#define SCLK_TIMER4            89
+#define SCLK_TIMER5            90
+#define SCLK_TIMER6            91
+#define SCLK_OTGPHY0           93
+#define SCLK_OTG_ADP           96
+#define SCLK_HSICPHY480M       97
+#define SCLK_HSICPHY12M                98
+#define SCLK_MACREF            99
+#define SCLK_VOP0_PWM          100
+#define SCLK_MAC_RX            102
+#define SCLK_MAC_TX            103
+#define SCLK_EDP_24M           104
+#define SCLK_EDP               105
+#define SCLK_RGA               106
+#define SCLK_ISP               107
+#define SCLK_HDCP              108
+#define SCLK_HDMI_HDCP         109
+#define SCLK_HDMI_CEC          110
+#define SCLK_HEVC_CABAC                111
+#define SCLK_HEVC_CORE         112
+#define SCLK_I2S_8CH_OUT       113
+#define SCLK_SDMMC_DRV         114
+#define SCLK_SDIO0_DRV         115
+#define SCLK_EMMC_DRV          117
+#define SCLK_SDMMC_SAMPLE      118
+#define SCLK_SDIO0_SAMPLE      119
+#define SCLK_EMMC_SAMPLE       121
+#define SCLK_USBPHY480M                122
+#define SCLK_PVTM_CORE         123
+#define SCLK_PVTM_GPU          124
+#define SCLK_PVTM_PMU          125
+#define SCLK_SFC               126
+#define SCLK_MAC               127
+#define SCLK_MACREF_OUT                128
+
+#define DCLK_VOP               190
+#define MCLK_CRYPTO            191
+
+/* aclk gates */
+#define ACLK_GPU_MEM           192
+#define ACLK_GPU_CFG           193
+#define ACLK_DMAC_BUS          194
+#define ACLK_DMAC_PERI         195
+#define ACLK_PERI_MMU          196
+#define ACLK_GMAC              197
+#define ACLK_VOP               198
+#define ACLK_VOP_IEP           199
+#define ACLK_RGA               200
+#define ACLK_HDCP              201
+#define ACLK_IEP               202
+#define ACLK_VIO0_NOC          203
+#define ACLK_VIP               204
+#define ACLK_ISP               205
+#define ACLK_VIO1_NOC          206
+#define ACLK_VIDEO             208
+#define ACLK_BUS               209
+#define ACLK_PERI              210
+
+/* pclk gates */
+#define PCLK_GPIO0             320
+#define PCLK_GPIO1             321
+#define PCLK_GPIO2             322
+#define PCLK_GPIO3             323
+#define PCLK_PMUGRF            324
+#define PCLK_MAILBOX           325
+#define PCLK_GRF               329
+#define PCLK_SGRF              330
+#define PCLK_PMU               331
+#define PCLK_I2C0              332
+#define PCLK_I2C1              333
+#define PCLK_I2C2              334
+#define PCLK_I2C3              335
+#define PCLK_I2C4              336
+#define PCLK_I2C5              337
+#define PCLK_SPI0              338
+#define PCLK_SPI1              339
+#define PCLK_SPI2              340
+#define PCLK_UART0             341
+#define PCLK_UART1             342
+#define PCLK_UART2             343
+#define PCLK_UART3             344
+#define PCLK_UART4             345
+#define PCLK_TSADC             346
+#define PCLK_SARADC            347
+#define PCLK_SIM               348
+#define PCLK_GMAC              349
+#define PCLK_PWM0              350
+#define PCLK_PWM1              351
+#define PCLK_TIMER0            353
+#define PCLK_TIMER1            354
+#define PCLK_EDP_CTRL          355
+#define PCLK_MIPI_DSI0         356
+#define PCLK_MIPI_CSI          358
+#define PCLK_HDCP              359
+#define PCLK_HDMI_CTRL         360
+#define PCLK_VIO_H2P           361
+#define PCLK_BUS               362
+#define PCLK_PERI              363
+#define PCLK_DDRUPCTL          364
+#define PCLK_DDRPHY            365
+#define PCLK_ISP               366
+#define PCLK_VIP               367
+#define PCLK_WDT               368
+
+/* hclk gates */
+#define HCLK_SFC               448
+#define HCLK_OTG0              449
+#define HCLK_HOST0             450
+#define HCLK_HOST1             451
+#define HCLK_HSIC              452
+#define HCLK_NANDC0            453
+#define HCLK_TSP               455
+#define HCLK_SDMMC             456
+#define HCLK_SDIO0             457
+#define HCLK_EMMC              459
+#define HCLK_HSADC             460
+#define HCLK_CRYPTO            461
+#define HCLK_I2S_2CH           462
+#define HCLK_I2S_8CH           463
+#define HCLK_SPDIF             464
+#define HCLK_VOP               465
+#define HCLK_ROM               467
+#define HCLK_IEP               468
+#define HCLK_ISP               469
+#define HCLK_RGA               470
+#define HCLK_VIO_AHB_ARBI      471
+#define HCLK_VIO_NOC           472
+#define HCLK_VIP               473
+#define HCLK_VIO_H2P           474
+#define HCLK_VIO_HDCPMMU       475
+#define HCLK_VIDEO             476
+#define HCLK_BUS               477
+#define HCLK_PERI              478
+
+#define CLK_NR_CLKS            (HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE_B0           0
+#define SRST_CORE_B1           1
+#define SRST_CORE_B2           2
+#define SRST_CORE_B3           3
+#define SRST_CORE_B0_PO                4
+#define SRST_CORE_B1_PO                5
+#define SRST_CORE_B2_PO                6
+#define SRST_CORE_B3_PO                7
+#define SRST_L2_B              8
+#define SRST_ADB_B             9
+#define SRST_PD_CORE_B_NIU     10
+#define SRST_PDBUS_STRSYS      11
+#define SRST_SOCDBG_B          14
+#define SRST_CORE_B_DBG                15
+
+#define SRST_DMAC1             18
+#define SRST_INTMEM            19
+#define SRST_ROM               20
+#define SRST_SPDIF8CH          21
+#define SRST_I2S8CH            23
+#define SRST_MAILBOX           24
+#define SRST_I2S2CH            25
+#define SRST_EFUSE_256         26
+#define SRST_MCU_SYS           28
+#define SRST_MCU_PO            29
+#define SRST_MCU_NOC           30
+#define SRST_EFUSE             31
+
+#define SRST_GPIO0             32
+#define SRST_GPIO1             33
+#define SRST_GPIO2             34
+#define SRST_GPIO3             35
+#define SRST_GPIO4             36
+#define SRST_PMUGRF            41
+#define SRST_I2C0              42
+#define SRST_I2C1              43
+#define SRST_I2C2              44
+#define SRST_I2C3              45
+#define SRST_I2C4              46
+#define SRST_I2C5              47
+
+#define SRST_DWPWM             48
+#define SRST_MMC_PERI          49
+#define SRST_PERIPH_MMU                50
+#define SRST_GRF               55
+#define SRST_PMU               56
+#define SRST_PERIPH_AXI                57
+#define SRST_PERIPH_AHB                58
+#define SRST_PERIPH_APB                59
+#define SRST_PERIPH_NIU                60
+#define SRST_PDPERI_AHB_ARBI   61
+#define SRST_EMEM              62
+#define SRST_USB_PERI          63
+
+#define SRST_DMAC2             64
+#define SRST_MAC               66
+#define SRST_GPS               67
+#define SRST_RKPWM             69
+#define SRST_USBHOST0          72
+#define SRST_HSIC              73
+#define SRST_HSIC_AUX          74
+#define SRST_HSIC_PHY          75
+#define SRST_HSADC             76
+#define SRST_NANDC0            77
+#define SRST_SFC               79
+
+#define SRST_SPI0              83
+#define SRST_SPI1              84
+#define SRST_SPI2              85
+#define SRST_SARADC            87
+#define SRST_PDALIVE_NIU       88
+#define SRST_PDPMU_INTMEM      89
+#define SRST_PDPMU_NIU         90
+#define SRST_SGRF              91
+
+#define SRST_VIO_ARBI          96
+#define SRST_RGA_NIU           97
+#define SRST_VIO0_NIU_AXI      98
+#define SRST_VIO_NIU_AHB       99
+#define SRST_LCDC0_AXI         100
+#define SRST_LCDC0_AHB         101
+#define SRST_LCDC0_DCLK                102
+#define SRST_VIP               104
+#define SRST_RGA_CORE          105
+#define SRST_IEP_AXI           106
+#define SRST_IEP_AHB           107
+#define SRST_RGA_AXI           108
+#define SRST_RGA_AHB           109
+#define SRST_ISP               110
+#define SRST_EDP_24M           111
+
+#define SRST_VIDEO_AXI         112
+#define SRST_VIDEO_AHB         113
+#define SRST_MIPIDPHYTX                114
+#define SRST_MIPIDSI0          115
+#define SRST_MIPIDPHYRX                116
+#define SRST_MIPICSI           117
+#define SRST_GPU               120
+#define SRST_HDMI              121
+#define SRST_EDP               122
+#define SRST_PMU_PVTM          123
+#define SRST_CORE_PVTM         124
+#define SRST_GPU_PVTM          125
+#define SRST_GPU_SYS           126
+#define SRST_GPU_MEM_NIU       127
+
+#define SRST_MMC0              128
+#define SRST_SDIO0             129
+#define SRST_EMMC              131
+#define SRST_USBOTG_AHB                132
+#define SRST_USBOTG_PHY                133
+#define SRST_USBOTG_CON                134
+#define SRST_USBHOST0_AHB      135
+#define SRST_USBHOST0_PHY      136
+#define SRST_USBHOST0_CON      137
+#define SRST_USBOTG_UTMI       138
+#define SRST_USBHOST1_UTMI     139
+#define SRST_USB_ADP           141
+
+#define SRST_CORESIGHT         144
+#define SRST_PD_CORE_AHB_NOC   145
+#define SRST_PD_CORE_APB_NOC   146
+#define SRST_GIC               148
+#define SRST_LCDC_PWM0         149
+#define SRST_RGA_H2P_BRG       153
+#define SRST_VIDEO             154
+#define SRST_GPU_CFG_NIU       157
+#define SRST_TSADC             159
+
+#define SRST_DDRPHY0           160
+#define SRST_DDRPHY0_APB       161
+#define SRST_DDRCTRL0          162
+#define SRST_DDRCTRL0_APB      163
+#define SRST_VIDEO_NIU         165
+#define SRST_VIDEO_NIU_AHB     167
+#define SRST_DDRMSCH0          170
+#define SRST_PDBUS_AHB         173
+#define SRST_CRYPTO            174
+
+#define SRST_UART0             179
+#define SRST_UART1             180
+#define SRST_UART2             181
+#define SRST_UART3             182
+#define SRST_UART4             183
+#define SRST_SIMC              186
+#define SRST_TSP               188
+#define SRST_TSP_CLKIN0                189
+
+#define SRST_CORE_L0           192
+#define SRST_CORE_L1           193
+#define SRST_CORE_L2           194
+#define SRST_CORE_L3           195
+#define SRST_CORE_L0_PO                195
+#define SRST_CORE_L1_PO                197
+#define SRST_CORE_L2_PO                198
+#define SRST_CORE_L3_PO                199
+#define SRST_L2_L              200
+#define SRST_ADB_L             201
+#define SRST_PD_CORE_L_NIU     202
+#define SRST_CCI_SYS           203
+#define SRST_CCI_DDR           204
+#define SRST_CCI               205
+#define SRST_SOCDBG_L          206
+#define SRST_CORE_L_DBG                207
+
+#define SRST_CORE_B0_NC                208
+#define SRST_CORE_B0_PO_NC     209
+#define SRST_L2_B_NC           210
+#define SRST_ADB_B_NC          211
+#define SRST_PD_CORE_B_NIU_NC  212
+#define SRST_PDBUS_STRSYS_NC   213
+#define SRST_CORE_L0_NC                214
+#define SRST_CORE_L0_PO_NC     215
+#define SRST_L2_L_NC           216
+#define SRST_ADB_L_NC          217
+#define SRST_PD_CORE_L_NIU_NC  218
+#define SRST_CCI_SYS_NC                219
+#define SRST_CCI_DDR_NC                220
+#define SRST_CCI_NC            221
+#define SRST_TRACE_NC          222
+
+#define SRST_TIMER00           224
+#define SRST_TIMER01           225
+#define SRST_TIMER02           226
+#define SRST_TIMER03           227
+#define SRST_TIMER04           228
+#define SRST_TIMER05           229
+#define SRST_TIMER10           230
+#define SRST_TIMER11           231
+#define SRST_TIMER12           232
+#define SRST_TIMER13           233
+#define SRST_TIMER14           234
+#define SRST_TIMER15           235
+#define SRST_TIMER0_APB                236
+#define SRST_TIMER1_APB                237
+
+#endif
index e683dbb7e7c5496e4dbe95b08bc5d1c7872dba78..26ee564b0e6892809869ba98c1902cedb9ea9d14 100644 (file)
 #define ZX296702_I2S0_WCLK                     9
 #define ZX296702_I2S0_PCLK                     10
 #define ZX296702_I2S0_DIV                      11
-#define ZX296702_LSP0CLK_END                   12
+#define ZX296702_I2S1_WCLK_MUX                 12
+#define ZX296702_I2S1_WCLK                     13
+#define ZX296702_I2S1_PCLK                     14
+#define ZX296702_I2S1_DIV                      15
+#define ZX296702_I2S2_WCLK_MUX                 16
+#define ZX296702_I2S2_WCLK                     17
+#define ZX296702_I2S2_PCLK                     18
+#define ZX296702_I2S2_DIV                      19
+#define ZX296702_GPIO_CLK                      20
+#define ZX296702_LSP0CLK_END                   21
 
 #define ZX296702_UART0_WCLK_MUX                        0
 #define ZX296702_UART0_WCLK                    1
 #define ZX296702_SDMMC0_WCLK_DIV               7
 #define ZX296702_SDMMC0_WCLK                   8
 #define ZX296702_SDMMC0_PCLK                   9
-#define ZX296702_LSP1CLK_END                   10
+#define ZX296702_SPDIF1_WCLK_MUX               10
+#define ZX296702_SPDIF1_WCLK                   11
+#define ZX296702_SPDIF1_PCLK                   12
+#define ZX296702_SPDIF1_DIV                    13
+#define ZX296702_LSP1CLK_END                   14
 
 #endif /* __DT_BINDINGS_CLOCK_ZX296702_H */
diff --git a/include/dt-bindings/leds/leds-ns2.h b/include/dt-bindings/leds/leds-ns2.h
new file mode 100644 (file)
index 0000000..491c5f9
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _DT_BINDINGS_LEDS_NS2_H
+#define _DT_BINDINGS_LEDS_NS2_H
+
+#define NS_V2_LED_OFF  0
+#define NS_V2_LED_ON   1
+#define NS_V2_LED_SATA 2
+
+#endif
diff --git a/include/dt-bindings/reset/tegra124-car.h b/include/dt-bindings/reset/tegra124-car.h
new file mode 100644 (file)
index 0000000..070e4f6
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * This header provides Tegra124-specific constants for binding
+ * nvidia,tegra124-car.
+ */
+
+#ifndef _DT_BINDINGS_RESET_TEGRA124_CAR_H
+#define _DT_BINDINGS_RESET_TEGRA124_CAR_H
+
+#define TEGRA124_RESET(x)              (6 * 32 + (x))
+#define TEGRA124_RST_DFLL_DVCO         TEGRA124_RESET(0)
+
+#endif /* _DT_BINDINGS_RESET_TEGRA124_CAR_H */
index 0ddb5c02ad8b6c279047c4c8c9c90e5516327ca7..6a0a89ed7f81cac2b9eb4d04414874fc46243cb3 100644 (file)
 #define UART01x_DR             0x00    /* Data read or written from the interface. */
 #define UART01x_RSR            0x04    /* Receive status register (Read). */
 #define UART01x_ECR            0x04    /* Error clear register (Write). */
+#define ZX_UART01x_DR          0x04    /* Data read or written from the interface. */
 #define UART010_LCRH           0x08    /* Line control register, high byte. */
 #define ST_UART011_DMAWM       0x08    /* DMA watermark configure register. */
 #define UART010_LCRM           0x0C    /* Line control register, middle byte. */
 #define ST_UART011_TIMEOUT     0x0C    /* Timeout period register. */
 #define UART010_LCRL           0x10    /* Line control register, low byte. */
 #define UART010_CR             0x14    /* Control register. */
+#define ZX_UART01x_FR          0x14    /* Flag register (Read only). */
 #define UART01x_FR             0x18    /* Flag register (Read only). */
 #define UART010_IIR            0x1C    /* Interrupt identification register (Read). */
 #define UART010_ICR            0x1C    /* Interrupt clear register (Write). */
 #define UART011_LCRH           0x2c    /* Line control register. */
 #define ST_UART011_LCRH_TX     0x2c    /* Tx Line control register. */
 #define UART011_CR             0x30    /* Control register. */
+#define ZX_UART011_LCRH_TX     0x30    /* Tx Line control register. */
 #define UART011_IFLS           0x34    /* Interrupt fifo level select. */
+#define ZX_UART011_CR          0x34    /* Control register. */
+#define ZX_UART011_IFLS                0x38    /* Interrupt fifo level select. */
 #define UART011_IMSC           0x38    /* Interrupt mask. */
 #define UART011_RIS            0x3c    /* Raw interrupt status. */
 #define UART011_MIS            0x40    /* Masked interrupt status. */
+#define ZX_UART011_IMSC                0x40    /* Interrupt mask. */
 #define UART011_ICR            0x44    /* Interrupt clear register. */
+#define ZX_UART011_RIS         0x44    /* Raw interrupt status. */
 #define UART011_DMACR          0x48    /* DMA control register. */
+#define ZX_UART011_MIS         0x48    /* Masked interrupt status. */
+#define ZX_UART011_ICR         0x4c    /* Interrupt clear register. */
 #define ST_UART011_XFCR                0x50    /* XON/XOFF control register. */
+#define ZX_UART011_DMACR       0x50    /* DMA control register. */
 #define ST_UART011_XON1                0x54    /* XON1 register. */
 #define ST_UART011_XON2                0x58    /* XON2 register. */
 #define ST_UART011_XOFF1       0x5C    /* XON1 register. */
 #define UART01x_RSR_PE                 0x02
 #define UART01x_RSR_FE                 0x01
 
+#define ZX_UART01x_FR_BUSY     0x300
 #define UART011_FR_RI          0x100
 #define UART011_FR_TXFE                0x080
 #define UART011_FR_RXFF                0x040
 #define UART01x_FR_TXFF                0x020
 #define UART01x_FR_RXFE                0x010
 #define UART01x_FR_BUSY                0x008
+#define ZX_UART01x_FR_DSR       0x008
 #define UART01x_FR_DCD                 0x004
 #define UART01x_FR_DSR                 0x002
+#define ZX_UART01x_FR_CTS      0x002
 #define UART01x_FR_CTS                 0x001
+#define ZX_UART011_FR_RI       0x001
 #define UART01x_FR_TMSK                (UART01x_FR_TXFF + UART01x_FR_BUSY)
 
 #define UART011_CR_CTSEN       0x8000  /* CTS hardware flow control */
index 6c78956aa47092440edb3a73e7b9389ac3a57558..d2992bfa17063a052a08a106b9105284ce4bfa4a 100644 (file)
@@ -385,8 +385,6 @@ enum {
        SATA_SSP                = 0x06, /* Software Settings Preservation */
        SATA_DEVSLP             = 0x09, /* Device Sleep */
 
-       SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */
-
        /* feature values for SET_MAX */
        ATA_SET_MAX_ADDR        = 0x00,
        ATA_SET_MAX_PASSWD      = 0x01,
@@ -530,8 +528,6 @@ struct ata_bmdma_prd {
 #define ata_id_cdb_intr(id)    (((id)[ATA_ID_CONFIG] & 0x60) == 0x20)
 #define ata_id_has_da(id)      ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4))
 #define ata_id_has_devslp(id)  ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))
-#define ata_id_has_ncq_autosense(id) \
-                               ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7))
 
 static inline bool ata_id_has_hipm(const u16 *id)
 {
@@ -720,20 +716,6 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id)
        return false;
 }
 
-static inline bool ata_id_has_sense_reporting(const u16 *id)
-{
-       if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
-               return false;
-       return id[ATA_ID_COMMAND_SET_3] & (1 << 6);
-}
-
-static inline bool ata_id_sense_reporting_enabled(const u16 *id)
-{
-       if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
-               return false;
-       return id[ATA_ID_COMMAND_SET_4] & (1 << 6);
-}
-
 /**
  *     ata_id_major_version    -       get ATA level of drive
  *     @id: Identify data
index 00beddf6be20358ca7cd108b54a45902c4478c8b..ee696d7e8a43e4faabcfd843bbf75ab0c4cc05bb 100644 (file)
 #ifndef ATMEL_SERIAL_H
 #define ATMEL_SERIAL_H
 
-#define ATMEL_US_CR            0x00                    /* Control Register */
-#define                ATMEL_US_RSTRX          (1 <<  2)               /* Reset Receiver */
-#define                ATMEL_US_RSTTX          (1 <<  3)               /* Reset Transmitter */
-#define                ATMEL_US_RXEN           (1 <<  4)               /* Receiver Enable */
-#define                ATMEL_US_RXDIS          (1 <<  5)               /* Receiver Disable */
-#define                ATMEL_US_TXEN           (1 <<  6)               /* Transmitter Enable */
-#define                ATMEL_US_TXDIS          (1 <<  7)               /* Transmitter Disable */
-#define                ATMEL_US_RSTSTA         (1 <<  8)               /* Reset Status Bits */
-#define                ATMEL_US_STTBRK         (1 <<  9)               /* Start Break */
-#define                ATMEL_US_STPBRK         (1 << 10)               /* Stop Break */
-#define                ATMEL_US_STTTO          (1 << 11)               /* Start Time-out */
-#define                ATMEL_US_SENDA          (1 << 12)               /* Send Address */
-#define                ATMEL_US_RSTIT          (1 << 13)               /* Reset Iterations */
-#define                ATMEL_US_RSTNACK        (1 << 14)               /* Reset Non Acknowledge */
-#define                ATMEL_US_RETTO          (1 << 15)               /* Rearm Time-out */
-#define                ATMEL_US_DTREN          (1 << 16)               /* Data Terminal Ready Enable [AT91RM9200 only] */
-#define                ATMEL_US_DTRDIS         (1 << 17)               /* Data Terminal Ready Disable [AT91RM9200 only] */
-#define                ATMEL_US_RTSEN          (1 << 18)               /* Request To Send Enable */
-#define                ATMEL_US_RTSDIS         (1 << 19)               /* Request To Send Disable */
+#define ATMEL_US_CR            0x00    /* Control Register */
+#define        ATMEL_US_RSTRX          BIT(2)  /* Reset Receiver */
+#define        ATMEL_US_RSTTX          BIT(3)  /* Reset Transmitter */
+#define        ATMEL_US_RXEN           BIT(4)  /* Receiver Enable */
+#define        ATMEL_US_RXDIS          BIT(5)  /* Receiver Disable */
+#define        ATMEL_US_TXEN           BIT(6)  /* Transmitter Enable */
+#define        ATMEL_US_TXDIS          BIT(7)  /* Transmitter Disable */
+#define        ATMEL_US_RSTSTA         BIT(8)  /* Reset Status Bits */
+#define        ATMEL_US_STTBRK         BIT(9)  /* Start Break */
+#define        ATMEL_US_STPBRK         BIT(10) /* Stop Break */
+#define        ATMEL_US_STTTO          BIT(11) /* Start Time-out */
+#define        ATMEL_US_SENDA          BIT(12) /* Send Address */
+#define        ATMEL_US_RSTIT          BIT(13) /* Reset Iterations */
+#define        ATMEL_US_RSTNACK        BIT(14) /* Reset Non Acknowledge */
+#define        ATMEL_US_RETTO          BIT(15) /* Rearm Time-out */
+#define        ATMEL_US_DTREN          BIT(16) /* Data Terminal Ready Enable */
+#define        ATMEL_US_DTRDIS         BIT(17) /* Data Terminal Ready Disable */
+#define        ATMEL_US_RTSEN          BIT(18) /* Request To Send Enable */
+#define        ATMEL_US_RTSDIS         BIT(19) /* Request To Send Disable */
+#define        ATMEL_US_TXFCLR         BIT(24) /* Transmit FIFO Clear */
+#define        ATMEL_US_RXFCLR         BIT(25) /* Receive FIFO Clear */
+#define        ATMEL_US_TXFLCLR        BIT(26) /* Transmit FIFO Lock Clear */
+#define        ATMEL_US_FIFOEN         BIT(30) /* FIFO enable */
+#define        ATMEL_US_FIFODIS        BIT(31) /* FIFO disable */
 
-#define ATMEL_US_MR            0x04                    /* Mode Register */
-#define                ATMEL_US_USMODE         (0xf <<  0)             /* Mode of the USART */
-#define                        ATMEL_US_USMODE_NORMAL          0
-#define                        ATMEL_US_USMODE_RS485           1
-#define                        ATMEL_US_USMODE_HWHS            2
-#define                        ATMEL_US_USMODE_MODEM           3
-#define                        ATMEL_US_USMODE_ISO7816_T0      4
-#define                        ATMEL_US_USMODE_ISO7816_T1      6
-#define                        ATMEL_US_USMODE_IRDA            8
-#define                ATMEL_US_USCLKS         (3   <<  4)             /* Clock Selection */
-#define                        ATMEL_US_USCLKS_MCK             (0 <<  4)
-#define                        ATMEL_US_USCLKS_MCK_DIV8        (1 <<  4)
-#define                        ATMEL_US_USCLKS_SCK             (3 <<  4)
-#define                ATMEL_US_CHRL           (3   <<  6)             /* Character Length */
-#define                        ATMEL_US_CHRL_5                 (0 <<  6)
-#define                        ATMEL_US_CHRL_6                 (1 <<  6)
-#define                        ATMEL_US_CHRL_7                 (2 <<  6)
-#define                        ATMEL_US_CHRL_8                 (3 <<  6)
-#define                ATMEL_US_SYNC           (1 <<  8)               /* Synchronous Mode Select */
-#define                ATMEL_US_PAR            (7 <<  9)               /* Parity Type */
-#define                        ATMEL_US_PAR_EVEN               (0 <<  9)
-#define                        ATMEL_US_PAR_ODD                (1 <<  9)
-#define                        ATMEL_US_PAR_SPACE              (2 <<  9)
-#define                        ATMEL_US_PAR_MARK               (3 <<  9)
-#define                        ATMEL_US_PAR_NONE               (4 <<  9)
-#define                        ATMEL_US_PAR_MULTI_DROP         (6 <<  9)
-#define                ATMEL_US_NBSTOP         (3 << 12)               /* Number of Stop Bits */
-#define                        ATMEL_US_NBSTOP_1               (0 << 12)
-#define                        ATMEL_US_NBSTOP_1_5             (1 << 12)
-#define                        ATMEL_US_NBSTOP_2               (2 << 12)
-#define                ATMEL_US_CHMODE         (3 << 14)               /* Channel Mode */
-#define                        ATMEL_US_CHMODE_NORMAL          (0 << 14)
-#define                        ATMEL_US_CHMODE_ECHO            (1 << 14)
-#define                        ATMEL_US_CHMODE_LOC_LOOP        (2 << 14)
-#define                        ATMEL_US_CHMODE_REM_LOOP        (3 << 14)
-#define                ATMEL_US_MSBF           (1 << 16)               /* Bit Order */
-#define                ATMEL_US_MODE9          (1 << 17)               /* 9-bit Character Length */
-#define                ATMEL_US_CLKO           (1 << 18)               /* Clock Output Select */
-#define                ATMEL_US_OVER           (1 << 19)               /* Oversampling Mode */
-#define                ATMEL_US_INACK          (1 << 20)               /* Inhibit Non Acknowledge */
-#define                ATMEL_US_DSNACK         (1 << 21)               /* Disable Successive NACK */
-#define                ATMEL_US_MAX_ITER       (7 << 24)               /* Max Iterations */
-#define                ATMEL_US_FILTER         (1 << 28)               /* Infrared Receive Line Filter */
+#define ATMEL_US_MR            0x04    /* Mode Register */
+#define        ATMEL_US_USMODE         GENMASK(3, 0)   /* Mode of the USART */
+#define                ATMEL_US_USMODE_NORMAL          0
+#define                ATMEL_US_USMODE_RS485           1
+#define                ATMEL_US_USMODE_HWHS            2
+#define                ATMEL_US_USMODE_MODEM           3
+#define                ATMEL_US_USMODE_ISO7816_T0      4
+#define                ATMEL_US_USMODE_ISO7816_T1      6
+#define                ATMEL_US_USMODE_IRDA            8
+#define        ATMEL_US_USCLKS         GENMASK(5, 4)   /* Clock Selection */
+#define                ATMEL_US_USCLKS_MCK             (0 <<  4)
+#define                ATMEL_US_USCLKS_MCK_DIV8        (1 <<  4)
+#define                ATMEL_US_USCLKS_SCK             (3 <<  4)
+#define        ATMEL_US_CHRL           GENMASK(7, 6)   /* Character Length */
+#define                ATMEL_US_CHRL_5                 (0 <<  6)
+#define                ATMEL_US_CHRL_6                 (1 <<  6)
+#define                ATMEL_US_CHRL_7                 (2 <<  6)
+#define                ATMEL_US_CHRL_8                 (3 <<  6)
+#define        ATMEL_US_SYNC           BIT(8)          /* Synchronous Mode Select */
+#define        ATMEL_US_PAR            GENMASK(11, 9)  /* Parity Type */
+#define                ATMEL_US_PAR_EVEN               (0 <<  9)
+#define                ATMEL_US_PAR_ODD                (1 <<  9)
+#define                ATMEL_US_PAR_SPACE              (2 <<  9)
+#define                ATMEL_US_PAR_MARK               (3 <<  9)
+#define                ATMEL_US_PAR_NONE               (4 <<  9)
+#define                ATMEL_US_PAR_MULTI_DROP         (6 <<  9)
+#define        ATMEL_US_NBSTOP         GENMASK(13, 12) /* Number of Stop Bits */
+#define                ATMEL_US_NBSTOP_1               (0 << 12)
+#define                ATMEL_US_NBSTOP_1_5             (1 << 12)
+#define                ATMEL_US_NBSTOP_2               (2 << 12)
+#define        ATMEL_US_CHMODE         GENMASK(15, 14) /* Channel Mode */
+#define                ATMEL_US_CHMODE_NORMAL          (0 << 14)
+#define                ATMEL_US_CHMODE_ECHO            (1 << 14)
+#define                ATMEL_US_CHMODE_LOC_LOOP        (2 << 14)
+#define                ATMEL_US_CHMODE_REM_LOOP        (3 << 14)
+#define        ATMEL_US_MSBF           BIT(16) /* Bit Order */
+#define        ATMEL_US_MODE9          BIT(17) /* 9-bit Character Length */
+#define        ATMEL_US_CLKO           BIT(18) /* Clock Output Select */
+#define        ATMEL_US_OVER           BIT(19) /* Oversampling Mode */
+#define        ATMEL_US_INACK          BIT(20) /* Inhibit Non Acknowledge */
+#define        ATMEL_US_DSNACK         BIT(21) /* Disable Successive NACK */
+#define        ATMEL_US_MAX_ITER       GENMASK(26, 24) /* Max Iterations */
+#define        ATMEL_US_FILTER         BIT(28) /* Infrared Receive Line Filter */
 
-#define ATMEL_US_IER           0x08                    /* Interrupt Enable Register */
-#define                ATMEL_US_RXRDY          (1 <<  0)               /* Receiver Ready */
-#define                ATMEL_US_TXRDY          (1 <<  1)               /* Transmitter Ready */
-#define                ATMEL_US_RXBRK          (1 <<  2)               /* Break Received / End of Break */
-#define                ATMEL_US_ENDRX          (1 <<  3)               /* End of Receiver Transfer */
-#define                ATMEL_US_ENDTX          (1 <<  4)               /* End of Transmitter Transfer */
-#define                ATMEL_US_OVRE           (1 <<  5)               /* Overrun Error */
-#define                ATMEL_US_FRAME          (1 <<  6)               /* Framing Error */
-#define                ATMEL_US_PARE           (1 <<  7)               /* Parity Error */
-#define                ATMEL_US_TIMEOUT        (1 <<  8)               /* Receiver Time-out */
-#define                ATMEL_US_TXEMPTY        (1 <<  9)               /* Transmitter Empty */
-#define                ATMEL_US_ITERATION      (1 << 10)               /* Max number of Repetitions Reached */
-#define                ATMEL_US_TXBUFE         (1 << 11)               /* Transmission Buffer Empty */
-#define                ATMEL_US_RXBUFF         (1 << 12)               /* Reception Buffer Full */
-#define                ATMEL_US_NACK           (1 << 13)               /* Non Acknowledge */
-#define                ATMEL_US_RIIC           (1 << 16)               /* Ring Indicator Input Change [AT91RM9200 only] */
-#define                ATMEL_US_DSRIC          (1 << 17)               /* Data Set Ready Input Change [AT91RM9200 only] */
-#define                ATMEL_US_DCDIC          (1 << 18)               /* Data Carrier Detect Input Change [AT91RM9200 only] */
-#define                ATMEL_US_CTSIC          (1 << 19)               /* Clear to Send Input Change */
-#define                ATMEL_US_RI             (1 << 20)               /* RI */
-#define                ATMEL_US_DSR            (1 << 21)               /* DSR */
-#define                ATMEL_US_DCD            (1 << 22)               /* DCD */
-#define                ATMEL_US_CTS            (1 << 23)               /* CTS */
+#define ATMEL_US_IER           0x08    /* Interrupt Enable Register */
+#define        ATMEL_US_RXRDY          BIT(0)  /* Receiver Ready */
+#define        ATMEL_US_TXRDY          BIT(1)  /* Transmitter Ready */
+#define        ATMEL_US_RXBRK          BIT(2)  /* Break Received / End of Break */
+#define        ATMEL_US_ENDRX          BIT(3)  /* End of Receiver Transfer */
+#define        ATMEL_US_ENDTX          BIT(4)  /* End of Transmitter Transfer */
+#define        ATMEL_US_OVRE           BIT(5)  /* Overrun Error */
+#define        ATMEL_US_FRAME          BIT(6)  /* Framing Error */
+#define        ATMEL_US_PARE           BIT(7)  /* Parity Error */
+#define        ATMEL_US_TIMEOUT        BIT(8)  /* Receiver Time-out */
+#define        ATMEL_US_TXEMPTY        BIT(9)  /* Transmitter Empty */
+#define        ATMEL_US_ITERATION      BIT(10) /* Max number of Repetitions Reached */
+#define        ATMEL_US_TXBUFE         BIT(11) /* Transmission Buffer Empty */
+#define        ATMEL_US_RXBUFF         BIT(12) /* Reception Buffer Full */
+#define        ATMEL_US_NACK           BIT(13) /* Non Acknowledge */
+#define        ATMEL_US_RIIC           BIT(16) /* Ring Indicator Input Change */
+#define        ATMEL_US_DSRIC          BIT(17) /* Data Set Ready Input Change */
+#define        ATMEL_US_DCDIC          BIT(18) /* Data Carrier Detect Input Change */
+#define        ATMEL_US_CTSIC          BIT(19) /* Clear to Send Input Change */
+#define        ATMEL_US_RI             BIT(20) /* RI */
+#define        ATMEL_US_DSR            BIT(21) /* DSR */
+#define        ATMEL_US_DCD            BIT(22) /* DCD */
+#define        ATMEL_US_CTS            BIT(23) /* CTS */
 
-#define ATMEL_US_IDR           0x0c                    /* Interrupt Disable Register */
-#define ATMEL_US_IMR           0x10                    /* Interrupt Mask Register */
-#define ATMEL_US_CSR           0x14                    /* Channel Status Register */
-#define ATMEL_US_RHR           0x18                    /* Receiver Holding Register */
-#define ATMEL_US_THR           0x1c                    /* Transmitter Holding Register */
-#define                ATMEL_US_SYNH           (1 << 15)               /* Transmit/Receive Sync [AT91SAM9261 only] */
+#define ATMEL_US_IDR           0x0c    /* Interrupt Disable Register */
+#define ATMEL_US_IMR           0x10    /* Interrupt Mask Register */
+#define ATMEL_US_CSR           0x14    /* Channel Status Register */
+#define ATMEL_US_RHR           0x18    /* Receiver Holding Register */
+#define ATMEL_US_THR           0x1c    /* Transmitter Holding Register */
+#define        ATMEL_US_SYNH           BIT(15) /* Transmit/Receive Sync */
 
-#define ATMEL_US_BRGR          0x20                    /* Baud Rate Generator Register */
-#define                ATMEL_US_CD             (0xffff << 0)           /* Clock Divider */
+#define ATMEL_US_BRGR          0x20    /* Baud Rate Generator Register */
+#define        ATMEL_US_CD             GENMASK(15, 0)  /* Clock Divider */
 
-#define ATMEL_US_RTOR          0x24                    /* Receiver Time-out Register */
-#define                ATMEL_US_TO             (0xffff << 0)           /* Time-out Value */
+#define ATMEL_US_RTOR          0x24    /* Receiver Time-out Register */
+#define        ATMEL_US_TO             GENMASK(15, 0)  /* Time-out Value */
 
-#define ATMEL_US_TTGR          0x28                    /* Transmitter Timeguard Register */
-#define                ATMEL_US_TG             (0xff << 0)             /* Timeguard Value */
+#define ATMEL_US_TTGR          0x28    /* Transmitter Timeguard Register */
+#define        ATMEL_US_TG             GENMASK(7, 0)   /* Timeguard Value */
 
-#define ATMEL_US_FIDI          0x40                    /* FI DI Ratio Register */
-#define ATMEL_US_NER           0x44                    /* Number of Errors Register */
-#define ATMEL_US_IF            0x4c                    /* IrDA Filter Register */
+#define ATMEL_US_FIDI          0x40    /* FI DI Ratio Register */
+#define ATMEL_US_NER           0x44    /* Number of Errors Register */
+#define ATMEL_US_IF            0x4c    /* IrDA Filter Register */
 
-#define ATMEL_US_NAME          0xf0                    /* Ip Name */
-#define ATMEL_US_VERSION       0xfc                    /* Ip Version */
+#define ATMEL_US_CMPR          0x90    /* Comparaison Register */
+#define ATMEL_US_FMR           0xa0    /* FIFO Mode Register */
+#define        ATMEL_US_TXRDYM(data)   (((data) & 0x3) << 0)   /* TX Ready Mode */
+#define        ATMEL_US_RXRDYM(data)   (((data) & 0x3) << 4)   /* RX Ready Mode */
+#define                ATMEL_US_ONE_DATA       0x0
+#define                ATMEL_US_TWO_DATA       0x1
+#define                ATMEL_US_FOUR_DATA      0x2
+#define        ATMEL_US_FRTSC          BIT(7)  /* FIFO RTS pin Control */
+#define        ATMEL_US_TXFTHRES(thr)  (((thr) & 0x3f) << 8)   /* TX FIFO Threshold */
+#define        ATMEL_US_RXFTHRES(thr)  (((thr) & 0x3f) << 16)  /* RX FIFO Threshold */
+#define        ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24)  /* RX FIFO Threshold2 */
+
+#define ATMEL_US_FLR           0xa4    /* FIFO Level Register */
+#define        ATMEL_US_TXFL(reg)      (((reg) >> 0) & 0x3f)   /* TX FIFO Level */
+#define        ATMEL_US_RXFL(reg)      (((reg) >> 16) & 0x3f)  /* RX FIFO Level */
+
+#define ATMEL_US_FIER          0xa8    /* FIFO Interrupt Enable Register */
+#define ATMEL_US_FIDR          0xac    /* FIFO Interrupt Disable Register */
+#define ATMEL_US_FIMR          0xb0    /* FIFO Interrupt Mask Register */
+#define ATMEL_US_FESR          0xb4    /* FIFO Event Status Register */
+#define        ATMEL_US_TXFEF          BIT(0)  /* Transmit FIFO Empty Flag */
+#define        ATMEL_US_TXFFF          BIT(1)  /* Transmit FIFO Full Flag */
+#define        ATMEL_US_TXFTHF         BIT(2)  /* Transmit FIFO Threshold Flag */
+#define        ATMEL_US_RXFEF          BIT(3)  /* Receive FIFO Empty Flag */
+#define        ATMEL_US_RXFFF          BIT(4)  /* Receive FIFO Full Flag */
+#define        ATMEL_US_RXFTHF         BIT(5)  /* Receive FIFO Threshold Flag */
+#define        ATMEL_US_TXFPTEF        BIT(6)  /* Transmit FIFO Pointer Error Flag */
+#define        ATMEL_US_RXFPTEF        BIT(7)  /* Receive FIFO Pointer Error Flag */
+#define        ATMEL_US_TXFLOCK        BIT(8)  /* Transmit FIFO Lock (FESR only) */
+#define        ATMEL_US_RXFTHF2        BIT(9)  /* Receive FIFO Threshold Flag 2 */
+
+#define ATMEL_US_NAME          0xf0    /* Ip Name */
+#define ATMEL_US_VERSION       0xfc    /* Ip Version */
 
 #endif
index 78842f46f152694906e0b73f99fd2aa93611e2f7..3ecc07d0da7767555bbe21959c5540375a9a3859 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __LINUX_CLK_PROVIDER_H
 #define __LINUX_CLK_PROVIDER_H
 
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of.h>
 
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 #define CLK_RECALC_NEW_RATES   BIT(9) /* recalc rates after notifications */
 
+struct clk;
 struct clk_hw;
 struct clk_core;
 struct dentry;
 
+/**
+ * struct clk_rate_request - Structure encoding the clk constraints that
+ * a clock user might require.
+ *
+ * @rate:              Requested clock rate. This field will be adjusted by
+ *                     clock drivers according to hardware capabilities.
+ * @min_rate:          Minimum rate imposed by clk users.
+ * @max_rate:          Maximum rate a imposed by clk users.
+ * @best_parent_rate:  The best parent rate a parent can provide to fulfill the
+ *                     requested constraints.
+ * @best_parent_hw:    The most appropriate parent clock that fulfills the
+ *                     requested constraints.
+ *
+ */
+struct clk_rate_request {
+       unsigned long rate;
+       unsigned long min_rate;
+       unsigned long max_rate;
+       unsigned long best_parent_rate;
+       struct clk_hw *best_parent_hw;
+};
+
 /**
  * struct clk_ops -  Callback operations for hardware clocks; these are to
  * be provided by the clock implementation, and will be called by drivers
@@ -176,12 +198,8 @@ struct clk_ops {
                                        unsigned long parent_rate);
        long            (*round_rate)(struct clk_hw *hw, unsigned long rate,
                                        unsigned long *parent_rate);
-       long            (*determine_rate)(struct clk_hw *hw,
-                                         unsigned long rate,
-                                         unsigned long min_rate,
-                                         unsigned long max_rate,
-                                         unsigned long *best_parent_rate,
-                                         struct clk_hw **best_parent_hw);
+       int             (*determine_rate)(struct clk_hw *hw,
+                                         struct clk_rate_request *req);
        int             (*set_parent)(struct clk_hw *hw, u8 index);
        u8              (*get_parent)(struct clk_hw *hw);
        int             (*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -343,6 +361,9 @@ struct clk_div_table {
  *     to the closest integer instead of the up one.
  * CLK_DIVIDER_READ_ONLY - The divider settings are preconfigured and should
  *     not be changed by the clock framework.
+ * CLK_DIVIDER_MAX_AT_ZERO - For dividers which are like CLK_DIVIDER_ONE_BASED
+ *     except when the value read from the register is zero, the divisor is
+ *     2^width of the field.
  */
 struct clk_divider {
        struct clk_hw   hw;
@@ -360,6 +381,7 @@ struct clk_divider {
 #define CLK_DIVIDER_HIWORD_MASK                BIT(3)
 #define CLK_DIVIDER_ROUND_CLOSEST      BIT(4)
 #define CLK_DIVIDER_READ_ONLY          BIT(5)
+#define CLK_DIVIDER_MAX_AT_ZERO                BIT(6)
 
 extern const struct clk_ops clk_divider_ops;
 
@@ -549,6 +571,23 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
 
 void of_gpio_clk_gate_setup(struct device_node *node);
 
+/**
+ * struct clk_gpio_mux - gpio controlled clock multiplexer
+ *
+ * @hw:                see struct clk_gpio
+ * @gpiod:     gpio descriptor to select the parent of this clock multiplexer
+ *
+ * Clock with a gpio control for selecting the parent clock.
+ * Implements .get_parent, .set_parent and .determine_rate
+ */
+
+extern const struct clk_ops clk_gpio_mux_ops;
+struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
+               const char * const *parent_names, u8 num_parents, unsigned gpio,
+               bool active_low, unsigned long flags);
+
+void of_gpio_mux_clk_setup(struct device_node *node);
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -568,31 +607,27 @@ void devm_clk_unregister(struct device *dev, struct clk *clk);
 
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
+const char *clk_hw_get_name(const struct clk_hw *hw);
 struct clk_hw *__clk_get_hw(struct clk *clk);
-u8 __clk_get_num_parents(struct clk *clk);
-struct clk *__clk_get_parent(struct clk *clk);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
+unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
+struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
+struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
+                                         unsigned int index);
 unsigned int __clk_get_enable_count(struct clk *clk);
-unsigned long __clk_get_rate(struct clk *clk);
+unsigned long clk_hw_get_rate(const struct clk_hw *hw);
 unsigned long __clk_get_flags(struct clk *clk);
-bool __clk_is_prepared(struct clk *clk);
+unsigned long clk_hw_get_flags(const struct clk_hw *hw);
+bool clk_hw_is_prepared(const struct clk_hw *hw);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
-long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p);
-unsigned long __clk_determine_rate(struct clk_hw *core,
-                                  unsigned long rate,
-                                  unsigned long min_rate,
-                                  unsigned long max_rate);
-long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
-                             unsigned long min_rate,
-                             unsigned long max_rate,
-                             unsigned long *best_parent_rate,
-                             struct clk_hw **best_parent_p);
+int __clk_mux_determine_rate(struct clk_hw *hw,
+                            struct clk_rate_request *req);
+int __clk_determine_rate(struct clk_hw *core, struct clk_rate_request *req);
+int __clk_mux_determine_rate_closest(struct clk_hw *hw,
+                                    struct clk_rate_request *req);
 void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
+void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
+                          unsigned long max_rate);
 
 static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
 {
@@ -603,7 +638,7 @@ static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
 /*
  * FIXME clock api without lock protection
  */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate);
 
 struct of_device_id;
 
index f3050e15f8333ce596388588f6c1dc0c69d3b4d0..e0c362363c385126de1d90eee5e3a432fa363447 100644 (file)
@@ -7,6 +7,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/types.h>
+
 struct device_node;
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
index 19c4208f4752fd6957712b8a9e900a6baa0b4945..57bf7aab4516eac15cf609642f68b412e290a402 100644 (file)
@@ -17,7 +17,8 @@
 #ifndef __LINUX_CLK_TEGRA_H_
 #define __LINUX_CLK_TEGRA_H_
 
-#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/bug.h>
 
 /*
  * Tegra CPU clock and reset control ops
index 79b76e13d90425db1ed1320b1bfe9f11aecfd767..9299222d680dbbb381e929dd18f5522532565d66 100644 (file)
@@ -188,33 +188,6 @@ struct clk_hw_omap {
 /* DPLL Type and DCO Selection Flags */
 #define DPLL_J_TYPE            0x1
 
-/* Composite clock component types */
-enum {
-       CLK_COMPONENT_TYPE_GATE = 0,
-       CLK_COMPONENT_TYPE_DIVIDER,
-       CLK_COMPONENT_TYPE_MUX,
-       CLK_COMPONENT_TYPE_MAX,
-};
-
-/**
- * struct ti_dt_clk - OMAP DT clock alias declarations
- * @lk: clock lookup definition
- * @node_name: clock DT node to map to
- */
-struct ti_dt_clk {
-       struct clk_lookup               lk;
-       char                            *node_name;
-};
-
-#define DT_CLK(dev, con, name)         \
-       {                               \
-               .lk = {                 \
-                       .dev_id = dev,  \
-                       .con_id = con,  \
-               },                      \
-               .node_name = name,      \
-       }
-
 /* Static memmap indices */
 enum {
        TI_CLKM_CM = 0,
@@ -225,8 +198,6 @@ enum {
        CLK_MAX_MEMMAPS
 };
 
-typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
-
 /**
  * struct clk_omap_reg - OMAP register declaration
  * @offset: offset from the master IP module base address
@@ -238,93 +209,56 @@ struct clk_omap_reg {
 };
 
 /**
- * struct ti_clk_ll_ops - low-level register access ops for a clock
+ * struct ti_clk_ll_ops - low-level ops for clocks
  * @clk_readl: pointer to register read function
  * @clk_writel: pointer to register write function
+ * @clkdm_clk_enable: pointer to clockdomain enable function
+ * @clkdm_clk_disable: pointer to clockdomain disable function
+ * @cm_wait_module_ready: pointer to CM module wait ready function
+ * @cm_split_idlest_reg: pointer to CM module function to split idlest reg
  *
- * Low-level register access ops are generally used by the basic clock types
- * (clk-gate, clk-mux, clk-divider etc.) to provide support for various
- * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be
- * used by other hardware-specific clock drivers if needed.
+ * Low-level ops are generally used by the basic clock types (clk-gate,
+ * clk-mux, clk-divider etc.) to provide support for various low-level
+ * hadrware interfaces (direct MMIO, regmap etc.), and is initialized
+ * by board code. Low-level ops also contain some other platform specific
+ * operations not provided directly by clock drivers.
  */
 struct ti_clk_ll_ops {
        u32     (*clk_readl)(void __iomem *reg);
        void    (*clk_writel)(u32 val, void __iomem *reg);
+       int     (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
+       int     (*clkdm_clk_disable)(struct clockdomain *clkdm,
+                                    struct clk *clk);
+       int     (*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
+                                       u8 idlest_shift);
+       int     (*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
+                                      u8 *idlest_reg_id);
 };
 
-extern struct ti_clk_ll_ops *ti_clk_ll_ops;
-
-extern const struct clk_ops ti_clk_divider_ops;
-extern const struct clk_ops ti_clk_mux_ops;
-
 #define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
 
-void omap2_init_clk_hw_omap_clocks(struct clk *clk);
-int omap3_noncore_dpll_enable(struct clk_hw *hw);
-void omap3_noncore_dpll_disable(struct clk_hw *hw);
-int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate);
-int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
-                                          unsigned long rate,
-                                          unsigned long parent_rate,
-                                          u8 index);
-long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
-                                      unsigned long rate,
-                                      unsigned long min_rate,
-                                      unsigned long max_rate,
-                                      unsigned long *best_parent_rate,
-                                      struct clk_hw **best_parent_clk);
-unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-                                        unsigned long parent_rate);
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-                                   unsigned long target_rate,
-                                   unsigned long *parent_rate);
-long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
-                                       unsigned long rate,
-                                       unsigned long min_rate,
-                                       unsigned long max_rate,
-                                       unsigned long *best_parent_rate,
-                                       struct clk_hw **best_parent_clk);
-u8 omap2_init_dpll_parent(struct clk_hw *hw);
-unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                          unsigned long *parent_rate);
 void omap2_init_clk_clkdm(struct clk_hw *clk);
-unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
-                                   unsigned long parent_rate);
-int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long parent_rate);
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *prate);
-int omap2_clkops_enable_clkdm(struct clk_hw *hw);
-void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
-int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
-                        unsigned long parent_rate);
-int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
-                                   unsigned long parent_rate, u8 index);
-int omap2_dflt_clk_enable(struct clk_hw *hw);
-void omap2_dflt_clk_disable(struct clk_hw *hw);
-int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
-void omap3_clk_lock_dpll5(void);
+int omap2_clk_enable_autoidle_all(void);
+int omap2_clk_allow_idle(struct clk *clk);
+int omap2_clk_deny_idle(struct clk *clk);
 unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
 int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
                             unsigned long parent_rate);
 void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
 void omap2xxx_clkt_vps_init(void);
+unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
 
-void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
-void ti_dt_clocks_register(struct ti_dt_clk *oclks);
-void ti_dt_clk_init_provider(struct device_node *np, int index);
 void ti_dt_clk_init_retry_clks(void);
 void ti_dt_clockdomains_setup(void);
-int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
-                     ti_of_clk_init_cb_t func);
-int of_ti_clk_autoidle_setup(struct device_node *node);
-int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
+int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops);
+
+struct regmap;
+
+int omap2_clk_provider_init(struct device_node *parent, int index,
+                           struct regmap *syscon, void __iomem *mem);
+void omap2_clk_legacy_provider_init(int index, void __iomem *mem);
 
 int omap3430_dt_clk_init(void);
 int omap3630_dt_clk_init(void);
@@ -338,27 +272,24 @@ int am43xx_dt_clk_init(void);
 int omap2420_dt_clk_init(void);
 int omap2430_dt_clk_init(void);
 
-#ifdef CONFIG_OF
-void of_ti_clk_allow_autoidle_all(void);
-void of_ti_clk_deny_autoidle_all(void);
-#else
-static inline void of_ti_clk_allow_autoidle_all(void) { }
-static inline void of_ti_clk_deny_autoidle_all(void) { }
-#endif
+struct ti_clk_features {
+       u32 flags;
+       long fint_min;
+       long fint_max;
+       long fint_band1_max;
+       long fint_band2_min;
+       u8 dpll_bypass_vals;
+       u8 cm_idlest_val;
+};
+
+#define TI_CLK_DPLL_HAS_FREQSEL                        BIT(0)
+#define TI_CLK_DPLL4_DENY_REPROGRAM            BIT(1)
+#define TI_CLK_DISABLE_CLKDM_CONTROL           BIT(2)
+
+void ti_clk_setup_features(struct ti_clk_features *features);
+const struct ti_clk_features *ti_clk_get_features(void);
 
 extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
-extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
-extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
-extern const struct clk_hw_omap_ops clkhwops_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
-extern const struct clk_hw_omap_ops clkhwops_iclk;
-extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
 
 #ifdef CONFIG_ATAGS
 int omap3430_clk_legacy_init(void);
index 3486b9082adbcf885d62d0011f32e1ac2709eb11..c69e1b9328094ed6452f152d8d9a8d3ad46ab9c9 100644 (file)
@@ -14,6 +14,7 @@
 #define _LINUX_CORESIGHT_H
 
 #include <linux/device.h>
+#include <linux/sched.h>
 
 /* Peripheral id registers (0xFD0-0xFEC) */
 #define CORESIGHT_PERIPHIDR4   0xfd0
@@ -248,4 +249,24 @@ static inline struct coresight_platform_data *of_get_coresight_platform_data(
        struct device *dev, struct device_node *node) { return NULL; }
 #endif
 
+#ifdef CONFIG_PID_NS
+static inline unsigned long
+coresight_vpid_to_pid(unsigned long vpid)
+{
+       struct task_struct *task = NULL;
+       unsigned long pid = 0;
+
+       rcu_read_lock();
+       task = find_task_by_vpid(vpid);
+       if (task)
+               pid = task_pid_nr(task);
+       rcu_read_unlock();
+
+       return pid;
+}
+#else
+static inline unsigned long
+coresight_vpid_to_pid(unsigned long vpid) { return vpid; }
+#endif
+
 #endif
index c4d4eb8ac9fe2bbd24c42646d95716a95e705859..986c06c88d81426b2d0629eb85994ba1f26616d8 100644 (file)
@@ -11,6 +11,7 @@
 
 #ifdef CONFIG_GENERIC_CPU_AUTOPROBE
 
+#include <linux/init.h>
 #include <linux/mod_devicetable.h>
 #include <asm/cpufeature.h>
 
  * For a list of legal values for 'feature', please consult the file
  * 'asm/cpufeature.h' of your favorite architecture.
  */
-#define module_cpu_feature_match(x, __init)                    \
+#define module_cpu_feature_match(x, __initfunc)                        \
 static struct cpu_feature const cpu_feature_match_ ## x[] =    \
        { { .feature = cpu_feature(x) }, { } };                 \
 MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x);             \
                                                                \
-static int cpu_feature_match_ ## x ## _init(void)              \
+static int __init cpu_feature_match_ ## x ## _init(void)       \
 {                                                              \
        if (!cpu_have_feature(cpu_feature(x)))                  \
                return -ENODEV;                                 \
-       return __init();                                        \
+       return __initfunc();                                    \
 }                                                              \
 module_init(cpu_feature_match_ ## x ## _init)
 
index 81ef938b0a8e9d34342ddbf8459a7a8b30b489d1..e71cb70a1ac2f6eb1faf9023671f469574786c60 100644 (file)
  */
 #define CRYPTO_ALG_INTERNAL            0x00002000
 
-/*
- * Temporary flag used to prevent legacy AEAD implementations from
- * being used by user-space.
- */
-#define CRYPTO_ALG_AEAD_NEW            0x00004000
-
 /*
  * Transform masks and values (for crt_flags).
  */
 struct scatterlist;
 struct crypto_ablkcipher;
 struct crypto_async_request;
-struct crypto_aead;
 struct crypto_blkcipher;
 struct crypto_hash;
 struct crypto_tfm;
 struct crypto_type;
-struct aead_request;
-struct aead_givcrypt_request;
 struct skcipher_givcrypt_request;
 
 typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err);
@@ -274,47 +265,6 @@ struct ablkcipher_alg {
        unsigned int ivsize;
 };
 
-/**
- * struct old_aead_alg - AEAD cipher definition
- * @maxauthsize: Set the maximum authentication tag size supported by the
- *              transformation. A transformation may support smaller tag sizes.
- *              As the authentication tag is a message digest to ensure the
- *              integrity of the encrypted data, a consumer typically wants the
- *              largest authentication tag possible as defined by this
- *              variable.
- * @setauthsize: Set authentication size for the AEAD transformation. This
- *              function is used to specify the consumer requested size of the
- *              authentication tag to be either generated by the transformation
- *              during encryption or the size of the authentication tag to be
- *              supplied during the decryption operation. This function is also
- *              responsible for checking the authentication tag size for
- *              validity.
- * @setkey: see struct ablkcipher_alg
- * @encrypt: see struct ablkcipher_alg
- * @decrypt: see struct ablkcipher_alg
- * @givencrypt: see struct ablkcipher_alg
- * @givdecrypt: see struct ablkcipher_alg
- * @geniv: see struct ablkcipher_alg
- * @ivsize: see struct ablkcipher_alg
- *
- * All fields except @givencrypt , @givdecrypt , @geniv and @ivsize are
- * mandatory and must be filled.
- */
-struct old_aead_alg {
-       int (*setkey)(struct crypto_aead *tfm, const u8 *key,
-                     unsigned int keylen);
-       int (*setauthsize)(struct crypto_aead *tfm, unsigned int authsize);
-       int (*encrypt)(struct aead_request *req);
-       int (*decrypt)(struct aead_request *req);
-       int (*givencrypt)(struct aead_givcrypt_request *req);
-       int (*givdecrypt)(struct aead_givcrypt_request *req);
-
-       const char *geniv;
-
-       unsigned int ivsize;
-       unsigned int maxauthsize;
-};
-
 /**
  * struct blkcipher_alg - synchronous block cipher definition
  * @min_keysize: see struct ablkcipher_alg
@@ -409,7 +359,6 @@ struct compress_alg {
 
 
 #define cra_ablkcipher cra_u.ablkcipher
-#define cra_aead       cra_u.aead
 #define cra_blkcipher  cra_u.blkcipher
 #define cra_cipher     cra_u.cipher
 #define cra_compress   cra_u.compress
@@ -460,7 +409,7 @@ struct compress_alg {
  *           struct crypto_type, which implements callbacks common for all
  *           transformation types. There are multiple options:
  *           &crypto_blkcipher_type, &crypto_ablkcipher_type,
- *           &crypto_ahash_type, &crypto_aead_type, &crypto_rng_type.
+ *           &crypto_ahash_type, &crypto_rng_type.
  *           This field might be empty. In that case, there are no common
  *           callbacks. This is the case for: cipher, compress, shash.
  * @cra_u: Callbacks implementing the transformation. This is a union of
@@ -508,7 +457,6 @@ struct crypto_alg {
 
        union {
                struct ablkcipher_alg ablkcipher;
-               struct old_aead_alg aead;
                struct blkcipher_alg blkcipher;
                struct cipher_alg cipher;
                struct compress_alg compress;
index a2b4ea70a9467520d93a556190ca8995183e4af9..1225f98e9240226ff7685190aef463b8d640a6e0 100644 (file)
@@ -341,7 +341,7 @@ struct subsys_interface {
        struct bus_type *subsys;
        struct list_head node;
        int (*add_dev)(struct device *dev, struct subsys_interface *sif);
-       int (*remove_dev)(struct device *dev, struct subsys_interface *sif);
+       void (*remove_dev)(struct device *dev, struct subsys_interface *sif);
 };
 
 int subsys_interface_register(struct subsys_interface *sif);
index b16d929fa75f811c211d171abb9c2f96d64a930f..c0f8c4fc5d45ae01be88cc26e9a07c6d273c84ce 100644 (file)
@@ -27,8 +27,6 @@
 #define __LINUX_EXTCON_H__
 
 #include <linux/device.h>
-#include <linux/notifier.h>
-#include <linux/sysfs.h>
 
 /*
  * Define the unique id of supported external connectors
@@ -77,8 +75,6 @@ struct extcon_cable;
  *                     be attached simulataneously. {0x7, 0} is equivalent to
  *                     {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
  *                     can be no simultaneous connections.
- * @print_state:       An optional callback to override the method to print the
- *                     status of the extcon device.
  * @dev:               Device of this extcon.
  * @state:             Attach/detach state of this extcon. Do not provide at
  *                     register-time.
@@ -102,9 +98,6 @@ struct extcon_dev {
        const unsigned int *supported_cable;
        const u32 *mutually_exclusive;
 
-       /* Optional callbacks to override class functions */
-       ssize_t (*print_state)(struct extcon_dev *edev, char *buf);
-
        /* Internal data. Please do not set. */
        struct device dev;
        struct raw_notifier_head *nh;
index 2a2f56b292c172408f889a33c63297d6e7d661aa..f2912914141a83df04090ab1f95b04521517188a 100644 (file)
 #define FSL_UTMI_PHY_DLY       10      /*As per P1010RM, delay for UTMI
                                PHY CLK to become stable - 10ms*/
 #define FSL_USB_PHY_CLK_TIMEOUT        10000   /* uSec */
-#define FSL_USB_VER_OLD                0
-#define FSL_USB_VER_1_6                1
-#define FSL_USB_VER_2_2                2
-#define FSL_USB_VER_2_4                3
-#define FSL_USB_VER_2_5                4
 
 #include <linux/types.h>
 
  *
  */
 
+enum fsl_usb2_controller_ver {
+       FSL_USB_VER_NONE = -1,
+       FSL_USB_VER_OLD = 0,
+       FSL_USB_VER_1_6 = 1,
+       FSL_USB_VER_2_2 = 2,
+       FSL_USB_VER_2_4 = 3,
+       FSL_USB_VER_2_5 = 4,
+};
+
 enum fsl_usb2_operating_modes {
        FSL_USB2_MPH_HOST,
        FSL_USB2_DR_HOST,
@@ -65,6 +69,7 @@ enum fsl_usb2_phy_modes {
        FSL_USB2_PHY_UTMI,
        FSL_USB2_PHY_UTMI_WIDE,
        FSL_USB2_PHY_SERIAL,
+       FSL_USB2_PHY_UTMI_DUAL,
 };
 
 struct clk;
@@ -72,7 +77,7 @@ struct platform_device;
 
 struct fsl_usb2_platform_data {
        /* board specific information */
-       int                             controller_ver;
+       enum fsl_usb2_controller_ver    controller_ver;
        enum fsl_usb2_operating_modes   operating_mode;
        enum fsl_usb2_phy_modes         phy_mode;
        unsigned int                    port_enables;
@@ -93,6 +98,9 @@ struct fsl_usb2_platform_data {
 
        unsigned        suspended:1;
        unsigned        already_suspended:1;
+       unsigned        has_fsl_erratum_a007792:1;
+       unsigned        has_fsl_erratum_a005275:1;
+       unsigned        check_phy_clk_valid:1;
 
        /* register save area for suspend/resume */
        u32             pm_command;
index 30d3a1f794507e06f5a91ab12d589172f34d3444..54733d5b503e091e01825c8fd195d1173db92ef3 100644 (file)
@@ -977,6 +977,11 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
                                         const char *mod_name);
 void vmbus_driver_unregister(struct hv_driver *hv_driver);
 
+int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
+                       resource_size_t min, resource_size_t max,
+                       resource_size_t size, resource_size_t align,
+                       bool fb_overlap_ok);
+
 /**
  * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device
  *
@@ -1233,8 +1238,6 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *,
 
 void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
 
-extern struct resource hyperv_mmio;
-
 /*
  * Negotiated version with the Host.
  */
index 2c476acb87d92784529690c6dd1b5d299a9aa2fe..3c17cd7fdf06f08b9c8a85c502f592e4124e6053 100644 (file)
@@ -166,6 +166,7 @@ struct st_sensor_transfer_function {
 /**
  * struct st_sensor_settings - ST specific sensor settings
  * @wai: Contents of WhoAmI register.
+ * @wai_addr: The address of WhoAmI register.
  * @sensors_supported: List of supported sensors by struct itself.
  * @ch: IIO channels for the sensor.
  * @odr: Output data rate register and ODR list available.
@@ -179,6 +180,7 @@ struct st_sensor_transfer_function {
  */
 struct st_sensor_settings {
        u8 wai;
+       u8 wai_addr;
        char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
        struct iio_chan_spec *ch;
        int num_ch;
index 26fb8f6342bb5267ebe0289b9a6474d2fdb18ed8..fad58671c49e00217907275865eed4987bdd87ea 100644 (file)
@@ -100,7 +100,7 @@ void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff);
 
 /**
  * iio_channel_cb_get_channels() - get access to the underlying channels.
- * @cb_buff:           The callback buffer from whom we want the channel
+ * @cb_buffer:         The callback buffer from whom we want the channel
  *                     information.
  *
  * This function allows one to obtain information about the channels.
index f79148261d16c3ebf7e5e3bf34eb022fb65bb71a..7bb7f673cb3faeb55c911e4c4d75d538f61ac787 100644 (file)
@@ -644,6 +644,15 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
  */
 #define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
 
+/**
+ * IIO_RAD_TO_DEGREE() - Convert rad to degree
+ * @rad: A value in rad
+ *
+ * Returns the given value converted from rad to degree
+ */
+#define IIO_RAD_TO_DEGREE(rad) \
+       (((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL)
+
 /**
  * IIO_G_TO_M_S_2() - Convert g to meter / second**2
  * @g: A value in g
@@ -652,4 +661,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
  */
 #define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
 
+/**
+ * IIO_M_S_2_TO_G() - Convert meter / second**2 to g
+ * @ms2: A value in meter / second**2
+ *
+ * Returns the given value converted from meter / second**2 to g
+ */
+#define IIO_M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL)
+
 #endif /* _INDUSTRIAL_IO_H_ */
index 8a1d18640ab94dd7d29ddec3473f3c5c0e9ef112..9cd8f747212fb75ad0f462d5ad4349fbd3eb94c9 100644 (file)
@@ -18,7 +18,8 @@ struct iio_chan_spec;
  * struct iio_dev_attr - iio specific device attribute
  * @dev_attr:  underlying device attribute
  * @address:   associated register address
- * @l:         list head for maintaining list of dynamically created attrs.
+ * @l:         list head for maintaining list of dynamically created attrs
+ * @c:         specification for the underlying channel
  */
 struct iio_dev_attr {
        struct device_attribute dev_attr;
index fa76c79a52a1bf5c209e6cd8a8df7dc2cad66d28..1c9e028e0d4a8223ace9236194c376b96a27d9d8 100644 (file)
@@ -18,6 +18,9 @@ struct iio_subirq {
        bool enabled;
 };
 
+struct iio_dev;
+struct iio_trigger;
+
 /**
  * struct iio_trigger_ops - operations structure for an iio_trigger.
  * @owner:             used to monitor usage count of the trigger.
index c378ebec605ec617c101078b953799f49f9b8ebe..f72f70d5a97b2ae58b7ed769d0bb6984021d5d06 100644 (file)
@@ -7,8 +7,8 @@ struct iio_dev;
 struct iio_buffer_setup_ops;
 
 int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
-       irqreturn_t (*pollfunc_bh)(int irq, void *p),
-       irqreturn_t (*pollfunc_th)(int irq, void *p),
+       irqreturn_t (*h)(int irq, void *p),
+       irqreturn_t (*thread)(int irq, void *p),
        const struct iio_buffer_setup_ops *setup_ops);
 void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev);
 
index 92188b0225bb31f33eba9deacc4b9b88036c1d8e..51744bcf74eec7bee678b9e1f63c3a10f247350e 100644 (file)
@@ -484,6 +484,7 @@ extern int irq_chip_set_affinity_parent(struct irq_data *data,
 extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
 extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data,
                                             void *vcpu_info);
+extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
 #endif
 
 /* Handling of unhandled and spurious interrupts: */
index e804306ef5e88d7b02b8b7399b4d525c16b69cd3..b63218f68c4b5a2c2862b082f62a1fe6caa5d128 100644 (file)
@@ -323,6 +323,7 @@ struct pt_regs;
 struct task_struct;
 static inline void crash_kexec(struct pt_regs *regs) { }
 static inline int kexec_should_crash(struct task_struct *p) { return 0; }
+#define kexec_in_progress false
 #endif /* CONFIG_KEXEC */
 
 #endif /* !defined(__ASSEBMLY__) */
index 05e99b8ef465bcc10ca979b26b68277191951d86..81089cf1f0c11c025b6f448d20ddcc1117ab5367 100644 (file)
@@ -139,6 +139,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQ_DISABLE_IBS       24
 #define KVM_REQ_APIC_PAGE_RELOAD  25
 #define KVM_REQ_SMI               26
+#define KVM_REQ_HV_CRASH          27
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID            0
 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID       1
@@ -363,9 +364,6 @@ struct kvm {
        struct kvm_memslots *memslots[KVM_ADDRESS_SPACE_NUM];
        struct srcu_struct srcu;
        struct srcu_struct irq_srcu;
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
-       u32 bsp_vcpu_id;
-#endif
        struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
        atomic_t online_vcpus;
        int last_boosted_vcpu;
@@ -424,8 +422,15 @@ struct kvm {
 #define vcpu_unimpl(vcpu, fmt, ...)                                    \
        kvm_pr_unimpl("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
 
+#define vcpu_debug(vcpu, fmt, ...)                                     \
+       kvm_debug("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
+
 static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
 {
+       /* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu, in case
+        * the caller has read kvm->online_vcpus before (as is the case
+        * for kvm_for_each_vcpu, for example).
+        */
        smp_rmb();
        return kvm->vcpus[i];
 }
@@ -1055,22 +1060,9 @@ static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 #endif /* CONFIG_HAVE_KVM_EVENTFD */
 
 #ifdef CONFIG_KVM_APIC_ARCHITECTURE
-static inline bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu)
-{
-       return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
-}
-
-static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
-{
-       return (vcpu->arch.apic_base & MSR_IA32_APICBASE_BSP) != 0;
-}
-
 bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
-
 #else
-
 static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
-
 #endif
 
 static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
index a16b1f9c1aca50ec2e48d917369e23f19921cf6a..0962b2ca628a932e4d2c1a84f43205fd5ddf34d5 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/mod_devicetable.h>
 
 struct mei_cl_device;
+struct mei_device;
 
 typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device,
                               u32 events, void *context);
@@ -17,6 +18,8 @@ typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device,
  * Drivers for MEI devices will get an mei_cl_device pointer
  * when being probed and shall use it for doing ME bus I/O.
  *
+ * @bus_list: device on the bus list
+ * @bus: parent mei device
  * @dev: linux driver model device pointer
  * @me_cl: me client
  * @cl: mei client
@@ -25,10 +28,16 @@ typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device,
  * @event_cb: Drivers register this callback to get asynchronous ME
  *     events (e.g. Rx buffer pending) notifications.
  * @event_context: event callback run context
+ * @events_mask: Events bit mask requested by driver.
  * @events: Events bitmask sent to the driver.
+ *
+ * @do_match: wheather device can be matched with a driver
+ * @is_added: device is already scanned
  * @priv_data: client private data
  */
 struct mei_cl_device {
+       struct list_head bus_list;
+       struct mei_device *bus;
        struct device dev;
 
        struct mei_me_client *me_cl;
@@ -38,8 +47,12 @@ struct mei_cl_device {
        struct work_struct event_work;
        mei_cl_event_cb_t event_cb;
        void *event_context;
+       unsigned long events_mask;
        unsigned long events;
 
+       unsigned int do_match:1;
+       unsigned int is_added:1;
+
        void *priv_data;
 };
 
@@ -65,10 +78,12 @@ ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length);
 ssize_t  mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length);
 
 int mei_cl_register_event_cb(struct mei_cl_device *device,
+                         unsigned long event_mask,
                          mei_cl_event_cb_t read_cb, void *context);
 
 #define MEI_CL_EVENT_RX 0
 #define MEI_CL_EVENT_TX 1
+#define MEI_CL_EVENT_NOTIF 2
 
 void *mei_cl_get_drvdata(const struct mei_cl_device *device);
 void mei_cl_set_drvdata(struct mei_cl_device *device, void *data);
diff --git a/include/linux/mfd/max77693-common.h b/include/linux/mfd/max77693-common.h
new file mode 100644 (file)
index 0000000..095b121
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Common data shared between Maxim 77693 and 77843 drivers
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ *
+ * 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_MFD_MAX77693_COMMON_H
+#define __LINUX_MFD_MAX77693_COMMON_H
+
+enum max77693_types {
+       TYPE_MAX77693_UNKNOWN,
+       TYPE_MAX77693,
+       TYPE_MAX77843,
+
+       TYPE_MAX77693_NUM,
+};
+
+/*
+ * Shared also with max77843.
+ */
+struct max77693_dev {
+       struct device *dev;
+       struct i2c_client *i2c;         /* 0xCC , PMIC, Charger, Flash LED */
+       struct i2c_client *i2c_muic;    /* 0x4A , MUIC */
+       struct i2c_client *i2c_haptic;  /* MAX77693: 0x90 , Haptic */
+       struct i2c_client *i2c_chg;     /* MAX77843: 0xD2, Charger */
+
+       enum max77693_types type;
+
+       struct regmap *regmap;
+       struct regmap *regmap_muic;
+       struct regmap *regmap_haptic;   /* Only MAX77693 */
+       struct regmap *regmap_chg;      /* Only MAX77843 */
+
+       struct regmap_irq_chip_data *irq_data_led;
+       struct regmap_irq_chip_data *irq_data_topsys;
+       struct regmap_irq_chip_data *irq_data_chg; /* Only MAX77693 */
+       struct regmap_irq_chip_data *irq_data_muic;
+
+       int irq;
+};
+
+
+#endif /*  __LINUX_MFD_MAX77693_COMMON_H */
index 51633ea6f9103cbf8f28b89901fcef48e7a7b57a..3c7a63b98ad6e7a9ec3bf687028b99424787da41 100644 (file)
@@ -310,30 +310,30 @@ enum max77693_muic_reg {
 #define INTMASK2_CHGTYP_MASK           (1 << INTMASK2_CHGTYP_SHIFT)
 
 /* MAX77693 MUIC - STATUS1~3 Register */
-#define STATUS1_ADC_SHIFT              (0)
-#define STATUS1_ADCLOW_SHIFT           (5)
-#define STATUS1_ADCERR_SHIFT           (6)
-#define STATUS1_ADC1K_SHIFT            (7)
-#define STATUS1_ADC_MASK               (0x1f << STATUS1_ADC_SHIFT)
-#define STATUS1_ADCLOW_MASK            (0x1 << STATUS1_ADCLOW_SHIFT)
-#define STATUS1_ADCERR_MASK            (0x1 << STATUS1_ADCERR_SHIFT)
-#define STATUS1_ADC1K_MASK             (0x1 << STATUS1_ADC1K_SHIFT)
-
-#define STATUS2_CHGTYP_SHIFT           (0)
-#define STATUS2_CHGDETRUN_SHIFT                (3)
-#define STATUS2_DCDTMR_SHIFT           (4)
-#define STATUS2_DXOVP_SHIFT            (5)
-#define STATUS2_VBVOLT_SHIFT           (6)
-#define STATUS2_VIDRM_SHIFT            (7)
-#define STATUS2_CHGTYP_MASK            (0x7 << STATUS2_CHGTYP_SHIFT)
-#define STATUS2_CHGDETRUN_MASK         (0x1 << STATUS2_CHGDETRUN_SHIFT)
-#define STATUS2_DCDTMR_MASK            (0x1 << STATUS2_DCDTMR_SHIFT)
-#define STATUS2_DXOVP_MASK             (0x1 << STATUS2_DXOVP_SHIFT)
-#define STATUS2_VBVOLT_MASK            (0x1 << STATUS2_VBVOLT_SHIFT)
-#define STATUS2_VIDRM_MASK             (0x1 << STATUS2_VIDRM_SHIFT)
-
-#define STATUS3_OVP_SHIFT              (2)
-#define STATUS3_OVP_MASK               (0x1 << STATUS3_OVP_SHIFT)
+#define MAX77693_STATUS1_ADC_SHIFT             0
+#define MAX77693_STATUS1_ADCLOW_SHIFT          5
+#define MAX77693_STATUS1_ADCERR_SHIFT          6
+#define MAX77693_STATUS1_ADC1K_SHIFT           7
+#define MAX77693_STATUS1_ADC_MASK              (0x1f << MAX77693_STATUS1_ADC_SHIFT)
+#define MAX77693_STATUS1_ADCLOW_MASK           BIT(MAX77693_STATUS1_ADCLOW_SHIFT)
+#define MAX77693_STATUS1_ADCERR_MASK           BIT(MAX77693_STATUS1_ADCERR_SHIFT)
+#define MAX77693_STATUS1_ADC1K_MASK            BIT(MAX77693_STATUS1_ADC1K_SHIFT)
+
+#define MAX77693_STATUS2_CHGTYP_SHIFT          0
+#define MAX77693_STATUS2_CHGDETRUN_SHIFT       3
+#define MAX77693_STATUS2_DCDTMR_SHIFT          4
+#define MAX77693_STATUS2_DXOVP_SHIFT           5
+#define MAX77693_STATUS2_VBVOLT_SHIFT          6
+#define MAX77693_STATUS2_VIDRM_SHIFT           7
+#define MAX77693_STATUS2_CHGTYP_MASK           (0x7 << MAX77693_STATUS2_CHGTYP_SHIFT)
+#define MAX77693_STATUS2_CHGDETRUN_MASK                BIT(MAX77693_STATUS2_CHGDETRUN_SHIFT)
+#define MAX77693_STATUS2_DCDTMR_MASK           BIT(MAX77693_STATUS2_DCDTMR_SHIFT)
+#define MAX77693_STATUS2_DXOVP_MASK            BIT(MAX77693_STATUS2_DXOVP_SHIFT)
+#define MAX77693_STATUS2_VBVOLT_MASK           BIT(MAX77693_STATUS2_VBVOLT_SHIFT)
+#define MAX77693_STATUS2_VIDRM_MASK            BIT(MAX77693_STATUS2_VIDRM_SHIFT)
+
+#define MAX77693_STATUS3_OVP_SHIFT             2
+#define MAX77693_STATUS3_OVP_MASK              BIT(MAX77693_STATUS3_OVP_SHIFT)
 
 /* MAX77693 CDETCTRL1~2 register */
 #define CDETCTRL1_CHGDETEN_SHIFT       (0)
@@ -362,38 +362,38 @@ enum max77693_muic_reg {
 #define COMN1SW_MASK                   (0x7 << COMN1SW_SHIFT)
 #define COMP2SW_MASK                   (0x7 << COMP2SW_SHIFT)
 #define COMP_SW_MASK                   (COMP2SW_MASK | COMN1SW_MASK)
-#define CONTROL1_SW_USB                        ((1 << COMP2SW_SHIFT) \
+#define MAX77693_CONTROL1_SW_USB       ((1 << COMP2SW_SHIFT) \
                                                | (1 << COMN1SW_SHIFT))
-#define CONTROL1_SW_AUDIO              ((2 << COMP2SW_SHIFT) \
+#define MAX77693_CONTROL1_SW_AUDIO     ((2 << COMP2SW_SHIFT) \
                                                | (2 << COMN1SW_SHIFT))
-#define CONTROL1_SW_UART               ((3 << COMP2SW_SHIFT) \
+#define MAX77693_CONTROL1_SW_UART      ((3 << COMP2SW_SHIFT) \
                                                | (3 << COMN1SW_SHIFT))
-#define CONTROL1_SW_OPEN               ((0 << COMP2SW_SHIFT) \
+#define MAX77693_CONTROL1_SW_OPEN      ((0 << COMP2SW_SHIFT) \
                                                | (0 << COMN1SW_SHIFT))
 
-#define CONTROL2_LOWPWR_SHIFT          (0)
-#define CONTROL2_ADCEN_SHIFT           (1)
-#define CONTROL2_CPEN_SHIFT            (2)
-#define CONTROL2_SFOUTASRT_SHIFT       (3)
-#define CONTROL2_SFOUTORD_SHIFT                (4)
-#define CONTROL2_ACCDET_SHIFT          (5)
-#define CONTROL2_USBCPINT_SHIFT                (6)
-#define CONTROL2_RCPS_SHIFT            (7)
-#define CONTROL2_LOWPWR_MASK           (0x1 << CONTROL2_LOWPWR_SHIFT)
-#define CONTROL2_ADCEN_MASK            (0x1 << CONTROL2_ADCEN_SHIFT)
-#define CONTROL2_CPEN_MASK             (0x1 << CONTROL2_CPEN_SHIFT)
-#define CONTROL2_SFOUTASRT_MASK                (0x1 << CONTROL2_SFOUTASRT_SHIFT)
-#define CONTROL2_SFOUTORD_MASK         (0x1 << CONTROL2_SFOUTORD_SHIFT)
-#define CONTROL2_ACCDET_MASK           (0x1 << CONTROL2_ACCDET_SHIFT)
-#define CONTROL2_USBCPINT_MASK         (0x1 << CONTROL2_USBCPINT_SHIFT)
-#define CONTROL2_RCPS_MASK             (0x1 << CONTROL2_RCPS_SHIFT)
-
-#define CONTROL3_JIGSET_SHIFT          (0)
-#define CONTROL3_BTLDSET_SHIFT         (2)
-#define CONTROL3_ADCDBSET_SHIFT                (4)
-#define CONTROL3_JIGSET_MASK           (0x3 << CONTROL3_JIGSET_SHIFT)
-#define CONTROL3_BTLDSET_MASK          (0x3 << CONTROL3_BTLDSET_SHIFT)
-#define CONTROL3_ADCDBSET_MASK         (0x3 << CONTROL3_ADCDBSET_SHIFT)
+#define MAX77693_CONTROL2_LOWPWR_SHIFT         0
+#define MAX77693_CONTROL2_ADCEN_SHIFT          1
+#define MAX77693_CONTROL2_CPEN_SHIFT           2
+#define MAX77693_CONTROL2_SFOUTASRT_SHIFT      3
+#define MAX77693_CONTROL2_SFOUTORD_SHIFT       4
+#define MAX77693_CONTROL2_ACCDET_SHIFT         5
+#define MAX77693_CONTROL2_USBCPINT_SHIFT       6
+#define MAX77693_CONTROL2_RCPS_SHIFT           7
+#define MAX77693_CONTROL2_LOWPWR_MASK          BIT(MAX77693_CONTROL2_LOWPWR_SHIFT)
+#define MAX77693_CONTROL2_ADCEN_MASK           BIT(MAX77693_CONTROL2_ADCEN_SHIFT)
+#define MAX77693_CONTROL2_CPEN_MASK            BIT(MAX77693_CONTROL2_CPEN_SHIFT)
+#define MAX77693_CONTROL2_SFOUTASRT_MASK       BIT(MAX77693_CONTROL2_SFOUTASRT_SHIFT)
+#define MAX77693_CONTROL2_SFOUTORD_MASK                BIT(MAX77693_CONTROL2_SFOUTORD_SHIFT)
+#define MAX77693_CONTROL2_ACCDET_MASK          BIT(MAX77693_CONTROL2_ACCDET_SHIFT)
+#define MAX77693_CONTROL2_USBCPINT_MASK                BIT(MAX77693_CONTROL2_USBCPINT_SHIFT)
+#define MAX77693_CONTROL2_RCPS_MASK            BIT(MAX77693_CONTROL2_RCPS_SHIFT)
+
+#define MAX77693_CONTROL3_JIGSET_SHIFT         0
+#define MAX77693_CONTROL3_BTLDSET_SHIFT                2
+#define MAX77693_CONTROL3_ADCDBSET_SHIFT       4
+#define MAX77693_CONTROL3_JIGSET_MASK          (0x3 << MAX77693_CONTROL3_JIGSET_SHIFT)
+#define MAX77693_CONTROL3_BTLDSET_MASK         (0x3 << MAX77693_CONTROL3_BTLDSET_SHIFT)
+#define MAX77693_CONTROL3_ADCDBSET_MASK                (0x3 << MAX77693_CONTROL3_ADCDBSET_SHIFT)
 
 /* Slave addr = 0x90: Haptic */
 enum max77693_haptic_reg {
@@ -529,36 +529,4 @@ enum max77693_irq_muic {
        MAX77693_MUIC_IRQ_NR,
 };
 
-struct max77693_dev {
-       struct device *dev;
-       struct i2c_client *i2c;         /* 0xCC , PMIC, Charger, Flash LED */
-       struct i2c_client *muic;        /* 0x4A , MUIC */
-       struct i2c_client *haptic;      /* 0x90 , Haptic */
-
-       int type;
-
-       struct regmap *regmap;
-       struct regmap *regmap_muic;
-       struct regmap *regmap_haptic;
-
-       struct regmap_irq_chip_data *irq_data_led;
-       struct regmap_irq_chip_data *irq_data_topsys;
-       struct regmap_irq_chip_data *irq_data_charger;
-       struct regmap_irq_chip_data *irq_data_muic;
-
-       int irq;
-       int irq_gpio;
-       struct mutex irqlock;
-       int irq_masks_cur[MAX77693_IRQ_GROUP_NR];
-       int irq_masks_cache[MAX77693_IRQ_GROUP_NR];
-};
-
-enum max77693_types {
-       TYPE_MAX77693,
-};
-
-extern int max77693_irq_init(struct max77693_dev *max77686);
-extern void max77693_irq_exit(struct max77693_dev *max77686);
-extern int max77693_irq_resume(struct max77693_dev *max77686);
-
 #endif /*  __LINUX_MFD_MAX77693_PRIV_H */
index 7178ace8379e77080b904037ec73747a6c0aa2a7..c19303b0ccfdb8c4b75b09fb9eb2f8a63299330f 100644 (file)
@@ -318,62 +318,62 @@ enum max77843_irq_muic {
        MAX77843_INTSRCMASK_SYS_MASK | MAX77843_INTSRCMASK_CHGR_MASK)
 
 /* MAX77843 STATUS register*/
-#define STATUS1_ADC_SHIFT                      0
-#define STATUS1_ADCERROR_SHIFT                 6
-#define STATUS1_ADC1K_SHIFT                    7
-#define STATUS2_CHGTYP_SHIFT                   0
-#define STATUS2_CHGDETRUN_SHIFT                        3
-#define STATUS2_DCDTMR_SHIFT                   4
-#define STATUS2_DXOVP_SHIFT                    5
-#define STATUS2_VBVOLT_SHIFT                   6
-#define STATUS3_VBADC_SHIFT                    0
-#define STATUS3_VDNMON_SHIFT                   4
-#define STATUS3_DNRES_SHIFT                    5
-#define STATUS3_MPNACK_SHIFT                   6
-
-#define MAX77843_MUIC_STATUS1_ADC_MASK         (0x1f << STATUS1_ADC_SHIFT)
-#define MAX77843_MUIC_STATUS1_ADCERROR_MASK    BIT(STATUS1_ADCERROR_SHIFT)
-#define MAX77843_MUIC_STATUS1_ADC1K_MASK       BIT(STATUS1_ADC1K_SHIFT)
-#define MAX77843_MUIC_STATUS2_CHGTYP_MASK      (0x7 << STATUS2_CHGTYP_SHIFT)
-#define MAX77843_MUIC_STATUS2_CHGDETRUN_MASK   BIT(STATUS2_CHGDETRUN_SHIFT)
-#define MAX77843_MUIC_STATUS2_DCDTMR_MASK      BIT(STATUS2_DCDTMR_SHIFT)
-#define MAX77843_MUIC_STATUS2_DXOVP_MASK       BIT(STATUS2_DXOVP_SHIFT)
-#define MAX77843_MUIC_STATUS2_VBVOLT_MASK      BIT(STATUS2_VBVOLT_SHIFT)
-#define MAX77843_MUIC_STATUS3_VBADC_MASK       (0xf << STATUS3_VBADC_SHIFT)
-#define MAX77843_MUIC_STATUS3_VDNMON_MASK      BIT(STATUS3_VDNMON_SHIFT)
-#define MAX77843_MUIC_STATUS3_DNRES_MASK       BIT(STATUS3_DNRES_SHIFT)
-#define MAX77843_MUIC_STATUS3_MPNACK_MASK      BIT(STATUS3_MPNACK_SHIFT)
+#define MAX77843_MUIC_STATUS1_ADC_SHIFT                0
+#define MAX77843_MUIC_STATUS1_ADCERROR_SHIFT   6
+#define MAX77843_MUIC_STATUS1_ADC1K_SHIFT      7
+#define MAX77843_MUIC_STATUS2_CHGTYP_SHIFT     0
+#define MAX77843_MUIC_STATUS2_CHGDETRUN_SHIFT  3
+#define MAX77843_MUIC_STATUS2_DCDTMR_SHIFT     4
+#define MAX77843_MUIC_STATUS2_DXOVP_SHIFT      5
+#define MAX77843_MUIC_STATUS2_VBVOLT_SHIFT     6
+#define MAX77843_MUIC_STATUS3_VBADC_SHIFT      0
+#define MAX77843_MUIC_STATUS3_VDNMON_SHIFT     4
+#define MAX77843_MUIC_STATUS3_DNRES_SHIFT      5
+#define MAX77843_MUIC_STATUS3_MPNACK_SHIFT     6
+
+#define MAX77843_MUIC_STATUS1_ADC_MASK         (0x1f << MAX77843_MUIC_STATUS1_ADC_SHIFT)
+#define MAX77843_MUIC_STATUS1_ADCERROR_MASK    BIT(MAX77843_MUIC_STATUS1_ADCERROR_SHIFT)
+#define MAX77843_MUIC_STATUS1_ADC1K_MASK       BIT(MAX77843_MUIC_STATUS1_ADC1K_SHIFT)
+#define MAX77843_MUIC_STATUS2_CHGTYP_MASK      (0x7 << MAX77843_MUIC_STATUS2_CHGTYP_SHIFT)
+#define MAX77843_MUIC_STATUS2_CHGDETRUN_MASK   BIT(MAX77843_MUIC_STATUS2_CHGDETRUN_SHIFT)
+#define MAX77843_MUIC_STATUS2_DCDTMR_MASK      BIT(MAX77843_MUIC_STATUS2_DCDTMR_SHIFT)
+#define MAX77843_MUIC_STATUS2_DXOVP_MASK       BIT(MAX77843_MUIC_STATUS2_DXOVP_SHIFT)
+#define MAX77843_MUIC_STATUS2_VBVOLT_MASK      BIT(MAX77843_MUIC_STATUS2_VBVOLT_SHIFT)
+#define MAX77843_MUIC_STATUS3_VBADC_MASK       (0xf << MAX77843_MUIC_STATUS3_VBADC_SHIFT)
+#define MAX77843_MUIC_STATUS3_VDNMON_MASK      BIT(MAX77843_MUIC_STATUS3_VDNMON_SHIFT)
+#define MAX77843_MUIC_STATUS3_DNRES_MASK       BIT(MAX77843_MUIC_STATUS3_DNRES_SHIFT)
+#define MAX77843_MUIC_STATUS3_MPNACK_MASK      BIT(MAX77843_MUIC_STATUS3_MPNACK_SHIFT)
 
 /* MAX77843 CONTROL register */
-#define CONTROL1_COMP1SW_SHIFT                 0
-#define CONTROL1_COMP2SW_SHIFT                 3
-#define CONTROL1_IDBEN_SHIFT                   7
-#define CONTROL2_LOWPWR_SHIFT                  0
-#define CONTROL2_ADCEN_SHIFT                   1
-#define CONTROL2_CPEN_SHIFT                    2
-#define CONTROL2_ACC_DET_SHIFT                 5
-#define CONTROL2_USBCPINT_SHIFT                        6
-#define CONTROL2_RCPS_SHIFT                    7
-#define CONTROL3_JIGSET_SHIFT                  0
-#define CONTROL4_ADCDBSET_SHIFT                        0
-#define CONTROL4_USBAUTO_SHIFT                 4
-#define CONTROL4_FCTAUTO_SHIFT                 5
-#define CONTROL4_ADCMODE_SHIFT                 6
-
-#define MAX77843_MUIC_CONTROL1_COMP1SW_MASK    (0x7 << CONTROL1_COMP1SW_SHIFT)
-#define MAX77843_MUIC_CONTROL1_COMP2SW_MASK    (0x7 << CONTROL1_COMP2SW_SHIFT)
-#define MAX77843_MUIC_CONTROL1_IDBEN_MASK      BIT(CONTROL1_IDBEN_SHIFT)
-#define MAX77843_MUIC_CONTROL2_LOWPWR_MASK     BIT(CONTROL2_LOWPWR_SHIFT)
-#define MAX77843_MUIC_CONTROL2_ADCEN_MASK      BIT(CONTROL2_ADCEN_SHIFT)
-#define MAX77843_MUIC_CONTROL2_CPEN_MASK       BIT(CONTROL2_CPEN_SHIFT)
-#define MAX77843_MUIC_CONTROL2_ACC_DET_MASK    BIT(CONTROL2_ACC_DET_SHIFT)
-#define MAX77843_MUIC_CONTROL2_USBCPINT_MASK   BIT(CONTROL2_USBCPINT_SHIFT)
-#define MAX77843_MUIC_CONTROL2_RCPS_MASK       BIT(CONTROL2_RCPS_SHIFT)
-#define MAX77843_MUIC_CONTROL3_JIGSET_MASK     (0x3 << CONTROL3_JIGSET_SHIFT)
-#define MAX77843_MUIC_CONTROL4_ADCDBSET_MASK   (0x3 << CONTROL4_ADCDBSET_SHIFT)
-#define MAX77843_MUIC_CONTROL4_USBAUTO_MASK    BIT(CONTROL4_USBAUTO_SHIFT)
-#define MAX77843_MUIC_CONTROL4_FCTAUTO_MASK    BIT(CONTROL4_FCTAUTO_SHIFT)
-#define MAX77843_MUIC_CONTROL4_ADCMODE_MASK    (0x3 << CONTROL4_ADCMODE_SHIFT)
+#define MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT   0
+#define MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT   3
+#define MAX77843_MUIC_CONTROL1_IDBEN_SHIFT     7
+#define MAX77843_MUIC_CONTROL2_LOWPWR_SHIFT    0
+#define MAX77843_MUIC_CONTROL2_ADCEN_SHIFT     1
+#define MAX77843_MUIC_CONTROL2_CPEN_SHIFT      2
+#define MAX77843_MUIC_CONTROL2_ACC_DET_SHIFT   5
+#define MAX77843_MUIC_CONTROL2_USBCPINT_SHIFT  6
+#define MAX77843_MUIC_CONTROL2_RCPS_SHIFT      7
+#define MAX77843_MUIC_CONTROL3_JIGSET_SHIFT    0
+#define MAX77843_MUIC_CONTROL4_ADCDBSET_SHIFT  0
+#define MAX77843_MUIC_CONTROL4_USBAUTO_SHIFT   4
+#define MAX77843_MUIC_CONTROL4_FCTAUTO_SHIFT   5
+#define MAX77843_MUIC_CONTROL4_ADCMODE_SHIFT   6
+
+#define MAX77843_MUIC_CONTROL1_COMP1SW_MASK    (0x7 << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT)
+#define MAX77843_MUIC_CONTROL1_COMP2SW_MASK    (0x7 << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT)
+#define MAX77843_MUIC_CONTROL1_IDBEN_MASK      BIT(MAX77843_MUIC_CONTROL1_IDBEN_SHIFT)
+#define MAX77843_MUIC_CONTROL2_LOWPWR_MASK     BIT(MAX77843_MUIC_CONTROL2_LOWPWR_SHIFT)
+#define MAX77843_MUIC_CONTROL2_ADCEN_MASK      BIT(MAX77843_MUIC_CONTROL2_ADCEN_SHIFT)
+#define MAX77843_MUIC_CONTROL2_CPEN_MASK       BIT(MAX77843_MUIC_CONTROL2_CPEN_SHIFT)
+#define MAX77843_MUIC_CONTROL2_ACC_DET_MASK    BIT(MAX77843_MUIC_CONTROL2_ACC_DET_SHIFT)
+#define MAX77843_MUIC_CONTROL2_USBCPINT_MASK   BIT(MAX77843_MUIC_CONTROL2_USBCPINT_SHIFT)
+#define MAX77843_MUIC_CONTROL2_RCPS_MASK       BIT(MAX77843_MUIC_CONTROL2_RCPS_SHIFT)
+#define MAX77843_MUIC_CONTROL3_JIGSET_MASK     (0x3 << MAX77843_MUIC_CONTROL3_JIGSET_SHIFT)
+#define MAX77843_MUIC_CONTROL4_ADCDBSET_MASK   (0x3 << MAX77843_MUIC_CONTROL4_ADCDBSET_SHIFT)
+#define MAX77843_MUIC_CONTROL4_USBAUTO_MASK    BIT(MAX77843_MUIC_CONTROL4_USBAUTO_SHIFT)
+#define MAX77843_MUIC_CONTROL4_FCTAUTO_MASK    BIT(MAX77843_MUIC_CONTROL4_FCTAUTO_SHIFT)
+#define MAX77843_MUIC_CONTROL4_ADCMODE_MASK    (0x3 << MAX77843_MUIC_CONTROL4_ADCMODE_SHIFT)
 
 /* MAX77843 switch port */
 #define COM_OPEN                               0
@@ -383,38 +383,38 @@ enum max77843_irq_muic {
 #define COM_AUX_USB                            4
 #define COM_AUX_UART                           5
 
-#define CONTROL1_COM_SW \
+#define MAX77843_MUIC_CONTROL1_COM_SW \
        ((MAX77843_MUIC_CONTROL1_COMP1SW_MASK | \
         MAX77843_MUIC_CONTROL1_COMP2SW_MASK))
 
-#define CONTROL1_SW_OPEN \
-       ((COM_OPEN << CONTROL1_COMP1SW_SHIFT | \
-        COM_OPEN << CONTROL1_COMP2SW_SHIFT))
-#define CONTROL1_SW_USB \
-       ((COM_USB << CONTROL1_COMP1SW_SHIFT | \
-        COM_USB << CONTROL1_COMP2SW_SHIFT))
-#define CONTROL1_SW_AUDIO \
-       ((COM_AUDIO << CONTROL1_COMP1SW_SHIFT | \
-        COM_AUDIO << CONTROL1_COMP2SW_SHIFT))
-#define CONTROL1_SW_UART \
-       ((COM_UART << CONTROL1_COMP1SW_SHIFT | \
-        COM_UART << CONTROL1_COMP2SW_SHIFT))
-#define CONTROL1_SW_AUX_USB \
-       ((COM_AUX_USB << CONTROL1_COMP1SW_SHIFT | \
-        COM_AUX_USB << CONTROL1_COMP2SW_SHIFT))
-#define CONTROL1_SW_AUX_UART \
-       ((COM_AUX_UART << CONTROL1_COMP1SW_SHIFT | \
-        COM_AUX_UART << CONTROL1_COMP2SW_SHIFT))
+#define MAX77843_MUIC_CONTROL1_SW_OPEN \
+       ((COM_OPEN << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT | \
+        COM_OPEN << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT))
+#define MAX77843_MUIC_CONTROL1_SW_USB \
+       ((COM_USB << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT | \
+        COM_USB << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT))
+#define MAX77843_MUIC_CONTROL1_SW_AUDIO \
+       ((COM_AUDIO << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT | \
+        COM_AUDIO << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT))
+#define MAX77843_MUIC_CONTROL1_SW_UART \
+       ((COM_UART << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT | \
+        COM_UART << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT))
+#define MAX77843_MUIC_CONTROL1_SW_AUX_USB \
+       ((COM_AUX_USB << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT | \
+        COM_AUX_USB << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT))
+#define MAX77843_MUIC_CONTROL1_SW_AUX_UART \
+       ((COM_AUX_UART << MAX77843_MUIC_CONTROL1_COMP1SW_SHIFT | \
+        COM_AUX_UART << MAX77843_MUIC_CONTROL1_COMP2SW_SHIFT))
 
 #define MAX77843_DISABLE                       0
 #define MAX77843_ENABLE                                1
 
 #define CONTROL4_AUTO_DISABLE \
-       ((MAX77843_DISABLE << CONTROL4_USBAUTO_SHIFT) | \
-       (MAX77843_DISABLE << CONTROL4_FCTAUTO_SHIFT))
+       ((MAX77843_DISABLE << MAX77843_MUIC_CONTROL4_USBAUTO_SHIFT) | \
+       (MAX77843_DISABLE << MAX77843_MUIC_CONTROL4_FCTAUTO_SHIFT))
 #define CONTROL4_AUTO_ENABLE \
-       ((MAX77843_ENABLE << CONTROL4_USBAUTO_SHIFT) | \
-       (MAX77843_ENABLE << CONTROL4_FCTAUTO_SHIFT))
+       ((MAX77843_ENABLE << MAX77843_MUIC_CONTROL4_USBAUTO_SHIFT) | \
+       (MAX77843_ENABLE << MAX77843_MUIC_CONTROL4_FCTAUTO_SHIFT))
 
 /* MAX77843 SAFEOUT LDO Control register */
 #define SAFEOUTCTRL_SAFEOUT1_SHIFT             0
@@ -431,24 +431,4 @@ enum max77843_irq_muic {
 #define MAX77843_REG_SAFEOUTCTRL_SAFEOUT2_MASK \
                (0x3 << SAFEOUTCTRL_SAFEOUT2_SHIFT)
 
-struct max77843 {
-       struct device *dev;
-
-       struct i2c_client *i2c;
-       struct i2c_client *i2c_chg;
-       struct i2c_client *i2c_fuel;
-       struct i2c_client *i2c_muic;
-
-       struct regmap *regmap;
-       struct regmap *regmap_chg;
-       struct regmap *regmap_fuel;
-       struct regmap *regmap_muic;
-
-       struct regmap_irq_chip_data *irq_data;
-       struct regmap_irq_chip_data *irq_data_chg;
-       struct regmap_irq_chip_data *irq_data_fuel;
-       struct regmap_irq_chip_data *irq_data_muic;
-
-       int irq;
-};
 #endif /* __MAX77843_H__ */
index bb270bd03eedc3eb570555b9929b7ba652a38f6e..13e1d96935ed7248a645b9b207ef64577a4b2653 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/regmap.h>
 #include <linux/regulator/driver.h>
 #include <linux/extcon.h>
+#include <linux/of_gpio.h>
 #include <linux/usb/phy_companion.h>
 
 #define PALMAS_NUM_CLIENTS             3
@@ -551,10 +552,16 @@ struct palmas_usb {
        int vbus_otg_irq;
        int vbus_irq;
 
+       int gpio_id_irq;
+       struct gpio_desc *id_gpiod;
+       unsigned long sw_debounce_jiffies;
+       struct delayed_work wq_detectid;
+
        enum palmas_usb_state linkstat;
        int wakeup;
        bool enable_vbus_detection;
        bool enable_id_detection;
+       bool enable_gpio_id_detection;
 };
 
 #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
index 819077c326901384ec3bdb8d16217a1363ab8e28..81f6e427ba6bbb9b65f52a5d5937c39aee0c0125 100644 (file)
@@ -67,7 +67,7 @@ struct miscdevice  {
 };
 
 extern int misc_register(struct miscdevice *misc);
-extern int misc_deregister(struct miscdevice *misc);
+extern void misc_deregister(struct miscdevice *misc);
 
 #define MODULE_ALIAS_MISCDEV(minor)                            \
        MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR)      \
index 2e872f92dbac0cecc2c5b3a65fbe7ff8678e48d5..bf6f117fcf4d80cb7de6147e86c6ba19fa13febd 100644 (file)
@@ -1002,6 +1002,34 @@ static inline int page_mapped(struct page *page)
        return atomic_read(&(page)->_mapcount) >= 0;
 }
 
+/*
+ * Return true only if the page has been allocated with
+ * ALLOC_NO_WATERMARKS and the low watermark was not
+ * met implying that the system is under some pressure.
+ */
+static inline bool page_is_pfmemalloc(struct page *page)
+{
+       /*
+        * Page index cannot be this large so this must be
+        * a pfmemalloc page.
+        */
+       return page->index == -1UL;
+}
+
+/*
+ * Only to be called by the page allocator on a freshly allocated
+ * page.
+ */
+static inline void set_page_pfmemalloc(struct page *page)
+{
+       page->index = -1UL;
+}
+
+static inline void clear_page_pfmemalloc(struct page *page)
+{
+       page->index = 0;
+}
+
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
  * Used to decide whether a process gets delivered SIGBUS or
index 0038ac7466fd26e7562a026af68632573e3bb0ea..15549578d55998e5497c5da58a50fa1531e132d8 100644 (file)
@@ -63,15 +63,6 @@ struct page {
                union {
                        pgoff_t index;          /* Our offset within mapping. */
                        void *freelist;         /* sl[aou]b first free object */
-                       bool pfmemalloc;        /* If set by the page allocator,
-                                                * ALLOC_NO_WATERMARKS was set
-                                                * and the low watermark was not
-                                                * met implying that the system
-                                                * is under some pressure. The
-                                                * caller should try ensure
-                                                * this page is only used to
-                                                * free other pages.
-                                                */
                };
 
                union {
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
new file mode 100644 (file)
index 0000000..9bb77d3
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * nvmem framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@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 _LINUX_NVMEM_CONSUMER_H
+#define _LINUX_NVMEM_CONSUMER_H
+
+struct device;
+struct device_node;
+/* consumer cookie */
+struct nvmem_cell;
+struct nvmem_device;
+
+struct nvmem_cell_info {
+       const char              *name;
+       unsigned int            offset;
+       unsigned int            bytes;
+       unsigned int            bit_offset;
+       unsigned int            nbits;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+/* Cell based interface */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
+
+/* direct nvmem device read/write interface */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+                                          const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+                     size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+                      size_t bytes, void *buf);
+ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+                          struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+                           struct nvmem_cell_info *info, void *buf);
+
+#else
+
+static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
+                                               const char *name)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_cell *devm_nvmem_cell_get(struct device *dev,
+                                      const char *name)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_nvmem_cell_put(struct device *dev,
+                                      struct nvmem_cell *cell)
+{
+
+}
+static inline void nvmem_cell_put(struct nvmem_cell *cell)
+{
+}
+
+static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_cell_write(struct nvmem_cell *cell,
+                                   const char *buf, size_t len)
+{
+       return -ENOSYS;
+}
+
+static inline struct nvmem_device *nvmem_device_get(struct device *dev,
+                                                   const char *name)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+                                                        const char *name)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline void nvmem_device_put(struct nvmem_device *nvmem)
+{
+}
+
+static inline void devm_nvmem_device_put(struct device *dev,
+                                        struct nvmem_device *nvmem)
+{
+}
+
+static inline ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+                                        struct nvmem_cell_info *info,
+                                        void *buf)
+{
+       return -ENOSYS;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+                                         struct nvmem_cell_info *info,
+                                         void *buf)
+{
+       return -ENOSYS;
+}
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+                                   unsigned int offset, size_t bytes,
+                                   void *buf)
+{
+       return -ENOSYS;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+                                    unsigned int offset, size_t bytes,
+                                    void *buf)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_NVMEM */
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+                                    const char *name);
+struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+                                        const char *name);
+#else
+static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+                                    const char *name)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+                                                      const char *name)
+{
+       return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_NVMEM && CONFIG_OF */
+
+#endif  /* ifndef _LINUX_NVMEM_CONSUMER_H */
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
new file mode 100644 (file)
index 0000000..0b68caf
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * nvmem framework provider.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@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 _LINUX_NVMEM_PROVIDER_H
+#define _LINUX_NVMEM_PROVIDER_H
+
+struct nvmem_device;
+struct nvmem_cell_info;
+
+struct nvmem_config {
+       struct device           *dev;
+       const char              *name;
+       int                     id;
+       struct module           *owner;
+       const struct nvmem_cell_info    *cells;
+       int                     ncells;
+       bool                    read_only;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
+int nvmem_unregister(struct nvmem_device *nvmem);
+
+#else
+
+static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_unregister(struct nvmem_device *nvmem)
+{
+       return -ENOSYS;
+}
+
+#endif /* CONFIG_NVMEM */
+
+#endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
index 72031785fe1d810f186257a33e66ddb3147b9b59..57e0b8250947b099110e999246cba662684b3149 100644 (file)
@@ -3,55 +3,6 @@
 
 #include <linux/pci.h>
 
-/* Address Translation Service */
-struct pci_ats {
-       int pos;        /* capability position */
-       int stu;        /* Smallest Translation Unit */
-       int qdep;       /* Invalidate Queue Depth */
-       int ref_cnt;    /* Physical Function reference count */
-       unsigned int is_enabled:1;      /* Enable bit is set */
-};
-
-#ifdef CONFIG_PCI_ATS
-
-int pci_enable_ats(struct pci_dev *dev, int ps);
-void pci_disable_ats(struct pci_dev *dev);
-int pci_ats_queue_depth(struct pci_dev *dev);
-
-/**
- * pci_ats_enabled - query the ATS status
- * @dev: the PCI device
- *
- * Returns 1 if ATS capability is enabled, or 0 if not.
- */
-static inline int pci_ats_enabled(struct pci_dev *dev)
-{
-       return dev->ats && dev->ats->is_enabled;
-}
-
-#else /* CONFIG_PCI_ATS */
-
-static inline int pci_enable_ats(struct pci_dev *dev, int ps)
-{
-       return -ENODEV;
-}
-
-static inline void pci_disable_ats(struct pci_dev *dev)
-{
-}
-
-static inline int pci_ats_queue_depth(struct pci_dev *dev)
-{
-       return -ENODEV;
-}
-
-static inline int pci_ats_enabled(struct pci_dev *dev)
-{
-       return 0;
-}
-
-#endif /* CONFIG_PCI_ATS */
-
 #ifdef CONFIG_PCI_PRI
 
 int pci_enable_pri(struct pci_dev *pdev, u32 reqs);
index 8a0321a8fb595892c5e80910d5c914c89ded63de..3c8eb57de620018bfb90fb56b24e891b8a831dc1 100644 (file)
@@ -180,6 +180,8 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_BUS_RESET = (__force pci_dev_flags_t) (1 << 6),
        /* Do not use PM reset even if device advertises NoSoftRst- */
        PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
+       /* Get VPD from function 0 VPD */
+       PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
 };
 
 enum pci_irq_reroute_variant {
@@ -343,6 +345,7 @@ struct pci_dev {
        unsigned int    msi_enabled:1;
        unsigned int    msix_enabled:1;
        unsigned int    ari_enabled:1;  /* ARI forwarding */
+       unsigned int    ats_enabled:1;  /* Address Translation Service */
        unsigned int    is_managed:1;
        unsigned int    needs_freset:1; /* Dev requires fundamental reset */
        unsigned int    state_saved:1;
@@ -375,7 +378,9 @@ struct pci_dev {
                struct pci_sriov *sriov;        /* SR-IOV capability related */
                struct pci_dev *physfn; /* the PF this VF is associated with */
        };
-       struct pci_ats  *ats;   /* Address Translation Service */
+       u16             ats_cap;        /* ATS Capability offset */
+       u8              ats_stu;        /* ATS Smallest Translation Unit */
+       atomic_t        ats_ref_cnt;    /* number of VFs with ATS enabled */
 #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 */
@@ -446,7 +451,8 @@ struct pci_bus {
        struct list_head children;      /* list of child buses */
        struct list_head devices;       /* list of devices on this bus */
        struct pci_dev  *self;          /* bridge device as seen by parent */
-       struct list_head slots;         /* list of slots on this bus */
+       struct list_head slots;         /* list of slots on this bus;
+                                          protected by pci_slot_mutex */
        struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
        struct list_head resources;     /* address space routed to this bus */
        struct resource busn_res;       /* bus numbers routed to this bus */
@@ -738,10 +744,11 @@ struct pci_driver {
 void pcie_bus_configure_settings(struct pci_bus *bus);
 
 enum pcie_bus_config_types {
-       PCIE_BUS_TUNE_OFF,
-       PCIE_BUS_SAFE,
-       PCIE_BUS_PERFORMANCE,
-       PCIE_BUS_PEER2PEER,
+       PCIE_BUS_TUNE_OFF,      /* don't touch MPS at all */
+       PCIE_BUS_DEFAULT,       /* ensure MPS matches upstream bridge */
+       PCIE_BUS_SAFE,          /* use largest MPS boot-time devices support */
+       PCIE_BUS_PERFORMANCE,   /* use MPS and MRRS for best performance */
+       PCIE_BUS_PEER2PEER,     /* set MPS = 128 for all devices */
 };
 
 extern enum pcie_bus_config_types pcie_bus_config;
@@ -787,6 +794,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
 int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
 void pci_bus_release_busn_res(struct pci_bus *b);
+struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
+                                     struct pci_ops *ops, void *sysdata,
+                                     struct list_head *resources,
+                                     struct msi_controller *msi);
 struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
                                             struct pci_ops *ops, void *sysdata,
                                             struct list_head *resources);
@@ -797,6 +808,11 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
                                 const char *name,
                                 struct hotplug_slot *hotplug);
 void pci_destroy_slot(struct pci_slot *slot);
+#ifdef CONFIG_SYSFS
+void pci_dev_assign_slot(struct pci_dev *dev);
+#else
+static inline void pci_dev_assign_slot(struct pci_dev *dev) { }
+#endif
 int pci_scan_slot(struct pci_bus *bus, int devfn);
 struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
@@ -963,6 +979,23 @@ static inline int pci_is_managed(struct pci_dev *pdev)
        return pdev->is_managed;
 }
 
+static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq)
+{
+       pdev->irq = irq;
+       pdev->irq_managed = 1;
+}
+
+static inline void pci_reset_managed_irq(struct pci_dev *pdev)
+{
+       pdev->irq = 0;
+       pdev->irq_managed = 0;
+}
+
+static inline bool pci_has_managed_irq(struct pci_dev *pdev)
+{
+       return pdev->irq_managed && pdev->irq > 0;
+}
+
 void pci_disable_device(struct pci_dev *dev);
 
 extern unsigned int pcibios_max_latency;
@@ -1202,6 +1235,7 @@ struct msix_entry {
        u16     entry;  /* driver uses to specify entry, OS writes */
 };
 
+void pci_msi_setup_pci_dev(struct pci_dev *dev);
 
 #ifdef CONFIG_PCI_MSI
 int pci_msi_vec_count(struct pci_dev *dev);
@@ -1294,6 +1328,19 @@ int  ht_create_irq(struct pci_dev *dev, int idx);
 void ht_destroy_irq(unsigned int irq);
 #endif /* CONFIG_HT_IRQ */
 
+#ifdef CONFIG_PCI_ATS
+/* Address Translation Service */
+void pci_ats_init(struct pci_dev *dev);
+int pci_enable_ats(struct pci_dev *dev, int ps);
+void pci_disable_ats(struct pci_dev *dev);
+int pci_ats_queue_depth(struct pci_dev *dev);
+#else
+static inline void pci_ats_init(struct pci_dev *d) { }
+static inline int pci_enable_ats(struct pci_dev *d, int ps) { return -ENODEV; }
+static inline void pci_disable_ats(struct pci_dev *d) { }
+static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; }
+#endif
+
 void pci_cfg_access_lock(struct pci_dev *dev);
 bool pci_cfg_access_trylock(struct pci_dev *dev);
 void pci_cfg_access_unlock(struct pci_dev *dev);
@@ -1645,6 +1692,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
 int pcibios_add_device(struct pci_dev *dev);
 void pcibios_release_device(struct pci_dev *dev);
 void pcibios_penalize_isa_irq(int irq, int active);
+int pcibios_alloc_irq(struct pci_dev *dev);
+void pcibios_free_irq(struct pci_dev *dev);
 
 #ifdef CONFIG_HIBERNATE_CALLBACKS
 extern struct dev_pm_ops pcibios_pm_ops;
index 4b452c6a2f7be58b65214c3c6b6002e00d23bacd..527a85c6192443a50ca8846f24fe40d7e726eca9 100644 (file)
@@ -46,18 +46,6 @@ struct at91_cf_data {
 #define AT91_IDE_SWAP_A0_A2    0x02
 };
 
- /* USB Host */
-#define AT91_MAX_USBH_PORTS    3
-struct at91_usbh_data {
-       int             vbus_pin[AT91_MAX_USBH_PORTS];  /* port power-control pin */
-       int             overcurrent_pin[AT91_MAX_USBH_PORTS];
-       u8              ports;                          /* number of ports on root hub */
-       u8              overcurrent_supported;
-       u8              vbus_pin_active_low[AT91_MAX_USBH_PORTS];
-       u8              overcurrent_status[AT91_MAX_USBH_PORTS];
-       u8              overcurrent_changed[AT91_MAX_USBH_PORTS];
-};
-
  /* NAND / SmartMedia */
 struct atmel_nand_data {
        int             enable_pin;             /* chip enable */
index 97baf831e07114c04b5e3d4163738da98b0ba5be..3af0da1f3be58bc3f118f2de25d6784261ff8871 100644 (file)
 #ifndef __CLK_UX500_H
 #define __CLK_UX500_H
 
-void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                      u32 clkrst5_base, u32 clkrst6_base);
-
-void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base);
-void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base);
-void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
-                   u32 clkrst5_base, u32 clkrst6_base);
+void u8500_clk_init(void);
+void u9540_clk_init(void);
+void u8540_clk_init(void);
 
 #endif /* __CLK_UX500_H */
index 6a9fed57f34620c20a931f317150e5a381058e8f..eb8a6860e81691085e1735ce565a37a28bbfd7d3 100644 (file)
@@ -9,11 +9,25 @@
 #ifndef __LEDS_KIRKWOOD_NS2_H
 #define __LEDS_KIRKWOOD_NS2_H
 
+enum ns2_led_modes {
+       NS_V2_LED_OFF,
+       NS_V2_LED_ON,
+       NS_V2_LED_SATA,
+};
+
+struct ns2_led_modval {
+       enum ns2_led_modes      mode;
+       int                     cmd_level;
+       int                     slow_level;
+};
+
 struct ns2_led {
        const char      *name;
        const char      *default_trigger;
        unsigned        cmd;
        unsigned        slow;
+       int             num_modes;
+       struct ns2_led_modval *modval;
 };
 
 struct ns2_led_platform_data {
index 8dc2fa47a2aa3c095f66f234d2975c5e18e10f53..f4edcb03c40c9f22bbefc708c831c922cfc9fe4f 100644 (file)
@@ -49,6 +49,7 @@ struct davinci_spi_platform_data {
        u8                      num_chipselect;
        u8                      intr_line;
        u8                      *chip_sel;
+       u8                      prescaler_limit;
        bool                    cshold_bug;
        enum dma_event_q        dma_event_q;
 };
diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h
new file mode 100644 (file)
index 0000000..54b0448
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  MTK SPI bus driver definitions
+ *
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Leilk Liu <leilk.liu@mediatek.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 ____LINUX_PLATFORM_DATA_SPI_MTK_H
+#define ____LINUX_PLATFORM_DATA_SPI_MTK_H
+
+/* Board specific platform_data */
+struct mtk_chip_config {
+       u32 tx_mlsb;
+       u32 rx_mlsb;
+};
+#endif
index 0485bab061fd3936a1f53aafefbf87b659df0365..92273776bce6ba9845ab2584644718cbabcb0dd6 100644 (file)
@@ -197,6 +197,7 @@ enum pxa_ssp_type {
        QUARK_X1000_SSP,
        LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
        LPSS_BYT_SSP,
+       LPSS_SPT_SSP,
 };
 
 struct ssp_device {
index f8a689ed62a58753cb3d4863f61d834cdca74f62..9e0e76992be082f68ba6651207fc8b7a4f9bc976 100644 (file)
@@ -550,8 +550,24 @@ static inline int regulator_count_voltages(struct regulator *regulator)
 {
        return 0;
 }
+
+static inline int regulator_list_voltage(struct regulator *regulator, unsigned selector)
+{
+       return -EINVAL;
+}
+
 #endif
 
+static inline int regulator_set_voltage_triplet(struct regulator *regulator,
+                                               int min_uV, int target_uV,
+                                               int max_uV)
+{
+       if (regulator_set_voltage(regulator, target_uV, max_uV) == 0)
+               return 0;
+
+       return regulator_set_voltage(regulator, min_uV, max_uV);
+}
+
 static inline int regulator_set_voltage_tol(struct regulator *regulator,
                                            int new_uV, int tol_uV)
 {
index 5dd65acc2a69e5188bb1f5d95ac1223c67fd36bc..a43a5ca1167b753938bedcc984771fead101b89d 100644 (file)
@@ -1,16 +1,16 @@
 /*
- * da9211.h - Regulator device driver for DA9211/DA9213
- * Copyright (C) 2014  Dialog Semiconductor Ltd.
+ * da9211.h - Regulator device driver for DA9211/DA9213/DA9215
+ * Copyright (C) 2015  Dialog Semiconductor Ltd.
  *
- * 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 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 library is distributed in the hope that it will be useful,
+ * 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
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __LINUX_REGULATOR_DA9211_H
@@ -23,6 +23,7 @@
 enum da9211_chip_id {
        DA9211,
        DA9213,
+       DA9215,
 };
 
 struct da9211_pdata {
index 4db9fbe4889d3c54f76c2c2c1e3d50ce404d0965..45932228cbf5924c507bbc4b39c405bb9ab750f7 100644 (file)
@@ -148,6 +148,7 @@ struct regulator_ops {
        int (*get_current_limit) (struct regulator_dev *);
 
        int (*set_input_current_limit) (struct regulator_dev *, int lim_uA);
+       int (*set_over_current_protection) (struct regulator_dev *);
 
        /* enable/disable regulator */
        int (*enable) (struct regulator_dev *);
index b11be126012974ebf4877220c8949310d649ddea..a1067d0b39916b869eebc6a179c3696a115e3996 100644 (file)
@@ -147,6 +147,7 @@ struct regulation_constraints {
        unsigned ramp_disable:1; /* disable ramp delay */
        unsigned soft_start:1;  /* ramp voltage slowly */
        unsigned pull_down:1;   /* pull down resistor when regulator off */
+       unsigned over_current_protection:1; /* auto disable on over current */
 };
 
 /**
diff --git a/include/linux/regulator/mt6311.h b/include/linux/regulator/mt6311.h
new file mode 100644 (file)
index 0000000..8473259
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Henry Chen <henryc.chen@mediatek.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.
+ */
+
+#ifndef __LINUX_REGULATOR_MT6311_H
+#define __LINUX_REGULATOR_MT6311_H
+
+#define MT6311_MAX_REGULATORS  2
+
+enum {
+       MT6311_ID_VDVFS = 0,
+       MT6311_ID_VBIASN,
+};
+
+#define MT6311_E1_CID_CODE    0x10
+#define MT6311_E2_CID_CODE    0x20
+#define MT6311_E3_CID_CODE    0x30
+
+#endif /* __LINUX_REGULATOR_MT6311_H */
index ba82c07feb95cbe8eb9e2362f49e4eadc5fcf04d..faa0e0370ce73c59305ed2a14928ad8bb0c4cbe2 100644 (file)
@@ -136,8 +136,6 @@ void serial8250_resume_port(int line);
 
 extern int early_serial_setup(struct uart_port *port);
 
-extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
-extern void serial8250_early_out(struct uart_port *port, int offset, int value);
 extern int early_serial8250_setup(struct earlycon_device *device,
                                         const char *options);
 extern void serial8250_do_set_termios(struct uart_port *port,
@@ -152,6 +150,11 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
 unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
 void serial8250_tx_chars(struct uart_8250_port *up);
 unsigned int serial8250_modem_status(struct uart_8250_port *up);
+void serial8250_init_port(struct uart_8250_port *up);
+void serial8250_set_defaults(struct uart_8250_port *up);
+void serial8250_console_write(struct uart_8250_port *up, const char *s,
+                             unsigned int count);
+int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
 
 extern void serial8250_set_isa_configurator(void (*v)
                                        (int port, struct uart_port *up,
index d6cdd6e87d53bcd1b4f390f61f73b1c91b076bdd..9b88536487e667b8727414e4131188db869711d4 100644 (file)
@@ -1602,20 +1602,16 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
        /*
-        * Propagate page->pfmemalloc to the skb if we can. The problem is
-        * that not all callers have unique ownership of the page. If
-        * pfmemalloc is set, we check the mapping as a mapping implies
-        * page->index is set (index and pfmemalloc share space).
-        * If it's a valid mapping, we cannot use page->pfmemalloc but we
-        * do not lose pfmemalloc information as the pages would not be
-        * allocated using __GFP_MEMALLOC.
+        * Propagate page pfmemalloc to the skb if we can. The problem is
+        * that not all callers have unique ownership of the page but rely
+        * on page_is_pfmemalloc doing the right thing(tm).
         */
        frag->page.p              = page;
        frag->page_offset         = off;
        skb_frag_size_set(frag, size);
 
        page = compound_head(page);
-       if (page->pfmemalloc && !page->mapping)
+       if (page_is_pfmemalloc(page))
                skb->pfmemalloc = true;
 }
 
@@ -2263,7 +2259,7 @@ static inline struct page *dev_alloc_page(void)
 static inline void skb_propagate_pfmemalloc(struct page *page,
                                             struct sk_buff *skb)
 {
-       if (page && page->pfmemalloc)
+       if (page_is_pfmemalloc(page))
                skb->pfmemalloc = true;
 }
 
@@ -2884,11 +2880,11 @@ static inline bool skb_defer_rx_timestamp(struct sk_buff *skb)
  *
  * PHY drivers may accept clones of transmitted packets for
  * timestamping via their phy_driver.txtstamp method. These drivers
- * must call this function to return the skb back to the stack, with
- * or without a timestamp.
+ * must call this function to return the skb back to the stack with a
+ * timestamp.
  *
  * @skb: clone of the the original outgoing packet
- * @hwtstamps: hardware time stamps, may be NULL if not available
+ * @hwtstamps: hardware time stamps
  *
  */
 void skb_complete_tx_timestamp(struct sk_buff *skb,
index d673072346f2e0415fd4706c7606d5081f87f686..269e8afd3e2a5826c38282a3577447f3ff42997b 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/scatterlist.h>
 
 struct dma_chan;
+struct spi_master;
+struct spi_transfer;
 
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@ -30,6 +32,59 @@ struct dma_chan;
  */
 extern struct bus_type spi_bus_type;
 
+/**
+ * struct spi_statistics - statistics for spi transfers
+ * @clock:         lock protecting this structure
+ *
+ * @messages:      number of spi-messages handled
+ * @transfers:     number of spi_transfers handled
+ * @errors:        number of errors during spi_transfer
+ * @timedout:      number of timeouts during spi_transfer
+ *
+ * @spi_sync:      number of times spi_sync is used
+ * @spi_sync_immediate:
+ *                 number of times spi_sync is executed immediately
+ *                 in calling context without queuing and scheduling
+ * @spi_async:     number of times spi_async is used
+ *
+ * @bytes:         number of bytes transferred to/from device
+ * @bytes_tx:      number of bytes sent to device
+ * @bytes_rx:      number of bytes received from device
+ *
+ */
+struct spi_statistics {
+       spinlock_t              lock; /* lock for the whole structure */
+
+       unsigned long           messages;
+       unsigned long           transfers;
+       unsigned long           errors;
+       unsigned long           timedout;
+
+       unsigned long           spi_sync;
+       unsigned long           spi_sync_immediate;
+       unsigned long           spi_async;
+
+       unsigned long long      bytes;
+       unsigned long long      bytes_rx;
+       unsigned long long      bytes_tx;
+
+};
+
+void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
+                                      struct spi_transfer *xfer,
+                                      struct spi_master *master);
+
+#define SPI_STATISTICS_ADD_TO_FIELD(stats, field, count)       \
+       do {                                                    \
+               unsigned long flags;                            \
+               spin_lock_irqsave(&(stats)->lock, flags);       \
+               (stats)->field += count;                        \
+               spin_unlock_irqrestore(&(stats)->lock, flags);  \
+       } while (0)
+
+#define SPI_STATISTICS_INCREMENT_FIELD(stats, field)   \
+       SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1)
+
 /**
  * struct spi_device - Master side proxy for an SPI slave device
  * @dev: Driver model representation of the device.
@@ -60,6 +115,8 @@ extern struct bus_type spi_bus_type;
  * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when
  *     when not using a GPIO line)
  *
+ * @statistics: statistics for the spi_device
+ *
  * A @spi_device is used to interchange data between an SPI slave
  * (usually a discrete chip) and CPU memory.
  *
@@ -98,6 +155,9 @@ struct spi_device {
        char                    modalias[SPI_NAME_SIZE];
        int                     cs_gpio;        /* chip select gpio */
 
+       /* the statistics */
+       struct spi_statistics   statistics;
+
        /*
         * likely need more hooks for more protocol options affecting how
         * the controller talks to each chip, like:
@@ -296,6 +356,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *     number. Any individual value may be -ENOENT for CS lines that
  *     are not GPIOs (driven by the SPI controller itself).
+ * @statistics: statistics for the spi_master
  * @dma_tx: DMA transmit channel
  * @dma_rx: DMA receive channel
  * @dummy_rx: dummy receive buffer for full-duplex devices
@@ -452,6 +513,9 @@ struct spi_master {
        /* gpio chip select */
        int                     *cs_gpios;
 
+       /* statistics */
+       struct spi_statistics   statistics;
+
        /* DMA channels for use with core dmaengine helpers */
        struct dma_chan         *dma_tx;
        struct dma_chan         *dma_rx;
index c78dcfeaf25f846ce105274d7c905aa181a53174..d4217eff489fe96087c49c491602ead6e88a9e44 100644 (file)
@@ -86,7 +86,6 @@ struct st_proto_s {
 extern long st_register(struct st_proto_s *);
 extern long st_unregister(struct st_proto_s *);
 
-extern struct ti_st_plat_data   *dt_pdata;
 
 /*
  * header information used by st_core.c
index ad6c8913aa3edacc0ee4dc4c4cf07f94fcebf669..d072ded416786631838ec0aefaf6428362b0f291 100644 (file)
@@ -709,4 +709,10 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {}
 static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
 #endif
 
+#define tty_debug(tty, f, args...)                                     \
+       do {                                                            \
+               printk(KERN_DEBUG "%s: %s: " f, __func__,               \
+                      tty_name(tty), ##args);                          \
+       } while (0)
+
 #endif
index 92e337c18839b0df2e9c213fd0604983dfcdaefd..161052477f77009e59744339ac5377e4a9b03356 100644 (file)
@@ -296,7 +296,7 @@ struct tty_operations {
 struct tty_driver {
        int     magic;          /* magic number for this structure */
        struct kref kref;       /* Reference management */
-       struct cdev *cdevs;
+       struct cdev **cdevs;
        struct module   *owner;
        const char      *driver_name;
        const char      *name;
index ab94f78c4dd15ee4554a4eff996c862b7a6fd869..a41833cd184c64dbc99a02731b508ade382e2538 100644 (file)
@@ -19,8 +19,11 @@ struct ci_hdrc_platform_data {
        enum usb_phy_interface phy_mode;
        unsigned long    flags;
 #define CI_HDRC_REGS_SHARED            BIT(0)
+#define CI_HDRC_DISABLE_DEVICE_STREAMING       BIT(1)
 #define CI_HDRC_SUPPORTS_RUNTIME_PM    BIT(2)
-#define CI_HDRC_DISABLE_STREAMING      BIT(3)
+#define CI_HDRC_DISABLE_HOST_STREAMING BIT(3)
+#define CI_HDRC_DISABLE_STREAMING (CI_HDRC_DISABLE_DEVICE_STREAMING |  \
+               CI_HDRC_DISABLE_HOST_STREAMING)
        /*
         * Only set it when DCCPARAMS.DC==1 and DCCPARAMS.HC==1,
         * but otg is not supported (no register otgsc).
@@ -29,12 +32,22 @@ struct ci_hdrc_platform_data {
 #define CI_HDRC_IMX28_WRITE_FIX                BIT(5)
 #define CI_HDRC_FORCE_FULLSPEED                BIT(6)
 #define CI_HDRC_TURN_VBUS_EARLY_ON     BIT(7)
+#define CI_HDRC_SET_NON_ZERO_TTHA      BIT(8)
+#define CI_HDRC_OVERRIDE_AHB_BURST     BIT(9)
+#define CI_HDRC_OVERRIDE_TX_BURST      BIT(10)
+#define CI_HDRC_OVERRIDE_RX_BURST      BIT(11)
        enum usb_dr_mode        dr_mode;
 #define CI_HDRC_CONTROLLER_RESET_EVENT         0
 #define CI_HDRC_CONTROLLER_STOPPED_EVENT       1
        void    (*notify_event) (struct ci_hdrc *ci, unsigned event);
        struct regulator        *reg_vbus;
+       struct usb_otg_caps     ci_otg_caps;
        bool                    tpl_support;
+       /* interrupt threshold setting */
+       u32                     itc_setting;
+       u32                     ahb_burst_config;
+       u32                     tx_burst_size;
+       u32                     rx_burst_size;
 };
 
 /* Default offset of capability registers */
index 2511469a99048996fa53232801fdb6a72bb90d4b..1074b8921a5dc59dda948ef39e7281f63d420efb 100644 (file)
@@ -228,6 +228,8 @@ struct usb_function {
        struct list_head                list;
        DECLARE_BITMAP(endpoints, 32);
        const struct usb_function_instance *fi;
+
+       unsigned int            bind_deactivated:1;
 };
 
 int usb_add_function(struct usb_configuration *, struct usb_function *);
index 4f3dfb7d065420d012eeade7154575100473602c..c14a69b36d27b14afc1da26ab616797e7daaaf8d 100644 (file)
@@ -140,11 +140,50 @@ struct usb_ep_ops {
        void (*fifo_flush) (struct usb_ep *ep);
 };
 
+/**
+ * struct usb_ep_caps - endpoint capabilities description
+ * @type_control:Endpoint supports control type (reserved for ep0).
+ * @type_iso:Endpoint supports isochronous transfers.
+ * @type_bulk:Endpoint supports bulk transfers.
+ * @type_int:Endpoint supports interrupt transfers.
+ * @dir_in:Endpoint supports IN direction.
+ * @dir_out:Endpoint supports OUT direction.
+ */
+struct usb_ep_caps {
+       unsigned type_control:1;
+       unsigned type_iso:1;
+       unsigned type_bulk:1;
+       unsigned type_int:1;
+       unsigned dir_in:1;
+       unsigned dir_out:1;
+};
+
+#define USB_EP_CAPS_TYPE_CONTROL     0x01
+#define USB_EP_CAPS_TYPE_ISO         0x02
+#define USB_EP_CAPS_TYPE_BULK        0x04
+#define USB_EP_CAPS_TYPE_INT         0x08
+#define USB_EP_CAPS_TYPE_ALL \
+       (USB_EP_CAPS_TYPE_ISO | USB_EP_CAPS_TYPE_BULK | USB_EP_CAPS_TYPE_INT)
+#define USB_EP_CAPS_DIR_IN           0x01
+#define USB_EP_CAPS_DIR_OUT          0x02
+#define USB_EP_CAPS_DIR_ALL  (USB_EP_CAPS_DIR_IN | USB_EP_CAPS_DIR_OUT)
+
+#define USB_EP_CAPS(_type, _dir) \
+       { \
+               .type_control = !!(_type & USB_EP_CAPS_TYPE_CONTROL), \
+               .type_iso = !!(_type & USB_EP_CAPS_TYPE_ISO), \
+               .type_bulk = !!(_type & USB_EP_CAPS_TYPE_BULK), \
+               .type_int = !!(_type & USB_EP_CAPS_TYPE_INT), \
+               .dir_in = !!(_dir & USB_EP_CAPS_DIR_IN), \
+               .dir_out = !!(_dir & USB_EP_CAPS_DIR_OUT), \
+       }
+
 /**
  * struct usb_ep - device side representation of USB endpoint
  * @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk"
  * @ops: Function pointers used to access hardware-specific operations.
  * @ep_list:the gadget's ep_list holds all of its endpoints
+ * @caps:The structure describing types and directions supported by endoint.
  * @maxpacket:The maximum packet size used on this endpoint.  The initial
  *     value can sometimes be reduced (hardware allowing), according to
  *      the endpoint descriptor used to configure the endpoint.
@@ -167,12 +206,15 @@ struct usb_ep_ops {
  * gadget->ep_list.  the control endpoint (gadget->ep0) is not in that list,
  * and is accessed only in response to a driver setup() callback.
  */
+
 struct usb_ep {
        void                    *driver_data;
 
        const char              *name;
        const struct usb_ep_ops *ops;
        struct list_head        ep_list;
+       struct usb_ep_caps      caps;
+       bool                    claimed;
        unsigned                maxpacket:16;
        unsigned                maxpacket_limit:16;
        unsigned                max_streams:16;
@@ -492,6 +534,9 @@ struct usb_gadget_ops {
        int     (*udc_start)(struct usb_gadget *,
                        struct usb_gadget_driver *);
        int     (*udc_stop)(struct usb_gadget *);
+       struct usb_ep *(*match_ep)(struct usb_gadget *,
+                       struct usb_endpoint_descriptor *,
+                       struct usb_ss_ep_comp_descriptor *);
 };
 
 /**
@@ -511,6 +556,7 @@ struct usb_gadget_ops {
  * @dev: Driver model state for this abstract device.
  * @out_epnum: last used out ep number
  * @in_epnum: last used in ep number
+ * @otg_caps: OTG capabilities of this gadget.
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  *     gadget driver must provide a USB OTG descriptor.
@@ -526,6 +572,9 @@ struct usb_gadget_ops {
  * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
  *     MaxPacketSize.
  * @is_selfpowered: if the gadget is self-powered.
+ * @deactivated: True if gadget is deactivated - in deactivated state it cannot
+ *     be connected.
+ * @connected: True if gadget is connected.
  *
  * Gadgets have a mostly-portable "gadget driver" implementing device
  * functions, handling all usb configurations and interfaces.  Gadget
@@ -559,6 +608,7 @@ struct usb_gadget {
        struct device                   dev;
        unsigned                        out_epnum;
        unsigned                        in_epnum;
+       struct usb_otg_caps             *otg_caps;
 
        unsigned                        sg_supported:1;
        unsigned                        is_otg:1;
@@ -567,7 +617,12 @@ struct usb_gadget {
        unsigned                        a_hnp_support:1;
        unsigned                        a_alt_hnp_support:1;
        unsigned                        quirk_ep_out_aligned_size:1;
+       unsigned                        quirk_altset_not_supp:1;
+       unsigned                        quirk_stall_not_supp:1;
+       unsigned                        quirk_zlp_not_supp:1;
        unsigned                        is_selfpowered:1;
+       unsigned                        deactivated:1;
+       unsigned                        connected:1;
 };
 #define work_to_gadget(w)      (container_of((w), struct usb_gadget, work))
 
@@ -584,7 +639,6 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev)
 #define gadget_for_each_ep(tmp, gadget) \
        list_for_each_entry(tmp, &(gadget)->ep_list, ep_list)
 
-
 /**
  * usb_ep_align_maybe - returns @len aligned to ep's maxpacketsize if gadget
  *     requires quirk_ep_out_aligned_size, otherwise reguens len.
@@ -602,6 +656,34 @@ usb_ep_align_maybe(struct usb_gadget *g, struct usb_ep *ep, size_t len)
                        round_up(len, (size_t)ep->desc->wMaxPacketSize);
 }
 
+/**
+ * gadget_is_altset_supported - return true iff the hardware supports
+ *     altsettings
+ * @g: controller to check for quirk
+ */
+static inline int gadget_is_altset_supported(struct usb_gadget *g)
+{
+       return !g->quirk_altset_not_supp;
+}
+
+/**
+ * gadget_is_stall_supported - return true iff the hardware supports stalling
+ * @g: controller to check for quirk
+ */
+static inline int gadget_is_stall_supported(struct usb_gadget *g)
+{
+       return !g->quirk_stall_not_supp;
+}
+
+/**
+ * gadget_is_zlp_supported - return true iff the hardware supports zlp
+ * @g: controller to check for quirk
+ */
+static inline int gadget_is_zlp_supported(struct usb_gadget *g)
+{
+       return !g->quirk_zlp_not_supp;
+}
+
 /**
  * gadget_is_dualspeed - return true iff the hardware handles high speed
  * @g: controller that might support both high and full speeds
@@ -771,9 +853,24 @@ static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
  */
 static inline int usb_gadget_connect(struct usb_gadget *gadget)
 {
+       int ret;
+
        if (!gadget->ops->pullup)
                return -EOPNOTSUPP;
-       return gadget->ops->pullup(gadget, 1);
+
+       if (gadget->deactivated) {
+               /*
+                * If gadget is deactivated we only save new state.
+                * Gadget will be connected automatically after activation.
+                */
+               gadget->connected = true;
+               return 0;
+       }
+
+       ret = gadget->ops->pullup(gadget, 1);
+       if (!ret)
+               gadget->connected = 1;
+       return ret;
 }
 
 /**
@@ -784,20 +881,88 @@ static inline int usb_gadget_connect(struct usb_gadget *gadget)
  * as a disconnect (when a VBUS session is active).  Not all systems
  * support software pullup controls.
  *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
+{
+       int ret;
+
+       if (!gadget->ops->pullup)
+               return -EOPNOTSUPP;
+
+       if (gadget->deactivated) {
+               /*
+                * If gadget is deactivated we only save new state.
+                * Gadget will stay disconnected after activation.
+                */
+               gadget->connected = false;
+               return 0;
+       }
+
+       ret = gadget->ops->pullup(gadget, 0);
+       if (!ret)
+               gadget->connected = 0;
+       return ret;
+}
+
+/**
+ * usb_gadget_deactivate - deactivate function which is not ready to work
+ * @gadget: the peripheral being deactivated
+ *
  * This routine may be used during the gadget driver bind() call to prevent
  * the peripheral from ever being visible to the USB host, unless later
- * usb_gadget_connect() is called.  For example, user mode components may
+ * usb_gadget_activate() is called.  For example, user mode components may
  * need to be activated before the system can talk to hosts.
  *
  * Returns zero on success, else negative errno.
  */
-static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
+static inline int usb_gadget_deactivate(struct usb_gadget *gadget)
 {
-       if (!gadget->ops->pullup)
-               return -EOPNOTSUPP;
-       return gadget->ops->pullup(gadget, 0);
+       int ret;
+
+       if (gadget->deactivated)
+               return 0;
+
+       if (gadget->connected) {
+               ret = usb_gadget_disconnect(gadget);
+               if (ret)
+                       return ret;
+               /*
+                * If gadget was being connected before deactivation, we want
+                * to reconnect it in usb_gadget_activate().
+                */
+               gadget->connected = true;
+       }
+       gadget->deactivated = true;
+
+       return 0;
 }
 
+/**
+ * usb_gadget_activate - activate function which is not ready to work
+ * @gadget: the peripheral being activated
+ *
+ * This routine activates gadget which was previously deactivated with
+ * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_activate(struct usb_gadget *gadget)
+{
+       if (!gadget->deactivated)
+               return 0;
+
+       gadget->deactivated = false;
+
+       /*
+        * If gadget has been connected before deactivation, or became connected
+        * while it was being deactivated, we call usb_gadget_connect().
+        */
+       if (gadget->connected)
+               return usb_gadget_connect(gadget);
+
+       return 0;
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -1002,6 +1167,10 @@ int usb_assign_descriptors(struct usb_function *f,
                struct usb_descriptor_header **ss);
 void usb_free_all_descriptors(struct usb_function *f);
 
+struct usb_descriptor_header *usb_otg_descriptor_alloc(
+                               struct usb_gadget *gadget);
+int usb_otg_descriptor_init(struct usb_gadget *gadget,
+               struct usb_descriptor_header *otg_desc);
 /*-------------------------------------------------------------------------*/
 
 /* utility to simplify map/unmap of usb_requests to/from DMA */
@@ -1034,6 +1203,21 @@ extern void usb_gadget_giveback_request(struct usb_ep *ep,
 
 /*-------------------------------------------------------------------------*/
 
+/* utility to find endpoint by name */
+
+extern struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g,
+               const char *name);
+
+/*-------------------------------------------------------------------------*/
+
+/* utility to check if endpoint caps match descriptor needs */
+
+extern int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
+               struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
+               struct usb_ss_ep_comp_descriptor *ep_comp);
+
+/*-------------------------------------------------------------------------*/
+
 /* utility to update vbus status for udc core, it may be scheduled */
 extern void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status);
 
index c9aa7792de10ac1b7f4676d4a0a5c8b6ac5c362f..d2784c10bfe2ce23dfcd64d773dbe3beaeb34c22 100644 (file)
@@ -564,9 +564,9 @@ extern void usb_ep0_reinit(struct usb_device *);
 
 /*-------------------------------------------------------------------------*/
 
-/* class requests from USB 3.0 hub spec, table 10-5 */
-#define SetHubDepth            (0x3000 | HUB_SET_DEPTH)
-#define GetPortErrorCount      (0x8000 | HUB_GET_PORT_ERR_COUNT)
+/* class requests from USB 3.1 hub spec, table 10-7 */
+#define SetHubDepth            (0x2000 | HUB_SET_DEPTH)
+#define GetPortErrorCount      (0xa300 | HUB_GET_PORT_ERR_COUNT)
 
 /*
  * Generic bandwidth allocation constants/support
index e55a1504266ec0333853793fa17e947feac02efd..8c8f6854c993b056ae6246ca58091fa9904602b2 100644 (file)
@@ -128,7 +128,7 @@ struct msm_otg_platform_data {
  */
 struct msm_usb_cable {
        struct notifier_block           nb;
-       struct extcon_specific_cable_nb conn;
+       struct extcon_dev               *extcon;
 };
 
 /**
@@ -155,6 +155,10 @@ struct msm_usb_cable {
  *     starting controller using usbcmd run/stop bit.
  * @vbus: VBUS signal state trakining, using extcon framework
  * @id: ID signal state trakining, using extcon framework
+ * @switch_gpio: Descriptor for GPIO used to control external Dual
+ *               SPDT USB Switch.
+ * @reboot: Used to inform the driver to route USB D+/D- line to Device
+ *         connector
  */
 struct msm_otg {
        struct usb_phy phy;
@@ -188,6 +192,9 @@ struct msm_otg {
 
        struct msm_usb_cable vbus;
        struct msm_usb_cable id;
+
+       struct gpio_desc *switch_gpio;
+       struct notifier_block reboot;
 };
 
 #endif
index cfe0528cdbb1048dd87e3d2910f2eaec454d3607..8c5a818ec2447aca31ce542e1cbb087f7b6fb04e 100644 (file)
@@ -15,6 +15,8 @@
 enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
 enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np);
 bool of_usb_host_tpl_support(struct device_node *np);
+int of_usb_update_otg_caps(struct device_node *np,
+                       struct usb_otg_caps *otg_caps);
 #else
 static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
 {
@@ -30,6 +32,11 @@ static inline bool of_usb_host_tpl_support(struct device_node *np)
 {
        return false;
 }
+static inline int of_usb_update_otg_caps(struct device_node *np,
+                               struct usb_otg_caps *otg_caps)
+{
+       return 0;
+}
 #endif
 
 #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)
index 52661c5da69012a3da3aa75d76a69ee45e6e92f0..bd1dcf8161009d78153082c23e7890a57f1b6b4f 100644 (file)
@@ -41,6 +41,21 @@ struct usb_otg {
 
 };
 
+/**
+ * struct usb_otg_caps - describes the otg capabilities of the device
+ * @otg_rev: The OTG revision number the device is compliant with, it's
+ *             in binary-coded decimal (i.e. 2.0 is 0200H).
+ * @hnp_support: Indicates if the device supports HNP.
+ * @srp_support: Indicates if the device supports SRP.
+ * @adp_support: Indicates if the device supports ADP.
+ */
+struct usb_otg_caps {
+       u16 otg_rev;
+       bool hnp_support;
+       bool srp_support;
+       bool adp_support;
+};
+
 extern const char *usb_otg_state_string(enum usb_otg_state state);
 
 /* Context: can sleep */
index 45534da57759a30d4a8c281bda094c8d4921dba3..644bdc61c387581c29a29d20c0cf1c3fc5085830 100644 (file)
@@ -74,8 +74,6 @@ enum rc_filter_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
- * @encode_wakeup: wakeup filtering uses IR encode API, therefore the allowed
- *     wakeup protocols is the set of all raw encoders
  * @allowed_protocols: bitmask with the supported RC_BIT_* protocols
  * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
  * @allowed_wakeup_protocols: bitmask with the supported RC_BIT_* wakeup protocols
@@ -136,7 +134,6 @@ struct rc_dev {
        struct input_dev                *input_dev;
        enum rc_driver_type             driver_type;
        bool                            idle;
-       bool                            encode_wakeup;
        u64                             allowed_protocols;
        u64                             enabled_protocols;
        u64                             allowed_wakeup_protocols;
@@ -246,7 +243,6 @@ static inline void init_ir_raw_event(struct ir_raw_event *ev)
 #define US_TO_NS(usec)         ((usec) * 1000)
 #define MS_TO_US(msec)         ((msec) * 1000)
 #define MS_TO_NS(msec)         ((msec) * 1000 * 1000)
-#define NS_TO_US(nsec)         DIV_ROUND_UP(nsec, 1000L)
 
 void ir_raw_event_handle(struct rc_dev *dev);
 int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev);
@@ -254,9 +250,6 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type);
 int ir_raw_event_store_with_filter(struct rc_dev *dev,
                                struct ir_raw_event *ev);
 void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
-int ir_raw_encode_scancode(u64 protocols,
-                          const struct rc_scancode_filter *scancode,
-                          struct ir_raw_event *events, unsigned int max);
 
 static inline void ir_raw_event_reset(struct rc_dev *dev)
 {
index 22a44c2f596380856acb1bccf95f14d0c2144994..c192e1b46cdc27372dc56ba704aa630ff113dfd6 100644 (file)
@@ -139,6 +139,7 @@ enum vb2_io_modes {
  * @VB2_BUF_STATE_PREPARING:   buffer is being prepared in videobuf
  * @VB2_BUF_STATE_PREPARED:    buffer prepared in videobuf and by the driver
  * @VB2_BUF_STATE_QUEUED:      buffer queued in videobuf, but not in driver
+ * @VB2_BUF_STATE_REQUEUEING:  re-queue a buffer to the driver
  * @VB2_BUF_STATE_ACTIVE:      buffer queued in driver and possibly used
  *                             in a hardware operation
  * @VB2_BUF_STATE_DONE:                buffer returned from driver to videobuf, but
@@ -152,6 +153,7 @@ enum vb2_buffer_state {
        VB2_BUF_STATE_PREPARING,
        VB2_BUF_STATE_PREPARED,
        VB2_BUF_STATE_QUEUED,
+       VB2_BUF_STATE_REQUEUEING,
        VB2_BUF_STATE_ACTIVE,
        VB2_BUF_STATE_DONE,
        VB2_BUF_STATE_ERROR,
index 4942710ef720ea5716e8cc6ebf0df941e22500ba..8d1d7fa67ec48bad6872be07258066f9410eec6e 100644 (file)
@@ -28,7 +28,6 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
                                   u64 * info_out);
 
 extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
-extern void scsi_set_sense_information(u8 *buf, u64 info);
 
 extern int scsi_ioctl_reset(struct scsi_device *, int __user *);
 
index 865a141b118b15874e27b0e56473bac8854c4823..427bc41df3aef3a3f931bd94830f027bafea2661 100644 (file)
@@ -141,6 +141,8 @@ struct snd_soc_tplg_ops {
        int io_ops_count;
 };
 
+#ifdef CONFIG_SND_SOC_TOPOLOGY
+
 /* gets a pointer to data from the firmware block header */
 static inline const void *snd_soc_tplg_get_data(struct snd_soc_tplg_hdr *hdr)
 {
@@ -165,4 +167,14 @@ int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w,
        const struct snd_soc_tplg_widget_events *events, int num_events,
        u16 event_type);
 
+#else
+
+static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp,
+                                               u32 index)
+{
+       return 0;
+}
+
+#endif
+
 #endif
diff --git a/include/trace/events/spmi.h b/include/trace/events/spmi.h
new file mode 100644 (file)
index 0000000..62f005e
--- /dev/null
@@ -0,0 +1,135 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM spmi
+
+#if !defined(_TRACE_SPMI_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SPMI_H
+
+#include <linux/spmi.h>
+#include <linux/tracepoint.h>
+
+/*
+ * drivers/spmi/spmi.c
+ */
+
+TRACE_EVENT(spmi_write_begin,
+       TP_PROTO(u8 opcode, u8 sid, u16 addr, u8 len, const u8 *buf),
+       TP_ARGS(opcode, sid, addr, len, buf),
+
+       TP_STRUCT__entry(
+               __field         ( u8,         opcode    )
+               __field         ( u8,         sid       )
+               __field         ( u16,        addr      )
+               __field         ( u8,         len       )
+               __dynamic_array ( u8,   buf,  len + 1   )
+       ),
+
+       TP_fast_assign(
+               __entry->opcode = opcode;
+               __entry->sid    = sid;
+               __entry->addr   = addr;
+               __entry->len    = len + 1;
+               memcpy(__get_dynamic_array(buf), buf, len + 1);
+       ),
+
+       TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]",
+                 (int)__entry->opcode, (int)__entry->sid,
+                 (int)__entry->addr, (int)__entry->len,
+                 (int)__entry->len, __get_dynamic_array(buf))
+);
+
+TRACE_EVENT(spmi_write_end,
+       TP_PROTO(u8 opcode, u8 sid, u16 addr, int ret),
+       TP_ARGS(opcode, sid, addr, ret),
+
+       TP_STRUCT__entry(
+               __field         ( u8,         opcode    )
+               __field         ( u8,         sid       )
+               __field         ( u16,        addr      )
+               __field         ( int,        ret       )
+       ),
+
+       TP_fast_assign(
+               __entry->opcode = opcode;
+               __entry->sid    = sid;
+               __entry->addr   = addr;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d",
+                 (int)__entry->opcode, (int)__entry->sid,
+                 (int)__entry->addr, __entry->ret)
+);
+
+TRACE_EVENT(spmi_read_begin,
+       TP_PROTO(u8 opcode, u8 sid, u16 addr),
+       TP_ARGS(opcode, sid, addr),
+
+       TP_STRUCT__entry(
+               __field         ( u8,         opcode    )
+               __field         ( u8,         sid       )
+               __field         ( u16,        addr      )
+       ),
+
+       TP_fast_assign(
+               __entry->opcode = opcode;
+               __entry->sid    = sid;
+               __entry->addr   = addr;
+       ),
+
+       TP_printk("opc=%d sid=%02d addr=0x%04x",
+                 (int)__entry->opcode, (int)__entry->sid,
+                 (int)__entry->addr)
+);
+
+TRACE_EVENT(spmi_read_end,
+       TP_PROTO(u8 opcode, u8 sid, u16 addr, int ret, u8 len, const u8 *buf),
+       TP_ARGS(opcode, sid, addr, ret, len, buf),
+
+       TP_STRUCT__entry(
+               __field         ( u8,         opcode    )
+               __field         ( u8,         sid       )
+               __field         ( u16,        addr      )
+               __field         ( int,        ret       )
+               __field         ( u8,         len       )
+               __dynamic_array ( u8,   buf,  len + 1   )
+       ),
+
+       TP_fast_assign(
+               __entry->opcode = opcode;
+               __entry->sid    = sid;
+               __entry->addr   = addr;
+               __entry->ret    = ret;
+               __entry->len    = len + 1;
+               memcpy(__get_dynamic_array(buf), buf, len + 1);
+       ),
+
+       TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]",
+                 (int)__entry->opcode, (int)__entry->sid,
+                 (int)__entry->addr, __entry->ret, (int)__entry->len,
+                 (int)__entry->len, __get_dynamic_array(buf))
+);
+
+TRACE_EVENT(spmi_cmd,
+       TP_PROTO(u8 opcode, u8 sid, int ret),
+       TP_ARGS(opcode, sid, ret),
+
+       TP_STRUCT__entry(
+               __field         ( u8,         opcode    )
+               __field         ( u8,         sid       )
+               __field         ( int,        ret       )
+       ),
+
+       TP_fast_assign(
+               __entry->opcode = opcode;
+               __entry->sid    = sid;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk("opc=%d sid=%02d ret=%d", (int)__entry->opcode,
+                 (int)__entry->sid, ret)
+);
+
+#endif /* _TRACE_SPMI_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index c06742d528562e12761eda74f6b421e5fb370a39..ab055d8cddef7a94289f198becb435a56ae37ca3 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/if.h>
 #include <linux/ioctl.h>
+#include <linux/types.h>
 
 struct gsm_config
 {
index 716ad4ae4d4b10443f4618bd96e86a71fa521d78..0d831f94f8a8f773e3ff034554d911bf8de4cc17 100644 (file)
@@ -317,6 +317,7 @@ struct kvm_run {
                struct {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
+#define KVM_SYSTEM_EVENT_CRASH          3
                        __u32 type;
                        __u64 flags;
                } system_event;
@@ -481,6 +482,7 @@ struct kvm_s390_psw {
         ((ai) << 26))
 #define KVM_S390_INT_IO_MIN            0x00000000u
 #define KVM_S390_INT_IO_MAX            0xfffdffffu
+#define KVM_S390_INT_IO_AI_MASK                0x04000000u
 
 
 struct kvm_s390_interrupt {
index bc0d8b69c49e51bbae1bd780028b4422c2d284cb..7c3b64f6a2158f02f676609ade423fc805ca3564 100644 (file)
@@ -107,4 +107,23 @@ struct mei_connect_client_data {
        };
 };
 
+/**
+ * DOC: set and unset event notification for a connected client
+ *
+ * The IOCTL argument is 1 for enabling event notification and 0 for
+ * disabling the service
+ * Return:  -EOPNOTSUPP if the devices doesn't support the feature
+ */
+#define IOCTL_MEI_NOTIFY_SET _IOW('H', 0x02, __u32)
+
+/**
+ * DOC: retrieve notification
+ *
+ * The IOCTL output argument is 1 if an event was is pending and 0 otherwise
+ * the ioctl has to be called in order to acknowledge pending event
+ *
+ * Return:  -EOPNOTSUPP if the devices doesn't support the feature
+ */
+#define IOCTL_MEI_NOTIFY_GET _IOR('H', 0x03, __u32)
+
 #endif /* _LINUX_MEI_H  */
index aa33fd1b2d4f3a7575dc160d906907133119f1d5..f7adc6e01f9ea4544363d6f1bfa446854c813dec 100644 (file)
@@ -674,9 +674,21 @@ struct usb_otg_descriptor {
        __u8  bmAttributes;     /* support for HNP, SRP, etc */
 } __attribute__ ((packed));
 
+/* USB_DT_OTG (from OTG 2.0 supplement) */
+struct usb_otg20_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bmAttributes;     /* support for HNP, SRP and ADP, etc */
+       __le16 bcdOTG;          /* OTG and EH supplement release number
+                                * in binary-coded decimal(i.e. 2.0 is 0200H)
+                                */
+} __attribute__ ((packed));
+
 /* from usb_otg_descriptor.bmAttributes */
 #define USB_OTG_SRP            (1 << 0)
 #define USB_OTG_HNP            (1 << 1)        /* swap host/device roles */
+#define USB_OTG_ADP            (1 << 2)        /* support ADP */
 
 /*-------------------------------------------------------------------------*/
 
index 51b8066a223b504ebf14ec287da3e56109a0e674..247c50bd60f0d067ad8884dbe4574adf0bfcf596 100644 (file)
 #include <linux/types.h>
 #include <sound/asound.h>
 
+#ifndef __KERNEL__
+#error This API is an early revision and not enabled in the current
+#error kernel release, it will be enabled in a future kernel version
+#error with incompatible changes to what is here.
+#endif
+
 /*
  * Maximum number of channels topology kcontrol can represent.
  */
index bc3d530cb23efacb2e5695ad85a9bd3898524fa2..b471e5a3863ddbca70f2bf4dee22f40df0345fbe 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -252,6 +252,16 @@ static void sem_rcu_free(struct rcu_head *head)
        ipc_rcu_free(head);
 }
 
+/*
+ * spin_unlock_wait() and !spin_is_locked() are not memory barriers, they
+ * are only control barriers.
+ * The code must pair with spin_unlock(&sem->lock) or
+ * spin_unlock(&sem_perm.lock), thus just the control barrier is insufficient.
+ *
+ * smp_rmb() is sufficient, as writes cannot pass the control barrier.
+ */
+#define ipc_smp_acquire__after_spin_is_unlocked()      smp_rmb()
+
 /*
  * Wait until all currently ongoing simple ops have completed.
  * Caller must own sem_perm.lock.
@@ -275,6 +285,7 @@ static void sem_wait_array(struct sem_array *sma)
                sem = sma->sem_base + i;
                spin_unlock_wait(&sem->lock);
        }
+       ipc_smp_acquire__after_spin_is_unlocked();
 }
 
 /*
@@ -327,13 +338,12 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
                /* Then check that the global lock is free */
                if (!spin_is_locked(&sma->sem_perm.lock)) {
                        /*
-                        * The ipc object lock check must be visible on all
-                        * cores before rechecking the complex count.  Otherwise
-                        * we can race with  another thread that does:
+                        * We need a memory barrier with acquire semantics,
+                        * otherwise we can race with another thread that does:
                         *      complex_count++;
                         *      spin_unlock(sem_perm.lock);
                         */
-                       smp_rmb();
+                       ipc_smp_acquire__after_spin_is_unlocked();
 
                        /*
                         * Now repeat the test of complex_count:
@@ -2074,17 +2084,28 @@ void exit_sem(struct task_struct *tsk)
                rcu_read_lock();
                un = list_entry_rcu(ulp->list_proc.next,
                                    struct sem_undo, list_proc);
-               if (&un->list_proc == &ulp->list_proc)
-                       semid = -1;
-                else
-                       semid = un->semid;
+               if (&un->list_proc == &ulp->list_proc) {
+                       /*
+                        * We must wait for freeary() before freeing this ulp,
+                        * in case we raced with last sem_undo. There is a small
+                        * possibility where we exit while freeary() didn't
+                        * finish unlocking sem_undo_list.
+                        */
+                       spin_unlock_wait(&ulp->lock);
+                       rcu_read_unlock();
+                       break;
+               }
+               spin_lock(&ulp->lock);
+               semid = un->semid;
+               spin_unlock(&ulp->lock);
 
+               /* exit_sem raced with IPC_RMID, nothing to do */
                if (semid == -1) {
                        rcu_read_unlock();
-                       break;
+                       continue;
                }
 
-               sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, un->semid);
+               sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, semid);
                /* exit_sem raced with IPC_RMID, nothing to do */
                if (IS_ERR(sma)) {
                        rcu_read_unlock();
@@ -2112,9 +2133,11 @@ void exit_sem(struct task_struct *tsk)
                ipc_assert_locked_object(&sma->sem_perm);
                list_del(&un->list_id);
 
-               spin_lock(&ulp->lock);
+               /* we are the last process using this ulp, acquiring ulp->lock
+                * isn't required. Besides that, we are also protected against
+                * IPC_RMID as we hold sma->sem_perm lock now
+                */
                list_del_rcu(&un->list_proc);
-               spin_unlock(&ulp->lock);
 
                /* perform adjustments registered in un */
                for (i = 0; i < sma->sem_nsems; i++) {
index 910d709b578abe6588a2800d3b82f7a4f651cff8..3c91a3fdfce58681ce33d311da9a876a126539c6 100644 (file)
@@ -191,21 +191,22 @@ void cpu_hotplug_done(void)
 void cpu_hotplug_disable(void)
 {
        cpu_maps_update_begin();
-       cpu_hotplug_disabled = 1;
+       cpu_hotplug_disabled++;
        cpu_maps_update_done();
 }
+EXPORT_SYMBOL_GPL(cpu_hotplug_disable);
 
 void cpu_hotplug_enable(void)
 {
        cpu_maps_update_begin();
-       cpu_hotplug_disabled = 0;
+       WARN_ON(--cpu_hotplug_disabled < 0);
        cpu_maps_update_done();
 }
-
+EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
 #endif /* CONFIG_HOTPLUG_CPU */
 
 /* Need to know about CPUs going up/down? */
-int __ref register_cpu_notifier(struct notifier_block *nb)
+int register_cpu_notifier(struct notifier_block *nb)
 {
        int ret;
        cpu_maps_update_begin();
@@ -214,7 +215,7 @@ int __ref register_cpu_notifier(struct notifier_block *nb)
        return ret;
 }
 
-int __ref __register_cpu_notifier(struct notifier_block *nb)
+int __register_cpu_notifier(struct notifier_block *nb)
 {
        return raw_notifier_chain_register(&cpu_chain, nb);
 }
@@ -244,7 +245,7 @@ static void cpu_notify_nofail(unsigned long val, void *v)
 EXPORT_SYMBOL(register_cpu_notifier);
 EXPORT_SYMBOL(__register_cpu_notifier);
 
-void __ref unregister_cpu_notifier(struct notifier_block *nb)
+void unregister_cpu_notifier(struct notifier_block *nb)
 {
        cpu_maps_update_begin();
        raw_notifier_chain_unregister(&cpu_chain, nb);
@@ -252,7 +253,7 @@ void __ref unregister_cpu_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
-void __ref __unregister_cpu_notifier(struct notifier_block *nb)
+void __unregister_cpu_notifier(struct notifier_block *nb)
 {
        raw_notifier_chain_unregister(&cpu_chain, nb);
 }
@@ -329,7 +330,7 @@ struct take_cpu_down_param {
 };
 
 /* Take this CPU down. */
-static int __ref take_cpu_down(void *_param)
+static int take_cpu_down(void *_param)
 {
        struct take_cpu_down_param *param = _param;
        int err;
@@ -348,7 +349,7 @@ static int __ref take_cpu_down(void *_param)
 }
 
 /* Requires cpu_add_remove_lock to be held */
-static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
+static int _cpu_down(unsigned int cpu, int tasks_frozen)
 {
        int err, nr_calls = 0;
        void *hcpu = (void *)(long)cpu;
@@ -442,7 +443,7 @@ out_release:
        return err;
 }
 
-int __ref cpu_down(unsigned int cpu)
+int cpu_down(unsigned int cpu)
 {
        int err;
 
@@ -608,13 +609,18 @@ int disable_nonboot_cpus(void)
                }
        }
 
-       if (!error) {
+       if (!error)
                BUG_ON(num_online_cpus() > 1);
-               /* Make sure the CPUs won't be enabled by someone else */
-               cpu_hotplug_disabled = 1;
-       } else {
+       else
                pr_err("Non-boot CPUs are not disabled\n");
-       }
+
+       /*
+        * Make sure the CPUs won't be enabled by someone else. We need to do
+        * this even in case of failure as all disable_nonboot_cpus() users are
+        * supposed to do enable_nonboot_cpus() on the failure path.
+        */
+       cpu_hotplug_disabled++;
+
        cpu_maps_update_done();
        return error;
 }
@@ -627,13 +633,13 @@ void __weak arch_enable_nonboot_cpus_end(void)
 {
 }
 
-void __ref enable_nonboot_cpus(void)
+void enable_nonboot_cpus(void)
 {
        int cpu, error;
 
        /* Allow everyone to use the CPU hotplug again */
        cpu_maps_update_begin();
-       cpu_hotplug_disabled = 0;
+       WARN_ON(--cpu_hotplug_disabled < 0);
        if (cpumask_empty(frozen_cpus))
                goto out;
 
index ee14e3a35a2994399edf176e7775e778c395e592..f0acff0f66c91380412dcbc1c899c94b1d3236b0 100644 (file)
@@ -1223,7 +1223,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
        spin_unlock_irq(&callback_lock);
 
        /* use trialcs->mems_allowed as a temp variable */
-       update_nodemasks_hier(cs, &cs->mems_allowed);
+       update_nodemasks_hier(cs, &trialcs->mems_allowed);
 done:
        return retval;
 }
index d3dae3419b99566c127f1682b29f39bb184bbdb1..e6feb51141340a99a248fea0ad1dc17402b0dbdb 100644 (file)
@@ -1868,8 +1868,6 @@ event_sched_in(struct perf_event *event,
 
        perf_pmu_disable(event->pmu);
 
-       event->tstamp_running += tstamp - event->tstamp_stopped;
-
        perf_set_shadow_time(event, ctx, tstamp);
 
        perf_log_itrace_start(event);
@@ -1881,6 +1879,8 @@ event_sched_in(struct perf_event *event,
                goto out;
        }
 
+       event->tstamp_running += tstamp - event->tstamp_stopped;
+
        if (!is_software_event(event))
                cpuctx->active_oncpu++;
        if (!ctx->nr_active++)
@@ -3958,28 +3958,21 @@ static void perf_event_for_each(struct perf_event *event,
                perf_event_for_each_child(sibling, func);
 }
 
-static int perf_event_period(struct perf_event *event, u64 __user *arg)
-{
-       struct perf_event_context *ctx = event->ctx;
-       int ret = 0, active;
+struct period_event {
+       struct perf_event *event;
        u64 value;
+};
 
-       if (!is_sampling_event(event))
-               return -EINVAL;
-
-       if (copy_from_user(&value, arg, sizeof(value)))
-               return -EFAULT;
-
-       if (!value)
-               return -EINVAL;
+static int __perf_event_period(void *info)
+{
+       struct period_event *pe = info;
+       struct perf_event *event = pe->event;
+       struct perf_event_context *ctx = event->ctx;
+       u64 value = pe->value;
+       bool active;
 
-       raw_spin_lock_irq(&ctx->lock);
+       raw_spin_lock(&ctx->lock);
        if (event->attr.freq) {
-               if (value > sysctl_perf_event_sample_rate) {
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-
                event->attr.sample_freq = value;
        } else {
                event->attr.sample_period = value;
@@ -3998,11 +3991,53 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
                event->pmu->start(event, PERF_EF_RELOAD);
                perf_pmu_enable(ctx->pmu);
        }
+       raw_spin_unlock(&ctx->lock);
 
-unlock:
+       return 0;
+}
+
+static int perf_event_period(struct perf_event *event, u64 __user *arg)
+{
+       struct period_event pe = { .event = event, };
+       struct perf_event_context *ctx = event->ctx;
+       struct task_struct *task;
+       u64 value;
+
+       if (!is_sampling_event(event))
+               return -EINVAL;
+
+       if (copy_from_user(&value, arg, sizeof(value)))
+               return -EFAULT;
+
+       if (!value)
+               return -EINVAL;
+
+       if (event->attr.freq && value > sysctl_perf_event_sample_rate)
+               return -EINVAL;
+
+       task = ctx->task;
+       pe.value = value;
+
+       if (!task) {
+               cpu_function_call(event->cpu, __perf_event_period, &pe);
+               return 0;
+       }
+
+retry:
+       if (!task_function_call(task, __perf_event_period, &pe))
+               return 0;
+
+       raw_spin_lock_irq(&ctx->lock);
+       if (ctx->is_active) {
+               raw_spin_unlock_irq(&ctx->lock);
+               task = ctx->task;
+               goto retry;
+       }
+
+       __perf_event_period(&pe);
        raw_spin_unlock_irq(&ctx->lock);
 
-       return ret;
+       return 0;
 }
 
 static const struct file_operations perf_fops;
@@ -4740,12 +4775,20 @@ static const struct file_operations perf_fops = {
  * to user-space before waking everybody up.
  */
 
+static inline struct fasync_struct **perf_event_fasync(struct perf_event *event)
+{
+       /* only the parent has fasync state */
+       if (event->parent)
+               event = event->parent;
+       return &event->fasync;
+}
+
 void perf_event_wakeup(struct perf_event *event)
 {
        ring_buffer_wakeup(event);
 
        if (event->pending_kill) {
-               kill_fasync(&event->fasync, SIGIO, event->pending_kill);
+               kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill);
                event->pending_kill = 0;
        }
 }
@@ -6124,7 +6167,7 @@ static int __perf_event_overflow(struct perf_event *event,
        else
                perf_event_output(event, data, regs);
 
-       if (event->fasync && event->pending_kill) {
+       if (*perf_event_fasync(event) && event->pending_kill) {
                event->pending_wakeup = 1;
                irq_work_queue(&event->pending);
        }
index b2be01b1aa9dcb7a70792fa381c264b229a106d0..c8aa3f75bc4db8ad7a2242aae6406bfd6f86f8c5 100644 (file)
@@ -559,11 +559,13 @@ static void __rb_free_aux(struct ring_buffer *rb)
                rb->aux_priv = NULL;
        }
 
-       for (pg = 0; pg < rb->aux_nr_pages; pg++)
-               rb_free_aux_page(rb, pg);
+       if (rb->aux_nr_pages) {
+               for (pg = 0; pg < rb->aux_nr_pages; pg++)
+                       rb_free_aux_page(rb, pg);
 
-       kfree(rb->aux_pages);
-       rb->aux_nr_pages = 0;
+               kfree(rb->aux_pages);
+               rb->aux_nr_pages = 0;
+       }
 }
 
 void rb_free_aux(struct ring_buffer *rb)
index 27f4332c7f84ea8b3d7ec8bb3466a64f225a8487..ae216824e8ca9224c4b76f225ef58d664a3e1726 100644 (file)
@@ -984,6 +984,23 @@ int irq_chip_set_affinity_parent(struct irq_data *data,
        return -ENOSYS;
 }
 
+/**
+ * irq_chip_set_type_parent - Set IRQ type on the parent interrupt
+ * @data:      Pointer to interrupt specific data
+ * @type:      IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
+ *
+ * Conditional, as the underlying parent chip might not implement it.
+ */
+int irq_chip_set_type_parent(struct irq_data *data, unsigned int type)
+{
+       data = data->parent_data;
+
+       if (data->chip->irq_set_type)
+               return data->chip->irq_set_type(data, type);
+
+       return -ENOSYS;
+}
+
 /**
  * irq_chip_retrigger_hierarchy - Retrigger an interrupt in hardware
  * @data:      Pointer to interrupt specific data
@@ -997,7 +1014,7 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data)
                if (data->chip && data->chip->irq_retrigger)
                        return data->chip->irq_retrigger(data);
 
-       return -ENOSYS;
+       return 0;
 }
 
 /**
index 04ab18151cc8fa174a5859124ee07c144f33d505..df19ae4debd09c134d438b57e4ead7c71462c2b6 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/hash.h>
 #include <linux/bootmem.h>
+#include <linux/debug_locks.h>
 
 /*
  * Implement paravirt qspinlocks; the general idea is to halt the vcpus instead
@@ -286,15 +287,23 @@ __visible void __pv_queued_spin_unlock(struct qspinlock *lock)
 {
        struct __qspinlock *l = (void *)lock;
        struct pv_node *node;
+       u8 lockval = cmpxchg(&l->locked, _Q_LOCKED_VAL, 0);
 
        /*
         * We must not unlock if SLOW, because in that case we must first
         * unhash. Otherwise it would be possible to have multiple @lock
         * entries, which would be BAD.
         */
-       if (likely(cmpxchg(&l->locked, _Q_LOCKED_VAL, 0) == _Q_LOCKED_VAL))
+       if (likely(lockval == _Q_LOCKED_VAL))
                return;
 
+       if (unlikely(lockval != _Q_SLOW_VAL)) {
+               if (debug_locks_silent)
+                       return;
+               WARN(1, "pvqspinlock: lock %p has corrupted value 0x%x!\n", lock, atomic_read(&lock->val));
+               return;
+       }
+
        /*
         * Since the above failed to release, this must be the SLOW path.
         * Therefore start by looking up the blocked node and unhashing it.
index 5e097fa9faf7016470b8283931023a15d20ed97d..84190f02b521c9fc77cee6e6a6722000939ee470 100644 (file)
@@ -807,8 +807,8 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
                        spin_unlock(&base->lock);
                        base = new_base;
                        spin_lock(&base->lock);
-                       timer->flags &= ~TIMER_BASEMASK;
-                       timer->flags |= base->cpu;
+                       WRITE_ONCE(timer->flags,
+                                  (timer->flags & ~TIMER_BASEMASK) | base->cpu);
                }
        }
 
index bc0a1da8afba2c5362fb55772e7154a8ad2ea844..95c52a95259e89b6fc0ab279c4e51cfc5f35bf1f 100644 (file)
@@ -146,18 +146,25 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes,
        uint8_t *p;
        mpi_limb_t alimb;
        unsigned int n = mpi_get_size(a);
-       int i;
+       int i, lzeros = 0;
 
-       if (buf_len < n || !buf)
+       if (buf_len < n || !buf || !nbytes)
                return -EINVAL;
 
        if (sign)
                *sign = a->sign;
 
-       if (nbytes)
-               *nbytes = n;
+       p = (void *)&a->d[a->nlimbs] - 1;
+
+       for (i = a->nlimbs * sizeof(alimb) - 1; i >= 0; i--, p--) {
+               if (!*p)
+                       lzeros++;
+               else
+                       break;
+       }
 
        p = buf;
+       *nbytes = n - lzeros;
 
        for (i = a->nlimbs - 1; i >= 0; i--) {
                alimb = a->d[i];
@@ -178,6 +185,19 @@ int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes,
 #else
 #error please implement for this limb size.
 #endif
+
+               if (lzeros > 0) {
+                       if (lzeros >= sizeof(alimb)) {
+                               p -= sizeof(alimb);
+                       } else {
+                               mpi_limb_t *limb1 = (void *)p - sizeof(alimb);
+                               mpi_limb_t *limb2 = (void *)p - sizeof(alimb)
+                                                       + lzeros;
+                               *limb1 = *limb2;
+                               p -= lzeros;
+                       }
+                       lzeros -= sizeof(alimb);
+               }
        }
        return 0;
 }
@@ -197,7 +217,7 @@ EXPORT_SYMBOL_GPL(mpi_read_buffer);
  */
 void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
 {
-       uint8_t *buf, *p;
+       uint8_t *buf;
        unsigned int n;
        int ret;
 
@@ -220,14 +240,6 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
                kfree(buf);
                return NULL;
        }
-
-       /* this is sub-optimal but we need to do the shift operation
-        * because the caller has to free the returned buffer */
-       for (p = buf; !*p && *nbytes; p++, --*nbytes)
-               ;
-       if (p != buf)
-               memmove(buf, p, *nbytes);
-
        return buf;
 }
 EXPORT_SYMBOL_GPL(mpi_get_buffer);
index da39c608a28cb910a98697345afa15e8929711e0..95cd63b43b99fa83798fb68dadfbd95a8c0bc57c 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/module.h>      /* for KSYM_SYMBOL_LEN */
 #include <linux/types.h>
index 1132d733556dbc330d32eda5460f55e6e067b627..17c75a4246c8bbab8b56fe4d562cd85ea670a21f 100644 (file)
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -16,7 +16,7 @@ struct cma {
 extern struct cma cma_areas[MAX_CMA_AREAS];
 extern unsigned cma_area_count;
 
-static unsigned long cma_bitmap_maxno(struct cma *cma)
+static inline unsigned long cma_bitmap_maxno(struct cma *cma)
 {
        return cma->count >> cma->order_per_bit;
 }
index 6c513a63ea84c3c7ffd41201b7a419ff7b6dfd5d..7b28e9cdf1c7686428fe49802fced44088043555 100644 (file)
@@ -2,7 +2,7 @@
  * This file contains shadow memory manipulation code.
  *
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- * Author: Andrey Ryabinin <a.ryabinin@samsung.com>
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
  *
  * Some of code borrowed from https://github.com/xairy/linux by
  *        Andrey Konovalov <adech.fo@gmail.com>
index 680ceedf810ab4c9cd08c9929f5d445de9f5aa6a..e07c94fbd0ac5a141ecf95ab7d39d046fea13e67 100644 (file)
@@ -2,7 +2,7 @@
  * This file contains error reporting code.
  *
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- * Author: Andrey Ryabinin <a.ryabinin@samsung.com>
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
  *
  * Some of code borrowed from https://github.com/xairy/linux by
  *        Andrey Konovalov <adech.fo@gmail.com>
index ea5a936594887c43506fefe82a61a4ad6fcf4274..1f4446a90cef07c67ee1082b83f0ca87ebfefea1 100644 (file)
@@ -1146,8 +1146,11 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
        }
 
        if (!PageHuge(p) && PageTransHuge(hpage)) {
-               if (unlikely(split_huge_page(hpage))) {
-                       pr_err("MCE: %#lx: thp split failed\n", pfn);
+               if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) {
+                       if (!PageAnon(hpage))
+                               pr_err("MCE: %#lx: non anonymous thp\n", pfn);
+                       else
+                               pr_err("MCE: %#lx: thp split failed\n", pfn);
                        if (TestClearPageHWPoison(p))
                                atomic_long_sub(nr_pages, &num_poisoned_pages);
                        put_page(p);
@@ -1538,6 +1541,8 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags)
                 */
                ret = __get_any_page(page, pfn, 0);
                if (!PageLRU(page)) {
+                       /* Drop page reference which is from __get_any_page() */
+                       put_page(page);
                        pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
                                pfn, page->flags);
                        return -EIO;
@@ -1567,13 +1572,12 @@ static int soft_offline_huge_page(struct page *page, int flags)
        unlock_page(hpage);
 
        ret = isolate_huge_page(hpage, &pagelist);
-       if (ret) {
-               /*
-                * get_any_page() and isolate_huge_page() takes a refcount each,
-                * so need to drop one here.
-                */
-               put_page(hpage);
-       } else {
+       /*
+        * get_any_page() and isolate_huge_page() takes a refcount each,
+        * so need to drop one here.
+        */
+       put_page(hpage);
+       if (!ret) {
                pr_info("soft offline: %#lx hugepage failed to isolate\n", pfn);
                return -EBUSY;
        }
index 003dbe4b060d914dae4e93997c372ddd3e1a8e92..6da82bcb0a8b66b7326c1a021a7eac3b476cd85e 100644 (file)
@@ -1277,6 +1277,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
 
        /* create new memmap entry */
        firmware_map_add_hotplug(start, start + size, "System RAM");
+       memblock_add_node(start, size, nid);
 
        goto out;
 
@@ -2013,6 +2014,8 @@ void __ref remove_memory(int nid, u64 start, u64 size)
 
        /* remove memmap entry */
        firmware_map_remove(start, start + size, "System RAM");
+       memblock_free(start, size);
+       memblock_remove(start, size);
 
        arch_remove_memory(start, size);
 
index beda4171080232f37e779a3658045e1f813a1cff..5b5240b7f642de179efa3552245fbf9326d7a206 100644 (file)
@@ -1343,12 +1343,15 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
        set_page_owner(page, order, gfp_flags);
 
        /*
-        * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was necessary to
+        * page is set pfmemalloc when ALLOC_NO_WATERMARKS was necessary to
         * allocate the page. The expectation is that the caller is taking
         * steps that will free more memory. The caller should avoid the page
         * being used for !PFMEMALLOC purposes.
         */
-       page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS);
+       if (alloc_flags & ALLOC_NO_WATERMARKS)
+               set_page_pfmemalloc(page);
+       else
+               clear_page_pfmemalloc(page);
 
        return 0;
 }
@@ -3345,7 +3348,7 @@ refill:
                atomic_add(size - 1, &page->_count);
 
                /* reset page count bias and offset to start of new frag */
-               nc->pfmemalloc = page->pfmemalloc;
+               nc->pfmemalloc = page_is_pfmemalloc(page);
                nc->pagecnt_bias = size;
                nc->offset = size;
        }
@@ -5060,6 +5063,10 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
 {
        unsigned long zone_start_pfn, zone_end_pfn;
 
+       /* When hotadd a new node, the node should be empty */
+       if (!node_start_pfn && !node_end_pfn)
+               return 0;
+
        /* Get the start and end of the zone */
        zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
        zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
@@ -5123,6 +5130,10 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
        unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
        unsigned long zone_start_pfn, zone_end_pfn;
 
+       /* When hotadd a new node, the node should be empty */
+       if (!node_start_pfn && !node_end_pfn)
+               return 0;
+
        zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
        zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
 
index 200e22412a161fc7a2232bcb923f07bc117362b8..bbd0b47dc6a97eecea7650ce6b351e88d5a17295 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1603,7 +1603,7 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags,
        }
 
        /* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */
-       if (unlikely(page->pfmemalloc))
+       if (page_is_pfmemalloc(page))
                pfmemalloc_active = true;
 
        nr_pages = (1 << cachep->gfporder);
@@ -1614,7 +1614,7 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags,
                add_zone_page_state(page_zone(page),
                        NR_SLAB_UNRECLAIMABLE, nr_pages);
        __SetPageSlab(page);
-       if (page->pfmemalloc)
+       if (page_is_pfmemalloc(page))
                SetPageSlabPfmemalloc(page);
 
        if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) {
index 816df0016555ad8a5cf03c8020e0b39b75b0a498..f68c0e50f3c083abe295a1dcd60668321a8f9232 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1427,7 +1427,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
        inc_slabs_node(s, page_to_nid(page), page->objects);
        page->slab_cache = s;
        __SetPageSlab(page);
-       if (page->pfmemalloc)
+       if (page_is_pfmemalloc(page))
                SetPageSlabPfmemalloc(page);
 
        start = page_address(page);
index 498454b3c06c3ddf0e8c3989e23bef9360587544..ea79ee9a73489f43a88e57c2eb529fc11d894e5f 100644 (file)
@@ -1541,6 +1541,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
        struct p9_client *clnt = fid->clnt;
        struct p9_req_t *req;
        int total = 0;
+       *err = 0;
 
        p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
                   fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));
@@ -1620,6 +1621,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
        struct p9_client *clnt = fid->clnt;
        struct p9_req_t *req;
        int total = 0;
+       *err = 0;
 
        p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n",
                                fid->fid, (unsigned long long) offset,
index fb54e6aed096edd267fc211e4cd2a0139fe71f8a..6d0b471eede8639f55b33c5c4d434c8fddef6ee5 100644 (file)
@@ -1138,6 +1138,9 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: packet to check
  * @hdr_size: size of the encapsulation header
+ *
+ * Returns true if the packet was snooped and consumed by DAT. False if the
+ * packet has to be delivered to the interface
  */
 bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
                                         struct sk_buff *skb, int hdr_size)
@@ -1145,7 +1148,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
        uint16_t type;
        __be32 ip_src, ip_dst;
        uint8_t *hw_src, *hw_dst;
-       bool ret = false;
+       bool dropped = false;
        unsigned short vid;
 
        if (!atomic_read(&bat_priv->distributed_arp_table))
@@ -1174,12 +1177,17 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
        /* if this REPLY is directed to a client of mine, let's deliver the
         * packet to the interface
         */
-       ret = !batadv_is_my_client(bat_priv, hw_dst, vid);
+       dropped = !batadv_is_my_client(bat_priv, hw_dst, vid);
+
+       /* if this REPLY is sent on behalf of a client of mine, let's drop the
+        * packet because the client will reply by itself
+        */
+       dropped |= batadv_is_my_client(bat_priv, hw_src, vid);
 out:
-       if (ret)
+       if (dropped)
                kfree_skb(skb);
-       /* if ret == false -> packet has to be delivered to the interface */
-       return ret;
+       /* if dropped == false -> deliver to the interface */
+       return dropped;
 }
 
 /**
index bb01586206289929f8c5e43153b75f9c279b9f85..cffa92dd98778bf2ffdf11107243fcc0f60cab6b 100644 (file)
@@ -439,6 +439,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
 
        INIT_HLIST_NODE(&gw_node->list);
        gw_node->orig_node = orig_node;
+       gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
+       gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
        atomic_set(&gw_node->refcount, 1);
 
        spin_lock_bh(&bat_priv->gw.list_lock);
index c002961da75d655deb813990f5706cf37fbd6d7d..a2fc843c22432e790980fa15653cf95e6c60b384 100644 (file)
@@ -479,6 +479,9 @@ out:
  */
 void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
 {
+       if (!vlan)
+               return;
+
        if (atomic_dec_and_test(&vlan->refcount)) {
                spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
                hlist_del_rcu(&vlan->list);
index b4824951010ba6b42bf7d7c7eb62c529ed340158..5809b39c1922320e8dbb353de212b472199c796d 100644 (file)
@@ -594,6 +594,12 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 
        /* increase the refcounter of the related vlan */
        vlan = batadv_softif_vlan_get(bat_priv, vid);
+       if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
+                addr, BATADV_PRINT_VID(vid))) {
+               kfree(tt_local);
+               tt_local = NULL;
+               goto out;
+       }
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
                   "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
@@ -1034,6 +1040,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
        struct batadv_tt_local_entry *tt_local_entry;
        uint16_t flags, curr_flags = BATADV_NO_FLAGS;
        struct batadv_softif_vlan *vlan;
+       void *tt_entry_exists;
 
        tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
        if (!tt_local_entry)
@@ -1061,11 +1068,22 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
         * immediately purge it
         */
        batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
-       hlist_del_rcu(&tt_local_entry->common.hash_entry);
+
+       tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
+                                            batadv_compare_tt,
+                                            batadv_choose_tt,
+                                            &tt_local_entry->common);
+       if (!tt_entry_exists)
+               goto out;
+
+       /* extra call to free the local tt entry */
        batadv_tt_local_entry_free_ref(tt_local_entry);
 
        /* decrease the reference held for this vlan */
        vlan = batadv_softif_vlan_get(bat_priv, vid);
+       if (!vlan)
+               goto out;
+
        batadv_softif_vlan_free_ref(vlan);
        batadv_softif_vlan_free_ref(vlan);
 
@@ -1166,8 +1184,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
                        /* decrease the reference held for this vlan */
                        vlan = batadv_softif_vlan_get(bat_priv,
                                                      tt_common_entry->vid);
-                       batadv_softif_vlan_free_ref(vlan);
-                       batadv_softif_vlan_free_ref(vlan);
+                       if (vlan) {
+                               batadv_softif_vlan_free_ref(vlan);
+                               batadv_softif_vlan_free_ref(vlan);
+                       }
 
                        batadv_tt_local_entry_free_ref(tt_local);
                }
@@ -3207,8 +3227,10 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
 
                        /* decrease the reference held for this vlan */
                        vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
-                       batadv_softif_vlan_free_ref(vlan);
-                       batadv_softif_vlan_free_ref(vlan);
+                       if (vlan) {
+                               batadv_softif_vlan_free_ref(vlan);
+                               batadv_softif_vlan_free_ref(vlan);
+                       }
 
                        batadv_tt_local_entry_free_ref(tt_local);
                }
index 7998fb27916568da087b2734a017355158044a75..92720f3fe57370137f22ae3d2b76b390da09e9a1 100644 (file)
@@ -7820,7 +7820,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
        /* Make sure we copy only the significant bytes based on the
         * encryption key size, and set the rest of the value to zeroes.
         */
-       memcpy(ev.key.val, key->val, sizeof(key->enc_size));
+       memcpy(ev.key.val, key->val, key->enc_size);
        memset(ev.key.val + key->enc_size, 0,
               sizeof(ev.key.val) - key->enc_size);
 
index 0b39dcc65b94f0aa571dc22dc0c97afbf4e3d744..1285eaf5dc222e7cf75f4da796f2075f098105ae 100644 (file)
@@ -1591,7 +1591,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
                break;
        }
 
-       if (skb_trimmed)
+       if (skb_trimmed && skb_trimmed != skb)
                kfree_skb(skb_trimmed);
 
        return err;
@@ -1636,7 +1636,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
                break;
        }
 
-       if (skb_trimmed)
+       if (skb_trimmed && skb_trimmed != skb)
                kfree_skb(skb_trimmed);
 
        return err;
index 3da5525eb8a2dc21e5f64638881a351a72a0d300..4d74a0639c4ccd040b6371665e6a74f8dca6f800 100644 (file)
@@ -112,6 +112,8 @@ static inline size_t br_port_info_size(void)
                + nla_total_size(1)     /* IFLA_BRPORT_FAST_LEAVE */
                + nla_total_size(1)     /* IFLA_BRPORT_LEARNING */
                + nla_total_size(1)     /* IFLA_BRPORT_UNICAST_FLOOD */
+               + nla_total_size(1)     /* IFLA_BRPORT_PROXYARP */
+               + nla_total_size(1)     /* IFLA_BRPORT_PROXYARP_WIFI */
                + 0;
 }
 
@@ -506,6 +508,8 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
        [IFLA_BRPORT_FAST_LEAVE]= { .type = NLA_U8 },
        [IFLA_BRPORT_LEARNING]  = { .type = NLA_U8 },
        [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
+       [IFLA_BRPORT_PROXYARP]  = { .type = NLA_U8 },
+       [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
 };
 
 /* Change the state of the port and notify spanning tree */
index 4967262b27076af66347d20eca54b65a2e61d789..617088aee21d41ba98d4ef5ebee5d6c002efe029 100644 (file)
@@ -131,12 +131,12 @@ out_noerr:
        goto out;
 }
 
-static int skb_set_peeked(struct sk_buff *skb)
+static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
 {
        struct sk_buff *nskb;
 
        if (skb->peeked)
-               return 0;
+               return skb;
 
        /* We have to unshare an skb before modifying it. */
        if (!skb_shared(skb))
@@ -144,7 +144,7 @@ static int skb_set_peeked(struct sk_buff *skb)
 
        nskb = skb_clone(skb, GFP_ATOMIC);
        if (!nskb)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        skb->prev->next = nskb;
        skb->next->prev = nskb;
@@ -157,7 +157,7 @@ static int skb_set_peeked(struct sk_buff *skb)
 done:
        skb->peeked = 1;
 
-       return 0;
+       return skb;
 }
 
 /**
@@ -229,8 +229,9 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
                                        continue;
                                }
 
-                               error = skb_set_peeked(skb);
-                               if (error)
+                               skb = skb_set_peeked(skb);
+                               error = PTR_ERR(skb);
+                               if (IS_ERR(skb))
                                        goto unlock_err;
 
                                atomic_inc(&skb->users);
index 1ebdf1c0d1188c309d854bc9145c9b2f5b7b58a4..1cbd209192eacd6b7ec9a13f8180a5138760fc7e 100644 (file)
@@ -3514,8 +3514,6 @@ static int pktgen_thread_worker(void *arg)
 
        set_freezable();
 
-       __set_current_state(TASK_RUNNING);
-
        while (!kthread_should_stop()) {
                pkt_dev = next_to_run(t);
 
@@ -3560,7 +3558,6 @@ static int pktgen_thread_worker(void *arg)
 
                try_to_freeze();
        }
-       set_current_state(TASK_INTERRUPTIBLE);
 
        pr_debug("%s stopping all device\n", t->tsk->comm);
        pktgen_stop(t);
index 87b22c0bc08c2f33fa31948b8b2604f48b8009bc..b42f0e26f89e4cf2e37a8329da549eb5cd1200c5 100644 (file)
@@ -103,10 +103,16 @@ void reqsk_queue_destroy(struct request_sock_queue *queue)
                        spin_lock_bh(&queue->syn_wait_lock);
                        while ((req = lopt->syn_table[i]) != NULL) {
                                lopt->syn_table[i] = req->dl_next;
+                               /* Because of following del_timer_sync(),
+                                * we must release the spinlock here
+                                * or risk a dead lock.
+                                */
+                               spin_unlock_bh(&queue->syn_wait_lock);
                                atomic_inc(&lopt->qlen_dec);
-                               if (del_timer(&req->rsk_timer))
+                               if (del_timer_sync(&req->rsk_timer))
                                        reqsk_put(req);
                                reqsk_put(req);
+                               spin_lock_bh(&queue->syn_wait_lock);
                        }
                        spin_unlock_bh(&queue->syn_wait_lock);
                }
index b6a19ca0f99e49c7406f1fedb6c59433bbd7fd38..7b84330e5d30693cf63fe2d04b7f64f2b8893362 100644 (file)
@@ -340,7 +340,7 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
 
        if (skb && frag_size) {
                skb->head_frag = 1;
-               if (virt_to_head_page(data)->pfmemalloc)
+               if (page_is_pfmemalloc(virt_to_head_page(data)))
                        skb->pfmemalloc = 1;
        }
        return skb;
@@ -4022,8 +4022,8 @@ EXPORT_SYMBOL(skb_checksum_setup);
  * Otherwise returns the provided skb. Returns NULL in error cases
  * (e.g. transport_len exceeds skb length or out-of-memory).
  *
- * Caller needs to set the skb transport header and release the returned skb.
- * Provided skb is consumed.
+ * Caller needs to set the skb transport header and free any returned skb if it
+ * differs from the provided skb.
  */
 static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
                                               unsigned int transport_len)
@@ -4032,16 +4032,12 @@ static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
        unsigned int len = skb_transport_offset(skb) + transport_len;
        int ret;
 
-       if (skb->len < len) {
-               kfree_skb(skb);
+       if (skb->len < len)
                return NULL;
-       } else if (skb->len == len) {
+       else if (skb->len == len)
                return skb;
-       }
 
        skb_chk = skb_clone(skb, GFP_ATOMIC);
-       kfree_skb(skb);
-
        if (!skb_chk)
                return NULL;
 
@@ -4066,8 +4062,8 @@ static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
  * If the skb has data beyond the given transport length, then a
  * trimmed & cloned skb is checked and returned.
  *
- * Caller needs to set the skb transport header and release the returned skb.
- * Provided skb is consumed.
+ * Caller needs to set the skb transport header and free any returned skb if it
+ * differs from the provided skb.
  */
 struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
                                     unsigned int transport_len,
@@ -4079,23 +4075,26 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
 
        skb_chk = skb_checksum_maybe_trim(skb, transport_len);
        if (!skb_chk)
-               return NULL;
+               goto err;
 
-       if (!pskb_may_pull(skb_chk, offset)) {
-               kfree_skb(skb_chk);
-               return NULL;
-       }
+       if (!pskb_may_pull(skb_chk, offset))
+               goto err;
 
        __skb_pull(skb_chk, offset);
        ret = skb_chkf(skb_chk);
        __skb_push(skb_chk, offset);
 
-       if (ret) {
-               kfree_skb(skb_chk);
-               return NULL;
-       }
+       if (ret)
+               goto err;
 
        return skb_chk;
+
+err:
+       if (skb_chk && skb_chk != skb)
+               kfree_skb(skb_chk);
+
+       return NULL;
+
 }
 EXPORT_SYMBOL(skb_checksum_trimmed);
 
index 0917123790eaf09b001c97a733039185fdb0a800..35c47ddd04f0ee3eb965fd99b06bab2ee4670774 100644 (file)
@@ -756,7 +756,8 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
                return -ENODEV;
 
        /* Use already configured phy mode */
-       p->phy_interface = p->phy->interface;
+       if (p->phy_interface == PHY_INTERFACE_MODE_NA)
+               p->phy_interface = p->phy->interface;
        phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
                           p->phy_interface);
 
index 37c4bb89a7082bbe36b40d928f7fd1d95bfe8252..b0c6258ffb79a7cbcaaf1296e4842db52876b5b2 100644 (file)
@@ -2465,7 +2465,7 @@ static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter,
                key = l->key + 1;
                iter->pos++;
 
-               if (pos-- <= 0)
+               if (--pos <= 0)
                        break;
 
                l = NULL;
index 651cdf648ec4728bff6e709b0324b7d52ffd65ed..9fdfd9deac11dde85bc62803068fbe50e45837b8 100644 (file)
@@ -1435,33 +1435,35 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed)
        struct sk_buff *skb_chk;
        unsigned int transport_len;
        unsigned int len = skb_transport_offset(skb) + sizeof(struct igmphdr);
-       int ret;
+       int ret = -EINVAL;
 
        transport_len = ntohs(ip_hdr(skb)->tot_len) - ip_hdrlen(skb);
 
-       skb_get(skb);
        skb_chk = skb_checksum_trimmed(skb, transport_len,
                                       ip_mc_validate_checksum);
        if (!skb_chk)
-               return -EINVAL;
+               goto err;
 
-       if (!pskb_may_pull(skb_chk, len)) {
-               kfree_skb(skb_chk);
-               return -EINVAL;
-       }
+       if (!pskb_may_pull(skb_chk, len))
+               goto err;
 
        ret = ip_mc_check_igmp_msg(skb_chk);
-       if (ret) {
-               kfree_skb(skb_chk);
-               return ret;
-       }
+       if (ret)
+               goto err;
 
        if (skb_trimmed)
                *skb_trimmed = skb_chk;
-       else
+       /* free now unneeded clone */
+       else if (skb_chk != skb)
                kfree_skb(skb_chk);
 
-       return 0;
+       ret = 0;
+
+err:
+       if (ret && skb_chk && skb_chk != skb)
+               kfree_skb(skb_chk);
+
+       return ret;
 }
 
 /**
@@ -1470,7 +1472,7 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed)
  * @skb_trimmed: to store an skb pointer trimmed to IPv4 packet tail (optional)
  *
  * Checks whether an IPv4 packet is a valid IGMP packet. If so sets
- * skb network and transport headers accordingly and returns zero.
+ * skb transport header accordingly and returns zero.
  *
  * -EINVAL: A broken packet was detected, i.e. it violates some internet
  *  standard
@@ -1485,7 +1487,8 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed)
  * to leave the original skb and its full frame unchanged (which might be
  * desirable for layer 2 frame jugglers).
  *
- * The caller needs to release a reference count from any returned skb_trimmed.
+ * Caller needs to set the skb network header and free any returned skb if it
+ * differs from the provided skb.
  */
 int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed)
 {
index 60021d0d9326ac691dcef21e1f9c20de5f8fe7c6..134957159c27eb9180e08b73360fe891574b4742 100644 (file)
@@ -593,7 +593,7 @@ static bool reqsk_queue_unlink(struct request_sock_queue *queue,
        }
 
        spin_unlock(&queue->syn_wait_lock);
-       if (del_timer(&req->rsk_timer))
+       if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
                reqsk_put(req);
        return found;
 }
index fe8cc183411e052f6e0ba4afefbeaef1e77313cd..95ea633e8356eb9b419e4027f9954810194aa23c 100644 (file)
@@ -226,7 +226,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
 
        synproxy_build_options(nth, opts);
 
-       synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+       synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+                         niph, nth, tcp_hdr_size);
 }
 
 static bool
index 433231ccfb17fc6d01179247d1d81226803d18df..0330ab2e2b6329ced120cd9b7100a5a34f50e82b 100644 (file)
@@ -41,8 +41,6 @@ static int tcp_syn_retries_min = 1;
 static int tcp_syn_retries_max = MAX_TCP_SYNCNT;
 static int ip_ping_group_range_min[] = { 0, 0 };
 static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
-static int min_sndbuf = SOCK_MIN_SNDBUF;
-static int min_rcvbuf = SOCK_MIN_RCVBUF;
 
 /* Update system visible IP port range */
 static void set_local_port_range(struct net *net, int range[2])
@@ -530,7 +528,7 @@ static struct ctl_table ipv4_table[] = {
                .maxlen         = sizeof(sysctl_tcp_wmem),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &min_sndbuf,
+               .extra1         = &one,
        },
        {
                .procname       = "tcp_notsent_lowat",
@@ -545,7 +543,7 @@ static struct ctl_table ipv4_table[] = {
                .maxlen         = sizeof(sysctl_tcp_rmem),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &min_rcvbuf,
+               .extra1         = &one,
        },
        {
                .procname       = "tcp_app_win",
@@ -758,7 +756,7 @@ static struct ctl_table ipv4_table[] = {
                .maxlen         = sizeof(sysctl_udp_rmem_min),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &min_rcvbuf,
+               .extra1         = &one
        },
        {
                .procname       = "udp_wmem_min",
@@ -766,7 +764,7 @@ static struct ctl_table ipv4_table[] = {
                .maxlen         = sizeof(sysctl_udp_wmem_min),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &min_sndbuf,
+               .extra1         = &one
        },
        { }
 };
index d7d4c2b79cf2f516f9e3f62c6fe4415e9bc137a0..0ea2e1c5d395ac979e9a301d006867d49b866ecb 100644 (file)
@@ -1348,7 +1348,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
        req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr);
        if (req) {
                nsk = tcp_check_req(sk, skb, req, false);
-               if (!nsk)
+               if (!nsk || nsk == sk)
                        reqsk_put(req);
                return nsk;
        }
index 83aa604f9273c332c5a0e5399253d961ef92eb9a..1b8c5ba7d5f732ea2220ada929049c5c7cfd5e83 100644 (file)
@@ -1995,12 +1995,19 @@ void udp_v4_early_demux(struct sk_buff *skb)
 
        skb->sk = sk;
        skb->destructor = sock_efree;
-       dst = sk->sk_rx_dst;
+       dst = READ_ONCE(sk->sk_rx_dst);
 
        if (dst)
                dst = dst_check(dst, 0);
-       if (dst)
-               skb_dst_set_noref(skb, dst);
+       if (dst) {
+               /* DST_NOCACHE can not be used without taking a reference */
+               if (dst->flags & DST_NOCACHE) {
+                       if (likely(atomic_inc_not_zero(&dst->__refcnt)))
+                               skb_dst_set(skb, dst);
+               } else {
+                       skb_dst_set_noref(skb, dst);
+               }
+       }
 }
 
 int udp_rcv(struct sk_buff *skb)
index 55d19861ab20f4a91b6b289be7ca3b0250df4531..548c6237b1e706f8ef72575a6a7dbad544b60fcc 100644 (file)
@@ -172,6 +172,8 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
                        *ppcpu_rt = NULL;
                }
        }
+
+       non_pcpu_rt->rt6i_pcpu = NULL;
 }
 
 static void rt6_release(struct rt6_info *rt)
index a38d3ac0f18f6e631e3a17904bf617f7a0dfe28a..69f4f689f06afb0bc1cdb4ab7d34ca3a8471a715 100644 (file)
@@ -361,6 +361,7 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
        struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
 
        ip6gre_tunnel_unlink(ign, t);
+       ip6_tnl_dst_reset(t);
        dev_put(dev);
 }
 
index df8afe5ab31e4b8e75bf2fbf844f8b3e798edbba..9405b04eecc64f478960329da93f6e01d437954e 100644 (file)
@@ -143,34 +143,36 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb,
        struct sk_buff *skb_chk = NULL;
        unsigned int transport_len;
        unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg);
-       int ret;
+       int ret = -EINVAL;
 
        transport_len = ntohs(ipv6_hdr(skb)->payload_len);
        transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr);
 
-       skb_get(skb);
        skb_chk = skb_checksum_trimmed(skb, transport_len,
                                       ipv6_mc_validate_checksum);
        if (!skb_chk)
-               return -EINVAL;
+               goto err;
 
-       if (!pskb_may_pull(skb_chk, len)) {
-               kfree_skb(skb_chk);
-               return -EINVAL;
-       }
+       if (!pskb_may_pull(skb_chk, len))
+               goto err;
 
        ret = ipv6_mc_check_mld_msg(skb_chk);
-       if (ret) {
-               kfree_skb(skb_chk);
-               return ret;
-       }
+       if (ret)
+               goto err;
 
        if (skb_trimmed)
                *skb_trimmed = skb_chk;
-       else
+       /* free now unneeded clone */
+       else if (skb_chk != skb)
                kfree_skb(skb_chk);
 
-       return 0;
+       ret = 0;
+
+err:
+       if (ret && skb_chk && skb_chk != skb)
+               kfree_skb(skb_chk);
+
+       return ret;
 }
 
 /**
@@ -179,7 +181,7 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb,
  * @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional)
  *
  * Checks whether an IPv6 packet is a valid MLD packet. If so sets
- * skb network and transport headers accordingly and returns zero.
+ * skb transport header accordingly and returns zero.
  *
  * -EINVAL: A broken packet was detected, i.e. it violates some internet
  *  standard
@@ -194,7 +196,8 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb,
  * to leave the original skb and its full frame unchanged (which might be
  * desirable for layer 2 frame jugglers).
  *
- * The caller needs to release a reference count from any returned skb_trimmed.
+ * Caller needs to set the skb network header and free any returned skb if it
+ * differs from the provided skb.
  */
 int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed)
 {
index 6edb7b106de769728357174d0657c644f83e41e8..ebbb754c2111b73c87fe85aa58b3124e0a3032ef 100644 (file)
@@ -37,12 +37,13 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
 }
 
 static void
-synproxy_send_tcp(const struct sk_buff *skb, struct sk_buff *nskb,
+synproxy_send_tcp(const struct synproxy_net *snet,
+                 const struct sk_buff *skb, struct sk_buff *nskb,
                  struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
                  struct ipv6hdr *niph, struct tcphdr *nth,
                  unsigned int tcp_hdr_size)
 {
-       struct net *net = nf_ct_net((struct nf_conn *)nfct);
+       struct net *net = nf_ct_net(snet->tmpl);
        struct dst_entry *dst;
        struct flowi6 fl6;
 
@@ -83,7 +84,8 @@ free_nskb:
 }
 
 static void
-synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th,
+synproxy_send_client_synack(const struct synproxy_net *snet,
+                           const struct sk_buff *skb, const struct tcphdr *th,
                            const struct synproxy_options *opts)
 {
        struct sk_buff *nskb;
@@ -119,7 +121,7 @@ synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th,
 
        synproxy_build_options(nth, opts);
 
-       synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+       synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
                          niph, nth, tcp_hdr_size);
 }
 
@@ -163,7 +165,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
 
        synproxy_build_options(nth, opts);
 
-       synproxy_send_tcp(skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
+       synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
                          niph, nth, tcp_hdr_size);
 }
 
@@ -203,7 +205,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
 
        synproxy_build_options(nth, opts);
 
-       synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+       synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
 }
 
 static void
@@ -241,7 +243,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
 
        synproxy_build_options(nth, opts);
 
-       synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+       synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+                         niph, nth, tcp_hdr_size);
 }
 
 static bool
@@ -301,7 +304,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
                                          XT_SYNPROXY_OPT_SACK_PERM |
                                          XT_SYNPROXY_OPT_ECN);
 
-               synproxy_send_client_synack(skb, th, &opts);
+               synproxy_send_client_synack(snet, skb, th, &opts);
                return NF_DROP;
 
        } else if (th->ack && !(th->fin || th->rst || th->syn)) {
index 6090969937f8b6809f74c3d03f29a0703089eff1..d15586490cecaedcc29bc821163cd6c85544b0b8 100644 (file)
@@ -318,8 +318,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
 /* allocate dst with ip6_dst_ops */
 static struct rt6_info *__ip6_dst_alloc(struct net *net,
                                        struct net_device *dev,
-                                       int flags,
-                                       struct fib6_table *table)
+                                       int flags)
 {
        struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
                                        0, DST_OBSOLETE_FORCE_CHK, flags);
@@ -336,10 +335,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net,
 
 static struct rt6_info *ip6_dst_alloc(struct net *net,
                                      struct net_device *dev,
-                                     int flags,
-                                     struct fib6_table *table)
+                                     int flags)
 {
-       struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags, table);
+       struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags);
 
        if (rt) {
                rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC);
@@ -950,8 +948,7 @@ static struct rt6_info *ip6_rt_cache_alloc(struct rt6_info *ort,
        if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
                ort = (struct rt6_info *)ort->dst.from;
 
-       rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev,
-                            0, ort->rt6i_table);
+       rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0);
 
        if (!rt)
                return NULL;
@@ -983,8 +980,7 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
        struct rt6_info *pcpu_rt;
 
        pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev),
-                                 rt->dst.dev, rt->dst.flags,
-                                 rt->rt6i_table);
+                                 rt->dst.dev, rt->dst.flags);
 
        if (!pcpu_rt)
                return NULL;
@@ -997,32 +993,53 @@ static struct rt6_info *ip6_rt_pcpu_alloc(struct rt6_info *rt)
 /* It should be called with read_lock_bh(&tb6_lock) acquired */
 static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt)
 {
-       struct rt6_info *pcpu_rt, *prev, **p;
+       struct rt6_info *pcpu_rt, **p;
 
        p = this_cpu_ptr(rt->rt6i_pcpu);
        pcpu_rt = *p;
 
-       if (pcpu_rt)
-               goto done;
+       if (pcpu_rt) {
+               dst_hold(&pcpu_rt->dst);
+               rt6_dst_from_metrics_check(pcpu_rt);
+       }
+       return pcpu_rt;
+}
+
+static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt)
+{
+       struct fib6_table *table = rt->rt6i_table;
+       struct rt6_info *pcpu_rt, *prev, **p;
 
        pcpu_rt = ip6_rt_pcpu_alloc(rt);
        if (!pcpu_rt) {
                struct net *net = dev_net(rt->dst.dev);
 
-               pcpu_rt = net->ipv6.ip6_null_entry;
-               goto done;
+               dst_hold(&net->ipv6.ip6_null_entry->dst);
+               return net->ipv6.ip6_null_entry;
        }
 
-       prev = cmpxchg(p, NULL, pcpu_rt);
-       if (prev) {
-               /* If someone did it before us, return prev instead */
+       read_lock_bh(&table->tb6_lock);
+       if (rt->rt6i_pcpu) {
+               p = this_cpu_ptr(rt->rt6i_pcpu);
+               prev = cmpxchg(p, NULL, pcpu_rt);
+               if (prev) {
+                       /* If someone did it before us, return prev instead */
+                       dst_destroy(&pcpu_rt->dst);
+                       pcpu_rt = prev;
+               }
+       } else {
+               /* rt has been removed from the fib6 tree
+                * before we have a chance to acquire the read_lock.
+                * In this case, don't brother to create a pcpu rt
+                * since rt is going away anyway.  The next
+                * dst_check() will trigger a re-lookup.
+                */
                dst_destroy(&pcpu_rt->dst);
-               pcpu_rt = prev;
+               pcpu_rt = rt;
        }
-
-done:
        dst_hold(&pcpu_rt->dst);
        rt6_dst_from_metrics_check(pcpu_rt);
+       read_unlock_bh(&table->tb6_lock);
        return pcpu_rt;
 }
 
@@ -1097,9 +1114,22 @@ redo_rt6_select:
                rt->dst.lastuse = jiffies;
                rt->dst.__use++;
                pcpu_rt = rt6_get_pcpu_route(rt);
-               read_unlock_bh(&table->tb6_lock);
+
+               if (pcpu_rt) {
+                       read_unlock_bh(&table->tb6_lock);
+               } else {
+                       /* We have to do the read_unlock first
+                        * because rt6_make_pcpu_route() may trigger
+                        * ip6_dst_gc() which will take the write_lock.
+                        */
+                       dst_hold(&rt->dst);
+                       read_unlock_bh(&table->tb6_lock);
+                       pcpu_rt = rt6_make_pcpu_route(rt);
+                       dst_release(&rt->dst);
+               }
 
                return pcpu_rt;
+
        }
 }
 
@@ -1555,7 +1585,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        if (unlikely(!idev))
                return ERR_PTR(-ENODEV);
 
-       rt = ip6_dst_alloc(net, dev, 0, NULL);
+       rt = ip6_dst_alloc(net, dev, 0);
        if (unlikely(!rt)) {
                in6_dev_put(idev);
                dst = ERR_PTR(-ENOMEM);
@@ -1742,7 +1772,8 @@ int ip6_route_add(struct fib6_config *cfg)
        if (!table)
                goto out;
 
-       rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table);
+       rt = ip6_dst_alloc(net, NULL,
+                          (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT);
 
        if (!rt) {
                err = -ENOMEM;
@@ -1831,6 +1862,7 @@ int ip6_route_add(struct fib6_config *cfg)
                int gwa_type;
 
                gw_addr = &cfg->fc_gateway;
+               gwa_type = ipv6_addr_type(gw_addr);
 
                /* if gw_addr is local we will fail to detect this in case
                 * address is still TENTATIVE (DAD in progress). rt6_lookup()
@@ -1838,11 +1870,12 @@ int ip6_route_add(struct fib6_config *cfg)
                 * prefix route was assigned to, which might be non-loopback.
                 */
                err = -EINVAL;
-               if (ipv6_chk_addr_and_flags(net, gw_addr, NULL, 0, 0))
+               if (ipv6_chk_addr_and_flags(net, gw_addr,
+                                           gwa_type & IPV6_ADDR_LINKLOCAL ?
+                                           dev : NULL, 0, 0))
                        goto out;
 
                rt->rt6i_gateway = *gw_addr;
-               gwa_type = ipv6_addr_type(gw_addr);
 
                if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
                        struct rt6_info *grt;
@@ -2397,7 +2430,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 {
        struct net *net = dev_net(idev->dev);
        struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
-                                           DST_NOCOUNT, NULL);
+                                           DST_NOCOUNT);
        if (!rt)
                return ERR_PTR(-ENOMEM);
 
index 6748c4277affad71cd721e3a985af10c31c047ad..7a6cea5e427414062f408cfa66f57808d48382d7 100644 (file)
@@ -943,7 +943,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
                                   &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
        if (req) {
                nsk = tcp_check_req(sk, skb, req, false);
-               if (!nsk)
+               if (!nsk || nsk == sk)
                        reqsk_put(req);
                return nsk;
        }
index b397f0aa9005543668c674df908c0ae817f53994..83a70688784b8449603e13f32ec26ff6fce06639 100644 (file)
@@ -219,7 +219,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
 #define BROADCAST_ONE          1
 #define BROADCAST_REGISTERED   2
 #define BROADCAST_PROMISC_ONLY 4
-static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
+static int pfkey_broadcast(struct sk_buff *skb,
                           int broadcast_flags, struct sock *one_sk,
                           struct net *net)
 {
@@ -244,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
                 * socket.
                 */
                if (pfk->promisc)
-                       pfkey_broadcast_one(skb, &skb2, allocation, sk);
+                       pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
 
                /* the exact target will be processed later */
                if (sk == one_sk)
@@ -259,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
                                continue;
                }
 
-               err2 = pfkey_broadcast_one(skb, &skb2, allocation, sk);
+               err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
 
                /* Error is cleare after succecful sending to at least one
                 * registered KM */
@@ -269,7 +269,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
        rcu_read_unlock();
 
        if (one_sk != NULL)
-               err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
+               err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk);
 
        kfree_skb(skb2);
        kfree_skb(skb);
@@ -292,7 +292,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
                hdr = (struct sadb_msg *) pfk->dump.skb->data;
                hdr->sadb_msg_seq = 0;
                hdr->sadb_msg_errno = rc;
-               pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+               pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
                                &pfk->sk, sock_net(&pfk->sk));
                pfk->dump.skb = NULL;
        }
@@ -333,7 +333,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
                             sizeof(uint64_t));
 
-       pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
+       pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
 
        return 0;
 }
@@ -1365,7 +1365,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
 
        xfrm_state_put(x);
 
-       pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net);
+       pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net);
 
        return 0;
 }
@@ -1452,7 +1452,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
        hdr->sadb_msg_seq = c->seq;
        hdr->sadb_msg_pid = c->portid;
 
-       pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x));
 
        return 0;
 }
@@ -1565,7 +1565,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg
        out_hdr->sadb_msg_reserved = 0;
        out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
        out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
+       pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk));
 
        return 0;
 }
@@ -1670,7 +1670,7 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
                return -ENOBUFS;
        }
 
-       pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, sock_net(sk));
+       pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk));
 
        return 0;
 }
@@ -1689,7 +1689,7 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
        hdr->sadb_msg_errno = (uint8_t) 0;
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
 
-       return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
+       return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
 }
 
 static int key_notify_sa_flush(const struct km_event *c)
@@ -1710,7 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c)
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
        hdr->sadb_msg_reserved = 0;
 
-       pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net);
 
        return 0;
 }
@@ -1767,7 +1767,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
        out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
 
        if (pfk->dump.skb)
-               pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+               pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
                                &pfk->sk, sock_net(&pfk->sk));
        pfk->dump.skb = out_skb;
 
@@ -1847,7 +1847,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb
                new_hdr->sadb_msg_errno = 0;
        }
 
-       pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk));
        return 0;
 }
 
@@ -2181,7 +2181,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev
        out_hdr->sadb_msg_errno = 0;
        out_hdr->sadb_msg_seq = c->seq;
        out_hdr->sadb_msg_pid = c->portid;
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
+       pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp));
        return 0;
 
 }
@@ -2401,7 +2401,7 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc
        out_hdr->sadb_msg_errno = 0;
        out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
        out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp));
+       pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp));
        err = 0;
 
 out:
@@ -2655,7 +2655,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
        out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
 
        if (pfk->dump.skb)
-               pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+               pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
                                &pfk->sk, sock_net(&pfk->sk));
        pfk->dump.skb = out_skb;
 
@@ -2708,7 +2708,7 @@ static int key_notify_policy_flush(const struct km_event *c)
        hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
        hdr->sadb_msg_reserved = 0;
-       pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
+       pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net);
        return 0;
 
 }
@@ -2770,7 +2770,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
        void *ext_hdrs[SADB_EXT_MAX];
        int err;
 
-       pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
+       pfkey_broadcast(skb_clone(skb, GFP_KERNEL),
                        BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
 
        memset(ext_hdrs, 0, sizeof(ext_hdrs));
@@ -2992,7 +2992,7 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
        out_hdr->sadb_msg_seq = 0;
        out_hdr->sadb_msg_pid = 0;
 
-       pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+       pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x));
        return 0;
 }
 
@@ -3182,7 +3182,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
                       xfrm_ctx->ctx_len);
        }
 
-       return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+       return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
 }
 
 static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
@@ -3380,7 +3380,7 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
        n_port->sadb_x_nat_t_port_port = sport;
        n_port->sadb_x_nat_t_port_reserved = 0;
 
-       return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+       return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
 }
 
 #ifdef CONFIG_NET_KEY_MIGRATE
@@ -3572,7 +3572,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
        }
 
        /* broadcast migrate message to sockets */
-       pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
+       pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net);
 
        return 0;
 
index 247552a7f6c2f23a1e4bc89b647d8d37680bf2c3..3ece7d1034c81ae8749cada074fbebecbe06d57f 100644 (file)
@@ -92,14 +92,15 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma)
 static inline void
 minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
 {
-       int j = MAX_THR_RATES;
-       struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats;
+       int j;
+       struct minstrel_rate_stats *tmp_mrs;
        struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats;
 
-       while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) >
-              minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) {
-               j--;
+       for (j = MAX_THR_RATES; j > 0; --j) {
                tmp_mrs = &mi->r[tp_list[j - 1]].stats;
+               if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <=
+                   minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))
+                       break;
        }
 
        if (j < MAX_THR_RATES - 1)
index 651039ad1681db0434cff21275f1bcbe3f8464bc..3c20d02aee738c5293a5b449f28ebff596c7232d 100644 (file)
@@ -292,7 +292,7 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags)
 {
        struct nf_conn *tmpl;
 
-       tmpl = kzalloc(sizeof(struct nf_conn), GFP_KERNEL);
+       tmpl = kzalloc(sizeof(*tmpl), flags);
        if (tmpl == NULL)
                return NULL;
 
@@ -303,7 +303,7 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags)
        if (zone) {
                struct nf_conntrack_zone *nf_ct_zone;
 
-               nf_ct_zone = nf_ct_ext_add(tmpl, NF_CT_EXT_ZONE, GFP_ATOMIC);
+               nf_ct_zone = nf_ct_ext_add(tmpl, NF_CT_EXT_ZONE, flags);
                if (!nf_ct_zone)
                        goto out_free;
                nf_ct_zone->id = zone;
@@ -1544,10 +1544,8 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
        sz = nr_slots * sizeof(struct hlist_nulls_head);
        hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
                                        get_order(sz));
-       if (!hash) {
-               printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
+       if (!hash)
                hash = vzalloc(sz);
-       }
 
        if (hash && nulls)
                for (i = 0; i < nr_slots; i++)
index 71f1e9fdfa18fb9b1f2f2730ca21af42dad98eea..d7f1685279034b5e3b62748284d24c52cc1f8907 100644 (file)
@@ -353,10 +353,8 @@ static int __net_init synproxy_net_init(struct net *net)
        int err = -ENOMEM;
 
        ct = nf_ct_tmpl_alloc(net, 0, GFP_KERNEL);
-       if (IS_ERR(ct)) {
-               err = PTR_ERR(ct);
+       if (!ct)
                goto err1;
-       }
 
        if (!nfct_seqadj_ext_add(ct))
                goto err2;
index c6630030c9121c7af27a3052ad776cd6646eb601..43ddeee404e91f97908fb9228c1e873931b75bcc 100644 (file)
@@ -202,9 +202,10 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
                goto err1;
 
        ct = nf_ct_tmpl_alloc(par->net, info->zone, GFP_KERNEL);
-       ret = PTR_ERR(ct);
-       if (IS_ERR(ct))
+       if (!ct) {
+               ret = -ENOMEM;
                goto err2;
+       }
 
        ret = 0;
        if ((info->ct_events || info->exp_events) &&
index d8e2e3918ce2fd95637c4cba8bfc4886feb91ea6..a774985489e21e3bafffa8c8b6947290d0f58f75 100644 (file)
@@ -1096,6 +1096,11 @@ static int netlink_insert(struct sock *sk, u32 portid)
 
        err = __netlink_insert(table, sk);
        if (err) {
+               /* In case the hashtable backend returns with -EBUSY
+                * from here, it must not escape to the caller.
+                */
+               if (unlikely(err == -EBUSY))
+                       err = -EOVERFLOW;
                if (err == -EEXIST)
                        err = -EADDRINUSE;
                nlk_sk(sk)->portid = 0;
@@ -2396,7 +2401,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
         * sendmsg(), but that's what we've got...
         */
        if (netlink_tx_is_mmaped(sk) &&
-           msg->msg_iter.type == ITER_IOVEC &&
+           iter_is_iovec(&msg->msg_iter) &&
            msg->msg_iter.nr_segs == 1 &&
            msg->msg_iter.iov->iov_base == NULL) {
                err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group,
index 8a8c0b8b4f63a4bd8e5ff776250189558e6fcb1e..ee34f474ad1465087da8fd506410559abe47d81e 100644 (file)
@@ -273,28 +273,36 @@ static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key,
        return 0;
 }
 
-static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
-                       __be32 *addr, __be32 new_addr)
+static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
+                                 __be32 addr, __be32 new_addr)
 {
        int transport_len = skb->len - skb_transport_offset(skb);
 
+       if (nh->frag_off & htons(IP_OFFSET))
+               return;
+
        if (nh->protocol == IPPROTO_TCP) {
                if (likely(transport_len >= sizeof(struct tcphdr)))
                        inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb,
-                                                *addr, new_addr, 1);
+                                                addr, new_addr, 1);
        } else if (nh->protocol == IPPROTO_UDP) {
                if (likely(transport_len >= sizeof(struct udphdr))) {
                        struct udphdr *uh = udp_hdr(skb);
 
                        if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
                                inet_proto_csum_replace4(&uh->check, skb,
-                                                        *addr, new_addr, 1);
+                                                        addr, new_addr, 1);
                                if (!uh->check)
                                        uh->check = CSUM_MANGLED_0;
                        }
                }
        }
+}
 
+static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
+                       __be32 *addr, __be32 new_addr)
+{
+       update_ip_l4_checksum(skb, nh, *addr, new_addr);
        csum_replace4(&nh->check, *addr, new_addr);
        skb_clear_hash(skb);
        *addr = new_addr;
index 9a6b4f66187cf3e5ab533cd01344c9856834ebb7..140a44a5f7b7f1c08b3f329707b72fc75a9a81fe 100644 (file)
@@ -176,7 +176,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
 
        /* check for all kinds of wrapping and the like */
        start = (unsigned long)optval;
-       if (len < 0 || len + PAGE_SIZE - 1 < len || start + len < start) {
+       if (len < 0 || len > INT_MAX - PAGE_SIZE + 1 || start + len < start) {
                ret = -EINVAL;
                goto out;
        }
index a42a3b257226178eb5af04054a17813c04368613..268545050ddbd67245ead8394a82f44503657ea5 100644 (file)
@@ -98,6 +98,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                        return ret;
                ret = ACT_P_CREATED;
        } else {
+               if (bind)
+                       return 0;
                if (!ovr) {
                        tcf_hash_release(a, bind);
                        return -EEXIST;
index cab9e9b43967a57780140b9229c8cadff088607c..4fbb67430ce4821fd66576132afec2d7a301b379 100644 (file)
@@ -490,6 +490,19 @@ static bool u32_destroy(struct tcf_proto *tp, bool force)
                                        return false;
                        }
                }
+
+               if (tp_c->refcnt > 1)
+                       return false;
+
+               if (tp_c->refcnt == 1) {
+                       struct tc_u_hnode *ht;
+
+                       for (ht = rtnl_dereference(tp_c->hlist);
+                            ht;
+                            ht = rtnl_dereference(ht->next))
+                               if (!ht_empty(ht))
+                                       return false;
+               }
        }
 
        if (root_ht && --root_ht->refcnt == 0)
index 21ca33c9f0368b21cdb00fbdbbca4851c2ad87a2..a9ba030435a2a5c2ca4bea21d62c6d631c6168f4 100644 (file)
@@ -288,10 +288,26 @@ begin:
 
 static void fq_codel_reset(struct Qdisc *sch)
 {
-       struct sk_buff *skb;
+       struct fq_codel_sched_data *q = qdisc_priv(sch);
+       int i;
 
-       while ((skb = fq_codel_dequeue(sch)) != NULL)
-               kfree_skb(skb);
+       INIT_LIST_HEAD(&q->new_flows);
+       INIT_LIST_HEAD(&q->old_flows);
+       for (i = 0; i < q->flows_cnt; i++) {
+               struct fq_codel_flow *flow = q->flows + i;
+
+               while (flow->head) {
+                       struct sk_buff *skb = dequeue_head(flow);
+
+                       qdisc_qstats_backlog_dec(sch, skb);
+                       kfree_skb(skb);
+               }
+
+               INIT_LIST_HEAD(&flow->flowchain);
+               codel_vars_init(&flow->cvars);
+       }
+       memset(q->backlogs, 0, q->flows_cnt * sizeof(u32));
+       sch->q.qlen = 0;
 }
 
 static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
index 06320c8c1c8660cdd4e1a56968353169236fb2df..a655ddc3f3530727f5225ee40f006964b8cb7a50 100644 (file)
@@ -3132,11 +3132,18 @@ bool sctp_verify_asconf(const struct sctp_association *asoc,
                case SCTP_PARAM_IPV4_ADDRESS:
                        if (length != sizeof(sctp_ipv4addr_param_t))
                                return false;
+                       /* ensure there is only one addr param and it's in the
+                        * beginning of addip_hdr params, or we reject it.
+                        */
+                       if (param.v != addip->addip_hdr.params)
+                               return false;
                        addr_param_seen = true;
                        break;
                case SCTP_PARAM_IPV6_ADDRESS:
                        if (length != sizeof(sctp_ipv6addr_param_t))
                                return false;
+                       if (param.v != addip->addip_hdr.params)
+                               return false;
                        addr_param_seen = true;
                        break;
                case SCTP_PARAM_ADD_IP:
index fef2acdf4a2e675c55dc9fbf2124d132499b89e3..85e6f03aeb700d8e5fcdb103464add4240ce29f9 100644 (file)
@@ -702,7 +702,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
         * outstanding data and rely on the retransmission limit be reached
         * to shutdown the association.
         */
-       if (t->asoc->state != SCTP_STATE_SHUTDOWN_PENDING)
+       if (t->asoc->state < SCTP_STATE_SHUTDOWN_PENDING)
                t->asoc->overall_error_count = 0;
 
        /* Clear the hb_sent flag to signal that we had a good
index 42f7c76cf853697341a6e34cf522f92927b36ad4..f07224d8b88f6a2479de02ce944181edcd2576ab 100644 (file)
@@ -31,7 +31,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 64,
                }
        },
@@ -50,7 +50,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 96,
                }
        },
@@ -69,7 +69,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 128,
                }
        },
@@ -88,7 +88,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 64,
                }
        },
@@ -107,7 +107,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 96,
                }
        },
@@ -126,7 +126,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 128,
                }
        },
@@ -164,7 +164,7 @@ static struct xfrm_algo_desc aead_list[] = {
 
        .uinfo = {
                .aead = {
-                       .geniv = "seqniv",
+                       .geniv = "seqiv",
                        .icv_truncbits = 128,
                }
        },
index c89fdcaf06e812d305073f038bc9fb11fd37d55d..2f4b7ffd5570011cbe7bbd733e41fc6ae5a686cc 100755 (executable)
@@ -2,7 +2,7 @@
 
 """Find Kconfig symbols that are referenced but not defined."""
 
-# (c) 2014-2015 Valentin Rothberg <Valentin.Rothberg@lip6.fr>
+# (c) 2014-2015 Valentin Rothberg <valentinrothberg@gmail.com>
 # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
 #
 # Licensed under the terms of the GNU GPL License version 2
@@ -20,18 +20,20 @@ OPERATORS = r"&|\(|\)|\||\!"
 FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}"
 DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*"
 EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+"
-STMT = r"^\s*(?:if|select|depends\s+on)\s+" + EXPR
+DEFAULT = r"default\s+.*?(?:if\s.+){,1}"
+STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR
 SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")"
 
 # regex objects
 REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$")
-REGEX_FEATURE = re.compile(r"(" + FEATURE + r")")
+REGEX_FEATURE = re.compile(r'(?!\B"[^"]*)' + FEATURE + r'(?![^"]*"\B)')
 REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE)
 REGEX_KCONFIG_DEF = re.compile(DEF)
 REGEX_KCONFIG_EXPR = re.compile(EXPR)
 REGEX_KCONFIG_STMT = re.compile(STMT)
 REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
 REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$")
+REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+")
 
 
 def parse_options():
@@ -58,6 +60,11 @@ def parse_options():
                            "input format bases on Git log's "
                            "\'commmit1..commit2\'.")
 
+    parser.add_option('-f', '--find', dest='find', action='store_true',
+                      default=False,
+                      help="Find and show commits that may cause symbols to be "
+                           "missing.  Required to run with --diff.")
+
     parser.add_option('-i', '--ignore', dest='ignore', action='store',
                       default="",
                       help="Ignore files matching this pattern.  Note that "
@@ -86,6 +93,9 @@ def parse_options():
                      "'--force' if you\nwant to ignore this warning and "
                      "continue.")
 
+    if opts.commit:
+        opts.find = False
+
     if opts.ignore:
         try:
             re.match(opts.ignore, "this/is/just/a/test.c")
@@ -128,13 +138,19 @@ def main():
             # feature has not been undefined before
             if not feature in undefined_a:
                 files = sorted(undefined_b.get(feature))
-                print "%s\t%s" % (feature, ", ".join(files))
+                print "%s\t%s" % (yel(feature), ", ".join(files))
+                if opts.find:
+                    commits = find_commits(feature, opts.diff)
+                    print red(commits)
             # check if there are new files that reference the undefined feature
             else:
                 files = sorted(undefined_b.get(feature) -
                                undefined_a.get(feature))
                 if files:
-                    print "%s\t%s" % (feature, ", ".join(files))
+                    print "%s\t%s" % (yel(feature), ", ".join(files))
+                    if opts.find:
+                        commits = find_commits(feature, opts.diff)
+                        print red(commits)
 
         # reset to head
         execute("git reset --hard %s" % head)
@@ -144,7 +160,21 @@ def main():
         undefined = check_symbols(opts.ignore)
         for feature in sorted(undefined):
             files = sorted(undefined.get(feature))
-            print "%s\t%s" % (feature, ", ".join(files))
+            print "%s\t%s" % (yel(feature), ", ".join(files))
+
+
+def yel(string):
+    """
+    Color %string yellow.
+    """
+    return "\033[33m%s\033[0m" % string
+
+
+def red(string):
+    """
+    Color %string red.
+    """
+    return "\033[31m%s\033[0m" % string
 
 
 def execute(cmd):
@@ -156,6 +186,13 @@ def execute(cmd):
     return stdout
 
 
+def find_commits(symbol, diff):
+    """Find commits changing %symbol in the given range of %diff."""
+    commits = execute("git log --pretty=oneline --abbrev-commit -G %s %s"
+                      % (symbol, diff))
+    return commits
+
+
 def tree_is_dirty():
     """Return true if the current working tree is dirty (i.e., if any file has
     been added, deleted, modified, renamed or copied but not committed)."""
@@ -279,6 +316,9 @@ def parse_kconfig_file(kfile, defined_features, referenced_features):
                 line = line.strip('\n')
                 features.extend(get_features_in_line(line))
             for feature in set(features):
+                if REGEX_NUMERIC.match(feature):
+                    # ignore numeric values
+                    continue
                 paths = referenced_features.get(feature, set())
                 paths.add(kfile)
                 referenced_features[feature] = paths
index 9922e66883a5b763eb2b24345b9925cbe06db3c3..a7bf5f68aacb2f80417f31c6b6663d3d76a149f6 100755 (executable)
@@ -133,6 +133,30 @@ use strict;
 #
 # All descriptions can be multiline, except the short function description.
 #
+# For really longs structs, you can also describe arguments inside the
+# body of the struct.
+# eg.
+# /**
+#  * struct my_struct - short description
+#  * @a: first member
+#  * @b: second member
+#  *
+#  * Longer description
+#  */
+# struct my_struct {
+#     int a;
+#     int b;
+#     /**
+#      * @c: This is longer description of C
+#      *
+#      * You can use paragraphs to describe arguments
+#      * using this method.
+#      */
+#     int c;
+# };
+#
+# This should be use only for struct/enum members.
+#
 # You can also add additional sections. When documenting kernel functions you
 # 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
@@ -253,11 +277,20 @@ my %highlights = %highlights_man;
 my $blankline = $blankline_man;
 my $modulename = "Kernel API";
 my $function_only = 0;
+my $show_not_found = 0;
+
+my @build_time;
+if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
+    (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
+    @build_time = gmtime($seconds);
+} else {
+    @build_time = localtime;
+}
+
 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
                'July', 'August', 'September', 'October',
-               'November', 'December')[(localtime)[4]] .
-  " " . ((localtime)[5]+1900);
-my $show_not_found = 0;
+               'November', 'December')[$build_time[4]] .
+  " " . ($build_time[5]+1900);
 
 # Essentially these are globals.
 # They probably want to be tidied up, made more localised or something.
@@ -287,9 +320,19 @@ my $lineprefix="";
 # 2 - scanning field start.
 # 3 - scanning prototype.
 # 4 - documentation block
+# 5 - gathering documentation outside main block
 my $state;
 my $in_doc_sect;
 
+# Split Doc State
+# 0 - Invalid (Before start or after finish)
+# 1 - Is started (the /** was found inside a struct)
+# 2 - The @parameter header was found, start accepting multi paragraph text.
+# 3 - Finished (the */ was found)
+# 4 - Error - Comment without header was found. Spit a warning as it's not
+#     proper kernel-doc and ignore the rest.
+my $split_doc_state;
+
 #declaration types: can be
 # 'function', 'struct', 'union', 'enum', 'typedef'
 my $decl_type;
@@ -304,6 +347,9 @@ my $doc_decl = $doc_com . '(\w+)';
 my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
 my $doc_content = $doc_com_body . '(.*)';
 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
+my $doc_split_start = '^\s*/\*\*\s*$';
+my $doc_split_sect = '\s*\*\s*(@[\w\s]+):(.*)';
+my $doc_split_end = '^\s*\*/\s*$';
 
 my %constants;
 my %parameterdescs;
@@ -1753,7 +1799,9 @@ sub dump_struct($$) {
        # strip kmemcheck_bitfield_{begin,end}.*;
        $members =~ s/kmemcheck_bitfield_.*?;//gos;
        # strip attributes
+       $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
        $members =~ s/__aligned\s*\([^;]*\)//gos;
+       $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
 
        create_parameterlist($members, ';', $file);
        check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
@@ -2181,6 +2229,7 @@ sub reset_state {
     $prototype = "";
 
     $state = 0;
+    $split_doc_state = 0;
 }
 
 sub tracepoint_munge($) {
@@ -2453,7 +2502,6 @@ sub process_file($) {
                }
                $section = $newsection;
            } elsif (/$doc_end/) {
-
                if (($contents ne "") && ($contents ne "\n")) {
                    dump_section($file, $section, xml_escape($contents));
                    $section = $section_default;
@@ -2494,8 +2542,44 @@ sub process_file($) {
                print STDERR "Warning(${file}:$.): bad line: $_";
                ++$warnings;
            }
+       } elsif ($state == 5) { # scanning for split parameters
+           # First line (state 1) needs to be a @parameter
+           if ($split_doc_state == 1 && /$doc_split_sect/o) {
+               $section = $1;
+               $contents = $2;
+               if ($contents ne "") {
+                   while ((substr($contents, 0, 1) eq " ") ||
+                          substr($contents, 0, 1) eq "\t") {
+                       $contents = substr($contents, 1);
+                   }
+               $contents .= "\n";
+               }
+               $split_doc_state = 2;
+           # Documentation block end */
+           } elsif (/$doc_split_end/) {
+               if (($contents ne "") && ($contents ne "\n")) {
+                   dump_section($file, $section, xml_escape($contents));
+                   $section = $section_default;
+                   $contents = "";
+               }
+               $state = 3;
+               $split_doc_state = 0;
+           # Regular text
+           } elsif (/$doc_content/) {
+               if ($split_doc_state == 2) {
+                   $contents .= $1 . "\n";
+               } elsif ($split_doc_state == 1) {
+                   $split_doc_state = 4;
+                   print STDERR "Warning(${file}:$.): ";
+                   print STDERR "Incorrect use of kernel-doc format: $_";
+                   ++$warnings;
+               }
+           }
        } elsif ($state == 3) { # scanning for function '{' (end of prototype)
-           if ($decl_type eq 'function') {
+           if (/$doc_split_start/) {
+               $state = 5;
+               $split_doc_state = 1;
+           } elsif ($decl_type eq 'function') {
                process_state3_function($_, $file);
            } else {
                process_state3_type($_, $file);
@@ -2587,7 +2671,7 @@ $kernelversion = get_kernel_version();
 
 # generate a sequence of code that will splice in highlighting information
 # using the s// operator.
-foreach my $pattern (keys %highlights) {
+foreach my $pattern (sort keys %highlights) {
 #   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
     $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
 }
diff --git a/scripts/kernel-doc-xml-ref b/scripts/kernel-doc-xml-ref
new file mode 100755 (executable)
index 0000000..104a5a5
--- /dev/null
@@ -0,0 +1,198 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+## Copyright (C) 2015  Intel Corporation                         ##
+#                                                                ##
+## This software falls under the GNU General Public License.     ##
+## Please read the COPYING file for more information             ##
+#
+#
+# This software reads a XML file and a list of valid interal
+# references to replace Docbook tags with links.
+#
+# The list of "valid internal references" must be one-per-line in the following format:
+#      API-struct-foo
+#      API-enum-bar
+#      API-my-function
+#
+# The software walks over the XML file looking for xml tags representing possible references
+# to the Document. Each reference will be cross checked against the "Valid Internal Reference" list. If
+# the referece is found it replaces its content by a <link> tag.
+#
+# usage:
+# kernel-doc-xml-ref -db filename
+#                   xml filename > outputfile
+
+# read arguments
+if ($#ARGV != 2) {
+       usage();
+}
+
+#Holds the database filename
+my $databasefile;
+my @database;
+
+#holds the inputfile
+my $inputfile;
+my $errors = 0;
+
+my %highlights = (
+       "<function>(.*?)</function>",
+           "\"<function>\" . convert_function(\$1, \$line) . \"</function>\"",
+       "<structname>(.*?)</structname>",
+           "\"<structname>\" . convert_struct(\$1) . \"</structname>\"",
+       "<funcdef>(.*?)<function>(.*?)</function></funcdef>",
+           "\"<funcdef>\" . convert_param(\$1) . \"<function>\$2</function></funcdef>\"",
+       "<paramdef>(.*?)<parameter>(.*?)</parameter></paramdef>",
+           "\"<paramdef>\" . convert_param(\$1) . \"<parameter>\$2</parameter></paramdef>\"");
+
+while($ARGV[0] =~ m/^-(.*)/) {
+       my $cmd = shift @ARGV;
+       if ($cmd eq "-db") {
+               $databasefile = shift @ARGV
+       } else {
+               usage();
+       }
+}
+$inputfile = shift @ARGV;
+
+sub open_database {
+       open (my $handle, '<', $databasefile) or die "Cannot open $databasefile";
+       chomp(my @lines = <$handle>);
+       close $handle;
+
+       @database = @lines;
+}
+
+sub process_file {
+       open_database();
+
+       my $dohighlight;
+       foreach my $pattern (keys %highlights) {
+               $dohighlight .=  "\$line =~ s:$pattern:$highlights{$pattern}:eg;\n";
+       }
+
+       open(FILE, $inputfile) or die("Could not open $inputfile") or die ("Cannot open $inputfile");
+       foreach my $line (<FILE>)  {
+               eval $dohighlight;
+               print $line;
+       }
+}
+
+sub trim($_)
+{
+       my $str = $_[0];
+       $str =~ s/^\s+|\s+$//g;
+       return $str
+}
+
+sub has_key_defined($_)
+{
+       if ( grep( /^$_[0]$/, @database)) {
+               return 1;
+       }
+       return 0;
+}
+
+# Gets a <function> content and add it a hyperlink if possible.
+sub convert_function($_)
+{
+       my $arg = $_[0];
+       my $key = $_[0];
+
+       my $line = $_[1];
+
+       $key = trim($key);
+
+       $key =~ s/[^A-Za-z0-9]/-/g;
+       $key = "API-" . $key;
+
+       # We shouldn't add links to <funcdef> prototype
+       if (!has_key_defined($key) || $line =~ m/\s+<funcdef/i) {
+               return $arg;
+       }
+
+       my $head = $arg;
+       my $tail = "";
+       if ($arg =~ /(.*?)( ?)$/) {
+               $head = $1;
+               $tail = $2;
+       }
+       return "<link linkend=\"$key\">$head</link>$tail";
+}
+
+# Converting a struct text to link
+sub convert_struct($_)
+{
+       my $arg = $_[0];
+       my $key = $_[0];
+       $key =~ s/(struct )?(\w)/$2/g;
+       $key =~ s/[^A-Za-z0-9]/-/g;
+       $key = "API-struct-" . $key;
+
+       if (!has_key_defined($key)) {
+               return $arg;
+       }
+
+       my ($head, $tail) = split_pointer($arg);
+       return "<link linkend=\"$key\">$head</link>$tail";
+}
+
+# Identify "object *" elements
+sub split_pointer($_)
+{
+       my $arg = $_[0];
+       if ($arg =~ /(.*?)( ?\* ?)/) {
+               return ($1, $2);
+       }
+       return ($arg, "");
+}
+
+sub convert_param($_)
+{
+       my $type = $_[0];
+       my $keyname = convert_key_name($type);
+
+       if (!has_key_defined($keyname)) {
+               return $type;
+       }
+
+       my ($head, $tail) = split_pointer($type);
+       return "<link linkend=\"$keyname\">$head</link>$tail";
+
+}
+
+# DocBook links are in the API-<TYPE>-<STRUCT-NAME> format
+# This method gets an element and returns a valid DocBook reference for it.
+sub convert_key_name($_)
+{
+       #Pattern $2 is optional and might be uninitialized
+       no warnings 'uninitialized';
+
+       my $str = $_[0];
+       $str =~ s/(const|static)? ?(struct)? ?([a-zA-Z0-9_]+) ?(\*|&)?/$2 $3/g ;
+
+       # trim
+       $str =~ s/^\s+|\s+$//g;
+
+       # spaces and _ to -
+       $str =~ s/[^A-Za-z0-9]/-/g;
+
+       return "API-" . $str;
+}
+
+sub usage {
+       print "Usage: $0 -db database filename\n";
+       print "         xml source file(s) > outputfile\n";
+       exit 1;
+}
+
+# starting point
+process_file();
+
+if ($errors) {
+       print STDERR "$errors errors\n";
+}
+
+exit($errors);
index 595fffab48b0a27077efa75ec9dd64e6983ae2d9..994283624bdb223e13fd99a93531909c6882b83d 100644 (file)
@@ -380,8 +380,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
                return 0;
 
        if (!initxattrs)
-               return call_int_hook(inode_init_security, 0, inode, dir, qstr,
-                                                        NULL, NULL, NULL);
+               return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
+                                    dir, qstr, NULL, NULL, NULL);
        memset(new_xattrs, 0, sizeof(new_xattrs));
        lsm_xattr = new_xattrs;
        ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
@@ -409,8 +409,8 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
 {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
-       return call_int_hook(inode_init_security, 0, inode, dir, qstr,
-                               name, value, len);
+       return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir,
+                            qstr, name, value, len);
 }
 EXPORT_SYMBOL(security_old_inode_init_security);
 
@@ -1281,7 +1281,8 @@ int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
 
 int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 {
-       return call_int_hook(socket_getpeersec_dgram, 0, sock, skb, secid);
+       return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock,
+                            skb, secid);
 }
 EXPORT_SYMBOL(security_socket_getpeersec_dgram);
 
index 5de3c5d8c2c0050c5c560c9aecfd0ab756932a59..d1a2cb65e27cd76b668c2ce2cb9a909787eca2a7 100644 (file)
@@ -3172,7 +3172,7 @@ static int add_std_chmaps(struct hda_codec *codec)
                        struct snd_pcm_chmap *chmap;
                        const struct snd_pcm_chmap_elem *elem;
 
-                       if (!pcm || pcm->own_chmap ||
+                       if (!pcm || !pcm->pcm || pcm->own_chmap ||
                            !hinfo->substreams)
                                continue;
                        elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
index b077bb644434734004b7afca348bbac4643478a5..24f91114a32cc73f54d72d8b008db51935519893 100644 (file)
@@ -671,7 +671,8 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
                }
                for (i = 0; i < path->depth; i++) {
                        if (path->path[i] == nid) {
-                               if (dir == HDA_OUTPUT || path->idx[i] == idx)
+                               if (dir == HDA_OUTPUT || idx == -1 ||
+                                   path->idx[i] == idx)
                                        return true;
                                break;
                        }
@@ -682,7 +683,7 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
 
 /* check whether the NID is referred by any active paths */
 #define is_active_nid_for_any(codec, nid) \
-       is_active_nid(codec, nid, HDA_OUTPUT, 0)
+       is_active_nid(codec, nid, HDA_OUTPUT, -1)
 
 /* get the default amp value for the target state */
 static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
@@ -883,8 +884,7 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
        struct hda_gen_spec *spec = codec->spec;
        int i;
 
-       if (!enable)
-               path->active = false;
+       path->active = enable;
 
        /* make sure the widget is powered up */
        if (enable && (spec->power_down_unused || codec->power_save_node))
@@ -902,9 +902,6 @@ void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
                if (has_amp_out(codec, path, i))
                        activate_amp_out(codec, path, i, enable);
        }
-
-       if (enable)
-               path->active = true;
 }
 EXPORT_SYMBOL_GPL(snd_hda_activate_path);
 
index f788a91b544a32f8e39f354e3ff95e328b0fd4bc..ca03c40609fcf09d8838ed05f4920de3f03a6cf7 100644 (file)
@@ -200,12 +200,33 @@ static int cx_auto_init(struct hda_codec *codec)
        return 0;
 }
 
-#define cx_auto_free   snd_hda_gen_free
+static void cx_auto_reboot_notify(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+
+       if (codec->core.vendor_id != 0x14f150f2)
+               return;
+
+       /* Turn the CX20722 codec into D3 to avoid spurious noises
+          from the internal speaker during (and after) reboot */
+       cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
+
+       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+       snd_hda_codec_write(codec, codec->core.afg, 0,
+                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
+
+static void cx_auto_free(struct hda_codec *codec)
+{
+       cx_auto_reboot_notify(codec);
+       snd_hda_gen_free(codec);
+}
 
 static const struct hda_codec_ops cx_auto_patch_ops = {
        .build_controls = cx_auto_build_controls,
        .build_pcms = snd_hda_gen_build_pcms,
        .init = cx_auto_init,
+       .reboot_notify = cx_auto_reboot_notify,
        .free = cx_auto_free,
        .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
index 0b9847affbeccbc4b1a807b642120a3feaa397d0..374ea53288ca25ff6093467012afd2607192f505 100644 (file)
@@ -5190,6 +5190,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
+       SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5291,6 +5292,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
index 2ae9619443d15dbeaf128cab385347db6bf26369..1d651b8a89570404cd306f239b17e939b1d5fa81 100644 (file)
@@ -30,6 +30,9 @@ config SND_SOC_GENERIC_DMAENGINE_PCM
        bool
        select SND_DMAENGINE_PCM
 
+config SND_SOC_TOPOLOGY
+       bool
+
 # All the supported SoCs
 source "sound/soc/adi/Kconfig"
 source "sound/soc/atmel/Kconfig"
index e189903fabf42958eff143e487999f0f013b85d7..669648b41d3027adf29ead27eda5f72a6ed0aaf1 100644 (file)
@@ -1,6 +1,9 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
 snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o
+
+ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
 snd-soc-core-objs += soc-topology.o
+endif
 
 ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
 snd-soc-core-objs += soc-generic-dmaengine-pcm.o
index 1fab9778807a0015f2578f0504306ed852eb4932..0450593980fd3525a65feca17dccea0e9940506e 100644 (file)
@@ -638,7 +638,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
        int err = -ENODEV;
 
        down_read(&chip->shutdown_rwsem);
-       if (chip->probing && chip->in_pm)
+       if (chip->probing || chip->in_pm)
                err = 0;
        else if (!chip->shutdown)
                err = usb_autopm_get_interface(chip->pm_intf);
index 754e689596a21b43f3b3a45b8f3062ec29b74099..00ebc0ca008e08b98b2f5fb6aed67dfb0d642ec1 100644 (file)
@@ -1268,6 +1268,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
+       case USB_ID(0x20b1, 0x000a): /* Gustard DAC-X20U */
        case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
        case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
                if (fp->altsetting == 3)
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
new file mode 100644 (file)
index 0000000..162a378
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+import os
+from optparse import OptionParser
+
+parser = OptionParser()
+parser.add_option("-v", "--verbose", dest="verbose",
+                  help="print verbose messages. Try -vv, -vvv for \
+                       more verbose messages", action="count")
+
+(options, args) = parser.parse_args()
+
+verbose = 0
+if options.verbose is not None:
+       verbose = options.verbose
+
+vmbus_sys_path = '/sys/bus/vmbus/devices'
+if not os.path.isdir(vmbus_sys_path):
+       print "%s doesn't exist: exiting..." % vmbus_sys_path
+       exit(-1)
+
+vmbus_dev_dict = {
+       '{0e0b6031-5213-4934-818b-38d90ced39db}' : '[Operating system shutdown]',
+       '{9527e630-d0ae-497b-adce-e80ab0175caf}' : '[Time Synchronization]',
+       '{57164f39-9115-4e78-ab55-382f3bd5422d}' : '[Heartbeat]',
+       '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}' : '[Data Exchange]',
+       '{35fa2e29-ea23-4236-96ae-3a6ebacba440}' : '[Backup (volume checkpoint)]',
+       '{34d14be3-dee4-41c8-9ae7-6b174977c192}' : '[Guest services]',
+       '{525074dc-8985-46e2-8057-a307dc18a502}' : '[Dynamic Memory]',
+       '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}' : 'Synthetic mouse',
+       '{f912ad6d-2b17-48ea-bd65-f927a61c7684}' : 'Synthetic keyboard',
+       '{da0a7802-e377-4aac-8e77-0558eb1073f8}' : 'Synthetic framebuffer adapter',
+       '{f8615163-df3e-46c5-913f-f2d2f965ed0e}' : 'Synthetic network adapter',
+       '{32412632-86cb-44a2-9b5c-50d1417354f5}' : 'Synthetic IDE Controller',
+       '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
+       '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
+       '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
+       '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
+       '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
+       '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
+}
+
+def get_vmbus_dev_attr(dev_name, attr):
+       try:
+               f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
+               lines = f.readlines()
+               f.close()
+       except IOError:
+               lines = []
+
+       return lines
+
+class VMBus_Dev:
+       pass
+
+
+vmbus_dev_list = []
+
+for f in os.listdir(vmbus_sys_path):
+       vmbus_id = get_vmbus_dev_attr(f, 'id')[0].strip()
+       class_id = get_vmbus_dev_attr(f, 'class_id')[0].strip()
+       device_id = get_vmbus_dev_attr(f, 'device_id')[0].strip()
+       dev_desc = vmbus_dev_dict.get(class_id, 'Unknown')
+
+       chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
+       chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
+       chn_vp_mapping = sorted(chn_vp_mapping,
+               key = lambda c : int(c.split(':')[0]))
+
+       chn_vp_mapping = ['\tRel_ID=%s, target_cpu=%s' %
+                               (c.split(':')[0], c.split(':')[1])
+                                       for c in chn_vp_mapping]
+       d = VMBus_Dev()
+       d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
+       d.vmbus_id = vmbus_id
+       d.class_id = class_id
+       d.device_id = device_id
+       d.dev_desc = dev_desc
+       d.chn_vp_mapping = '\n'.join(chn_vp_mapping)
+       if d.chn_vp_mapping:
+               d.chn_vp_mapping += '\n'
+
+       vmbus_dev_list.append(d)
+
+
+vmbus_dev_list  = sorted(vmbus_dev_list, key = lambda d : int(d.vmbus_id))
+
+format0 = '%2s: %s'
+format1 = '%2s: Class_ID = %s - %s\n%s'
+format2 = '%2s: Class_ID = %s - %s\n\tDevice_ID = %s\n\tSysfs path: %s\n%s'
+
+for d in vmbus_dev_list:
+       if verbose == 0:
+               print ('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc)
+       elif verbose == 1:
+               print ('VMBUS ID ' + format1) % \
+                       (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
+       else:
+               print ('VMBUS ID ' + format2) % \
+                       (d.vmbus_id, d.class_id, d.dev_desc, \
+                       d.device_id, d.sysfs_path, d.chn_vp_mapping)
index 4eebb6616e5ca33aca62a036db63c4a38a5fad61..9f7b85bf6ada3e3cdf43508ab9b3589daf14325a 100644 (file)
@@ -51,14 +51,33 @@ int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
                if (bytes % channels[i].bytes == 0)
                        channels[i].location = bytes;
                else
-                       channels[i].location = bytes - bytes%channels[i].bytes
-                               + channels[i].bytes;
+                       channels[i].location = bytes - bytes % channels[i].bytes
+                                              + channels[i].bytes;
+
                bytes = channels[i].location + channels[i].bytes;
                i++;
        }
+
        return bytes;
 }
 
+void print1byte(uint8_t input, struct iio_channel_info *info)
+{
+       /*
+        * Shift before conversion to avoid sign extension
+        * of left aligned data
+        */
+       input >>= info->shift;
+       input &= info->mask;
+       if (info->is_signed) {
+               int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
+                            (8 - info->bits_used);
+               printf("%05f ", ((float)val + info->offset) * info->scale);
+       } else {
+               printf("%05f ", ((float)input + info->offset) * info->scale);
+       }
+}
+
 void print2byte(uint16_t input, struct iio_channel_info *info)
 {
        /* First swap if incorrect endian */
@@ -136,9 +155,9 @@ void print8byte(uint64_t input, struct iio_channel_info *info)
 /**
  * process_scan() - print out the values in SI units
  * @data:              pointer to the start of the scan
- * @channels:          information about the channels. Note
- *  size_from_channelarray must have been called first to fill the
- *  location offsets.
+ * @channels:          information about the channels.
+ *                     Note: size_from_channelarray must have been called first
+ *                           to fill the location offsets.
  * @num_channels:      number of channels
  **/
 void process_scan(char *data,
@@ -150,6 +169,10 @@ void process_scan(char *data,
        for (k = 0; k < num_channels; k++)
                switch (channels[k].bytes) {
                        /* only a few cases implemented so far */
+               case 1:
+                       print1byte(*(uint8_t *)(data + channels[k].location),
+                                  &channels[k]);
+                       break;
                case 2:
                        print2byte(*(uint16_t *)(data + channels[k].location),
                                   &channels[k]);
@@ -170,15 +193,15 @@ void process_scan(char *data,
 
 void print_usage(void)
 {
-       printf("Usage: generic_buffer [options]...\n"
-              "Capture, convert and output data from IIO device buffer\n"
-              "  -c <n>     Do n conversions\n"
-              "  -e         Disable wait for event (new data)\n"
-              "  -g         Use trigger-less mode\n"
-              "  -l <n>     Set buffer length to n samples\n"
-              "  -n <name>  Set device name (mandatory)\n"
-              "  -t <name>  Set trigger name\n"
-              "  -w <n>     Set delay between reads in us (event-less mode)\n");
+       fprintf(stderr, "Usage: generic_buffer [options]...\n"
+               "Capture, convert and output data from IIO device buffer\n"
+               "  -c <n>     Do n conversions\n"
+               "  -e         Disable wait for event (new data)\n"
+               "  -g         Use trigger-less mode\n"
+               "  -l <n>     Set buffer length to n samples\n"
+               "  -n <name>  Set device name (mandatory)\n"
+               "  -t <name>  Set trigger name\n"
+               "  -w <n>     Set delay between reads in us (event-less mode)\n");
 }
 
 int main(int argc, char **argv)
@@ -213,6 +236,7 @@ int main(int argc, char **argv)
                        num_loops = strtoul(optarg, &dummy, 10);
                        if (errno)
                                return -errno;
+
                        break;
                case 'e':
                        noevents = 1;
@@ -225,6 +249,7 @@ int main(int argc, char **argv)
                        buf_len = strtoul(optarg, &dummy, 10);
                        if (errno)
                                return -errno;
+
                        break;
                case 'n':
                        device_name = optarg;
@@ -245,8 +270,8 @@ int main(int argc, char **argv)
                }
        }
 
-       if (device_name == NULL) {
-               printf("Device name not set\n");
+       if (!device_name) {
+               fprintf(stderr, "Device name not set\n");
                print_usage();
                return -1;
        }
@@ -254,9 +279,10 @@ int main(int argc, char **argv)
        /* Find the device requested */
        dev_num = find_type_by_name(device_name, "iio:device");
        if (dev_num < 0) {
-               printf("Failed to find the %s\n", device_name);
+               fprintf(stderr, "Failed to find the %s\n", device_name);
                return dev_num;
        }
+
        printf("iio device number being used is %d\n", dev_num);
 
        ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
@@ -264,7 +290,7 @@ int main(int argc, char **argv)
                return -ENOMEM;
 
        if (!notrigger) {
-               if (trigger_name == NULL) {
+               if (!trigger_name) {
                        /*
                         * Build the trigger name. If it is device associated
                         * its name is <device_name>_dev[n] where n matches
@@ -281,13 +307,16 @@ int main(int argc, char **argv)
                /* Verify the trigger exists */
                trig_num = find_type_by_name(trigger_name, "trigger");
                if (trig_num < 0) {
-                       printf("Failed to find the trigger %s\n", trigger_name);
+                       fprintf(stderr, "Failed to find the trigger %s\n",
+                               trigger_name);
                        ret = trig_num;
                        goto error_free_triggername;
                }
+
                printf("iio trigger number being used is %d\n", trig_num);
-       } else
+       } else {
                printf("trigger-less mode selected\n");
+       }
 
        /*
         * Parse the files in scan_elements to identify what channels are
@@ -295,8 +324,8 @@ int main(int argc, char **argv)
         */
        ret = build_channel_array(dev_dir_name, &channels, &num_channels);
        if (ret) {
-               printf("Problem reading scan element information\n");
-               printf("diag %s\n", dev_dir_name);
+               fprintf(stderr, "Problem reading scan element information\n"
+                       "diag %s\n", dev_dir_name);
                goto error_free_triggername;
        }
 
@@ -314,13 +343,16 @@ int main(int argc, char **argv)
 
        if (!notrigger) {
                printf("%s %s\n", dev_dir_name, trigger_name);
-               /* Set the device trigger to be the data ready trigger found
-                * above */
+               /*
+                * Set the device trigger to be the data ready trigger found
+                * above
+                */
                ret = write_sysfs_string_and_verify("trigger/current_trigger",
                                                    dev_dir_name,
                                                    trigger_name);
                if (ret < 0) {
-                       printf("Failed to write current_trigger file\n");
+                       fprintf(stderr,
+                               "Failed to write current_trigger file\n");
                        goto error_free_buf_dir_name;
                }
        }
@@ -332,10 +364,14 @@ int main(int argc, char **argv)
 
        /* Enable the buffer */
        ret = write_sysfs_int("enable", buf_dir_name, 1);
-       if (ret < 0)
+       if (ret < 0) {
+               fprintf(stderr,
+                       "Failed to enable buffer: %s\n", strerror(-ret));
                goto error_free_buf_dir_name;
+       }
+
        scan_size = size_from_channelarray(channels, num_channels);
-       data = malloc(scan_size*buf_len);
+       data = malloc(scan_size * buf_len);
        if (!data) {
                ret = -ENOMEM;
                goto error_free_buf_dir_name;
@@ -349,13 +385,12 @@ int main(int argc, char **argv)
 
        /* Attempt to open non blocking the access dev */
        fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
-       if (fp == -1) { /* If it isn't there make the node */
+       if (fp == -1) { /* TODO: If it isn't there make the node */
                ret = -errno;
-               printf("Failed to open %s\n", buffer_access);
+               fprintf(stderr, "Failed to open %s\n", buffer_access);
                goto error_free_buffer_access;
        }
 
-       /* Wait for events 10 times */
        for (j = 0; j < num_loops; j++) {
                if (!noevents) {
                        struct pollfd pfd = {
@@ -372,25 +407,22 @@ int main(int argc, char **argv)
                        }
 
                        toread = buf_len;
-
                } else {
                        usleep(timedelay);
                        toread = 64;
                }
 
-               read_size = read(fp,
-                                data,
-                                toread*scan_size);
+               read_size = read(fp, data, toread * scan_size);
                if (read_size < 0) {
                        if (errno == EAGAIN) {
-                               printf("nothing available\n");
+                               fprintf(stderr, "nothing available\n");
                                continue;
-                       } else
+                       } else {
                                break;
+                       }
                }
-               for (i = 0; i < read_size/scan_size; i++)
-                       process_scan(data + scan_size*i,
-                                    channels,
+               for (i = 0; i < read_size / scan_size; i++)
+                       process_scan(data + scan_size * i, channels,
                                     num_channels);
        }
 
@@ -404,11 +436,13 @@ int main(int argc, char **argv)
                ret = write_sysfs_string("trigger/current_trigger",
                                         dev_dir_name, "NULL");
                if (ret < 0)
-                       printf("Failed to write to %s\n", dev_dir_name);
+                       fprintf(stderr, "Failed to write to %s\n",
+                               dev_dir_name);
 
 error_close_buffer_access:
        if (close(fp) == -1)
                perror("Failed to close buffer");
+
 error_free_buffer_access:
        free(buffer_access);
 error_free_data:
@@ -424,6 +458,7 @@ error_free_channels:
 error_free_triggername:
        if (datardytrigger)
                free(trigger_name);
+
 error_free_dev_dir_name:
        free(dev_dir_name);
 
index 016760e769c0baf0f8eefee80f8a9f94ad42b586..cd3fd41b481dc111406e89c4ad65dd59c4dd334c 100644 (file)
@@ -13,7 +13,6 @@
  *
  * Usage:
  *     iio_event_monitor <device_name>
- *
  */
 
 #include <unistd.h>
@@ -51,6 +50,9 @@ static const char * const iio_chan_type_name_spec[] = {
        [IIO_HUMIDITYRELATIVE] = "humidityrelative",
        [IIO_ACTIVITY] = "activity",
        [IIO_STEPS] = "steps",
+       [IIO_ENERGY] = "energy",
+       [IIO_DISTANCE] = "distance",
+       [IIO_VELOCITY] = "velocity",
 };
 
 static const char * const iio_ev_type_text[] = {
@@ -99,6 +101,7 @@ static const char * const iio_modifier_names[] = {
        [IIO_MOD_JOGGING] = "jogging",
        [IIO_MOD_WALKING] = "walking",
        [IIO_MOD_STILL] = "still",
+       [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
 };
 
 static bool event_is_known(struct iio_event_data *event)
@@ -130,6 +133,9 @@ static bool event_is_known(struct iio_event_data *event)
        case IIO_HUMIDITYRELATIVE:
        case IIO_ACTIVITY:
        case IIO_STEPS:
+       case IIO_ENERGY:
+       case IIO_DISTANCE:
+       case IIO_VELOCITY:
                break;
        default:
                return false;
@@ -167,6 +173,7 @@ static bool event_is_known(struct iio_event_data *event)
        case IIO_MOD_JOGGING:
        case IIO_MOD_WALKING:
        case IIO_MOD_STILL:
+       case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
                break;
        default:
                return false;
@@ -208,8 +215,9 @@ static void print_event(struct iio_event_data *event)
        bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
 
        if (!event_is_known(event)) {
-               printf("Unknown event: time: %lld, id: %llx\n",
-                               event->timestamp, event->id);
+               fprintf(stderr, "Unknown event: time: %lld, id: %llx\n",
+                       event->timestamp, event->id);
+
                return;
        }
 
@@ -229,6 +237,7 @@ static void print_event(struct iio_event_data *event)
 
        if (dir != IIO_EV_DIR_NONE)
                printf(", direction: %s", iio_ev_dir_text[dir]);
+
        printf("\n");
 }
 
@@ -242,7 +251,7 @@ int main(int argc, char **argv)
        int fd, event_fd;
 
        if (argc <= 1) {
-               printf("Usage: %s <device_name>\n", argv[0]);
+               fprintf(stderr, "Usage: %s <device_name>\n", argv[0]);
                return -1;
        }
 
@@ -251,14 +260,15 @@ int main(int argc, char **argv)
        dev_num = find_type_by_name(device_name, "iio:device");
        if (dev_num >= 0) {
                printf("Found IIO device with name %s with device number %d\n",
-                       device_name, dev_num);
+                      device_name, dev_num);
                ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
-               if (ret < 0) {
+               if (ret < 0)
                        return -ENOMEM;
-               }
        } else {
-               /* If we can't find a IIO device by name assume device_name is a
-                  IIO chrdev */
+               /*
+                * If we can't find an IIO device by name assume device_name is
+                * an IIO chrdev
+                */
                chrdev_name = strdup(device_name);
                if (!chrdev_name)
                        return -ENOMEM;
@@ -267,14 +277,14 @@ int main(int argc, char **argv)
        fd = open(chrdev_name, 0);
        if (fd == -1) {
                ret = -errno;
-               fprintf(stdout, "Failed to open %s\n", chrdev_name);
+               fprintf(stderr, "Failed to open %s\n", chrdev_name);
                goto error_free_chrdev_name;
        }
 
        ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
        if (ret == -1 || event_fd == -1) {
                ret = -errno;
-               fprintf(stdout, "Failed to retrieve event fd\n");
+               fprintf(stderr, "Failed to retrieve event fd\n");
                if (close(fd) == -1)
                        perror("Failed to close character device file");
 
@@ -290,7 +300,7 @@ int main(int argc, char **argv)
                ret = read(event_fd, &event, sizeof(event));
                if (ret == -1) {
                        if (errno == EAGAIN) {
-                               printf("nothing available\n");
+                               fprintf(stderr, "nothing available\n");
                                continue;
                        } else {
                                ret = -errno;
@@ -299,6 +309,12 @@ int main(int argc, char **argv)
                        }
                }
 
+               if (ret != sizeof(event)) {
+                       fprintf(stderr, "Reading event failed!\n");
+                       ret = -EIO;
+                       break;
+               }
+
                print_event(&event);
        }
 
index ec9ab7f9ae4c50e5ac77bedbdff5e6a144eafe78..5eb6793f3972e64ed2c46533cd2e6aa5d65168fa 100644 (file)
@@ -6,9 +6,6 @@
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
-#ifndef _IIO_UTILS_H
-#define _IIO_UTILS_H
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -32,15 +29,14 @@ static char * const iio_direction[] = {
  *
  * Returns 0 on success, or a negative error code if string extraction failed.
  **/
-int iioutils_break_up_name(const char *full_name,
-                                 char **generic_name)
+int iioutils_break_up_name(const char *full_name, char **generic_name)
 {
        char *current;
        char *w, *r;
        char *working, *prefix = "";
        int i, ret;
 
-       for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
+       for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
                if (!strncmp(full_name, iio_direction[i],
                             strlen(iio_direction[i]))) {
                        prefix = iio_direction[i];
@@ -65,6 +61,7 @@ int iioutils_break_up_name(const char *full_name,
                        *w = *r;
                        w++;
                }
+
                r++;
        }
        *w = '\0';
@@ -88,15 +85,10 @@ int iioutils_break_up_name(const char *full_name,
  *
  * Returns a value >= 0 on success, otherwise a negative error code.
  **/
-int iioutils_get_type(unsigned *is_signed,
-                            unsigned *bytes,
-                            unsigned *bits_used,
-                            unsigned *shift,
-                            uint64_t *mask,
-                            unsigned *be,
-                            const char *device_dir,
-                            const char *name,
-                            const char *generic_name)
+int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
+                     unsigned *shift, uint64_t *mask, unsigned *be,
+                     const char *device_dir, const char *name,
+                     const char *generic_name)
 {
        FILE *sysfsfp;
        int ret;
@@ -122,12 +114,13 @@ int iioutils_get_type(unsigned *is_signed,
        }
 
        dp = opendir(scan_el_dir);
-       if (dp == NULL) {
+       if (!dp) {
                ret = -errno;
                goto error_free_builtname_generic;
        }
+
        ret = -ENOENT;
-       while (ent = readdir(dp), ent != NULL)
+       while (ent = readdir(dp), ent)
                /*
                 * Do we allow devices to override a generic name with
                 * a specific one?
@@ -140,10 +133,12 @@ int iioutils_get_type(unsigned *is_signed,
                                ret = -ENOMEM;
                                goto error_closedir;
                        }
+
                        sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
+                       if (!sysfsfp) {
                                ret = -errno;
-                               printf("failed to open %s\n", filename);
+                               fprintf(stderr, "failed to open %s\n",
+                                       filename);
                                goto error_free_filename;
                        }
 
@@ -155,31 +150,36 @@ int iioutils_get_type(unsigned *is_signed,
                                     &padint, shift);
                        if (ret < 0) {
                                ret = -errno;
-                               printf("failed to pass scan type description\n");
+                               fprintf(stderr,
+                                       "failed to pass scan type description\n");
                                goto error_close_sysfsfp;
                        } else if (ret != 5) {
                                ret = -EIO;
-                               printf("scan type description didn't match\n");
+                               fprintf(stderr,
+                                       "scan type description didn't match\n");
                                goto error_close_sysfsfp;
                        }
+
                        *be = (endianchar == 'b');
                        *bytes = padint / 8;
                        if (*bits_used == 64)
                                *mask = ~0;
                        else
-                               *mask = (1 << *bits_used) - 1;
+                               *mask = (1ULL << *bits_used) - 1;
+
                        *is_signed = (signchar == 's');
                        if (fclose(sysfsfp)) {
                                ret = -errno;
-                               printf("Failed to close %s\n", filename);
+                               fprintf(stderr, "Failed to close %s\n",
+                                       filename);
                                goto error_free_filename;
                        }
 
                        sysfsfp = 0;
                        free(filename);
-
                        filename = 0;
                }
+
 error_close_sysfsfp:
        if (sysfsfp)
                if (fclose(sysfsfp))
@@ -188,6 +188,7 @@ error_close_sysfsfp:
 error_free_filename:
        if (filename)
                free(filename);
+
 error_closedir:
        if (closedir(dp) == -1)
                perror("iioutils_get_type(): Failed to close directory");
@@ -212,11 +213,9 @@ error_free_scan_el_dir:
  *
  * Returns a value >= 0 on success, otherwise a negative error code.
  **/
-int iioutils_get_param_float(float *output,
-                                   const char *param_name,
-                                   const char *device_dir,
-                                   const char *name,
-                                   const char *generic_name)
+int iioutils_get_param_float(float *output, const char *param_name,
+                            const char *device_dir, const char *name,
+                            const char *generic_name)
 {
        FILE *sysfsfp;
        int ret;
@@ -235,13 +234,15 @@ int iioutils_get_param_float(float *output,
                ret = -ENOMEM;
                goto error_free_builtname;
        }
+
        dp = opendir(device_dir);
-       if (dp == NULL) {
+       if (!dp) {
                ret = -errno;
                goto error_free_builtname_generic;
        }
+
        ret = -ENOENT;
-       while (ent = readdir(dp), ent != NULL)
+       while (ent = readdir(dp), ent)
                if ((strcmp(builtname, ent->d_name) == 0) ||
                    (strcmp(builtname_generic, ent->d_name) == 0)) {
                        ret = asprintf(&filename,
@@ -250,11 +251,13 @@ int iioutils_get_param_float(float *output,
                                ret = -ENOMEM;
                                goto error_closedir;
                        }
+
                        sysfsfp = fopen(filename, "r");
                        if (!sysfsfp) {
                                ret = -errno;
                                goto error_free_filename;
                        }
+
                        errno = 0;
                        if (fscanf(sysfsfp, "%f", output) != 1)
                                ret = errno ? -errno : -ENODATA;
@@ -264,6 +267,7 @@ int iioutils_get_param_float(float *output,
 error_free_filename:
        if (filename)
                free(filename);
+
 error_closedir:
        if (closedir(dp) == -1)
                perror("iioutils_get_param_float(): Failed to close directory");
@@ -282,19 +286,17 @@ error_free_builtname:
  * @cnt: the amount of array elements
  **/
 
-void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
-                                        int cnt)
+void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt)
 {
-
        struct iio_channel_info temp;
        int x, y;
 
        for (x = 0; x < cnt; x++)
                for (y = 0; y < (cnt - 1); y++)
-                       if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
-                               temp = (*ci_array)[y + 1];
-                               (*ci_array)[y + 1] = (*ci_array)[y];
-                               (*ci_array)[y] = temp;
+                       if (ci_array[y].index > ci_array[y + 1].index) {
+                               temp = ci_array[y + 1];
+                               ci_array[y + 1] = ci_array[y];
+                               ci_array[y] = temp;
                        }
 }
 
@@ -307,8 +309,7 @@ void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
  * Returns 0 on success, otherwise a negative error code.
  **/
 int build_channel_array(const char *device_dir,
-                             struct iio_channel_info **ci_array,
-                             int *counter)
+                       struct iio_channel_info **ci_array, int *counter)
 {
        DIR *dp;
        FILE *sysfsfp;
@@ -325,11 +326,12 @@ int build_channel_array(const char *device_dir,
                return -ENOMEM;
 
        dp = opendir(scan_el_dir);
-       if (dp == NULL) {
+       if (!dp) {
                ret = -errno;
                goto error_free_name;
        }
-       while (ent = readdir(dp), ent != NULL)
+
+       while (ent = readdir(dp), ent)
                if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
                           "_en") == 0) {
                        ret = asprintf(&filename,
@@ -338,12 +340,14 @@ int build_channel_array(const char *device_dir,
                                ret = -ENOMEM;
                                goto error_close_dir;
                        }
+
                        sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
+                       if (!sysfsfp) {
                                ret = -errno;
                                free(filename);
                                goto error_close_dir;
                        }
+
                        errno = 0;
                        if (fscanf(sysfsfp, "%i", &ret) != 1) {
                                ret = errno ? -errno : -ENODATA;
@@ -353,9 +357,9 @@ int build_channel_array(const char *device_dir,
                                free(filename);
                                goto error_close_dir;
                        }
-
                        if (ret == 1)
                                (*counter)++;
+
                        if (fclose(sysfsfp)) {
                                ret = -errno;
                                free(filename);
@@ -364,13 +368,15 @@ int build_channel_array(const char *device_dir,
 
                        free(filename);
                }
+
        *ci_array = malloc(sizeof(**ci_array) * (*counter));
-       if (*ci_array == NULL) {
+       if (!*ci_array) {
                ret = -ENOMEM;
                goto error_close_dir;
        }
+
        seekdir(dp, 0);
-       while (ent = readdir(dp), ent != NULL) {
+       while (ent = readdir(dp), ent) {
                if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
                           "_en") == 0) {
                        int current_enabled = 0;
@@ -384,13 +390,15 @@ int build_channel_array(const char *device_dir,
                                count--;
                                goto error_cleanup_array;
                        }
+
                        sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
+                       if (!sysfsfp) {
                                ret = -errno;
                                free(filename);
                                count--;
                                goto error_cleanup_array;
                        }
+
                        errno = 0;
                        if (fscanf(sysfsfp, "%i", &current_enabled) != 1) {
                                ret = errno ? -errno : -ENODATA;
@@ -417,12 +425,13 @@ int build_channel_array(const char *device_dir,
                        current->name = strndup(ent->d_name,
                                                strlen(ent->d_name) -
                                                strlen("_en"));
-                       if (current->name == NULL) {
+                       if (!current->name) {
                                free(filename);
                                ret = -ENOMEM;
                                count--;
                                goto error_cleanup_array;
                        }
+
                        /* Get the generic and specific name elements */
                        ret = iioutils_break_up_name(current->name,
                                                     &current->generic_name);
@@ -432,6 +441,7 @@ int build_channel_array(const char *device_dir,
                                count--;
                                goto error_cleanup_array;
                        }
+
                        ret = asprintf(&filename,
                                       "%s/%s_index",
                                       scan_el_dir,
@@ -441,10 +451,12 @@ int build_channel_array(const char *device_dir,
                                ret = -ENOMEM;
                                goto error_cleanup_array;
                        }
+
                        sysfsfp = fopen(filename, "r");
-                       if (sysfsfp == NULL) {
+                       if (!sysfsfp) {
                                ret = -errno;
-                               printf("failed to open %s\n", filename);
+                               fprintf(stderr, "failed to open %s\n",
+                                       filename);
                                free(filename);
                                goto error_cleanup_array;
                        }
@@ -472,15 +484,17 @@ int build_channel_array(const char *device_dir,
                                                       device_dir,
                                                       current->name,
                                                       current->generic_name);
-                       if (ret < 0)
+                       if ((ret < 0) && (ret != -ENOENT))
                                goto error_cleanup_array;
+
                        ret = iioutils_get_param_float(&current->offset,
                                                       "offset",
                                                       device_dir,
                                                       current->name,
                                                       current->generic_name);
-                       if (ret < 0)
+                       if ((ret < 0) && (ret != -ENOENT))
                                goto error_cleanup_array;
+
                        ret = iioutils_get_type(&current->is_signed,
                                                &current->bytes,
                                                &current->bits_used,
@@ -502,7 +516,7 @@ int build_channel_array(const char *device_dir,
 
        free(scan_el_dir);
        /* reorder so that the array is in index order */
-       bsort_channel_array_by_index(ci_array, *counter);
+       bsort_channel_array_by_index(*ci_array, *counter);
 
        return 0;
 
@@ -512,6 +526,8 @@ error_cleanup_array:
                free((*ci_array)[i].generic_name);
        }
        free(*ci_array);
+       *ci_array = NULL;
+       *counter = 0;
 error_close_dir:
        if (dp)
                if (closedir(dp) == -1)
@@ -523,7 +539,7 @@ error_free_name:
        return ret;
 }
 
-int calc_digits(int num)
+static int calc_digits(int num)
 {
        int count = 0;
 
@@ -549,44 +565,43 @@ int find_type_by_name(const char *name, const char *type)
        const struct dirent *ent;
        int number, numstrlen, ret;
 
-       FILE *nameFile;
+       FILE *namefp;
        DIR *dp;
        char thisname[IIO_MAX_NAME_LENGTH];
        char *filename;
 
        dp = opendir(iio_dir);
-       if (dp == NULL) {
-               printf("No industrialio devices available\n");
+       if (!dp) {
+               fprintf(stderr, "No industrialio devices available\n");
                return -ENODEV;
        }
 
-       while (ent = readdir(dp), ent != NULL) {
+       while (ent = readdir(dp), ent) {
                if (strcmp(ent->d_name, ".") != 0 &&
-                       strcmp(ent->d_name, "..") != 0 &&
-                       strlen(ent->d_name) > strlen(type) &&
-                       strncmp(ent->d_name, type, strlen(type)) == 0) {
+                   strcmp(ent->d_name, "..") != 0 &&
+                   strlen(ent->d_name) > strlen(type) &&
+                   strncmp(ent->d_name, type, strlen(type)) == 0) {
                        errno = 0;
                        ret = sscanf(ent->d_name + strlen(type), "%d", &number);
                        if (ret < 0) {
                                ret = -errno;
-                               printf("failed to read element number\n");
+                               fprintf(stderr,
+                                       "failed to read element number\n");
                                goto error_close_dir;
                        } else if (ret != 1) {
                                ret = -EIO;
-                               printf("failed to match element number\n");
+                               fprintf(stderr,
+                                       "failed to match element number\n");
                                goto error_close_dir;
                        }
 
                        numstrlen = calc_digits(number);
                        /* verify the next character is not a colon */
                        if (strncmp(ent->d_name + strlen(type) + numstrlen,
-                                       ":",
-                                       1) != 0) {
-                               filename = malloc(strlen(iio_dir)
-                                               + strlen(type)
-                                               + numstrlen
-                                               + 6);
-                               if (filename == NULL) {
+                           ":", 1) != 0) {
+                               filename = malloc(strlen(iio_dir) + strlen(type)
+                                                 + numstrlen + 6);
+                               if (!filename) {
                                        ret = -ENOMEM;
                                        goto error_close_dir;
                                }
@@ -598,19 +613,20 @@ int find_type_by_name(const char *name, const char *type)
                                        goto error_close_dir;
                                }
 
-                               nameFile = fopen(filename, "r");
-                               if (!nameFile) {
+                               namefp = fopen(filename, "r");
+                               if (!namefp) {
                                        free(filename);
                                        continue;
                                }
+
                                free(filename);
                                errno = 0;
-                               if (fscanf(nameFile, "%s", thisname) != 1) {
+                               if (fscanf(namefp, "%s", thisname) != 1) {
                                        ret = errno ? -errno : -ENODATA;
                                        goto error_close_dir;
                                }
 
-                               if (fclose(nameFile)) {
+                               if (fclose(namefp)) {
                                        ret = -errno;
                                        goto error_close_dir;
                                }
@@ -618,6 +634,7 @@ int find_type_by_name(const char *name, const char *type)
                                if (strcmp(name, thisname) == 0) {
                                        if (closedir(dp) == -1)
                                                return -errno;
+
                                        return number;
                                }
                        }
@@ -631,6 +648,7 @@ int find_type_by_name(const char *name, const char *type)
 error_close_dir:
        if (closedir(dp) == -1)
                perror("find_type_by_name(): Failed to close directory");
+
        return ret;
 }
 
@@ -642,18 +660,20 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
        int test;
        char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
-       if (temp == NULL)
+       if (!temp)
                return -ENOMEM;
+
        ret = sprintf(temp, "%s/%s", basedir, filename);
        if (ret < 0)
                goto error_free;
 
        sysfsfp = fopen(temp, "w");
-       if (sysfsfp == NULL) {
+       if (!sysfsfp) {
                ret = -errno;
-               printf("failed to open %s\n", temp);
+               fprintf(stderr, "failed to open %s\n", temp);
                goto error_free;
        }
+
        ret = fprintf(sysfsfp, "%d", val);
        if (ret < 0) {
                if (fclose(sysfsfp))
@@ -669,11 +689,12 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
 
        if (verify) {
                sysfsfp = fopen(temp, "r");
-               if (sysfsfp == NULL) {
+               if (!sysfsfp) {
                        ret = -errno;
-                       printf("failed to open %s\n", temp);
+                       fprintf(stderr, "failed to open %s\n", temp);
                        goto error_free;
                }
+
                if (fscanf(sysfsfp, "%d", &test) != 1) {
                        ret = errno ? -errno : -ENODATA;
                        if (fclose(sysfsfp))
@@ -688,13 +709,13 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
                }
 
                if (test != val) {
-                       printf("Possible failure in int write %d to %s%s\n",
-                               val,
-                               basedir,
-                               filename);
+                       fprintf(stderr,
+                               "Possible failure in int write %d to %s/%s\n",
+                               val, basedir, filename);
                        ret = -1;
                }
        }
+
 error_free:
        free(temp);
        return ret;
@@ -735,20 +756,22 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
        FILE  *sysfsfp;
        char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
-       if (temp == NULL) {
-               printf("Memory allocation failed\n");
+       if (!temp) {
+               fprintf(stderr, "Memory allocation failed\n");
                return -ENOMEM;
        }
+
        ret = sprintf(temp, "%s/%s", basedir, filename);
        if (ret < 0)
                goto error_free;
 
        sysfsfp = fopen(temp, "w");
-       if (sysfsfp == NULL) {
+       if (!sysfsfp) {
                ret = -errno;
-               printf("Could not open %s\n", temp);
+               fprintf(stderr, "Could not open %s\n", temp);
                goto error_free;
        }
+
        ret = fprintf(sysfsfp, "%s", val);
        if (ret < 0) {
                if (fclose(sysfsfp))
@@ -764,11 +787,12 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
 
        if (verify) {
                sysfsfp = fopen(temp, "r");
-               if (sysfsfp == NULL) {
+               if (!sysfsfp) {
                        ret = -errno;
-                       printf("could not open file to verify\n");
+                       fprintf(stderr, "Could not open file to verify\n");
                        goto error_free;
                }
+
                if (fscanf(sysfsfp, "%s", temp) != 1) {
                        ret = errno ? -errno : -ENODATA;
                        if (fclose(sysfsfp))
@@ -783,16 +807,14 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
                }
 
                if (strcmp(temp, val) != 0) {
-                       printf("Possible failure in string write of %s "
-                               "Should be %s "
-                               "written to %s\%s\n",
-                               temp,
-                               val,
-                               basedir,
-                               filename);
+                       fprintf(stderr,
+                               "Possible failure in string write of %s "
+                               "Should be %s written to %s/%s\n", temp, val,
+                               basedir, filename);
                        ret = -1;
                }
        }
+
 error_free:
        free(temp);
 
@@ -841,19 +863,21 @@ int read_sysfs_posint(const char *filename, const char *basedir)
        FILE  *sysfsfp;
        char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
-       if (temp == NULL) {
-               printf("Memory allocation failed");
+       if (!temp) {
+               fprintf(stderr, "Memory allocation failed");
                return -ENOMEM;
        }
+
        ret = sprintf(temp, "%s/%s", basedir, filename);
        if (ret < 0)
                goto error_free;
 
        sysfsfp = fopen(temp, "r");
-       if (sysfsfp == NULL) {
+       if (!sysfsfp) {
                ret = -errno;
                goto error_free;
        }
+
        errno = 0;
        if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
                ret = errno ? -errno : -ENODATA;
@@ -868,6 +892,7 @@ int read_sysfs_posint(const char *filename, const char *basedir)
 
 error_free:
        free(temp);
+
        return ret;
 }
 
@@ -885,19 +910,21 @@ int read_sysfs_float(const char *filename, const char *basedir, float *val)
        FILE  *sysfsfp;
        char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
-       if (temp == NULL) {
-               printf("Memory allocation failed");
+       if (!temp) {
+               fprintf(stderr, "Memory allocation failed");
                return -ENOMEM;
        }
+
        ret = sprintf(temp, "%s/%s", basedir, filename);
        if (ret < 0)
                goto error_free;
 
        sysfsfp = fopen(temp, "r");
-       if (sysfsfp == NULL) {
+       if (!sysfsfp) {
                ret = -errno;
                goto error_free;
        }
+
        errno = 0;
        if (fscanf(sysfsfp, "%f\n", val) != 1) {
                ret = errno ? -errno : -ENODATA;
@@ -912,6 +939,7 @@ int read_sysfs_float(const char *filename, const char *basedir, float *val)
 
 error_free:
        free(temp);
+
        return ret;
 }
 
@@ -929,19 +957,21 @@ int read_sysfs_string(const char *filename, const char *basedir, char *str)
        FILE  *sysfsfp;
        char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
-       if (temp == NULL) {
-               printf("Memory allocation failed");
+       if (!temp) {
+               fprintf(stderr, "Memory allocation failed");
                return -ENOMEM;
        }
+
        ret = sprintf(temp, "%s/%s", basedir, filename);
        if (ret < 0)
                goto error_free;
 
        sysfsfp = fopen(temp, "r");
-       if (sysfsfp == NULL) {
+       if (!sysfsfp) {
                ret = -errno;
                goto error_free;
        }
+
        errno = 0;
        if (fscanf(sysfsfp, "%s\n", str) != 1) {
                ret = errno ? -errno : -ENODATA;
@@ -956,7 +986,6 @@ int read_sysfs_string(const char *filename, const char *basedir, char *str)
 
 error_free:
        free(temp);
+
        return ret;
 }
-
-#endif /* _IIO_UTILS_H */
index 379eed9deaea242025fc53e081bc350b3d931097..e3503bfe538b951102449e24e2e90e1a00fe407b 100644 (file)
@@ -18,6 +18,8 @@
 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
 #define FORMAT_TYPE_FILE "%s_type"
 
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
 extern const char *iio_dir;
 
 /**
@@ -51,17 +53,16 @@ struct iio_channel_info {
 };
 
 int iioutils_break_up_name(const char *full_name, char **generic_name);
-int iioutils_get_type(unsigned *is_signed, unsigned *bytes,
-                                         unsigned *bits_used, unsigned *shift,
-                                         uint64_t *mask, unsigned *be,
-                                         const char *device_dir, const char *name,
-                                         const char *generic_name);
+int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
+                     unsigned *shift, uint64_t *mask, unsigned *be,
+                     const char *device_dir, const char *name,
+                     const char *generic_name);
 int iioutils_get_param_float(float *output, const char *param_name,
-                                                        const char *device_dir, const char *name,
-                                                        const char *generic_name);
-void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
+                            const char *device_dir, const char *name,
+                            const char *generic_name);
+void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt);
 int build_channel_array(const char *device_dir,
-                                               struct iio_channel_info **ci_array, int *counter);
+                       struct iio_channel_info **ci_array, int *counter);
 int find_type_by_name(const char *name, const char *type);
 int write_sysfs_int(const char *filename, const char *basedir, int val);
 int write_sysfs_int_and_verify(const char *filename, const char *basedir,
index b59ee1733924025c240fd7e6dbcef4f29ce2802a..3d650e668252f8f195a8e6a14380117d60b329cc 100644 (file)
@@ -20,7 +20,6 @@
 #include <sys/dir.h>
 #include "iio_utils.h"
 
-
 static enum verbosity {
        VERBLEVEL_DEFAULT,      /* 0 gives lspci behaviour */
        VERBLEVEL_SENSORS,      /* 1 lists sensors */
@@ -29,17 +28,16 @@ static enum verbosity {
 const char *type_device = "iio:device";
 const char *type_trigger = "trigger";
 
-
 static inline int check_prefix(const char *str, const char *prefix)
 {
        return strlen(str) > strlen(prefix) &&
-               strncmp(str, prefix, strlen(prefix)) == 0;
+              strncmp(str, prefix, strlen(prefix)) == 0;
 }
 
 static inline int check_postfix(const char *str, const char *postfix)
 {
        return strlen(str) > strlen(postfix) &&
-               strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+              strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
 }
 
 static int dump_channels(const char *dev_dir_name)
@@ -48,13 +46,13 @@ static int dump_channels(const char *dev_dir_name)
        const struct dirent *ent;
 
        dp = opendir(dev_dir_name);
-       if (dp == NULL)
+       if (!dp)
                return -errno;
-       while (ent = readdir(dp), ent != NULL)
+
+       while (ent = readdir(dp), ent)
                if (check_prefix(ent->d_name, "in_") &&
-                   check_postfix(ent->d_name, "_raw")) {
+                   check_postfix(ent->d_name, "_raw"))
                        printf("   %-10s\n", ent->d_name);
-               }
 
        return (closedir(dp) == -1) ? -errno : 0;
 }
@@ -63,20 +61,22 @@ static int dump_one_device(const char *dev_dir_name)
 {
        char name[IIO_MAX_NAME_LENGTH];
        int dev_idx;
-       int retval;
+       int ret;
 
-       retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
-                       "%i", &dev_idx);
-       if (retval != 1)
+       ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device), "%i",
+                    &dev_idx);
+       if (ret != 1)
                return -EINVAL;
-       retval = read_sysfs_string("name", dev_dir_name, name);
-       if (retval)
-               return retval;
+
+       ret = read_sysfs_string("name", dev_dir_name, name);
+       if (ret < 0)
+               return ret;
 
        printf("Device %03d: %s\n", dev_idx, name);
 
        if (verblevel >= VERBLEVEL_SENSORS)
                return dump_channels(dev_dir_name);
+
        return 0;
 }
 
@@ -84,17 +84,19 @@ static int dump_one_trigger(const char *dev_dir_name)
 {
        char name[IIO_MAX_NAME_LENGTH];
        int dev_idx;
-       int retval;
+       int ret;
 
-       retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
-                       "%i", &dev_idx);
-       if (retval != 1)
+       ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
+                    "%i", &dev_idx);
+       if (ret != 1)
                return -EINVAL;
-       retval = read_sysfs_string("name", dev_dir_name, name);
-       if (retval)
-               return retval;
+
+       ret = read_sysfs_string("name", dev_dir_name, name);
+       if (ret < 0)
+               return ret;
 
        printf("Trigger %03d: %s\n", dev_idx, name);
+
        return 0;
 }
 
@@ -105,12 +107,12 @@ static int dump_devices(void)
        DIR *dp;
 
        dp = opendir(iio_dir);
-       if (dp == NULL) {
-               printf("No industrial I/O devices available\n");
+       if (!dp) {
+               fprintf(stderr, "No industrial I/O devices available\n");
                return -ENODEV;
        }
 
-       while (ent = readdir(dp), ent != NULL) {
+       while (ent = readdir(dp), ent) {
                if (check_prefix(ent->d_name, type_device)) {
                        char *dev_dir_name;
 
@@ -132,7 +134,7 @@ static int dump_devices(void)
                }
        }
        rewinddir(dp);
-       while (ent = readdir(dp), ent != NULL) {
+       while (ent = readdir(dp), ent) {
                if (check_prefix(ent->d_name, type_trigger)) {
                        char *dev_dir_name;
 
@@ -151,6 +153,7 @@ static int dump_devices(void)
                        free(dev_dir_name);
                }
        }
+
        return (closedir(dp) == -1) ? -errno : 0;
 
 error_close_dir:
diff --git a/tools/perf/arch/xtensa/Build b/tools/perf/arch/xtensa/Build
new file mode 100644 (file)
index 0000000..54afe4a
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += util/
diff --git a/tools/perf/arch/xtensa/Makefile b/tools/perf/arch/xtensa/Makefile
new file mode 100644 (file)
index 0000000..7fbca17
--- /dev/null
@@ -0,0 +1,3 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+endif
diff --git a/tools/perf/arch/xtensa/util/Build b/tools/perf/arch/xtensa/util/Build
new file mode 100644 (file)
index 0000000..954e287
--- /dev/null
@@ -0,0 +1 @@
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/xtensa/util/dwarf-regs.c b/tools/perf/arch/xtensa/util/dwarf-regs.c
new file mode 100644 (file)
index 0000000..4dba76b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ * Copyright (c) 2015 Cadence Design Systems 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.
+ */
+
+#include <stddef.h>
+#include <dwarf-regs.h>
+
+#define XTENSA_MAX_REGS 16
+
+const char *xtensa_regs_table[XTENSA_MAX_REGS] = {
+       "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+       "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
+};
+
+const char *get_arch_regstr(unsigned int n)
+{
+       return n < XTENSA_MAX_REGS ? xtensa_regs_table[n] : NULL;
+}
index de165a1b92402ac7a6267bd0a0c5aa30a0053c92..20b56eb987f89f21fe20e53decf8ee1fbe275a2e 100644 (file)
@@ -521,6 +521,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
                goto out_child;
        }
 
+       /*
+        * Normally perf_session__new would do this, but it doesn't have the
+        * evlist.
+        */
+       if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
+               pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
+               rec->tool.ordered_events = false;
+       }
+
        if (!rec->evlist->nr_groups)
                perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
 
@@ -965,9 +974,11 @@ static struct record record = {
        .tool = {
                .sample         = process_sample_event,
                .fork           = perf_event__process_fork,
+               .exit           = perf_event__process_exit,
                .comm           = perf_event__process_comm,
                .mmap           = perf_event__process_mmap,
                .mmap2          = perf_event__process_mmap2,
+               .ordered_events = true,
        },
 };
 
index ecf319728f25d649768e33b3e1f274d04432f3fc..6135cc07213cb0d3379d58033ea87aa8dc580878 100644 (file)
@@ -601,8 +601,8 @@ static void display_sig(int sig __maybe_unused)
 
 static void display_setup_sig(void)
 {
-       signal(SIGSEGV, display_sig);
-       signal(SIGFPE,  display_sig);
+       signal(SIGSEGV, sighandler_dump_stack);
+       signal(SIGFPE, sighandler_dump_stack);
        signal(SIGINT,  display_sig);
        signal(SIGQUIT, display_sig);
        signal(SIGTERM, display_sig);
index 094ddaee104c73d7caae22d851d79629c4715cd3..d31fac19c30b2d298ab2cf3a710b9b27c5764144 100644 (file)
@@ -638,7 +638,7 @@ ifndef DESTDIR
 prefix ?= $(HOME)
 endif
 bindir_relative = bin
-bindir = $(prefix)/$(bindir_relative)
+bindir = $(abspath $(prefix)/$(bindir_relative))
 mandir = share/man
 infodir = share/info
 perfexecdir = libexec/perf-core
index 7ff682770fdb16e71b368af16efad0edd9443d87..f1a4c833121e306a364851328f6409cb22d779eb 100644 (file)
@@ -1387,6 +1387,24 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
                                                        event->fork.ptid);
        int err = 0;
 
+       if (dump_trace)
+               perf_event__fprintf_task(event, stdout);
+
+       /*
+        * There may be an existing thread that is not actually the parent,
+        * either because we are processing events out of order, or because the
+        * (fork) event that would have removed the thread was lost. Assume the
+        * latter case and continue on as best we can.
+        */
+       if (parent->pid_ != (pid_t)event->fork.ppid) {
+               dump_printf("removing erroneous parent thread %d/%d\n",
+                           parent->pid_, parent->tid);
+               machine__remove_thread(machine, parent);
+               thread__put(parent);
+               parent = machine__findnew_thread(machine, event->fork.ppid,
+                                                event->fork.ptid);
+       }
+
        /* if a thread currently exists for the thread id remove it */
        if (thread != NULL) {
                machine__remove_thread(machine, thread);
@@ -1395,8 +1413,6 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
 
        thread = machine__findnew_thread(machine, event->fork.pid,
                                         event->fork.tid);
-       if (dump_trace)
-               perf_event__fprintf_task(event, stdout);
 
        if (thread == NULL || parent == NULL ||
            thread__fork(thread, parent, sample->time) < 0) {
index 53e8bb7bc8521a09f1347d48de2a0dd1eeb5e0bc..2a5d8d7698aedb8c82bdf8488f1fb62ded5b438a 100644 (file)
@@ -85,7 +85,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
        else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
                update_stats(&runtime_cycles_stats[ctx][cpu], count[0]);
        else if (perf_stat_evsel__is(counter, CYCLES_IN_TX))
-               update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
+               update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]);
        else if (perf_stat_evsel__is(counter, TRANSACTION_START))
                update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
        else if (perf_stat_evsel__is(counter, ELISION_START))
@@ -398,20 +398,18 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
                                " #   %5.2f%% aborted cycles         ",
                                100.0 * ((total2-avg) / total));
        } else if (perf_stat_evsel__is(evsel, TRANSACTION_START) &&
-                  avg > 0 &&
                   runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
                total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
 
-               if (total)
+               if (avg)
                        ratio = total / avg;
 
                fprintf(out, " # %8.0f cycles / transaction   ", ratio);
        } else if (perf_stat_evsel__is(evsel, ELISION_START) &&
-                  avg > 0 &&
                   runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
                total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
 
-               if (total)
+               if (avg)
                        ratio = total / avg;
 
                fprintf(out, " # %8.0f cycles / elision       ", ratio);
index 28c4b746baa19bef9830814c4fe7c69f1be0b06b..0a9ae8014729c085ffd2872e2bc13871f79c9908 100644 (file)
@@ -191,6 +191,12 @@ static int thread__clone_map_groups(struct thread *thread,
        if (thread->pid_ == parent->pid_)
                return 0;
 
+       if (thread->mg == parent->mg) {
+               pr_debug("broken map groups on thread %d/%d parent %d/%d\n",
+                        thread->pid_, thread->tid, parent->pid_, parent->tid);
+               return 0;
+       }
+
        /* But this one is new process, copy maps. */
        for (i = 0; i < MAP__NR_TYPES; ++i)
                if (map_groups__clone(thread->mg, parent->mg, i) < 0)
index 3fc6c10c2479c7ce4a61ebd197e84d9c917db198..c4366dc74e014b184cdac2b21bd746b4e03d94c6 100755 (executable)
@@ -9,7 +9,15 @@ modprobe test_firmware
 
 DIR=/sys/devices/virtual/misc/test_firmware
 
-OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
+# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
+# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
+HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
+
+if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+       OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+fi
+
 OLD_FWPATH=$(cat /sys/module/firmware_class/parameters/path)
 
 FWPATH=$(mktemp -d)
@@ -17,7 +25,9 @@ FW="$FWPATH/test-firmware.bin"
 
 test_finish()
 {
-       echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
+       if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+               echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
+       fi
        echo -n "$OLD_PATH" >/sys/module/firmware_class/parameters/path
        rm -f "$FW"
        rmdir "$FWPATH"
@@ -25,8 +35,11 @@ test_finish()
 
 trap "test_finish" EXIT
 
-# Turn down the timeout so failures don't take so long.
-echo 1 >/sys/class/firmware/timeout
+if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+       # Turn down the timeout so failures don't take so long.
+       echo 1 >/sys/class/firmware/timeout
+fi
+
 # Set the kernel search path.
 echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path
 
@@ -41,7 +54,9 @@ if diff -q "$FW" /dev/test_firmware >/dev/null ; then
        echo "$0: firmware was not expected to match" >&2
        exit 1
 else
-       echo "$0: timeout works"
+       if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+               echo "$0: timeout works"
+       fi
 fi
 
 # This should succeed via kernel load or will fail after 1 second after
index 6efbade1213943d55714820822ffb181c113e23a..b9983f8e09f68d00eb7166bd279d34db522c8114 100755 (executable)
@@ -9,7 +9,17 @@ modprobe test_firmware
 
 DIR=/sys/devices/virtual/misc/test_firmware
 
-OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
+# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
+# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
+HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
+
+if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+       OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+else
+       echo "usermode helper disabled so ignoring test"
+       exit 0
+fi
 
 FWPATH=$(mktemp -d)
 FW="$FWPATH/test-firmware.bin"
index 8b8a4445367011b31afdb06f5363a120ea1db019..d8db2f8fce9c7ab727fb5dfa957d5f7ba828fa42 100644 (file)
@@ -2206,6 +2206,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        }
 
        kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu;
+
+       /*
+        * Pairs with smp_rmb() in kvm_get_vcpu.  Write kvm->vcpus
+        * before kvm->online_vcpu's incremented value.
+        */
        smp_wmb();
        atomic_inc(&kvm->online_vcpus);
 
@@ -2618,9 +2623,6 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
        case KVM_CAP_USER_MEMORY:
        case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
        case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
-       case KVM_CAP_SET_BOOT_CPU_ID:
-#endif
        case KVM_CAP_INTERNAL_ERROR_DATA:
 #ifdef CONFIG_HAVE_KVM_MSI
        case KVM_CAP_SIGNAL_MSI:
@@ -2716,17 +2718,6 @@ static long kvm_vm_ioctl(struct file *filp,
                r = kvm_ioeventfd(kvm, &data);
                break;
        }
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
-       case KVM_SET_BOOT_CPU_ID:
-               r = 0;
-               mutex_lock(&kvm->lock);
-               if (atomic_read(&kvm->online_vcpus) != 0)
-                       r = -EBUSY;
-               else
-                       kvm->bsp_vcpu_id = arg;
-               mutex_unlock(&kvm->lock);
-               break;
-#endif
 #ifdef CONFIG_HAVE_KVM_MSI
        case KVM_SIGNAL_MSI: {
                struct kvm_msi msi;